@@ -47,6 +47,10 @@ class InstallOptions:
4747 In InstallOptions, it allows easy initialization and management of
4848 configuration options with default values and type hints.
4949 """
50+ # Compiler
51+ cc : str = ''
52+ cxx : str = ''
53+
5054 # Tools
5155 git_path : str = ''
5256 cmake_path : str = ''
@@ -60,12 +64,12 @@ class InstallOptions:
6064 mrdocs_repo : str = "https://github.com/cppalliance/mrdocs"
6165 mrdocs_branch : str = "develop"
6266 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> "
6569 mrdocs_build_tests : bool = True
6670 mrdocs_system_install : bool = field (default_factory = lambda : not running_from_mrdocs_source_dir ())
6771 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 "" )
6973 mrdocs_run_tests : bool = True
7074
7175 # Third-party dependencies
@@ -75,23 +79,23 @@ class InstallOptions:
7579 duktape_src_dir : str = "<third-party-src-dir>/duktape"
7680 duktape_url : str = "https://github.com/svaarala/duktape/releases/download/v2.7.0/duktape-2.7.0.tar.xz"
7781 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> "
8084
8185 # Libxml2
8286 libxml2_src_dir : str = "<third-party-src-dir>/libxml2"
8387 # purposefully does not depend on mrdocs-build-type because we only need the executable
8488 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> "
8791 libxml2_repo : str = "https://github.com/GNOME/libxml2"
8892 libxml2_branch : str = "v2.12.6"
8993
9094 # LLVM
9195 llvm_src_dir : str = "<third-party-src-dir>/llvm-project"
9296 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> "
9599 llvm_repo : str = "https://github.com/llvm/llvm-project.git"
96100 llvm_commit : str = "dd7a3d4d798e30dfe53b5bbbbcd9a23c24ea1af9"
97101
@@ -103,9 +107,10 @@ class InstallOptions:
103107 # Meta
104108 non_interactive : bool = False
105109
106-
107110# Constant for option descriptions
108111INSTALL_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." ,
109114 "git_path" : "Path to the git executable, if not in system PATH." ,
110115 "cmake_path" : "Path to the cmake executable, if not in system PATH." ,
111116 "java_path" : "Path to the java executable, if not in system PATH." ,
@@ -261,30 +266,41 @@ def prompt_option(self, name, force_prompt=False):
261266 def repl (match ):
262267 nonlocal has_dir_key
263268 key = match .group (1 )
264- has_dir_key = has_dir_key or key .endswith ("-dir" )
265- key = key .replace ("-" , "_" )
266269 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 ]
276274 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+
278288 if transform_fn :
279289 if transform_fn == "lower" :
280290 val = val .lower ()
281291 elif transform_fn == "upper" :
282292 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 = ""
284300 return val
285301
286302 # 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_\-\(\) ]+))?>"
288304 default_value = re .sub (pattern , repl , default_value )
289305 if has_dir_key :
290306 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
421437 """
422438 config_args = [self .options .cmake_path , "-S" , src_dir ]
423439
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+
424444 # "DebWithOpt" is not a valid type. However, we interpret it as a special case
425445 # where the build type is Debug and optimizations are enabled.
426446 # This is not very different from RelWithDebInfo on Unix, but ensures
@@ -487,6 +507,18 @@ def check_tool(self, tool):
487507 if not self .is_executable (tool_path ):
488508 raise FileNotFoundError (f"{ tool } executable not found at { tool_path } ." )
489509
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+
490522 def check_tools (self ):
491523 tools = ["git" , "cmake" ]
492524 for tool in tools :
@@ -707,10 +739,13 @@ def create_cmake_presets(self):
707739 parent_preset_name = "relwithdebinfo"
708740 build_type_is_debwithopt = self .options .mrdocs_build_type .lower () == 'debwithopt'
709741 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 )} )"
710745 new_preset = {
711746 "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 } ." ,
714749 "inherits" : parent_preset_name ,
715750 "binaryDir" : "${sourceDir}/build/${presetName}" ,
716751 "cacheVariables" : {
@@ -1158,7 +1193,7 @@ def generate_run_configs(self):
11581193 else :
11591194 bootstrap_args .append (f"--no-{ field .name .replace ('_' , '-' )} " )
11601195 elif field .type is str :
1161- if value != '' and default_value != '' :
1196+ if value != '' :
11621197 bootstrap_args .append (f"--{ field .name .replace ('_' , '-' )} " )
11631198 bootstrap_args .append (value )
11641199 else :
@@ -1312,6 +1347,7 @@ def generate_run_configs(self):
13121347 self .generate_visual_studio_run_configs (configs )
13131348
13141349 def install_all (self ):
1350+ self .check_compilers ()
13151351 self .check_tools ()
13161352 self .setup_mrdocs_dir ()
13171353 self .setup_third_party_dir ()
0 commit comments