From 393c6529e228a805eaf91473fd768b8996325f60 Mon Sep 17 00:00:00 2001 From: binaryDiv Date: Tue, 19 May 2026 20:08:50 +0200 Subject: [PATCH] shuriken: Implement header dependency detection --- tools/shuriken.py | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/tools/shuriken.py b/tools/shuriken.py index f65d5be..b7f38a7 100755 --- a/tools/shuriken.py +++ b/tools/shuriken.py @@ -600,7 +600,25 @@ class NinjaFileGenerator: config = self.config target = self.target target_config = self.target_config - build_dir = self.config.build_dir + build_dir = config.build_dir + ninja_file_path = config.get_ninja_file_path(config.default_target) + cpp_compiler = target_config.cpp_compiler + + # Generate list of all source input files to be used as implicit dependencies for the dyndep file + dyndep_file_implicit_inputs = ' '.join(sorted( + t.src for t in self.compile_targets_cpp + self.compile_targets_cppm + )) + + # Generate list of all .dep files that are generated implicitly during dyndep file generation. + # This is mostly necessary so that Ninja can create the directories for these files beforehand. + dyndep_file_implicit_outputs = ' '.join(sorted( + f'{t.obj}.dep' for t in self.compile_targets_cpp + self.compile_targets_cppm + )) + + # Generate list of generated source files (currently just the copied std module file) + generated_source_files = ' '.join(sorted( + t.generated_src for t in self.compile_targets_std_module + )) # Generate Ninja file return f""" @@ -626,19 +644,21 @@ rule copy # Rule to compile a .cpp file to a .o file rule cpp - command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out + depfile = $out.dep + command = {cpp_compiler} $cpp_flags -MMD -MF $out.dep -c $in -o $out # Rule to compile a .cppm file (C++20 module) to a .o file ($out) and a .pcm file ($pcm_out) rule cppm - command = {target_config.cpp_compiler} $cpp_flags -c $in -o $out -fmodule-output=$pcm_out + depfile = $out.dep + command = {cpp_compiler} $cpp_flags -MMD -MF $out.dep -c $in -o $out -fmodule-output=$pcm_out # Rule to compile a standard library module to a .pcm file (e.g. "import std") rule std_module - command = {target_config.cpp_compiler} $cpp_std_module_flags --precompile $in -o $out + command = {cpp_compiler} $cpp_std_module_flags --precompile $in -o $out # Rule to link several .o files to an executable rule link - command = {target_config.cpp_compiler} $linker_flags -o $out $in $linker_args + command = {cpp_compiler} $linker_flags -o $out $in $linker_args # Rule to generate a compilation database (JSON file) from the build targets defined in a Ninja file rule generate_compdb @@ -652,13 +672,13 @@ rule generate_dyndeps # -- STATIC BUILD TARGETS # Generate compilation database from default target Ninja file -build $compdb_file: generate_compdb {self.config.get_ninja_file_path(config.default_target)} | generate_source_files +build $compdb_file: generate_compdb {ninja_file_path} | generate_source_files # Shortcut alias to generate compilation database build compdb: phony $compdb_file # Generate Ninja dyndep file from compilation database -build $dyndep_file: generate_dyndeps $compdb_file +build $dyndep_file | {dyndep_file_implicit_outputs}: generate_dyndeps $compdb_file | {dyndep_file_implicit_inputs} # -- GENERATED BUILD TARGETS @@ -668,17 +688,13 @@ build $builddir/{target_config.output_file}: link {' '.join(self.link_target_obj 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()} +build generate_source_files: phony {generated_source_files} {self.render_compile_targets()} # End of build.{target}.ninja """.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: 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))