|
26 | 26 | from .. import compilers
|
27 | 27 | from ..arglist import CompilerArgs
|
28 | 28 | from ..compilers import Compiler
|
| 29 | +from ..compilers.cpp import CPPCompiler |
29 | 30 | from ..linkers import ArLikeLinker, RSPFileSyntax
|
30 | 31 | from ..mesonlib import (
|
31 | 32 | File, LibType, MachineChoice, MesonBugException, MesonException, OrderedSet, PerMachine,
|
@@ -1134,12 +1135,12 @@ def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool:
|
1134 | 1135 | if cpp.get_id() == 'clang':
|
1135 | 1136 | clang_version_ok = mesonlib.version_compare(cpp.version, '>=17')
|
1136 | 1137 | if not clang_version_ok:
|
1137 |
| - raise MesonException('Tried to compile a library that uses modules. Modules feature is available in clang startint at version 17.') |
| 1138 | + raise MesonException('Tried to compile a library that uses modules. Modules feature is available in clang starting at version 17.') |
1138 | 1139 | return (target_has_primary_module_interface or global_scan_enabled) and clang_version_ok and EXPERIMENTAL_CPP_MODULES_FEATURE != 'disabled'
|
1139 | 1140 | if cpp.get_id() == 'gcc':
|
1140 | 1141 | gcc_version_ok = mesonlib.version_compare(cpp.version, '>=14')
|
1141 | 1142 | if not gcc_version_ok:
|
1142 |
| - raise MesonException('Tried to compile a library that uses modules. Modules feature is available in gcc startint at version 14.') |
| 1143 | + raise MesonException('Tried to compile a library that uses modules. Modules feature is available in gcc starting at version 14.') |
1143 | 1144 | return (target_has_primary_module_interface or global_scan_enabled) and clang_version_ok and EXPERIMENTAL_CPP_MODULES_FEATURE != 'disabled'
|
1144 | 1145 |
|
1145 | 1146 | if cpp.get_id() != 'msvc':
|
@@ -1191,8 +1192,6 @@ def generate_global_dependency_scan_target(self) -> None:
|
1191 | 1192 | elem.add_dep(self._all_scan_sources)
|
1192 | 1193 | self.add_build(elem)
|
1193 | 1194 |
|
1194 |
| - |
1195 |
| - |
1196 | 1195 | # def generate_dependency_scan_target(self, target: build.BuildTarget,
|
1197 | 1196 | # compiled_sources: T.List[str],
|
1198 | 1197 | # source2object: T.Dict[str, str],
|
@@ -3166,6 +3165,35 @@ def generate_common_compile_args_per_src_type(self, target: build.BuildTarget) -
|
3166 | 3165 | src_type_to_args[src_type_str] = commands.to_native()
|
3167 | 3166 | return src_type_to_args
|
3168 | 3167 |
|
| 3168 | + def _get_cpp_module_output_name(self, src_basename: str, |
| 3169 | + compiler: CPPCompiler, |
| 3170 | + target: build.BuildTarget): |
| 3171 | + is_module_file = src_basename.endswith('.cppm') |
| 3172 | + if not is_module_file: |
| 3173 | + # The compiler will not use this output bc it is not a module |
| 3174 | + return 'dummy' |
| 3175 | + |
| 3176 | + # Split the filename into root and extension, and take the root part |
| 3177 | + src_without_extension = os.path.splitext(src_basename)[0] |
| 3178 | + |
| 3179 | + # The primary interface unit should have the name 'module.cpp' in all cases. It should |
| 3180 | + # export as the module name the name of your target. For example, 'hello.world' target |
| 3181 | + # 'export module hello.world' |
| 3182 | + if src_without_extension == 'module': |
| 3183 | + return f"{target.name}{compiler.get_cpp20_module_bmi_extension()}" |
| 3184 | + # This is an implementation partition. by convention, it is the name that |
| 3185 | + # will be used as the name of the module. |
| 3186 | + # For example, given GreetImpl.cppm, then it should declare 'module hello.world:Greet' |
| 3187 | + # internally. |
| 3188 | + elif (src_without_extension.endswith('Impl')): |
| 3189 | + private_partition_name = src_without_extension.split('Impl')[0] |
| 3190 | + return f"{target.name}-{private_partition_name}{compiler.get_cpp20_module_bmi_extension()}" |
| 3191 | + # This is an interface partition. Same convention as the Impl with the difference that |
| 3192 | + # it does not end in 'Impl'. So for a given file 'MySalutation.cppm', the module would do |
| 3193 | + # 'export hello.world:MySalutation' |
| 3194 | + else: |
| 3195 | + return f"{target.name}-{src_without_extension}{compiler.get_cpp20_module_bmi_extension()}" |
| 3196 | + |
3169 | 3197 | def generate_single_compile(self, target: build.BuildTarget, src,
|
3170 | 3198 | is_generated: bool = False, header_deps=None,
|
3171 | 3199 | order_deps: T.Optional[T.List[FileOrString]] = None,
|
@@ -3316,8 +3344,10 @@ def quote_make_target(targetName: str) -> str:
|
3316 | 3344 | element.add_item('CUDA_ESCAPED_TARGET', quote_make_target(rel_obj))
|
3317 | 3345 |
|
3318 | 3346 | if self.should_use_dyndeps_for_target(target) and compiler.get_language() == 'cpp' and compiler.get_id() == 'clang':
|
| 3347 | + src_with_extension = os.path.basename(src.fname) |
| 3348 | + mod_output_name = self._get_cpp_module_output_name(src_with_extension, compiler, target) |
3319 | 3349 | commands.extend(['--start-no-unused-arguments',
|
3320 |
| - f'-fmodule-output={target.name}{compiler.get_cpp20_module_bmi_extension()}', |
| 3350 | + f'-fmodule-output={mod_output_name}', |
3321 | 3351 | f'-fprebuilt-module-path={self.environment.get_build_dir()}',
|
3322 | 3352 | '--end-no-unused-arguments'])
|
3323 | 3353 | element.add_item('ARGS', commands)
|
|
0 commit comments