@@ -47,6 +47,10 @@ class InstallOptions:
47
47
In InstallOptions, it allows easy initialization and management of
48
48
configuration options with default values and type hints.
49
49
"""
50
+ # Compiler
51
+ cc : str = ''
52
+ cxx : str = ''
53
+
50
54
# Tools
51
55
git_path : str = ''
52
56
cmake_path : str = ''
@@ -60,12 +64,12 @@ class InstallOptions:
60
64
mrdocs_repo : str = "https://github.com/cppalliance/mrdocs"
61
65
mrdocs_branch : str = "develop"
62
66
mrdocs_use_user_presets : bool = True
63
- mrdocs_preset_name : str = "<mrdocs-build-type:lower>-<os:lower>"
64
- mrdocs_build_dir : str = "<mrdocs-src-dir>/build/<mrdocs-build-type:lower>-<os:lower>"
67
+ mrdocs_preset_name : str = "<mrdocs-build-type:lower>-<os:lower>< \" - \" :if(cc)><cc:basename> "
68
+ mrdocs_build_dir : str = "<mrdocs-src-dir>/build/<mrdocs-build-type:lower>-<os:lower>< \" - \" :if(cc)><cc:basename> "
65
69
mrdocs_build_tests : bool = True
66
70
mrdocs_system_install : bool = field (default_factory = lambda : not running_from_mrdocs_source_dir ())
67
71
mrdocs_install_dir : str = field (
68
- default_factory = lambda : "<mrdocs-src-dir>/install/<mrdocs-build-type:lower>-<os:lower>" if running_from_mrdocs_source_dir () else "" )
72
+ default_factory = lambda : "<mrdocs-src-dir>/install/<mrdocs-build-type:lower>-<os:lower>-<cc:basename> " if running_from_mrdocs_source_dir () else "" )
69
73
mrdocs_run_tests : bool = True
70
74
71
75
# Third-party dependencies
@@ -75,23 +79,23 @@ class InstallOptions:
75
79
duktape_src_dir : str = "<third-party-src-dir>/duktape"
76
80
duktape_url : str = "https://github.com/svaarala/duktape/releases/download/v2.7.0/duktape-2.7.0.tar.xz"
77
81
duktape_build_type : str = "<mrdocs-build-type>"
78
- duktape_build_dir : str = "<duktape-src-dir>/build/<duktape-build-type:lower>"
79
- duktape_install_dir : str = "<duktape-src-dir>/install/<duktape-build-type:lower>"
82
+ duktape_build_dir : str = "<duktape-src-dir>/build/<duktape-build-type:lower>< \" - \" :if(cc)><cc:basename> "
83
+ duktape_install_dir : str = "<duktape-src-dir>/install/<duktape-build-type:lower>< \" - \" :if(cc)><cc:basename> "
80
84
81
85
# Libxml2
82
86
libxml2_src_dir : str = "<third-party-src-dir>/libxml2"
83
87
# purposefully does not depend on mrdocs-build-type because we only need the executable
84
88
libxml2_build_type : str = "Release"
85
- libxml2_build_dir : str = "<libxml2-src-dir>/build/<libxml2-build-type:lower>"
86
- libxml2_install_dir : str = "<libxml2-src-dir>/install/<libxml2-build-type:lower>"
89
+ libxml2_build_dir : str = "<libxml2-src-dir>/build/<libxml2-build-type:lower>< \" - \" :if(cc)><cc:basename> "
90
+ libxml2_install_dir : str = "<libxml2-src-dir>/install/<libxml2-build-type:lower>< \" - \" :if(cc)><cc:basename> "
87
91
libxml2_repo : str = "https://github.com/GNOME/libxml2"
88
92
libxml2_branch : str = "v2.12.6"
89
93
90
94
# LLVM
91
95
llvm_src_dir : str = "<third-party-src-dir>/llvm-project"
92
96
llvm_build_type : str = "<mrdocs-build-type>"
93
- llvm_build_dir : str = "<llvm-src-dir>/build/<llvm-build-type:lower>"
94
- llvm_install_dir : str = "<llvm-src-dir>/install/<llvm-build-type:lower>"
97
+ llvm_build_dir : str = "<llvm-src-dir>/build/<llvm-build-type:lower>< \" - \" :if(cc)><cc:basename> "
98
+ llvm_install_dir : str = "<llvm-src-dir>/install/<llvm-build-type:lower>< \" - \" :if(cc)><cc:basename> "
95
99
llvm_repo : str = "https://github.com/llvm/llvm-project.git"
96
100
llvm_commit : str = "dd7a3d4d798e30dfe53b5bbbbcd9a23c24ea1af9"
97
101
@@ -103,9 +107,10 @@ class InstallOptions:
103
107
# Meta
104
108
non_interactive : bool = False
105
109
106
-
107
110
# Constant for option descriptions
108
111
INSTALL_OPTION_DESCRIPTIONS = {
112
+ "cc" : "Path to the C compiler executable. Leave empty for default." ,
113
+ "cxx" : "Path to the C++ compiler executable. Leave empty for default." ,
109
114
"git_path" : "Path to the git executable, if not in system PATH." ,
110
115
"cmake_path" : "Path to the cmake executable, if not in system PATH." ,
111
116
"java_path" : "Path to the java executable, if not in system PATH." ,
@@ -261,30 +266,41 @@ def prompt_option(self, name, force_prompt=False):
261
266
def repl (match ):
262
267
nonlocal has_dir_key
263
268
key = match .group (1 )
264
- has_dir_key = has_dir_key or key .endswith ("-dir" )
265
- key = key .replace ("-" , "_" )
266
269
transform_fn = match .group (2 )
267
- if key == 'os' :
268
- if self .is_windows ():
269
- val = "windows"
270
- elif self .is_linux ():
271
- val = "linux"
272
- elif self .is_macos ():
273
- val = "macos"
274
- else :
275
- raise ValueError ("Unsupported operating system." )
270
+ has_dir_key = has_dir_key or key .endswith ("-dir" )
271
+ key_surrounded_by_quotes = key .startswith ('"' ) and key .endswith ('"' )
272
+ if key_surrounded_by_quotes :
273
+ val = key [1 :- 1 ]
276
274
else :
277
- val = getattr (self .options , key , None )
275
+ if key == 'os' :
276
+ if self .is_windows ():
277
+ val = "windows"
278
+ elif self .is_linux ():
279
+ val = "linux"
280
+ elif self .is_macos ():
281
+ val = "macos"
282
+ else :
283
+ raise ValueError ("Unsupported operating system." )
284
+ else :
285
+ key = key .replace ("-" , "_" )
286
+ val = getattr (self .options , key , None )
287
+
278
288
if transform_fn :
279
289
if transform_fn == "lower" :
280
290
val = val .lower ()
281
291
elif transform_fn == "upper" :
282
292
val = val .upper ()
283
- # Add more formats as needed
293
+ elif transform_fn == "basename" :
294
+ val = os .path .basename (val )
295
+ elif transform_fn == "if(cc)" :
296
+ if self .options .cc :
297
+ val = val .lower ()
298
+ else :
299
+ val = ""
284
300
return val
285
301
286
302
# Regex: <key> or <key:format>
287
- pattern = r"<([a-zA-Z0-9_\-]+)(?::([a-zA-Z0-9_\-]+))?>"
303
+ pattern = r"<([\" a-zA-Z0-9_\-]+)(?::([a-zA-Z0-9_\-\(\) ]+))?>"
288
304
default_value = re .sub (pattern , repl , default_value )
289
305
if has_dir_key :
290
306
default_value = os .path .abspath (default_value )
@@ -421,6 +437,10 @@ def cmake_workflow(self, src_dir, build_type, build_dir, install_dir, extra_args
421
437
"""
422
438
config_args = [self .options .cmake_path , "-S" , src_dir ]
423
439
440
+ if self .options .cc and self .options .cxx :
441
+ config_args .extend (["-DCMAKE_C_COMPILER=" + self .options .cc ,
442
+ "-DCMAKE_CXX_COMPILER=" + self .options .cxx ])
443
+
424
444
# "DebWithOpt" is not a valid type. However, we interpret it as a special case
425
445
# where the build type is Debug and optimizations are enabled.
426
446
# This is not very different from RelWithDebInfo on Unix, but ensures
@@ -487,6 +507,18 @@ def check_tool(self, tool):
487
507
if not self .is_executable (tool_path ):
488
508
raise FileNotFoundError (f"{ tool } executable not found at { tool_path } ." )
489
509
510
+ def check_compilers (self ):
511
+ for option in ["cc" , "cxx" ]:
512
+ self .prompt_option (option )
513
+ if getattr (self .options , option ):
514
+ if not os .path .isabs (getattr (self .options , option )):
515
+ exec = shutil .which (getattr (self .options , option ))
516
+ if exec is None :
517
+ raise FileNotFoundError (f"{ option } executable '{ getattr (self .options , option )} ' not found in PATH." )
518
+ setattr (self .options , option , exec )
519
+ if not self .is_executable (getattr (self .options , option )):
520
+ raise FileNotFoundError (f"{ option } executable not found at { getattr (self .options , option )} ." )
521
+
490
522
def check_tools (self ):
491
523
tools = ["git" , "cmake" ]
492
524
for tool in tools :
@@ -707,10 +739,13 @@ def create_cmake_presets(self):
707
739
parent_preset_name = "relwithdebinfo"
708
740
build_type_is_debwithopt = self .options .mrdocs_build_type .lower () == 'debwithopt'
709
741
cmake_build_type = self .options .mrdocs_build_type if not build_type_is_debwithopt else "Debug"
742
+ display_name = f"{ self .options .mrdocs_build_type } { OSDisplayName } "
743
+ if self .options .cc :
744
+ display_name += f" ({ os .path .basename (self .options .cc )} )"
710
745
new_preset = {
711
746
"name" : self .options .mrdocs_preset_name ,
712
- "displayName" : f" { self . options . mrdocs_build_type } { OSDisplayName } " ,
713
- "description" : f"Preset for building MrDocs in { self .options .mrdocs_build_type } mode with the default compiler in { OSDisplayName } ." ,
747
+ "displayName" : display_name ,
748
+ "description" : f"Preset for building MrDocs in { self .options .mrdocs_build_type } mode with the { os . path . basename ( self . options . cc ) if self . options . cc else ' default' } compiler in { OSDisplayName } ." ,
714
749
"inherits" : parent_preset_name ,
715
750
"binaryDir" : "${sourceDir}/build/${presetName}" ,
716
751
"cacheVariables" : {
@@ -1158,7 +1193,7 @@ def generate_run_configs(self):
1158
1193
else :
1159
1194
bootstrap_args .append (f"--no-{ field .name .replace ('_' , '-' )} " )
1160
1195
elif field .type is str :
1161
- if value != '' and default_value != '' :
1196
+ if value != '' :
1162
1197
bootstrap_args .append (f"--{ field .name .replace ('_' , '-' )} " )
1163
1198
bootstrap_args .append (value )
1164
1199
else :
@@ -1312,6 +1347,7 @@ def generate_run_configs(self):
1312
1347
self .generate_visual_studio_run_configs (configs )
1313
1348
1314
1349
def install_all (self ):
1350
+ self .check_compilers ()
1315
1351
self .check_tools ()
1316
1352
self .setup_mrdocs_dir ()
1317
1353
self .setup_third_party_dir ()
0 commit comments