OBJECT libraries: Properly recognize if sources depend on configuration

Fixes: #21198
This commit is contained in:
Deniz Bahadir
2020-09-22 14:04:26 +02:00
committed by Brad King
parent d575ecc9de
commit 2f76e7429b
5 changed files with 50 additions and 10 deletions

View File

@@ -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);

View File

@@ -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<BT<std::string>> 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 &&

View File

@@ -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;

View File

@@ -8,7 +8,12 @@ project(ConfigSources CXX)
# Source file(s) named with the configuration(s).
file(GENERATE
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp"
CONTENT "void config_$<CONFIG>() {}\n"
CONTENT [[
#if defined(_WIN32) && defined(OBJ_SHARED)
__declspec(dllexport)
#endif
void config_$<CONFIG>() {}
]]
)
# Per-config sources via INTERFACE_SOURCES.
@@ -76,3 +81,13 @@ else()
endif()
add_library(OneConfigOnly OBJECT "$<$<CONFIG:${one_config}>:${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_$<CONFIG>.cpp)
add_library(SharedLibFromObjLibFromGeneratedSources SHARED shared.cpp)
target_link_libraries(SharedLibFromObjLibFromGeneratedSources PRIVATE ObjLibFromGeneratedSources)

View File

@@ -0,0 +1,8 @@
#if defined(_WIN32)
# define EXPORT __declspec(dllexport)
#else
# define EXPORT
#endif
EXPORT void shared()
{
}