Skip to content

Commit 0a751ac

Browse files
committed
build: bootstrap supports custom compilers
1 parent b5f53bd commit 0a751ac

File tree

2 files changed

+91
-27
lines changed

2 files changed

+91
-27
lines changed

CMakeUserPresets.json.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,34 @@
252252
"warnings": {
253253
"unusedCli": false
254254
}
255+
},
256+
{
257+
"name": "release-macos-gcc",
258+
"displayName": "Release macOS (gcc)",
259+
"description": "Preset for building MrDocs in Release mode with the gcc compiler in macOS.",
260+
"inherits": "release",
261+
"binaryDir": "${sourceDir}/build/${presetName}",
262+
"cacheVariables": {
263+
"CMAKE_BUILD_TYPE": "Release",
264+
"LLVM_ROOT": "$env{HOME}/Developer/cpp-libs/llvm-project/install/release-gcc",
265+
"Clang_ROOT": "$env{HOME}/Developer/cpp-libs/llvm-project/install/release-gcc",
266+
"duktape_ROOT": "$env{HOME}/Developer/cpp-libs/duktape/install/release-gcc",
267+
"Duktape_ROOT": "$env{HOME}/Developer/cpp-libs/duktape/install/release-gcc",
268+
"libxml2_ROOT": "$env{HOME}/Developer/cpp-libs/libxml2/install/release-gcc",
269+
"LibXml2_ROOT": "$env{HOME}/Developer/cpp-libs/libxml2/install/release-gcc",
270+
"MRDOCS_BUILD_TESTS": true,
271+
"MRDOCS_BUILD_DOCS": false,
272+
"MRDOCS_GENERATE_REFERENCE": false,
273+
"MRDOCS_GENERATE_ANTORA_REFERENCE": false
274+
},
275+
"warnings": {
276+
"unusedCli": false
277+
},
278+
"condition": {
279+
"type": "equals",
280+
"lhs": "${hostSystemName}",
281+
"rhs": "Darwin"
282+
}
255283
}
256284
]
257285
}

bootstrap.py

Lines changed: 63 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -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
108111
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.",
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

Comments
 (0)