diff options
author | Evan Wilde <etceterawilde@gmail.com> | 2023-12-02 02:23:16 (GMT) |
---|---|---|
committer | Evan Wilde <etceterawilde@gmail.com> | 2024-01-03 22:57:46 (GMT) |
commit | 44f29a4291c9de6f8a1ff9097cd36576d987da14 (patch) | |
tree | 23b24e51924f002deb2415b68ec35e165a8edc3b /Source/cmNinjaTargetGenerator.cxx | |
parent | 9090d340b45fa5092443d1abcf959a9a35a4d0e7 (diff) | |
download | CMake-44f29a4291c9de6f8a1ff9097cd36576d987da14.zip CMake-44f29a4291c9de6f8a1ff9097cd36576d987da14.tar.gz CMake-44f29a4291c9de6f8a1ff9097cd36576d987da14.tar.bz2 |
Swift/Ninja: Fix multifile module compile commands
Swift compile commands need to have all source files in the module
specified in the compile command or LSP systems will report errors on
missing types that are defined in other source files in the same module.
Issue: #25491
Diffstat (limited to 'Source/cmNinjaTargetGenerator.cxx')
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 98 |
1 files changed, 78 insertions, 20 deletions
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 7ea479e..2ea893d 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -1916,7 +1916,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( // indistinguishable from the old behavior. // // FIXME(#25490): Add response file support to Swift object build step - // FIXME(#25491): Include all files in module in compile_commands.json if (sources.empty()) { return; @@ -2027,15 +2026,7 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( std::string const sourceFilePath = this->GetCompiledSourceNinjaPath(sf); objBuild.ExplicitDeps.push_back(sourceFilePath); - if (isSingleOutput) { - if (firstForConfig) { - this->ExportObjectCompileCommand( - language, sourceFilePath, objectDir, targetObjectFilename, - cmSystemTools::GetFilenamePath(targetObjectFilename), vars["FLAGS"], - vars["DEFINES"], vars["INCLUDES"], - /*compile pdb*/ "", /*target pdb*/ "", config, WithScanning::No); - } - } else { + if (!isSingleOutput) { // Object outputs std::string const objectFilepath = this->ConvertToNinjaPath(this->GetObjectFilePath(sf, config)); @@ -2045,16 +2036,6 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( // Add OFM data this->EmitSwiftDependencyInfo(sf, config); - - // Emit compile commands - if (firstForConfig) { - this->ExportObjectCompileCommand( - language, sourceFilePath, objectDir, objectFilepath, - cmSystemTools::GetFilenamePath(objectFilepath), vars["FLAGS"], - vars["DEFINES"], vars["INCLUDES"], - /*compile pdb*/ "", - /*target pdb*/ "", config, WithScanning::No); - } } } @@ -2062,6 +2043,12 @@ void cmNinjaTargetGenerator::WriteSwiftObjectBuildStatement( this->GenerateSwiftOutputFileMap(config, vars["FLAGS"]); } + if (firstForConfig) { + this->ExportSwiftObjectCompileCommand( + sources, targetObjectFilename, vars["FLAGS"], vars["DEFINES"], + vars["INCLUDES"], config, isSingleOutput); + } + for (cmTargetDepend const& dep : this->GetGlobalGenerator()->GetTargetDirectDepends(&target)) { if (!dep->IsLanguageUsed("Swift", config)) { @@ -2326,6 +2313,77 @@ void cmNinjaTargetGenerator::ExportObjectCompileCommand( objectFileName); } +void cmNinjaTargetGenerator::ExportSwiftObjectCompileCommand( + std::vector<cmSourceFile const*> const& moduleSourceFiles, + std::string const& moduleObjectFilename, std::string const& flags, + std::string const& defines, std::string const& includes, + std::string const& outputConfig, bool singleOutput) +{ + if (!this->GeneratorTarget->GetPropertyAsBool("EXPORT_COMPILE_COMMANDS")) { + return; + } + + auto escapeSourceFileName = [this](std::string srcFilename) -> std::string { + if (!cmSystemTools::FileIsFullPath(srcFilename)) { + srcFilename = + cmSystemTools::CollapseFullPath(srcFilename, + this->GetGlobalGenerator() + ->GetCMakeInstance() + ->GetHomeOutputDirectory()); + } + + return this->LocalGenerator->ConvertToOutputFormat( + srcFilename, cmOutputConverter::SHELL); + }; + + cmRulePlaceholderExpander::RuleVariables compileObjectVars; + compileObjectVars.Language = "Swift"; + compileObjectVars.Flags = flags.c_str(); + compileObjectVars.Defines = defines.c_str(); + compileObjectVars.Includes = includes.c_str(); + + // Build up the list of source files in the module + std::vector<std::string> filenames; + filenames.reserve(moduleSourceFiles.size()); + for (cmSourceFile const* sf : moduleSourceFiles) { + filenames.emplace_back( + escapeSourceFileName(this->GetCompiledSourceNinjaPath(sf))); + } + // Note that `escapedSourceFilenames` must remain alive until the + // compileObjectVars is consumed or Source will be a dangling pointer. + std::string const escapedSourceFilenames = cmJoin(filenames, " "); + compileObjectVars.Source = escapedSourceFilenames.c_str(); + + std::string const& compileCommand = + this->Makefile->GetRequiredDefinition("CMAKE_Swift_COMPILE_OBJECT"); + cmList compileCmds(compileCommand); + + auto rulePlaceholderExpander = + this->GetLocalGenerator()->CreateRulePlaceholderExpander(); + + for (cmSourceFile const* sf : moduleSourceFiles) { + std::string const sourceFilename = this->GetCompiledSourceNinjaPath(sf); + std::string objectFilename = moduleObjectFilename; + + if (!singleOutput) { + // If it's not single-output, each source file gets a separate object + objectFilename = this->GetObjectFilePath(sf, outputConfig); + } + compileObjectVars.Objects = objectFilename.c_str(); + + for (std::string& cmd : compileCmds) { + rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), + cmd, compileObjectVars); + } + + std::string commandLine = this->GetLocalGenerator()->BuildCommandLine( + compileCmds, outputConfig, outputConfig); + + this->GetGlobalGenerator()->AddCXXCompileCommand( + commandLine, sourceFilename, objectFilename); + } +} + void cmNinjaTargetGenerator::AdditionalCleanFiles(const std::string& config) { if (cmValue prop_value = |