|
4 | 4 | from __future__ import annotations |
5 | 5 |
|
6 | 6 | import functools |
| 7 | +import os |
7 | 8 | import os.path |
8 | 9 | import typing as T |
9 | 10 |
|
10 | 11 | from .. import options |
11 | 12 | from .. import mlog |
12 | | -from ..mesonlib import MesonException, version_compare |
| 13 | +from ..mesonlib import (File, MesonException, Popen_safe_logged, |
| 14 | + version_compare) |
13 | 15 |
|
14 | 16 | from .compilers import ( |
15 | 17 | gnu_winlibs, |
16 | 18 | msvc_winlibs, |
17 | 19 | Compiler, |
18 | 20 | CompileCheckMode, |
| 21 | + CompileResult |
19 | 22 | ) |
20 | 23 | from .c_function_attributes import CXX_FUNC_ATTRIBUTES, C_FUNC_ATTRIBUTES |
21 | 24 | from .mixins.apple import AppleCompilerMixin, AppleCPPStdsMixin |
@@ -88,7 +91,57 @@ def get_no_stdlib_link_args(self) -> T.List[str]: |
88 | 91 |
|
89 | 92 | def sanity_check(self, work_dir: str, environment: 'Environment') -> None: |
90 | 93 | code = 'class breakCCompiler;int main(void) { return 0; }\n' |
91 | | - return self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) |
| 94 | + self._sanity_check_impl(work_dir, environment, 'sanitycheckcpp.cc', code) |
| 95 | + if environment.coredata.optstore.get_value('cpp_import_std'): |
| 96 | + self._import_cpp_std_sanity_check(work_dir, environment) |
| 97 | + |
| 98 | + def compile_import_std_module(self, |
| 99 | + env: 'Environment', |
| 100 | + code: File): |
| 101 | + cpp_std = env.coredata.optstore.get_value('cpp_std') |
| 102 | + srcname = code.fname |
| 103 | + # Construct the compiler command-line |
| 104 | + commands = self.compiler_args() |
| 105 | + commands.append(f"-std={cpp_std}") |
| 106 | + commands.extend(['-Wno-reserved-identifier', '-Wno-reserved-module-identifier']) |
| 107 | + commands.append("--precompile") |
| 108 | + |
| 109 | + all_lists_to_add = [self.get_always_args(), self.get_debug_args(env.coredata.optstore.get_value('buildtype') == 'debug'), |
| 110 | + self.get_assert_args(disable=env.coredata.optstore.get_value('b_ndebug') in ['if-release', 'true'], |
| 111 | + env=env)] |
| 112 | + for args_list in all_lists_to_add: |
| 113 | + for arg in args_list: |
| 114 | + commands.append(arg) |
| 115 | + commands.append(srcname) |
| 116 | + tmpdirname = env.build_dir |
| 117 | + |
| 118 | + # Preprocess mode outputs to stdout, so no output args |
| 119 | + print(f"***{self.get_exelist()}") |
| 120 | + output = f'std{self.get_cpp20_module_bmi_extension()}' |
| 121 | + commands += self.get_output_args(output) |
| 122 | + no_ccache = True |
| 123 | + os_env = os.environ.copy() |
| 124 | + os_env['LC_ALL'] = 'C' |
| 125 | + os_env['CCACHE_DISABLE'] = '1' |
| 126 | + command_list = self.get_exelist(ccache=not no_ccache) + commands.to_native() |
| 127 | + p, stdo, stde = Popen_safe_logged(command_list, msg="Command line for compiling 'import std' feature", cwd=tmpdirname, env=os_env) |
| 128 | + if p.returncode != 0: |
| 129 | + raise MesonException("Could not compile library for use with 'import std'") |
| 130 | + |
| 131 | + def get_import_std_lib_source_file(self) -> str: |
| 132 | + raise MesonException("Your compiler does not support 'import std' feature or it has not been implemented") |
| 133 | + |
| 134 | + def get_cpp20_module_bmi_extension(self) -> str: |
| 135 | + raise MesonException("Your compiler does not support 'import std' feature or it has not been implemented") |
| 136 | + |
| 137 | + def get_import_std_compile_args(self, environment: 'Environment'): |
| 138 | + raise MesonException("Your compiler does not support 'import std' feature or it has not been implemented") |
| 139 | + |
| 140 | + def check_cpp_import_std_support(self): |
| 141 | + raise MesonException("Your compiler does not support 'import std' feature or it has not been implemented") |
| 142 | + |
| 143 | + def _import_cpp_std_sanity_check(self, work_dir: str, environment: 'Environment') -> None: |
| 144 | + self.check_cpp_import_std_support() |
92 | 145 |
|
93 | 146 | def get_compiler_check_args(self, mode: CompileCheckMode) -> T.List[str]: |
94 | 147 | # -fpermissive allows non-conforming code to compile which is necessary |
@@ -174,9 +227,13 @@ def _find_best_cpp_std(self, cpp_std: str) -> str: |
174 | 227 | def get_options(self) -> 'MutableKeyedOptionDictType': |
175 | 228 | opts = super().get_options() |
176 | 229 | key = self.form_compileropt_key('std') |
| 230 | + import_std_key = self.form_compileropt_key('import_std') |
| 231 | + |
177 | 232 | opts.update({ |
178 | 233 | key: options.UserStdOption('cpp', ALL_STDS), |
| 234 | + import_std_key: options.UseImportStd('cpp') |
179 | 235 | }) |
| 236 | + |
180 | 237 | return opts |
181 | 238 |
|
182 | 239 |
|
@@ -235,6 +292,26 @@ def __init__(self, ccache: T.List[str], exelist: T.List[str], version: str, for_ |
235 | 292 | '3': default_warn_args + ['-Wextra', '-Wpedantic'], |
236 | 293 | 'everything': ['-Weverything']} |
237 | 294 |
|
| 295 | + def check_cpp_import_std_support(self): |
| 296 | + if int(self.version.split('.')[0]) < 17: |
| 297 | + raise MesonException('Your compiler does not support import std feature. Clang support starts at version >= 17') |
| 298 | + |
| 299 | + def get_import_std_compile_args(self, env: 'Environment'): |
| 300 | + bmi_path = f'{env.get_build_dir()}/std{self.get_cpp20_module_bmi_extension()}' |
| 301 | + return f'-fmodule-file=std={bmi_path}' |
| 302 | + |
| 303 | + def get_cpp20_module_bmi_extension(self) -> str: |
| 304 | + return '.pcm' |
| 305 | + |
| 306 | + #def get_compile_only_args(self) -> T.List[str]: |
| 307 | + # return [self.get_import_std_compile_args()].extend(CPPCompiler.get_compile_only_args(self)) |
| 308 | + |
| 309 | + def get_import_std_lib_source_file(self) -> str: |
| 310 | + comp = self.get_exelist(False)[0] |
| 311 | + bin_parent_dir = os.path.dirname(comp) |
| 312 | + llvm_dir = os.path.dirname(bin_parent_dir) |
| 313 | + return f'{llvm_dir}/share/libc++/v1/std.cppm' |
| 314 | + |
238 | 315 | def get_options(self) -> 'MutableKeyedOptionDictType': |
239 | 316 | opts = super().get_options() |
240 | 317 |
|
|
0 commit comments