shuriken: Copy source file to build dir for "import std"
Problem with the previous approach: CLion wouldn't recognize the std module, unless it's included in the compdb (but then /usr/include/c++/.../bits is listed as part of the project -.-)
This commit is contained in:
parent
ae1df9bc8b
commit
5a53457817
1 changed files with 23 additions and 17 deletions
|
|
@ -497,7 +497,7 @@ class ShurikenCli:
|
||||||
|
|
||||||
CompileTargetCpp = namedtuple('CompileTargetCpp', ['src', 'obj'])
|
CompileTargetCpp = namedtuple('CompileTargetCpp', ['src', 'obj'])
|
||||||
CompileTargetCppm = namedtuple('CompileTargetCppm', ['src', 'obj', 'pcm'])
|
CompileTargetCppm = namedtuple('CompileTargetCppm', ['src', 'obj', 'pcm'])
|
||||||
CompileTargetStdModule = namedtuple('CompileTargetStdModule', ['src', 'pcm'])
|
CompileTargetStdModule = namedtuple('CompileTargetStdModule', ['original_src', 'generated_src', 'pcm'])
|
||||||
|
|
||||||
|
|
||||||
class NinjaFileGenerator:
|
class NinjaFileGenerator:
|
||||||
|
|
@ -552,7 +552,8 @@ class NinjaFileGenerator:
|
||||||
std_module_sources = std_module_source_finder.find_module_sources(['std'])
|
std_module_sources = std_module_source_finder.find_module_sources(['std'])
|
||||||
for module_name, module_src_path in std_module_sources.items():
|
for module_name, module_src_path in std_module_sources.items():
|
||||||
self.compile_targets_std_module.append(CompileTargetStdModule(
|
self.compile_targets_std_module.append(CompileTargetStdModule(
|
||||||
src=str(module_src_path),
|
original_src=str(module_src_path),
|
||||||
|
generated_src=f"$builddir/generated/stdlib/{module_name}.cppm",
|
||||||
pcm=f"$builddir/pcm/{module_name}.pcm",
|
pcm=f"$builddir/pcm/{module_name}.pcm",
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
@ -589,6 +590,10 @@ linker_args = {target_config.merged_linker_args}
|
||||||
|
|
||||||
# -- RULES
|
# -- RULES
|
||||||
|
|
||||||
|
# Rule to copy an arbitrary file (or multiple) from in to out
|
||||||
|
rule copy
|
||||||
|
command = cp $in $out
|
||||||
|
|
||||||
# Rule to compile a .cpp file to a .o file
|
# Rule to compile a .cpp file to a .o file
|
||||||
rule cpp
|
rule cpp
|
||||||
command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out
|
command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out
|
||||||
|
|
@ -607,7 +612,7 @@ rule link
|
||||||
|
|
||||||
# Rule to generate a compilation database (JSON file) from the build targets defined in a Ninja file
|
# Rule to generate a compilation database (JSON file) from the build targets defined in a Ninja file
|
||||||
rule generate_compdb
|
rule generate_compdb
|
||||||
command = ninja -f $in -t compdb cpp cppm > $out
|
command = ninja -f $in -t compdb cpp cppm std_module > $out
|
||||||
|
|
||||||
# Rule to generate a Ninja dyndep file for C++ module dependencies based on a compilation database
|
# Rule to generate a Ninja dyndep file for C++ module dependencies based on a compilation database
|
||||||
rule generate_dyndeps
|
rule generate_dyndeps
|
||||||
|
|
@ -617,7 +622,7 @@ rule generate_dyndeps
|
||||||
# -- STATIC BUILD TARGETS
|
# -- STATIC BUILD TARGETS
|
||||||
|
|
||||||
# Generate compilation database from default target Ninja file
|
# Generate compilation database from default target Ninja file
|
||||||
build $compdb_file: generate_compdb {self.config.get_ninja_file_path(config.default_target)}
|
build $compdb_file: generate_compdb {self.config.get_ninja_file_path(config.default_target)} | generate_source_files
|
||||||
|
|
||||||
# Shortcut alias to generate compilation database
|
# Shortcut alias to generate compilation database
|
||||||
build compdb: phony $compdb_file
|
build compdb: phony $compdb_file
|
||||||
|
|
@ -632,11 +637,18 @@ build $dyndep_file: generate_dyndeps $compdb_file
|
||||||
build $builddir/{target_config.output_file}: link {' '.join(self.link_target_obj_files)}
|
build $builddir/{target_config.output_file}: link {' '.join(self.link_target_obj_files)}
|
||||||
default $builddir/{target_config.output_file}
|
default $builddir/{target_config.output_file}
|
||||||
|
|
||||||
|
# Phony target that depends on all generated source files
|
||||||
|
build generate_source_files: phony {self.list_generated_source_files()}
|
||||||
|
|
||||||
{self.render_compile_targets()}
|
{self.render_compile_targets()}
|
||||||
|
|
||||||
# End of build.{target}.ninja
|
# End of build.{target}.ninja
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
|
def list_generated_source_files(self) -> str:
|
||||||
|
generated_files = [target.generated_src for target in self.compile_targets_std_module]
|
||||||
|
return ' '.join(generated_files)
|
||||||
|
|
||||||
def render_compile_targets(self) -> str:
|
def render_compile_targets(self) -> str:
|
||||||
rendered_targets = list(map(self.render_compile_target_std_module, self.compile_targets_std_module))
|
rendered_targets = list(map(self.render_compile_target_std_module, self.compile_targets_std_module))
|
||||||
rendered_targets += list(map(self.render_compile_target_cpp, self.compile_targets_cpp))
|
rendered_targets += list(map(self.render_compile_target_cpp, self.compile_targets_cpp))
|
||||||
|
|
@ -661,7 +673,9 @@ build {target.obj} | {target.pcm}: cppm {target.src} || $dyndep_file
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def render_compile_target_std_module(target: CompileTargetStdModule) -> str:
|
def render_compile_target_std_module(target: CompileTargetStdModule) -> str:
|
||||||
return f"""
|
return f"""
|
||||||
build {target.pcm}: std_module {target.src} || $dyndep_file
|
build {target.generated_src}: copy {target.original_src}
|
||||||
|
|
||||||
|
build {target.pcm}: std_module {target.generated_src} || $dyndep_file
|
||||||
dyndep = $dyndep_file
|
dyndep = $dyndep_file
|
||||||
""".strip()
|
""".strip()
|
||||||
|
|
||||||
|
|
@ -683,10 +697,6 @@ class BuildDependencyParser:
|
||||||
# Map of module names to PCM file paths
|
# Map of module names to PCM file paths
|
||||||
module_map: dict[str, Path] = {}
|
module_map: dict[str, Path] = {}
|
||||||
|
|
||||||
# Add standard library modules to module map (if "import std" support is enabled)
|
|
||||||
if self.config.enable_import_std:
|
|
||||||
module_map['std'] = Path(target_build_dir, 'pcm', 'std.pcm')
|
|
||||||
|
|
||||||
# Validate module name and path convention, construct map of module names to PCM file paths
|
# Validate module name and path convention, construct map of module names to PCM file paths
|
||||||
for rule in parsed_p1689['rules']:
|
for rule in parsed_p1689['rules']:
|
||||||
provides = rule.get('provides', [])
|
provides = rule.get('provides', [])
|
||||||
|
|
@ -697,20 +707,16 @@ class BuildDependencyParser:
|
||||||
module_name: str = provides[0]['logical-name']
|
module_name: str = provides[0]['logical-name']
|
||||||
assert module_name not in module_map, f'Module "{module_name}" is provided more than once: {rule}'
|
assert module_name not in module_map, f'Module "{module_name}" is provided more than once: {rule}'
|
||||||
|
|
||||||
expected_source_path = str(Path(source_dir, module_name.replace('.', '/') + '.cppm'))
|
if module_name != 'std':
|
||||||
assert provides[0]['source-path'] == expected_source_path, \
|
expected_source_path = str(Path(source_dir, module_name.replace('.', '/') + '.cppm'))
|
||||||
f"Module name does not match source path: {rule}"
|
assert provides[0]['source-path'] == expected_source_path, \
|
||||||
|
f"Module name does not match source path: {rule}"
|
||||||
|
|
||||||
module_map[module_name] = Path(target_build_dir, 'pcm', module_name + '.pcm')
|
module_map[module_name] = Path(target_build_dir, 'pcm', module_name + '.pcm')
|
||||||
|
|
||||||
# Collect all module dependencies to generate dyndeps
|
# Collect all module dependencies to generate dyndeps
|
||||||
build_dependencies: dict[Path, list[Path]] = {}
|
build_dependencies: dict[Path, list[Path]] = {}
|
||||||
|
|
||||||
# If "import std" support is enabled, we need to add std to the build dependencies, even though it doesn't have
|
|
||||||
# any dependencies itself. This is needed, otherwise the module won't be built automatically.
|
|
||||||
if self.config.enable_import_std:
|
|
||||||
build_dependencies[target_build_dir / 'pcm/std.pcm'] = []
|
|
||||||
|
|
||||||
# Parse rules and get module dependencies
|
# Parse rules and get module dependencies
|
||||||
for rule in parsed_p1689['rules']:
|
for rule in parsed_p1689['rules']:
|
||||||
# Compilation database contains "build/{default_target}" paths, we need to map them to "build/{target}"
|
# Compilation database contains "build/{default_target}" paths, we need to map them to "build/{target}"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue