diff --git a/.gitlab/ci/configure_windows_msvc_v71_nmake.cmake b/.gitlab/ci/configure_windows_msvc_v71_nmake.cmake index 166690abe0..78587a953b 100644 --- a/.gitlab/ci/configure_windows_msvc_v71_nmake.cmake +++ b/.gitlab/ci/configure_windows_msvc_v71_nmake.cmake @@ -1 +1,3 @@ +set(CMake_TEST_PrecompileHeaders_TIMEOUT 1000 CACHE STRING "") + include("${CMAKE_CURRENT_LIST_DIR}/configure_windows_msvc_common.cmake") diff --git a/Help/prop_tgt/COMPILE_PDB_NAME.rst b/Help/prop_tgt/COMPILE_PDB_NAME.rst index 1b4657ede0..166cfc1949 100644 --- a/Help/prop_tgt/COMPILE_PDB_NAME.rst +++ b/Help/prop_tgt/COMPILE_PDB_NAME.rst @@ -9,6 +9,9 @@ compiler while building source files. This property specifies the base name for the debug symbols file. If not set, the default is unspecified. +If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property +is ignored and the reusage target's value of this property is used instead. + .. versionadded:: 4.1 Contents of ``COMPILE_PDB_NAME`` may use diff --git a/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst index f21bdc9a73..162011d4e0 100644 --- a/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst +++ b/Help/prop_tgt/COMPILE_PDB_NAME_CONFIG.rst @@ -13,5 +13,8 @@ This is the configuration-specific version of :prop_tgt:`COMPILE_PDB_NAME`. Contents of ``COMPILE_PDB_NAME_`` may use :manual:`generator expressions `. +If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property +is ignored and the reusage target's value of this property is used instead. + .. |PDB_XXX| replace:: :prop_tgt:`PDB_NAME_` .. include:: include/COMPILE_PDB_NOTE.rst diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst index 5bfb50b772..9fa7ff264a 100644 --- a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY.rst @@ -21,5 +21,8 @@ This property is initialized by the value of the :variable:`CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY` variable if it is set when a target is created. +If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property +is ignored and the reusage target's value of this property is used instead. + .. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY` .. include:: include/COMPILE_PDB_NOTE.rst diff --git a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst index c2d4a9431c..fc9121cae1 100644 --- a/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst +++ b/Help/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG.rst @@ -20,5 +20,8 @@ if it is set when a target is created. Contents of ``COMPILE_PDB_OUTPUT_DIRECTORY_`` may use :manual:`generator expressions `. +If the :prop_tgt:`PRECOMPILE_HEADERS_REUSE_FROM` target is set, this property +is ignored and the reusage target's value of this property is used instead. + .. |PDB_XXX| replace:: :prop_tgt:`PDB_OUTPUT_DIRECTORY_` .. include:: include/COMPILE_PDB_NOTE.rst diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 60df703dc3..9ad7f08adb 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1008,6 +1008,10 @@ std::set const& cmGeneratorTarget::GetUtilityItems() const cmLinkItem(i.Value.first, i.Value.second, i.Backtrace)); } } + if (cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget()) { + this->UtilityItems.insert( + cmLinkItem(reuseTarget, false, cmListFileBacktrace())); + } } return this->UtilityItems; } @@ -1269,6 +1273,12 @@ bool cmGeneratorTarget::GetPropertyAsBool(std::string const& prop) const std::string cmGeneratorTarget::GetCompilePDBName( std::string const& config) const { + if (cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget()) { + if (reuseTarget != this) { + return reuseTarget->GetCompilePDBName(config); + } + } + // Check for a per-configuration output directory target property. std::string configUpper = cmSystemTools::UpperCase(config); std::string configProp = cmStrCat("COMPILE_PDB_NAME_", configUpper); @@ -1290,6 +1300,14 @@ std::string cmGeneratorTarget::GetCompilePDBName( return components.prefix + pdbName + ".pdb"; } + // If the target is PCH-reused, we need a stable name for the PDB file so + // that reusing targets can construct a stable name for it. + if (this->PchReused) { + NameComponents const& components = GetFullNameInternalComponents( + config, cmStateEnums::RuntimeBinaryArtifact); + return cmStrCat(components.prefix, this->GetName(), ".pdb"); + } + return ""; } @@ -2799,6 +2817,122 @@ std::string cmGeneratorTarget::GetClangTidyExportFixesDirectory( return cmSystemTools::CollapseFullPath(path); } +struct CycleWatcher +{ + CycleWatcher(bool& flag) + : Flag(flag) + { + this->Flag = true; + } + ~CycleWatcher() { this->Flag = false; } + bool& Flag; +}; + +cmGeneratorTarget const* cmGeneratorTarget::GetPchReuseTarget() const +{ + if (this->ComputingPchReuse) { + // TODO: Get the full cycle. + if (!this->PchReuseCycleDetected) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Circular PCH reuse target involving '", this->GetName(), + '\'')); + } + this->PchReuseCycleDetected = true; + return nullptr; + } + CycleWatcher watch(this->ComputingPchReuse); + (void)watch; + cmValue pchReuseFrom = this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (!pchReuseFrom) { + return nullptr; + } + cmGeneratorTarget const* generatorTarget = + this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + if (!generatorTarget) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", *pchReuseFrom, "\" for the \"", this->GetName(), + R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property does not exist.)")); + } + if (this->GetProperty("PRECOMPILE_HEADERS").IsOn()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("PRECOMPILE_HEADERS property is already set on target (\"", + this->GetName(), "\")\n")); + } + + if (generatorTarget) { + if (generatorTarget->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", *pchReuseFrom, "\" for the \"", this->GetName(), + R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property has set "DISABLE_PRECOMPILE_HEADERS".)")); + return nullptr; + } + + if (auto const* recurseReuseTarget = + generatorTarget->GetPchReuseTarget()) { + return recurseReuseTarget; + } + } + return generatorTarget; +} + +cmGeneratorTarget* cmGeneratorTarget::GetPchReuseTarget() +{ + if (this->ComputingPchReuse) { + // TODO: Get the full cycle. + if (!this->PchReuseCycleDetected) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("Circular PCH reuse target involving '", this->GetName(), + '\'')); + } + this->PchReuseCycleDetected = true; + return nullptr; + } + CycleWatcher watch(this->ComputingPchReuse); + (void)watch; + cmValue pchReuseFrom = this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + if (!pchReuseFrom) { + return nullptr; + } + cmGeneratorTarget* generatorTarget = + this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + if (!generatorTarget) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", *pchReuseFrom, "\" for the \"", this->GetName(), + R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property does not exist.)")); + } + if (this->GetProperty("PRECOMPILE_HEADERS").IsOn()) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat("PRECOMPILE_HEADERS property is already set on target (\"", + this->GetName(), "\")\n")); + } + + if (generatorTarget) { + if (generatorTarget->GetPropertyAsBool("DISABLE_PRECOMPILE_HEADERS")) { + this->Makefile->IssueMessage( + MessageType::FATAL_ERROR, + cmStrCat( + "Target \"", *pchReuseFrom, "\" for the \"", this->GetName(), + R"(" target's "PRECOMPILE_HEADERS_REUSE_FROM" property has set "DISABLE_PRECOMPILE_HEADERS".)")); + return nullptr; + } + + if (auto* recurseReuseTarget = generatorTarget->GetPchReuseTarget()) { + return recurseReuseTarget; + } + } + return generatorTarget; +} + std::vector cmGeneratorTarget::GetPchArchs( std::string const& config, std::string const& lang) const { @@ -2826,24 +2960,22 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config, return std::string(); } cmGeneratorTarget const* generatorTarget = this; - cmValue pchReuseFrom = - generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget(); + bool const haveReuseTarget = reuseTarget && reuseTarget != this; + if (reuseTarget) { + generatorTarget = reuseTarget; + } auto const inserted = this->PchHeaders.insert(std::make_pair(language + config + arch, "")); if (inserted.second) { std::vector> const headers = this->GetPrecompileHeaders(config, language); - if (headers.empty() && !pchReuseFrom) { + if (headers.empty() && !haveReuseTarget) { return std::string(); } std::string& filename = inserted.first->second; - if (pchReuseFrom) { - generatorTarget = - this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); - } - std::map const languageToExtension = { { "C", ".h" }, { "CXX", ".hxx" }, @@ -2862,7 +2994,7 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config, languageToExtension.at(language)); std::string const filename_tmp = cmStrCat(filename, ".tmp"); - if (!pchReuseFrom) { + if (!haveReuseTarget) { cmValue pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); cmValue pchEpilogue = @@ -2937,11 +3069,10 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config, std::string& filename = inserted.first->second; cmGeneratorTarget const* generatorTarget = this; - cmValue pchReuseFrom = - generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); - if (pchReuseFrom) { - generatorTarget = - this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget(); + bool const haveReuseTarget = reuseTarget && reuseTarget != this; + if (reuseTarget) { + generatorTarget = reuseTarget; } filename = @@ -2968,7 +3099,7 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config, } std::string const filename_tmp = cmStrCat(filename, ".tmp"); - if (!pchReuseFrom) { + if (!haveReuseTarget) { { cmGeneratedFileStream file(filename_tmp); file << "/* generated by CMake */\n"; @@ -3034,11 +3165,9 @@ std::string cmGeneratorTarget::GetPchFile(std::string const& config, }; cmGeneratorTarget* generatorTarget = this; - cmValue pchReuseFrom = - generatorTarget->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); - if (pchReuseFrom) { - generatorTarget = - this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + cmGeneratorTarget* reuseTarget = this->GetPchReuseTarget(); + if (reuseTarget) { + generatorTarget = reuseTarget; } std::string const pchFileObject = @@ -4428,7 +4557,12 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind, } } if (out.empty()) { - return false; + // Compile output should always have a path. + if (kind == "COMPILE_PDB"_s) { + out = this->GetSupportDirectory(); + } else { + return false; + } } // Convert the output path to a full path in case it is diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 45f7b1fca0..34b66f7ea5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -692,6 +692,9 @@ public: std::vector> GetPrecompileHeaders( std::string const& config, std::string const& language) const; + void MarkAsPchReused() { this->PchReused = true; } + cmGeneratorTarget const* GetPchReuseTarget() const; + cmGeneratorTarget* GetPchReuseTarget(); std::vector GetPchArchs(std::string const& config, std::string const& lang) const; std::string GetPchHeader(std::string const& config, @@ -1518,6 +1521,9 @@ private: std::map SourceFlags; }; mutable std::map Configs; + bool PchReused = false; + mutable bool ComputingPchReuse = false; + mutable bool PchReuseCycleDetected = false; }; class cmGeneratorTarget::TargetPropertyEntry diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index bf155851c2..41352d9570 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -387,38 +387,15 @@ bool cmGlobalGenerator::CheckTargetsForType() const return failed; } -bool cmGlobalGenerator::CheckTargetsForPchCompilePdb() const +void cmGlobalGenerator::MarkTargetsForPchReuse() const { - if (!this->GetLanguageEnabled("C") && !this->GetLanguageEnabled("CXX")) { - return false; - } - bool failed = false; for (auto const& generator : this->LocalGenerators) { for (auto const& target : generator->GetGeneratorTargets()) { - if (!target->CanCompileSources() || - target->GetProperty("ghs_integrity_app").IsOn()) { - continue; - } - - std::string const& reuseFrom = - target->GetSafeProperty("PRECOMPILE_HEADERS_REUSE_FROM"); - std::string const& compilePdb = - target->GetSafeProperty("COMPILE_PDB_NAME"); - - if (!reuseFrom.empty() && reuseFrom != compilePdb) { - std::string const e = cmStrCat( - "PRECOMPILE_HEADERS_REUSE_FROM property is set on target (\"", - target->GetName(), - "\"). Reusable precompile headers requires the COMPILE_PDB_NAME" - " property to have the value \"", - reuseFrom, "\"\n"); - this->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR, e, - target->GetBacktrace()); - failed = true; + if (auto* reuseTarget = target->GetPchReuseTarget()) { + reuseTarget->MarkAsPchReused(); } } } - return failed; } bool cmGlobalGenerator::IsExportedTargetsFile( @@ -1550,6 +1527,8 @@ bool cmGlobalGenerator::Compute() localGen->AddHelperCommands(); } + this->MarkTargetsForPchReuse(); + // Add automatically generated sources (e.g. unity build). // Add unity sources after computing compile features. Unity sources do // not change the set of languages or features, but we need to know them @@ -1597,10 +1576,6 @@ bool cmGlobalGenerator::Compute() return false; } - if (this->CheckTargetsForPchCompilePdb()) { - return false; - } - for (auto const& localGen : this->LocalGenerators) { localGen->ComputeHomeRelativeOutputPath(); } diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index e7b252859d..daaf2aa700 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -858,7 +858,7 @@ private: void CheckTargetLinkLibraries() const; bool CheckTargetsForMissingSources() const; bool CheckTargetsForType() const; - bool CheckTargetsForPchCompilePdb() const; + void MarkTargetsForPchReuse() const; void CreateLocalGenerators(); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 2638af1d28..9e367ba19d 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2779,8 +2779,8 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) continue; } - cmValue ReuseFrom = - target->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM"); + auto* reuseTarget = target->GetPchReuseTarget(); + bool const haveReuseTarget = reuseTarget && reuseTarget != target; auto* pch_sf = this->Makefile->GetOrCreateSource( pchSource, false, cmSourceFileLocationKind::Known); @@ -2789,7 +2789,7 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) pch_sf->SetProperty("CXX_SCAN_FOR_MODULES", "0"); if (!this->GetGlobalGenerator()->IsXcode()) { - if (!ReuseFrom) { + if (!haveReuseTarget) { target->AddSource(pchSource, true); } @@ -2797,14 +2797,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) // Exclude the pch files from linking if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { - if (!ReuseFrom) { + if (!haveReuseTarget) { pch_sf->AppendProperty( "OBJECT_OUTPUTS", cmStrCat("$<$:", pchFile, '>')); } else { - auto* reuseTarget = - this->GlobalGenerator->FindGeneratorTarget(*ReuseFrom); - if (this->Makefile->IsOn("CMAKE_PCH_COPY_COMPILE_PDB")) { std::string const compilerId = @@ -2850,11 +2847,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } if (editAndContinueDebugInfo || msvc2008OrLess) { - this->CopyPchCompilePdb(config, lang, target, *ReuseFrom, - reuseTarget, { ".pdb", ".idb" }); + this->CopyPchCompilePdb(config, lang, target, reuseTarget, + { ".pdb", ".idb" }); } else if (programDatabaseDebugInfo) { - this->CopyPchCompilePdb(config, lang, target, *ReuseFrom, - reuseTarget, { ".pdb" }); + this->CopyPchCompilePdb(config, lang, target, reuseTarget, + { ".pdb" }); } } @@ -2906,18 +2903,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) void cmLocalGenerator::CopyPchCompilePdb( std::string const& config, std::string const& language, - cmGeneratorTarget* target, std::string const& ReuseFrom, - cmGeneratorTarget* reuseTarget, std::vector const& extensions) + cmGeneratorTarget* target, cmGeneratorTarget* reuseTarget, + std::vector const& extensions) { - std::string const pdb_prefix = - this->GetGlobalGenerator()->IsMultiConfig() ? cmStrCat(config, '/') : ""; - - std::string const target_compile_pdb_dir = - cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', - target->GetName(), ".dir/"); - - std::string const copy_script = - cmStrCat(target_compile_pdb_dir, "copy_idb_pdb_", config, ".cmake"); + std::string const copy_script = cmStrCat(target->GetSupportDirectory(), + "/copy_idb_pdb_", config, ".cmake"); cmGeneratedFileStream file(copy_script); file << "# CMake generated file\n"; @@ -2926,28 +2916,37 @@ void cmLocalGenerator::CopyPchCompilePdb( << "# by mspdbsrv. The foreach retry loop is needed to make sure\n" << "# the pdb file is ready to be copied.\n\n"; + auto configGenex = [&](cm::string_view expr) -> std::string { + if (this->GetGlobalGenerator()->IsMultiConfig()) { + return cmStrCat("$<$:", expr, '>'); + } + return std::string(expr); + }; + + std::vector outputs; + auto replaceExtension = [](std::string const& path, + std::string const& ext) -> std::string { + auto const dir = cmSystemTools::GetFilenamePath(path); + auto const base = cmSystemTools::GetFilenameWithoutLastExtension(path); + if (dir.empty()) { + return cmStrCat(base, ext); + } + return cmStrCat(dir, '/', base, ext); + }; for (auto const& extension : extensions) { std::string const from_file = - cmStrCat(reuseTarget->GetLocalGenerator()->GetCurrentBinaryDirectory(), - '/', ReuseFrom, ".dir/${PDB_PREFIX}", ReuseFrom, extension); - - std::string const to_dir = - cmStrCat(target->GetLocalGenerator()->GetCurrentBinaryDirectory(), '/', - target->GetName(), ".dir/${PDB_PREFIX}"); - - std::string const to_file = cmStrCat(to_dir, ReuseFrom, extension); - - std::string dest_file = to_file; - - std::string const& prefix = target->GetSafeProperty("PREFIX"); - if (!prefix.empty()) { - dest_file = cmStrCat(to_dir, prefix, ReuseFrom, extension); - } + replaceExtension(reuseTarget->GetCompilePDBPath(config), extension); + std::string const to_dir = target->GetCompilePDBDirectory(config); + std::string const to_file = cmStrCat( + replaceExtension(reuseTarget->GetCompilePDBName(config), extension), + '/'); + std::string const dest_file = cmStrCat(to_dir, to_file); file << "foreach(retry RANGE 1 30)\n"; file << " if (EXISTS \"" << from_file << "\" AND (NOT EXISTS \"" - << dest_file << "\" OR NOT \"" << dest_file << " \" IS_NEWER_THAN \"" + << dest_file << "\" OR NOT \"" << dest_file << "\" IS_NEWER_THAN \"" << from_file << "\"))\n"; + file << " file(MAKE_DIRECTORY \"" << to_dir << "\")\n"; file << " execute_process(COMMAND ${CMAKE_COMMAND} -E copy"; file << " \"" << from_file << "\"" << " \"" << to_dir << "\" RESULT_VARIABLE result " @@ -2956,10 +2955,6 @@ void cmLocalGenerator::CopyPchCompilePdb( << " execute_process(COMMAND ${CMAKE_COMMAND}" << " -E sleep 1)\n" << " else()\n"; - if (!prefix.empty()) { - file << " file(REMOVE \"" << dest_file << "\")\n"; - file << " file(RENAME \"" << to_file << "\" \"" << dest_file << "\")\n"; - } file << " break()\n" << " endif()\n"; file << " elseif(NOT EXISTS \"" << from_file << "\")\n" @@ -2967,31 +2962,24 @@ void cmLocalGenerator::CopyPchCompilePdb( << " -E sleep 1)\n" << " endif()\n"; file << "endforeach()\n"; + outputs.push_back(configGenex(dest_file)); } - auto configGenex = [&](cm::string_view expr) -> std::string { - if (this->GetGlobalGenerator()->IsMultiConfig()) { - return cmStrCat("$<$:", expr, '>'); - } - return std::string(expr); - }; + cmCustomCommandLines commandLines = + cmMakeSingleCommandLine({ configGenex(cmSystemTools::GetCMakeCommand()), + configGenex("-P"), configGenex(copy_script) }); - cmCustomCommandLines commandLines = cmMakeSingleCommandLine( - { configGenex(cmSystemTools::GetCMakeCommand()), - configGenex(cmStrCat("-DPDB_PREFIX=", pdb_prefix)), configGenex("-P"), - configGenex(copy_script) }); - - char const* no_message = ""; - - std::vector outputs; - outputs.push_back(configGenex( - cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb"))); + auto const comment = + cmStrCat("Copying PDB for PCH reuse from ", reuseTarget->GetName(), + " for ", target->GetName()); + ; auto cc = cm::make_unique(); cc->SetCommandLines(commandLines); - cc->SetComment(no_message); + cc->SetComment(comment.c_str()); cc->SetStdPipesUTF8(true); - cc->AppendDepends({ reuseTarget->GetPchFile(config, language) }); + cc->AppendDepends( + { reuseTarget->GetPchFile(config, language), copy_script }); if (this->GetGlobalGenerator()->IsVisualStudio()) { cc->SetByproducts(outputs); @@ -3007,9 +2995,6 @@ void cmLocalGenerator::CopyPchCompilePdb( target->AddSource(copy_rule->ResolveFullPath()); } } - - target->Target->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - target_compile_pdb_dir); } cm::optional cmLocalGenerator::GetMSVCDebugFormatName( diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 10421116f6..0eaa6b7154 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -640,7 +640,6 @@ private: void CopyPchCompilePdb(std::string const& config, std::string const& language, cmGeneratorTarget* target, - std::string const& ReuseFrom, cmGeneratorTarget* reuseTarget, std::vector const& extensions); diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 8c4973a1f9..d4ee14d89a 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1911,7 +1911,6 @@ MAKE_PROP(COMPILE_DEFINITIONS); MAKE_PROP(COMPILE_FEATURES); MAKE_PROP(COMPILE_OPTIONS); MAKE_PROP(PRECOMPILE_HEADERS); -MAKE_PROP(PRECOMPILE_HEADERS_REUSE_FROM); MAKE_PROP(CUDA_CUBIN_COMPILATION); MAKE_PROP(CUDA_FATBIN_COMPILATION); MAKE_PROP(CUDA_OPTIX_COMPILATION); @@ -2147,38 +2146,6 @@ void cmTarget::SetProperty(std::string const& prop, cmValue value) this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); return; } - } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) { - if (this->GetProperty("PRECOMPILE_HEADERS")) { - std::ostringstream e; - e << "PRECOMPILE_HEADERS property is already set on target (\"" - << this->impl->Name << "\")\n"; - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e.str()); - return; - } - auto* reusedTarget = this->impl->Makefile->GetCMakeInstance() - ->GetGlobalGenerator() - ->FindTarget(value); - if (!reusedTarget) { - std::string const e( - "PRECOMPILE_HEADERS_REUSE_FROM set with non existing target"); - this->impl->Makefile->IssueMessage(MessageType::FATAL_ERROR, e); - return; - } - - std::string reusedFrom = reusedTarget->GetSafeProperty(prop); - if (reusedFrom.empty()) { - reusedFrom = *value; - } - - this->impl->Properties.SetProperty(prop, reusedFrom); - - reusedTarget->SetProperty("COMPILE_PDB_NAME", reusedFrom); - reusedTarget->SetProperty("COMPILE_PDB_OUTPUT_DIRECTORY", - cmStrCat(reusedFrom, ".dir/")); - - cmValue tmp = reusedTarget->GetProperty("COMPILE_PDB_NAME"); - this->SetProperty("COMPILE_PDB_NAME", tmp); - this->AddUtility(reusedFrom, false, this->impl->Makefile); } else if (prop == propC_STANDARD || prop == propCXX_STANDARD || prop == propCUDA_STANDARD || prop == propHIP_STANDARD || prop == propOBJC_STANDARD || prop == propOBJCXX_STANDARD) { @@ -2208,15 +2175,6 @@ void cmTarget::AppendProperty(std::string const& prop, "imported targets (\"", this->impl->Name, "\")\n")); } - if (prop == propPRECOMPILE_HEADERS && - this->GetProperty("PRECOMPILE_HEADERS_REUSE_FROM")) { - this->impl->Makefile->IssueMessage( - MessageType::FATAL_ERROR, - cmStrCat( - "PRECOMPILE_HEADERS_REUSE_FROM property is already set on target (\"", - this->impl->Name, "\")\n")); - return; - } UsageRequirementProperty* usageRequirements[] = { &this->impl->IncludeDirectories, diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt index de287d8214..e9494dbfa7 100644 --- a/Tests/PDBDirectoryAndName/CMakeLists.txt +++ b/Tests/PDBDirectoryAndName/CMakeLists.txt @@ -76,16 +76,27 @@ endif() set(pdbs "") foreach(t ${my_targets}) + set(with_compile 0) get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME) get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY) if(NOT pdb_name) + set(with_compile 1) get_property(pdb_name TARGET ${t} PROPERTY COMPILE_PDB_NAME) endif() if(NOT pdb_dir) get_property(pdb_dir TARGET ${t} PROPERTY COMPILE_PDB_OUTPUT_DIRECTORY) endif() if(NOT pdb_dir) - set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}) + if (NOT with_compile) + set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}) + elseif (CMAKE_GENERATOR MATCHES "Ninja" OR + CMAKE_GENERATOR MATCHES "Makefiles") + set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${t}.dir) + elseif (CMAKE_GENERATOR MATCHES "Visual Studio") + set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/${t}.dir) + else () + set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR}/${t}.dir) + endif () endif() if (pdb_dir MATCHES "\\$<.*>") # Skip per-configuration subdirectory if the value contained diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt index fe069be9b9..b87222b27a 100644 --- a/Tests/RunCMake/CMakeLists.txt +++ b/Tests/RunCMake/CMakeLists.txt @@ -1340,6 +1340,12 @@ add_RunCMake_test(PrecompileHeaders -DCMAKE_C_COMPILER_ID=${CMAKE_C_COMPILER_ID} -DCMAKE_C_SIMULATE_ID=${CMAKE_C_SIMULATE_ID} -DCMAKE_C_COMPILER_VERSION=${CMAKE_C_COMPILER_VERSION}) +# This test can take a long time due to the number of test cases. +# Provide an option to customize it. +if(DEFINED CMake_TEST_PrecompileHeaders_TIMEOUT) + set_property(TEST RunCMake.PrecompileHeaders PROPERTY TIMEOUT ${CMake_TEST_PrecompileHeaders_TIMEOUT}) +endif() + add_RunCMake_test(UnityBuild -DCMake_TEST_OBJC=${CMake_TEST_OBJC} -DCMake_TEST_CUDA=${CMake_TEST_CUDA}) set_property(TEST RunCMake.UnityBuild APPEND PROPERTY LABELS "CUDA") diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseAppend-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseAppend-build-stderr.txt new file mode 100644 index 0000000000..005f3a0627 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseAppend-build-stderr.txt @@ -0,0 +1,2 @@ +((Classic Intel)?Warning #672: the command line options do not match those used[^ +]*)? diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseAppend.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseAppend.cmake new file mode 100644 index 0000000000..eb324fcacd --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseAppend.cmake @@ -0,0 +1,60 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(reuse_append ${CMAKE_BINARY_DIR}/message.cxx) +target_include_directories(reuse_append PRIVATE ${CMAKE_BINARY_DIR}) +set_property(TARGET reuse_append PROPERTY PRECOMPILE_HEADERS_REUSE_FROM "pch-") +set_property(TARGET reuse_append APPEND_STRING PROPERTY PRECOMPILE_HEADERS_REUSE_FROM "generator") diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency-build-stderr.txt new file mode 100644 index 0000000000..005f3a0627 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency-build-stderr.txt @@ -0,0 +1,2 @@ +((Classic Intel)?Warning #672: the command line options do not match those used[^ +]*)? diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency.cmake new file mode 100644 index 0000000000..f1f07ce03b --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency.cmake @@ -0,0 +1,79 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(pch_before_reuse_pch ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(pch_before_reuse_pch PRIVATE "${CMAKE_BINARY_DIR}/string.hxx") +target_precompile_headers(pch_before_reuse_pch REUSE_FROM pch-generator) +set_property(TARGET pch_before_reuse_pch PROPERTY PRECOMPILE_HEADERS_REUSE_FROM) +target_include_directories(pch_before_reuse_pch PRIVATE ${CMAKE_BINARY_DIR}) + +add_library(pch_before_reuse_reuse ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(pch_before_reuse_reuse PRIVATE "${CMAKE_BINARY_DIR}/string.hxx") +target_precompile_headers(pch_before_reuse_reuse REUSE_FROM pch-generator) +set_property(TARGET pch_before_reuse_reuse PROPERTY PRECOMPILE_HEADERS "") +target_include_directories(pch_before_reuse_reuse PRIVATE ${CMAKE_BINARY_DIR}) + +add_library(reuse_before_pch_pch ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(reuse_before_pch_pch REUSE_FROM pch-generator) +target_precompile_headers(reuse_before_pch_pch PRIVATE "${CMAKE_BINARY_DIR}/string.hxx") +set_property(TARGET reuse_before_pch_pch PROPERTY PRECOMPILE_HEADERS_REUSE_FROM) +target_include_directories(reuse_before_pch_pch PRIVATE ${CMAKE_BINARY_DIR}) + +add_library(reuse_before_pch_reuse ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(reuse_before_pch_reuse REUSE_FROM pch-generator) +target_precompile_headers(reuse_before_pch_reuse PRIVATE "${CMAKE_BINARY_DIR}/string.hxx") +set_property(TARGET reuse_before_pch_reuse PROPERTY PRECOMPILE_HEADERS "") +target_include_directories(reuse_before_pch_reuse PRIVATE ${CMAKE_BINARY_DIR}) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder-build-stderr.txt new file mode 100644 index 0000000000..005f3a0627 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder-build-stderr.txt @@ -0,0 +1,2 @@ +((Classic Intel)?Warning #672: the command line options do not match those used[^ +]*)? diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder.cmake new file mode 100644 index 0000000000..972cae2623 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseDeclarationOrder.cmake @@ -0,0 +1,59 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(reuse_decl_order ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(reuse_decl_order REUSE_FROM pch-generator) +target_include_directories(reuse_decl_order PRIVATE ${CMAKE_BINARY_DIR}) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake index 41c7d22f3e..9b88183b73 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW-empty.cmake @@ -1,4 +1,4 @@ cmake_policy(SET CMP0141 NEW) set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "") string(APPEND CMAKE_C_FLAGS_DEBUG_INIT " -Zi") -include(PchReuseFrom-common.cmake) +include(PchReuseFrom-CMP0141-common.cmake) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake index daf7a3879e..b72490450c 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-NEW.cmake @@ -1,2 +1,2 @@ cmake_policy(SET CMP0141 NEW) -include(PchReuseFrom-common.cmake) +include(PchReuseFrom-CMP0141-common.cmake) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake index 9586887fde..1d676fcd93 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-OLD.cmake @@ -1,2 +1,2 @@ cmake_policy(SET CMP0141 OLD) -include(PchReuseFrom-common.cmake) +include(PchReuseFrom-CMP0141-common.cmake) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-common.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-common.cmake similarity index 100% rename from Tests/RunCMake/PrecompileHeaders/PchReuseFrom-common.cmake rename to Tests/RunCMake/PrecompileHeaders/PchReuseFrom-CMP0141-common.cmake diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-result.txt similarity index 100% rename from Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt rename to Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-result.txt diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-stderr.txt new file mode 100644 index 0000000000..febdb0bf19 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-stderr.txt @@ -0,0 +1,2 @@ +CMake Error in CMakeLists.txt: + Circular PCH reuse target involving 'first' diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle.cmake new file mode 100644 index 0000000000..3a2d168df4 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle.cmake @@ -0,0 +1,10 @@ +enable_language(C) + +add_library(first foo.c) +target_precompile_headers(first REUSE_FROM third) + +add_library(second foo.c) +target_precompile_headers(second REUSE_FROM first) + +add_library(third foo.c) +target_precompile_headers(third REUSE_FROM second) diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-check.cmake new file mode 100644 index 0000000000..cc571a27ba --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-check.cmake @@ -0,0 +1,19 @@ +if(MSVC OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_SIMULATE_ID STREQUAL "MSVC")) + find_file(pdb_file + NAMES NOT_USED.pdb + PATHS "${RunCMake_TEST_BINARY_DIR}" + PATH_SUFFIXES NOT_USED NOT_USED_DEBUG) + if (EXISTS "${pdb_file}") + list(APPEND RunCMake_TEST_FAILED + "PDB file was created from properties meant to be ignored") + endif () + + if (EXISTS "${RunCMake_TEST_BINARY_DIR}/mycustomdir") + list(APPEND RunCMake_TEST_FAILED + "PDB output directory ('mycustomdir') was created (should have used debug variant)") + endif () + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/mycustomdir_debug") + list(APPEND RunCMake_TEST_FAILED + "PDB output directory ('mycustomdir_debug') was not created (separate PDBs required)") + endif () +endif () diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-stderr.txt new file mode 100644 index 0000000000..005f3a0627 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps-build-stderr.txt @@ -0,0 +1,2 @@ +((Classic Intel)?Warning #672: the command line options do not match those used[^ +]*)? diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps.cmake new file mode 100644 index 0000000000..66dbf5064c --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromIgnoreOwnProps.cmake @@ -0,0 +1,66 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(ignored_props ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(ignored_props REUSE_FROM pch-generator) +target_include_directories(ignored_props PRIVATE ${CMAKE_BINARY_DIR}) + +set_target_properties(ignored_props + PROPERTIES + COMPILE_PDB_NAME "NOT_USED" + COMPILE_PDB_NAME_DEBUG "NOT_USED_DEBUG" + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/mycustomdir" + COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_BINARY_DIR}/mycustomdir_debug") diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-check.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-check.cmake new file mode 100644 index 0000000000..1cb8b566d3 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-check.cmake @@ -0,0 +1,16 @@ +if(MSVC) + find_file(pdb_file + NAMES custom-post.pdb custom-post-debug.pdb + PATHS "${RunCMake_TEST_BINARY_DIR}" + PATH_SUFFIXES custom custom-debug) + if (NOT EXISTS "${pdb_file}") + list(APPEND RunCMake_TEST_FAILED + "PDB file was not created from properties updated after reuse link") + endif () + + if (NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/custom" AND + NOT EXISTS "${RunCMake_TEST_BINARY_DIR}/custom-debug") + list(APPEND RunCMake_TEST_FAILED + "Updated PDB output directory ('custom' or 'custom-debug') was not created") + endif () +endif () diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-stderr.txt new file mode 100644 index 0000000000..005f3a0627 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps-build-stderr.txt @@ -0,0 +1,2 @@ +((Classic Intel)?Warning #672: the command line options do not match those used[^ +]*)? diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps.cmake new file mode 100644 index 0000000000..a7bd9788fc --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromUseUpdatedProps.cmake @@ -0,0 +1,66 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(updated_props ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(updated_props REUSE_FROM pch-generator) +target_include_directories(updated_props PRIVATE ${CMAKE_BINARY_DIR}) + +set_target_properties(pch-generator + PROPERTIES + COMPILE_PDB_NAME "custom-post" + COMPILE_PDB_NAME_DEBUG "custom-post-debug" + COMPILE_PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/custom" + COMPILE_PDB_OUTPUT_DIRECTORY_DEBUG "${CMAKE_CURRENT_BINARY_DIR}/custom-debug") diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-result.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-result.txt @@ -0,0 +1 @@ +1 diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-stderr.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-stderr.txt new file mode 100644 index 0000000000..a2d912b4a1 --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch-stderr.txt @@ -0,0 +1,4 @@ +CMake Error in CMakeLists.txt: + Target "pch-generator" for the "reuse_from_nopch" target's + "PRECOMPILE_HEADERS_REUSE_FROM" property has set + "DISABLE_PRECOMPILE_HEADERS". diff --git a/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch.cmake b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch.cmake new file mode 100644 index 0000000000..316793e0fc --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseWithoutPch.cmake @@ -0,0 +1,60 @@ +enable_language(CXX) + +if(CMAKE_CXX_COMPILE_OPTIONS_USE_PCH) + add_definitions(-DHAVE_PCH_SUPPORT) +endif() + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/pch.cxx [=[ +void nothing() +{ +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/string.hxx [=[ +#include + +namespace std { + struct string + { + char storage[20]; + + string(const char* s) { + strcpy(storage, s); + } + + const char* c_str() const { + return storage; + } + }; +} +]=]) + +add_library(pch-generator ${CMAKE_BINARY_DIR}/pch.cxx) +target_precompile_headers(pch-generator PRIVATE ${CMAKE_BINARY_DIR}/string.hxx) +set_property(TARGET pch-generator PROPERTY DISABLE_PRECOMPILE_HEADERS 1) + +###################################################################### + +file(WRITE ${CMAKE_BINARY_DIR}/message.cxx [=[ +#include "message.hxx" + +#ifndef HAVE_PCH_SUPPORT + #include "string.hxx" +#endif + +const char* message() +{ + static std::string greeting("hi there"); + return greeting.c_str(); +} +]=]) + +file(WRITE ${CMAKE_BINARY_DIR}/message.hxx [=[ +const char* message(); +]=]) + +add_library(reuse_from_nopch ${CMAKE_BINARY_DIR}/message.cxx) +target_precompile_headers(reuse_from_nopch REUSE_FROM pch-generator) +target_include_directories(reuse_from_nopch PRIVATE ${CMAKE_BINARY_DIR}) diff --git a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index 139d58673c..e26163b177 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -8,6 +8,13 @@ function(run_test name) run_cmake_command(${name}-test ${CMAKE_CTEST_COMMAND} -C Debug) endfunction() +function(run_build_verbose name) + set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/${name}-build) + run_cmake(${name}) + set(RunCMake_TEST_NO_CLEAN 1) + run_cmake_command(${name}-build ${CMAKE_COMMAND} --build . --verbose --config Debug) +endfunction() + run_cmake(DisabledPch) run_cmake(PchDebugGenex) run_test(PchInterface) @@ -22,7 +29,14 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") endif() run_test(PchReuseFromPrefixed) run_test(PchReuseFromSubdir) +run_build_verbose(PchReuseFromIgnoreOwnProps) +run_build_verbose(PchReuseFromUseUpdatedProps) +run_build_verbose(PchReuseConsistency) +run_cmake(PchReuseFromCycle) +run_cmake(PchReuseWithoutPch) +run_build_verbose(PchReuseAppend) run_cmake(PchMultilanguage) +run_build_verbose(PchReuseDeclarationOrder) if(RunCMake_GENERATOR MATCHES "Make|Ninja") run_cmake(PchWarnInvalid) diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index 72b1c78b29..8ea38c89bb 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -43,7 +43,6 @@ run_cmake(VsDpiAware) run_cmake(VsDpiAwareBadParam) run_cmake(VsForceInclude) run_cmake(VsPrecompileHeaders) -run_cmake(VsPrecompileHeadersReuseFromCompilePDBName) run_cmake(VsDeployEnabled) run_cmake(VsSettings) run_cmake(VsSourceSettingsTool) diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt deleted file mode 100644 index 2ff57cda4e..0000000000 --- a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-stderr.txt +++ /dev/null @@ -1,7 +0,0 @@ -CMake Error at VsPrecompileHeadersReuseFromCompilePDBName.cmake:6 \(add_library\): - PRECOMPILE_HEADERS_REUSE_FROM property is set on target \("b"\). Reusable - precompile headers requires the COMPILE_PDB_NAME property to have the value - "a" - -Call Stack \(most recent call first\): - CMakeLists.txt:3 \(include\) diff --git a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake deleted file mode 100644 index ec11008056..0000000000 --- a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName.cmake +++ /dev/null @@ -1,9 +0,0 @@ -project(VsPrecompileHeadersReuseFromCompilePDBName CXX) - -add_library(a SHARED empty.cxx) -target_precompile_headers(a PRIVATE ) - -add_library(b SHARED empty.cxx) -target_precompile_headers(b REUSE_FROM a) - -set_target_properties(b PROPERTIES COMPILE_PDB_NAME b)