diff options
-rw-r--r-- | Source/cmCommonTargetGenerator.cxx | 13 | ||||
-rw-r--r-- | Source/cmCommonTargetGenerator.h | 3 | ||||
-rw-r--r-- | Source/cmFileAPICodemodel.cxx | 25 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 68 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 20 | ||||
-rw-r--r-- | Source/cmLocalGenerator.cxx | 278 | ||||
-rw-r--r-- | Source/cmLocalGenerator.h | 13 | ||||
-rw-r--r-- | Source/cmMakefileTargetGenerator.cxx | 67 | ||||
-rw-r--r-- | Source/cmNinjaTargetGenerator.cxx | 70 | ||||
-rw-r--r-- | Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake | 9 |
10 files changed, 352 insertions, 214 deletions
diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 033cb60..939f757 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -98,17 +98,20 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( } std::string cmCommonTargetGenerator::GetFlags(const std::string& l, - const std::string& config) + const std::string& config, + const std::string& arch) { - auto i = this->Configs[config].FlagsByLanguage.find(l); - if (i == this->Configs[config].FlagsByLanguage.end()) { + const std::string key = config + arch; + + auto i = this->Configs[key].FlagsByLanguage.find(l); + if (i == this->Configs[key].FlagsByLanguage.end()) { std::string flags; this->LocalCommonGenerator->GetTargetCompileFlags(this->GeneratorTarget, - config, l, flags); + config, l, flags, arch); ByLanguageMap::value_type entry(l, flags); - i = this->Configs[config].FlagsByLanguage.insert(entry).first; + i = this->Configs[key].FlagsByLanguage.insert(entry).first; } return i->second; } diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index b40a2ed..78cedf5 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -51,7 +51,8 @@ protected: void AppendOSXVerFlag(std::string& flags, const std::string& lang, const char* name, bool so); - std::string GetFlags(const std::string& l, const std::string& config); + std::string GetFlags(const std::string& l, const std::string& config, + const std::string& arch = std::string()); std::string GetDefines(const std::string& l, const std::string& config); std::string GetIncludes(std::string const& l, const std::string& config); std::string GetManifests(const std::string& config); diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 955195f..70f5847 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -872,14 +872,27 @@ CompileData Target::BuildCompileData(cmSourceFile* sf) } // Add precompile headers compile options. - const std::string pchSource = - this->GT->GetPchSource(this->Config, fd.Language); + std::vector<std::string> architectures; + this->GT->GetAppleArchs(this->Config, architectures); + if (architectures.empty()) { + architectures.emplace_back(); + } + + std::unordered_map<std::string, std::string> pchSources; + for (const std::string& arch : architectures) { + const std::string pchSource = + this->GT->GetPchSource(this->Config, fd.Language, arch); + if (!pchSource.empty()) { + pchSources.insert(std::make_pair(pchSource, arch)); + } + } - if (!pchSource.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + if (!pchSources.empty() && !sf->GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; - if (sf->ResolveFullPath() == pchSource) { - pchOptions = - this->GT->GetPchCreateCompileOptions(this->Config, fd.Language); + auto pchIt = pchSources.find(sf->ResolveFullPath()); + if (pchIt != pchSources.end()) { + pchOptions = this->GT->GetPchCreateCompileOptions( + this->Config, fd.Language, pchIt->second); } else { pchOptions = this->GT->GetPchUseCompileOptions(this->Config, fd.Language); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index e81b619..611f7b0 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -3540,7 +3540,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( } std::string cmGeneratorTarget::GetPchHeader(const std::string& config, - const std::string& language) const + const std::string& language, + const std::string& arch) const { if (language != "C" && language != "CXX" && language != "OBJC" && language != "OBJCXX") { @@ -3555,7 +3556,7 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); const auto inserted = - this->PchHeaders.insert(std::make_pair(language + config, "")); + this->PchHeaders.insert(std::make_pair(language + config + arch, "")); if (inserted.second) { const std::vector<BT<std::string>> headers = this->GetPrecompileHeaders(config, language); @@ -3587,7 +3588,8 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, } filename = - cmStrCat(filename, "/cmake_pch", languageToExtension.at(language)); + cmStrCat(filename, "/cmake_pch", arch.empty() ? "" : cmStrCat("_", arch), + languageToExtension.at(language)); const std::string filename_tmp = cmStrCat(filename, ".tmp"); if (!pchReuseFrom) { @@ -3646,16 +3648,17 @@ std::string cmGeneratorTarget::GetPchHeader(const std::string& config, } std::string cmGeneratorTarget::GetPchSource(const std::string& config, - const std::string& language) const + const std::string& language, + const std::string& arch) const { if (language != "C" && language != "CXX" && language != "OBJC" && language != "OBJCXX") { return std::string(); } const auto inserted = - this->PchSources.insert(std::make_pair(language + config, "")); + this->PchSources.insert(std::make_pair(language + config + arch, "")); if (inserted.second) { - const std::string pchHeader = this->GetPchHeader(config, language); + const std::string pchHeader = this->GetPchHeader(config, language, arch); if (pchHeader.empty()) { return std::string(); } @@ -3682,13 +3685,15 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, { "OBJCXX", ".objcxx.hxx.mm" } }; - filename += languageToExtension.at(language); + filename = cmStrCat(filename, arch.empty() ? "" : cmStrCat("_", arch), + languageToExtension.at(language)); } else { const std::map<std::string, std::string> languageToExtension = { { "C", ".c" }, { "CXX", ".cxx" }, { "OBJC", ".m" }, { "OBJCXX", ".mm" } }; - filename += languageToExtension.at(language); + filename = cmStrCat(filename, arch.empty() ? "" : cmStrCat("_", arch), + languageToExtension.at(language)); } const std::string filename_tmp = cmStrCat(filename, ".tmp"); @@ -3705,16 +3710,17 @@ std::string cmGeneratorTarget::GetPchSource(const std::string& config, } std::string cmGeneratorTarget::GetPchFileObject(const std::string& config, - const std::string& language) + const std::string& language, + const std::string& arch) { if (language != "C" && language != "CXX" && language != "OBJC" && language != "OBJCXX") { return std::string(); } const auto inserted = - this->PchObjectFiles.insert(std::make_pair(language + config, "")); + this->PchObjectFiles.insert(std::make_pair(language + config + arch, "")); if (inserted.second) { - const std::string pchSource = this->GetPchSource(config, language); + const std::string pchSource = this->GetPchSource(config, language, arch); if (pchSource.empty()) { return std::string(); } @@ -3731,10 +3737,11 @@ std::string cmGeneratorTarget::GetPchFileObject(const std::string& config, } std::string cmGeneratorTarget::GetPchFile(const std::string& config, - const std::string& language) + const std::string& language, + const std::string& arch) { const auto inserted = - this->PchFiles.insert(std::make_pair(language + config, "")); + this->PchFiles.insert(std::make_pair(language + config + arch, "")); if (inserted.second) { std::string& pchFile = inserted.first->second; @@ -3762,12 +3769,12 @@ std::string cmGeneratorTarget::GetPchFile(const std::string& config, } const std::string pchFileObject = - generatorTarget->GetPchFileObject(config, language); + generatorTarget->GetPchFileObject(config, language, arch); if (!pchExtension.empty()) { pchFile = replaceExtension(pchFileObject, pchExtension); } } else { - pchFile = this->GetPchHeader(config, language); + pchFile = this->GetPchHeader(config, language, arch); pchFile += pchExtension; } } @@ -3775,10 +3782,11 @@ std::string cmGeneratorTarget::GetPchFile(const std::string& config, } std::string cmGeneratorTarget::GetPchCreateCompileOptions( - const std::string& config, const std::string& language) + const std::string& config, const std::string& language, + const std::string& arch) { const auto inserted = this->PchCreateCompileOptions.insert( - std::make_pair(language + config, "")); + std::make_pair(language + config + arch, "")); if (inserted.second) { std::string& createOptionList = inserted.first->second; @@ -3793,8 +3801,8 @@ std::string cmGeneratorTarget::GetPchCreateCompileOptions( createOptionList = cmStrCat( createOptionList, ";", this->Makefile->GetSafeDefinition(createOptVar)); - const std::string pchHeader = this->GetPchHeader(config, language); - const std::string pchFile = this->GetPchFile(config, language); + const std::string pchHeader = this->GetPchHeader(config, language, arch); + const std::string pchFile = this->GetPchFile(config, language, arch); cmSystemTools::ReplaceString(createOptionList, "<PCH_HEADER>", pchHeader); cmSystemTools::ReplaceString(createOptionList, "<PCH_FILE>", pchFile); @@ -3803,10 +3811,11 @@ std::string cmGeneratorTarget::GetPchCreateCompileOptions( } std::string cmGeneratorTarget::GetPchUseCompileOptions( - const std::string& config, const std::string& language) + const std::string& config, const std::string& language, + const std::string& arch) { - const auto inserted = - this->PchUseCompileOptions.insert(std::make_pair(language + config, "")); + const auto inserted = this->PchUseCompileOptions.insert( + std::make_pair(language + config + arch, "")); if (inserted.second) { std::string& useOptionList = inserted.first->second; @@ -3816,13 +3825,18 @@ std::string cmGeneratorTarget::GetPchUseCompileOptions( } const std::string useOptVar = - cmStrCat("CMAKE_", language, "_COMPILE_OPTIONS_USE_PCH"); + cmStrCat(language, "_COMPILE_OPTIONS_USE_PCH"); + + const std::string useOptionListProperty = this->GetSafeProperty(useOptVar); - useOptionList = cmStrCat(useOptionList, ";", - this->Makefile->GetSafeDefinition(useOptVar)); + useOptionList = cmStrCat( + useOptionList, ";", + useOptionListProperty.empty() + ? this->Makefile->GetSafeDefinition(cmStrCat("CMAKE_", useOptVar)) + : useOptionListProperty); - const std::string pchHeader = this->GetPchHeader(config, language); - const std::string pchFile = this->GetPchFile(config, language); + const std::string pchHeader = this->GetPchHeader(config, language, arch); + const std::string pchFile = this->GetPchFile(config, language, arch); cmSystemTools::ReplaceString(useOptionList, "<PCH_HEADER>", pchHeader); cmSystemTools::ReplaceString(useOptionList, "<PCH_FILE>", pchFile); diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 12d30c5..9136928 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -478,17 +478,23 @@ public: const std::string& config, const std::string& language) const; std::string GetPchHeader(const std::string& config, - const std::string& language) const; + const std::string& language, + const std::string& arch = std::string()) const; std::string GetPchSource(const std::string& config, - const std::string& language) const; + const std::string& language, + const std::string& arch = std::string()) const; std::string GetPchFileObject(const std::string& config, - const std::string& language); + const std::string& language, + const std::string& arch = std::string()); std::string GetPchFile(const std::string& config, - const std::string& language); - std::string GetPchCreateCompileOptions(const std::string& config, - const std::string& language); + const std::string& language, + const std::string& arch = std::string()); + std::string GetPchCreateCompileOptions( + const std::string& config, const std::string& language, + const std::string& arch = std::string()); std::string GetPchUseCompileOptions(const std::string& config, - const std::string& language); + const std::string& language, + const std::string& arch = std::string()); void AddSourceFileToUnityBatch(const std::string& sourceFilename); bool IsSourceFilePartOfUnityBatch(const std::string& sourceFilename) const; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a80bc7c..6227f81 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -1520,16 +1520,17 @@ void cmLocalGenerator::GetTargetFlags( void cmLocalGenerator::GetTargetCompileFlags(cmGeneratorTarget* target, std::string const& config, std::string const& lang, - std::string& flags) + std::string& flags, + std::string const& arch) { std::vector<BT<std::string>> tmpFlags = - this->GetTargetCompileFlags(target, config, lang); + this->GetTargetCompileFlags(target, config, lang, arch); this->AppendFlags(flags, tmpFlags); } std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags( cmGeneratorTarget* target, std::string const& config, - std::string const& lang) + std::string const& lang, std::string const& arch) { std::vector<BT<std::string>> flags; std::string compileFlags; @@ -1543,7 +1544,7 @@ std::vector<BT<std::string>> cmLocalGenerator::GetTargetCompileFlags( this->AppendFeatureOptions(compileFlags, lang, "IPO"); } - this->AddArchitectureFlags(compileFlags, target, lang, config); + this->AddArchitectureFlags(compileFlags, target, lang, config, arch); if (lang == "Fortran") { this->AppendFlags(compileFlags, @@ -1771,7 +1772,8 @@ std::string cmLocalGenerator::GetLinkLibsCMP0065( void cmLocalGenerator::AddArchitectureFlags(std::string& flags, cmGeneratorTarget const* target, const std::string& lang, - const std::string& config) + const std::string& config, + const std::string& filterArch) { // Only add Apple specific flags on Apple platforms if (this->Makefile->IsOn("APPLE") && this->EmitUniversalBinaryFlags) { @@ -1780,8 +1782,10 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, if (!archs.empty() && !lang.empty() && (lang[0] == 'C' || lang[0] == 'F' || lang[0] == 'O')) { for (std::string const& arch : archs) { - flags += " -arch "; - flags += arch; + if (filterArch.empty() || filterArch == arch) { + flags += " -arch "; + flags += arch; + } } } @@ -1804,10 +1808,12 @@ void cmLocalGenerator::AddArchitectureFlags(std::string& flags, if (arch_sysroots[i].empty()) { continue; } - flags += " -Xarch_" + archs[i] + " "; - // Combine sysroot flag and path to work with -Xarch - std::string arch_sysroot = sysrootFlag + arch_sysroots[i]; - flags += this->ConvertToOutputFormat(arch_sysroot, SHELL); + if (filterArch.empty() || filterArch == archs[i]) { + flags += " -Xarch_" + archs[i] + " "; + // Combine sysroot flag and path to work with -Xarch + std::string arch_sysroot = sysrootFlag + arch_sysroots[i]; + flags += this->ConvertToOutputFormat(arch_sysroot, SHELL); + } } } else if (sysroot && *sysroot) { flags += " "; @@ -2446,146 +2452,174 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) continue; } - const std::string pchSource = target->GetPchSource(config, lang); - const std::string pchHeader = target->GetPchHeader(config, lang); - - if (pchSource.empty() || pchHeader.empty()) { - continue; + std::vector<std::string> architectures; + if (!this->GetGlobalGenerator()->IsXcode()) { + target->GetAppleArchs(config, architectures); } + if (architectures.empty()) { + architectures.emplace_back(); + } else { + std::string useMultiArchPch; + for (const std::string& arch : architectures) { + const std::string pchHeader = + target->GetPchHeader(config, lang, arch); + if (!pchHeader.empty()) { + useMultiArchPch = cmStrCat(useMultiArchPch, ";-Xarch_", arch, + ";-include", pchHeader); + } + } - const std::string pchExtension = - this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); - - if (pchExtension.empty()) { - continue; + if (!useMultiArchPch.empty()) { + target->Target->SetProperty( + cmStrCat(lang, "_COMPILE_OPTIONS_USE_PCH"), useMultiArchPch); + } } - const char* pchReuseFrom = - target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + for (const std::string& arch : architectures) { + const std::string pchSource = target->GetPchSource(config, lang, arch); + const std::string pchHeader = target->GetPchHeader(config, lang, arch); - auto pch_sf = this->Makefile->GetOrCreateSource( - pchSource, false, cmSourceFileLocationKind::Known); + if (pchSource.empty() || pchHeader.empty()) { + continue; + } - if (!this->GetGlobalGenerator()->IsXcode()) { - if (!pchReuseFrom) { - target->AddSource(pchSource, true); + const std::string pchExtension = + this->Makefile->GetSafeDefinition("CMAKE_PCH_EXTENSION"); + + if (pchExtension.empty()) { + continue; } - const std::string pchFile = target->GetPchFile(config, lang); + const char* pchReuseFrom = + target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); - // Exclude the pch files from linking - if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { - if (!pchReuseFrom) { - pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); - } else { - auto reuseTarget = - this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom); + auto pch_sf = this->Makefile->GetOrCreateSource( + pchSource, false, cmSourceFileLocationKind::Known); - if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { + if (!this->GetGlobalGenerator()->IsXcode()) { + if (!pchReuseFrom) { + target->AddSource(pchSource, true); + } - const std::string pdb_prefix = - this->GetGlobalGenerator()->IsMultiConfig() - ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/") - : ""; + const std::string pchFile = target->GetPchFile(config, lang, arch); - const std::string target_compile_pdb_dir = cmStrCat( - target->GetLocalGenerator()->GetCurrentBinaryDirectory(), "/", - target->GetName(), ".dir/"); + // Exclude the pch files from linking + if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { + if (!pchReuseFrom) { + pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + } else { + auto reuseTarget = + this->GlobalGenerator->FindGeneratorTarget(pchReuseFrom); - const std::string copy_script = - cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); - cmGeneratedFileStream file(copy_script); + if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { - file << "# CMake generated file\n"; - for (auto extension : { ".pdb", ".idb" }) { - const std::string from_file = - cmStrCat(reuseTarget->GetLocalGenerator() - ->GetCurrentBinaryDirectory(), - "/", pchReuseFrom, ".dir/${PDB_PREFIX}", - pchReuseFrom, extension); + const std::string pdb_prefix = + this->GetGlobalGenerator()->IsMultiConfig() + ? cmStrCat(this->GlobalGenerator->GetCMakeCFGIntDir(), "/") + : ""; - const std::string to_dir = cmStrCat( + const std::string target_compile_pdb_dir = cmStrCat( target->GetLocalGenerator()->GetCurrentBinaryDirectory(), - "/", target->GetName(), ".dir/${PDB_PREFIX}"); + "/", target->GetName(), ".dir/"); - const std::string to_file = - cmStrCat(to_dir, pchReuseFrom, extension); + const std::string copy_script = + cmStrCat(target_compile_pdb_dir, "copy_idb_pdb.cmake"); + cmGeneratedFileStream file(copy_script); - std::string dest_file = to_file; + file << "# CMake generated file\n"; + for (auto extension : { ".pdb", ".idb" }) { + const std::string from_file = + cmStrCat(reuseTarget->GetLocalGenerator() + ->GetCurrentBinaryDirectory(), + "/", pchReuseFrom, ".dir/${PDB_PREFIX}", + pchReuseFrom, extension); - const std::string prefix = target->GetSafeProperty("PREFIX"); - if (!prefix.empty()) { - dest_file = - cmStrCat(to_dir, prefix, pchReuseFrom, extension); - } + const std::string to_dir = cmStrCat( + target->GetLocalGenerator()->GetCurrentBinaryDirectory(), + "/", target->GetName(), ".dir/${PDB_PREFIX}"); - file << "if (EXISTS \"" << from_file << "\" AND \"" - << from_file << "\" IS_NEWER_THAN \"" << dest_file - << "\")\n"; - file << " file(COPY \"" << from_file << "\"" - << " DESTINATION \"" << to_dir << "\")\n"; - if (!prefix.empty()) { - file << " file(REMOVE \"" << dest_file << "\")\n"; - file << " file(RENAME \"" << to_file << "\" \"" << dest_file + const std::string to_file = + cmStrCat(to_dir, pchReuseFrom, extension); + + std::string dest_file = to_file; + + const std::string prefix = target->GetSafeProperty("PREFIX"); + if (!prefix.empty()) { + dest_file = + cmStrCat(to_dir, prefix, pchReuseFrom, extension); + } + + file << "if (EXISTS \"" << from_file << "\" AND \"" + << from_file << "\" IS_NEWER_THAN \"" << dest_file << "\")\n"; + file << " file(COPY \"" << from_file << "\"" + << " DESTINATION \"" << to_dir << "\")\n"; + if (!prefix.empty()) { + file << " file(REMOVE \"" << dest_file << "\")\n"; + file << " file(RENAME \"" << to_file << "\" \"" + << dest_file << "\")\n"; + } + file << "endif()\n"; } - file << "endif()\n"; - } - cmCustomCommandLines commandLines = cmMakeSingleCommandLine( - { cmSystemTools::GetCMakeCommand(), - cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P", copy_script }); - - const std::string no_main_dependency; - const std::vector<std::string> no_deps; - const char* no_message = ""; - const char* no_current_dir = nullptr; - std::vector<std::string> no_byproducts; - - std::vector<std::string> outputs; - outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix, - pchReuseFrom, ".pdb")); - - if (this->GetGlobalGenerator()->IsVisualStudio()) { - this->AddCustomCommandToTarget( - target->GetName(), outputs, no_deps, commandLines, - cmCustomCommandType::PRE_BUILD, no_message, no_current_dir); - } else { - cmImplicitDependsList no_implicit_depends; - cmSourceFile* copy_rule = this->AddCustomCommandToOutput( - outputs, no_byproducts, no_deps, no_main_dependency, - no_implicit_depends, commandLines, no_message, - no_current_dir); - - if (copy_rule) { - target->AddSource(copy_rule->ResolveFullPath()); + cmCustomCommandLines commandLines = cmMakeSingleCommandLine( + { cmSystemTools::GetCMakeCommand(), + cmStrCat("-DPDB_PREFIX=", pdb_prefix), "-P", + copy_script }); + + const std::string no_main_dependency; + const std::vector<std::string> no_deps; + const char* no_message = ""; + const char* no_current_dir = nullptr; + std::vector<std::string> no_byproducts; + + std::vector<std::string> outputs; + outputs.push_back(cmStrCat(target_compile_pdb_dir, pdb_prefix, + pchReuseFrom, ".pdb")); + + if (this->GetGlobalGenerator()->IsVisualStudio()) { + this->AddCustomCommandToTarget( + target->GetName(), outputs, no_deps, commandLines, + cmCustomCommandType::PRE_BUILD, no_message, + no_current_dir); + } else { + cmImplicitDependsList no_implicit_depends; + cmSourceFile* copy_rule = this->AddCustomCommandToOutput( + outputs, no_byproducts, no_deps, no_main_dependency, + no_implicit_depends, commandLines, no_message, + no_current_dir); + + if (copy_rule) { + target->AddSource(copy_rule->ResolveFullPath()); + } } - } - target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - target_compile_pdb_dir); - } + target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", + target_compile_pdb_dir); + } - std::string pchSourceObj = - reuseTarget->GetPchFileObject(config, lang); + std::string pchSourceObj = + reuseTarget->GetPchFileObject(config, lang, arch); - // Link to the pch object file - target->Target->AppendProperty( - "LINK_FLAGS", - cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), - true); + // Link to the pch object file + target->Target->AppendProperty( + "LINK_FLAGS", + cmStrCat(" ", + this->ConvertToOutputFormat(pchSourceObj, SHELL)), + true); + } + } else { + pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); } - } else { - pch_sf->SetProperty("PCH_EXTENSION", pchExtension.c_str()); - } - // Add pchHeader to source files, which will - // be grouped as "Precompile Header File" - auto pchHeader_sf = this->Makefile->GetOrCreateSource( - pchHeader, false, cmSourceFileLocationKind::Known); - std::string err; - pchHeader_sf->ResolveFullPath(&err); - target->AddSource(pchHeader); + // Add pchHeader to source files, which will + // be grouped as "Precompile Header File" + auto pchHeader_sf = this->Makefile->GetOrCreateSource( + pchHeader, false, cmSourceFileLocationKind::Known); + std::string err; + pchHeader_sf->ResolveFullPath(&err); + target->AddSource(pchHeader); + } } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 88194b7..25ed265 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -105,8 +105,8 @@ public: void AddArchitectureFlags(std::string& flags, cmGeneratorTarget const* target, - const std::string& lang, - const std::string& config); + const std::string& lang, const std::string& config, + const std::string& filterArch = std::string()); void AddLanguageFlags(std::string& flags, cmGeneratorTarget const* target, const std::string& lang, const std::string& config); @@ -435,10 +435,11 @@ public: std::string const& lang) const; void GetTargetCompileFlags(cmGeneratorTarget* target, std::string const& config, - std::string const& lang, std::string& flags); - std::vector<BT<std::string>> GetTargetCompileFlags(cmGeneratorTarget* target, - std::string const& config, - std::string const& lang); + std::string const& lang, std::string& flags, + std::string const& arch = std::string()); + std::vector<BT<std::string>> GetTargetCompileFlags( + cmGeneratorTarget* target, std::string const& config, + std::string const& lang, std::string const& arch = std::string()); std::string GetFrameworkFlags(std::string const& l, std::string const& config, diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index f687289..5bb4c57 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -5,6 +5,7 @@ #include <cassert> #include <cstdio> #include <sstream> +#include <unordered_map> #include <utility> #include <cm/memory> @@ -341,16 +342,25 @@ void cmMakefileTargetGenerator::WriteTargetLanguageFlags() } for (std::string const& language : languages) { - std::string flags = this->GetFlags(language, this->GetConfigName()); std::string defines = this->GetDefines(language, this->GetConfigName()); std::string includes = this->GetIncludes(language, this->GetConfigName()); // Escape comment characters so they do not terminate assignment. - cmSystemTools::ReplaceString(flags, "#", "\\#"); cmSystemTools::ReplaceString(defines, "#", "\\#"); cmSystemTools::ReplaceString(includes, "#", "\\#"); - *this->FlagFileStream << language << "_FLAGS = " << flags << "\n\n"; *this->FlagFileStream << language << "_DEFINES = " << defines << "\n\n"; *this->FlagFileStream << language << "_INCLUDES = " << includes << "\n\n"; + + std::vector<std::string> architectures; + this->GeneratorTarget->GetAppleArchs(this->GetConfigName(), architectures); + architectures.emplace_back(); + + for (const std::string& arch : architectures) { + std::string flags = + this->GetFlags(language, this->GetConfigName(), arch); + cmSystemTools::ReplaceString(flags, "#", "\\#"); + *this->FlagFileStream << language << "_FLAGS" << arch << " = " << flags + << "\n\n"; + } } } @@ -463,17 +473,37 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string configUpper = cmSystemTools::UpperCase(config); // Add precompile headers dependencies - const std::string pchSource = - this->GeneratorTarget->GetPchSource(config, lang); - if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { - std::string const& pchHeader = - this->GeneratorTarget->GetPchHeader(config, lang); - depends.push_back(pchHeader); - if (source.GetFullPath() != pchSource) { - depends.push_back(this->GeneratorTarget->GetPchFile(config, lang)); + std::vector<std::string> architectures; + this->GeneratorTarget->GetAppleArchs(config, architectures); + if (architectures.empty()) { + architectures.emplace_back(); + } + + std::string filterArch; + std::unordered_map<std::string, std::string> pchSources; + for (const std::string& arch : architectures) { + const std::string pchSource = + this->GeneratorTarget->GetPchSource(config, lang, arch); + if (pchSource == source.GetFullPath()) { + filterArch = arch; + } + if (!pchSource.empty()) { + pchSources.insert(std::make_pair(pchSource, arch)); + } + } + + if (!pchSources.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + for (const std::string& arch : architectures) { + std::string const& pchHeader = + this->GeneratorTarget->GetPchHeader(config, lang, arch); + depends.push_back(pchHeader); + if (pchSources.find(source.GetFullPath()) == pchSources.end()) { + depends.push_back( + this->GeneratorTarget->GetPchFile(config, lang, arch)); + } + this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, + objFullPath, pchHeader); } - this->LocalGenerator->AddImplicitDepends(this->GeneratorTarget, lang, - objFullPath, pchHeader); } std::string relativeObj = @@ -484,7 +514,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( std::string flags; // Add language-specific flags. - std::string langFlags = cmStrCat("$(", lang, "_FLAGS)"); + std::string langFlags = cmStrCat("$(", lang, "_FLAGS", filterArch, ")"); this->LocalGenerator->AppendFlags(flags, langFlags); cmGeneratorExpressionInterpreter genexInterpreter( @@ -517,11 +547,12 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( } // Add precompile headers compile options. - if (!pchSource.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { + if (!pchSources.empty() && !source.GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; - if (source.GetFullPath() == pchSource) { - pchOptions = - this->GeneratorTarget->GetPchCreateCompileOptions(config, lang); + auto pchIt = pchSources.find(source.GetFullPath()); + if (pchIt != pchSources.end()) { + pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( + config, lang, pchIt->second); } else { pchOptions = this->GeneratorTarget->GetPchUseCompileOptions(config, lang); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 8833fa4..ed74cf9 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -7,6 +7,8 @@ #include <iterator> #include <map> #include <ostream> +#include <unordered_map> +#include <unordered_set> #include <utility> #include <cm/memory> @@ -157,7 +159,26 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( cmSourceFile const* source, const std::string& language, const std::string& config) { - std::string flags = this->GetFlags(language, config); + std::vector<std::string> architectures; + std::unordered_map<std::string, std::string> pchSources; + this->GeneratorTarget->GetAppleArchs(config, architectures); + if (architectures.empty()) { + architectures.emplace_back(); + } + + std::string filterArch; + for (const std::string& arch : architectures) { + const std::string pchSource = + this->GeneratorTarget->GetPchSource(config, language, arch); + if (pchSource == source->GetFullPath()) { + filterArch = arch; + } + if (!pchSource.empty()) { + pchSources.insert(std::make_pair(pchSource, arch)); + } + } + + std::string flags = this->GetFlags(language, config, filterArch); // Add Fortran format flags. if (language == "Fortran") { @@ -181,14 +202,12 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( } // Add precompile headers compile options. - const std::string pchSource = - this->GeneratorTarget->GetPchSource(config, language); - - if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + if (!pchSources.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { std::string pchOptions; - if (source->GetFullPath() == pchSource) { - pchOptions = - this->GeneratorTarget->GetPchCreateCompileOptions(config, language); + auto pchIt = pchSources.find(source->GetFullPath()); + if (pchIt != pchSources.end()) { + pchOptions = this->GeneratorTarget->GetPchCreateCompileOptions( + config, language, pchIt->second); } else { pchOptions = this->GeneratorTarget->GetPchUseCompileOptions(config, language); @@ -1050,12 +1069,30 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // Add precompile headers dependencies std::vector<std::string> depList; - const std::string pchSource = - this->GeneratorTarget->GetPchSource(config, language); - if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { - depList.push_back(this->GeneratorTarget->GetPchHeader(config, language)); - if (source->GetFullPath() != pchSource) { - depList.push_back(this->GeneratorTarget->GetPchFile(config, language)); + std::vector<std::string> architectures; + this->GeneratorTarget->GetAppleArchs(config, architectures); + if (architectures.empty()) { + architectures.emplace_back(); + } + + std::unordered_set<std::string> pchSources; + for (const std::string& arch : architectures) { + const std::string pchSource = + this->GeneratorTarget->GetPchSource(config, language, arch); + + if (!pchSource.empty()) { + pchSources.insert(pchSource); + } + } + + if (!pchSources.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + for (const std::string& arch : architectures) { + depList.push_back( + this->GeneratorTarget->GetPchHeader(config, language, arch)); + if (pchSources.find(source->GetFullPath()) == pchSources.end()) { + depList.push_back( + this->GeneratorTarget->GetPchFile(config, language, arch)); + } } } @@ -1208,8 +1245,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), vars); - if (!pchSource.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { - if (source->GetFullPath() == pchSource) { + if (!pchSources.empty() && !source->GetProperty("SKIP_PRECOMPILE_HEADERS")) { + auto pchIt = pchSources.find(source->GetFullPath()); + if (pchIt != pchSources.end()) { this->addPoolNinjaVariable("JOB_POOL_PRECOMPILE_HEADER", this->GetGeneratorTarget(), vars); } diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index 3f684fc..381b800 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -4,12 +4,9 @@ include(RunCMake) function(run_test name) set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) run_cmake(${name}) - # Precompiled headers are not supported with multiple architectures. - if(NOT "$ENV{CMAKE_OSX_ARCHITECTURES}" MATCHES "[;$]") - set(RunCMake_TEST_NO_CLEAN 1) - run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) - run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug) - endif() + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --config Debug) + run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug) endfunction() run_cmake(DisabledPch) |