diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index dc9fbbbed6..7ec51bb086 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -1296,6 +1296,8 @@ 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); @@ -2811,12 +2813,45 @@ 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, @@ -2824,16 +2859,43 @@ cmGeneratorTarget const* cmGeneratorTarget::GetPchReuseTarget() const this->GetName(), "\")\n")); } - // Guaranteed to exist because `SetProperty` does a target lookup. - return this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + if (generatorTarget) { + 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, @@ -2841,8 +2903,12 @@ cmGeneratorTarget* cmGeneratorTarget::GetPchReuseTarget() this->GetName(), "\")\n")); } - // Guaranteed to exist because `SetProperty` does a target lookup. - return this->GetGlobalGenerator()->FindGeneratorTarget(*pchReuseFrom); + if (generatorTarget) { + if (auto* recurseReuseTarget = generatorTarget->GetPchReuseTarget()) { + return recurseReuseTarget; + } + } + return generatorTarget; } std::vector cmGeneratorTarget::GetPchArchs( @@ -2873,6 +2939,7 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config, } cmGeneratorTarget const* generatorTarget = this; cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget(); + bool const haveReuseTarget = reuseTarget && reuseTarget != this; if (reuseTarget) { generatorTarget = reuseTarget; } @@ -2882,7 +2949,7 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config, if (inserted.second) { std::vector> const headers = this->GetPrecompileHeaders(config, language); - if (headers.empty() && !reuseTarget) { + if (headers.empty() && !haveReuseTarget) { return std::string(); } std::string& filename = inserted.first->second; @@ -2905,7 +2972,7 @@ std::string cmGeneratorTarget::GetPchHeader(std::string const& config, languageToExtension.at(language)); std::string const filename_tmp = cmStrCat(filename, ".tmp"); - if (!reuseTarget) { + if (!haveReuseTarget) { cmValue pchPrologue = this->Makefile->GetDefinition("CMAKE_PCH_PROLOGUE"); cmValue pchEpilogue = @@ -2981,6 +3048,7 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config, cmGeneratorTarget const* generatorTarget = this; cmGeneratorTarget const* reuseTarget = this->GetPchReuseTarget(); + bool const haveReuseTarget = reuseTarget && reuseTarget != this; if (reuseTarget) { generatorTarget = reuseTarget; } @@ -3009,7 +3077,7 @@ std::string cmGeneratorTarget::GetPchSource(std::string const& config, } std::string const filename_tmp = cmStrCat(filename, ".tmp"); - if (!reuseTarget) { + if (!haveReuseTarget) { { cmGeneratedFileStream file(filename_tmp); file << "/* generated by CMake */\n"; @@ -4467,11 +4535,9 @@ bool cmGeneratorTarget::ComputePDBOutputDir(std::string const& kind, } } if (out.empty()) { - // 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/"); + // Compile output should always have a path. + if (kind == "COMPILE_PDB"_s) { + out = this->GetSupportDirectory(); } else { return false; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 8ced6b2aed..34b66f7ea5 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -1522,6 +1522,8 @@ private: }; mutable std::map Configs; bool PchReused = false; + mutable bool ComputingPchReuse = false; + mutable bool PchReuseCycleDetected = false; }; class cmGeneratorTarget::TargetPropertyEntry diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index a172199db4..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 \"" << 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,29 +2962,18 @@ 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(cmStrCat("-DPDB_PREFIX=", pdb_prefix)), configGenex("-P"), - configGenex(copy_script) }); + cmCustomCommandLines commandLines = + cmMakeSingleCommandLine({ configGenex(cmSystemTools::GetCMakeCommand()), + configGenex("-P"), configGenex(copy_script) }); auto const comment = cmStrCat("Copying PDB for PCH reuse from ", reuseTarget->GetName(), " for ", target->GetName()); ; - std::vector outputs; - outputs.push_back(configGenex( - cmStrCat(target_compile_pdb_dir, pdb_prefix, ReuseFrom, ".pdb"))); - auto cc = cm::make_unique(); cc->SetCommandLines(commandLines); cc->SetComment(comment.c_str()); @@ -3011,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 be4ae58d87..d2345dfbfa 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -2148,24 +2148,10 @@ void cmTarget::SetProperty(std::string const& prop, cmValue value) return; } } else if (prop == propPRECOMPILE_HEADERS_REUSE_FROM) { - 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; + this->impl->Properties.SetProperty(prop, value); + if (value) { + this->AddUtility(*value, false, this->impl->Makefile); } - - std::string reusedFrom = reusedTarget->GetSafeProperty(prop); - if (reusedFrom.empty()) { - reusedFrom = *value; - } - - this->impl->Properties.SetProperty(prop, reusedFrom); - - 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) { 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/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 index 1b404e01d9..f1f07ce03b 100644 --- a/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency.cmake +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseConsistency.cmake @@ -54,12 +54,24 @@ 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") 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/PchReuseFromCycle-result.txt b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-result.txt new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/Tests/RunCMake/PrecompileHeaders/PchReuseFromCycle-result.txt @@ -0,0 +1 @@ +1 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/RunCMakeTest.cmake b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake index ebf704bf17..386bbe2801 100644 --- a/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake +++ b/Tests/RunCMake/PrecompileHeaders/RunCMakeTest.cmake @@ -32,7 +32,9 @@ run_test(PchReuseFromSubdir) run_build_verbose(PchReuseFromIgnoreOwnProps) run_build_verbose(PchReuseFromUseUpdatedProps) run_build_verbose(PchReuseConsistency) +run_cmake(PchReuseFromCycle) run_cmake(PchMultilanguage) +run_build_verbose(PchReuseDeclarationOrder) if(RunCMake_GENERATOR MATCHES "Make|Ninja") run_cmake(PchWarnInvalid)