From 2f76e7429b96ae05e5f63d6458555a06b19c62e5 Mon Sep 17 00:00:00 2001 From: Deniz Bahadir Date: Tue, 22 Sep 2020 14:04:26 +0200 Subject: OBJECT libraries: Properly recognize if sources depend on configuration Fixes: #21198 --- Source/cmGeneratorExpressionNode.cxx | 5 ++--- Source/cmGeneratorTarget.cxx | 18 +++++++++++++----- Source/cmGeneratorTarget.h | 12 +++++++++++- Tests/ConfigSources/CMakeLists.txt | 17 ++++++++++++++++- Tests/ConfigSources/shared.cpp | 8 ++++++++ 5 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 Tests/ConfigSources/shared.cpp diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index d3308e2..4ca7405 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -1664,9 +1664,8 @@ static const struct TargetObjectsNode : public cmGeneratorExpressionNode if (context->EvaluateForBuildsystem) { // Use object file directory with buildsystem placeholder. obj_dir = gt->ObjectDirectory; - // Here we assume that the set of object files produced - // by an object library does not vary with configuration - // and do not set HadContextSensitiveCondition to true. + context->HadContextSensitiveCondition = + gt->HasContextDependentSources(); } else { // Use object file directory with per-config location. obj_dir = gt->GetObjectDirectory(context->Config); diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index d9b2f66..8589ab1 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -276,8 +276,8 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t, cmLocalGenerator* lg) , DebugLinkDirectoriesDone(false) , DebugPrecompileHeadersDone(false) , DebugSourcesDone(false) - , SourcesAreContextDependent(true) , UtilityItemsDone(false) + , SourcesAreContextDependent(Tribool::Indeterminate) { this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = lg; @@ -692,7 +692,7 @@ void cmGeneratorTarget::ClearSourcesCache() { this->AllConfigSources.clear(); this->KindedSourcesMap.clear(); - this->SourcesAreContextDependent = true; + this->SourcesAreContextDependent = Tribool::Indeterminate; this->Objects.clear(); this->VisitedConfigsForObjects.clear(); } @@ -1653,10 +1653,13 @@ std::vector> cmGeneratorTarget::GetSourceFilePaths( uniqueSrcs, debugSources); } + // Determine if sources are context-dependent or not. if (!contextDependentDirectSources && !(contextDependentInterfaceSources && numFilesBefore < files.size()) && !(contextDependentObjects && numFilesBefore2 < files.size())) { - this->SourcesAreContextDependent = false; + this->SourcesAreContextDependent = Tribool::False; + } else { + this->SourcesAreContextDependent = Tribool::True; } return files; @@ -1731,9 +1734,9 @@ cmGeneratorTarget::GetSourceFilesWithoutObjectLibraries( cmGeneratorTarget::KindedSources const& cmGeneratorTarget::GetKindedSources( std::string const& config) const { - // If we already processed one configuration and found no dependenc + // If we already processed one configuration and found no dependency // on configuration then always use the one result. - if (!this->SourcesAreContextDependent) { + if (this->SourcesAreContextDependent == Tribool::False) { return this->KindedSourcesMap.begin()->second; } @@ -7518,6 +7521,11 @@ bool cmGeneratorTarget::GetImplibGNUtoMS(std::string const& config, return false; } +bool cmGeneratorTarget::HasContextDependentSources() const +{ + return this->SourcesAreContextDependent == Tribool::True; +} + bool cmGeneratorTarget::IsExecutableWithExports() const { return (this->GetType() == cmStateEnums::EXECUTABLE && diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 4741b2a..8e0def7 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -713,6 +713,10 @@ public: bool GetImplibGNUtoMS(std::string const& config, std::string const& gnuName, std::string& out, const char* newExt = nullptr) const; + /** Can only ever return true if GetSourceFilePaths() was called before. + Otherwise, this is indeterminate and false will be assumed/returned! */ + bool HasContextDependentSources() const; + bool IsExecutableWithExports() const; /** Return whether or not the target has a DLL import library. */ @@ -1069,8 +1073,14 @@ private: mutable bool DebugLinkDirectoriesDone; mutable bool DebugPrecompileHeadersDone; mutable bool DebugSourcesDone; - mutable bool SourcesAreContextDependent; mutable bool UtilityItemsDone; + enum class Tribool + { + False = 0x0, + True = 0x1, + Indeterminate = 0x2 + }; + mutable Tribool SourcesAreContextDependent; bool ComputePDBOutputDir(const std::string& kind, const std::string& config, std::string& out) const; diff --git a/Tests/ConfigSources/CMakeLists.txt b/Tests/ConfigSources/CMakeLists.txt index 6e69e8b..7b1a312 100644 --- a/Tests/ConfigSources/CMakeLists.txt +++ b/Tests/ConfigSources/CMakeLists.txt @@ -8,7 +8,12 @@ project(ConfigSources CXX) # Source file(s) named with the configuration(s). file(GENERATE OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_$.cpp" - CONTENT "void config_$() {}\n" + CONTENT [[ +#if defined(_WIN32) && defined(OBJ_SHARED) +__declspec(dllexport) +#endif +void config_$() {} +]] ) # Per-config sources via INTERFACE_SOURCES. @@ -76,3 +81,13 @@ else() endif() add_library(OneConfigOnly OBJECT "$<$:${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp>") set_property(TARGET OneConfigOnly PROPERTY LINKER_LANGUAGE CXX) + + +# --------------------------------------------------------------------------- +# Makes sure that each configuration uses the correct generated file. +add_library(ObjLibFromGeneratedSources OBJECT) +set_property(TARGET ObjLibFromGeneratedSources PROPERTY POSITION_INDEPENDENT_CODE 1) +target_compile_definitions(ObjLibFromGeneratedSources PRIVATE OBJ_SHARED) +target_sources(ObjLibFromGeneratedSources PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config_$.cpp) +add_library(SharedLibFromObjLibFromGeneratedSources SHARED shared.cpp) +target_link_libraries(SharedLibFromObjLibFromGeneratedSources PRIVATE ObjLibFromGeneratedSources) diff --git a/Tests/ConfigSources/shared.cpp b/Tests/ConfigSources/shared.cpp new file mode 100644 index 0000000..1726c46 --- /dev/null +++ b/Tests/ConfigSources/shared.cpp @@ -0,0 +1,8 @@ +#if defined(_WIN32) +# define EXPORT __declspec(dllexport) +#else +# define EXPORT +#endif +EXPORT void shared() +{ +} -- cgit v0.12