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 9fd15418ff..e9a75cc5fb 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1269,6 +1269,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 +1296,12 @@ std::string cmGeneratorTarget::GetCompilePDBName( return components.prefix + pdbName + ".pdb"; } + if (this->PchReused) { + NameComponents const& components = GetFullNameInternalComponents( + config, cmStateEnums::RuntimeBinaryArtifact); + return cmStrCat(components.prefix, this->GetName(), ".pdb"); + } + return ""; } @@ -4441,7 +4453,14 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind, } } if (out.empty()) { - return false; + // A target which is PCH-reused must have a stable PDB output directory so + // that the PDB can be stably referred to when consuming the PCH file. + if (this->PchReused) { + out = cmStrCat(this->GetLocalGenerator()->GetCurrentBinaryDirectory(), + '/', this->GetName(), ".dir/"); + } 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 bdf6aa429c..8ced6b2aed 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -692,6 +692,7 @@ 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, @@ -1520,6 +1521,7 @@ private: std::map SourceFlags; }; mutable std::map Configs; + bool PchReused = 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/cmTarget.cxx b/Source/cmTarget.cxx index 8c4973a1f9..4101be88af 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2172,12 +2172,6 @@ void cmTarget::SetProperty(std::string const& prop, cmValue 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 || 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/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index 139d58673c..95aaafba50 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,6 +29,8 @@ if(CMAKE_C_COMPILER_ID STREQUAL "MSVC") endif() run_test(PchReuseFromPrefixed) run_test(PchReuseFromSubdir) +run_build_verbose(PchReuseFromIgnoreOwnProps) +run_build_verbose(PchReuseFromUseUpdatedProps) run_cmake(PchMultilanguage) 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-result.txt b/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt deleted file mode 100644 index d00491fd7e..0000000000 --- a/Tests/RunCMake/VS10Project/VsPrecompileHeadersReuseFromCompilePDBName-result.txt +++ /dev/null @@ -1 +0,0 @@ -1 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)