From 3c5cf1bb8c4e146f3d3d177f2be9dc53869f5d74 Mon Sep 17 00:00:00 2001 From: Brad King Date: Thu, 4 Sep 2008 17:34:25 -0400 Subject: [PATCH] ENH: Allow a custom list of debug configurations Create a DEBUG_CONFIGURATIONS global property as a way for projects to specify which configuration names are considered to be 'debug' configurations. --- Source/cmComputeLinkDepends.cxx | 19 ++------- Source/cmComputeLinkDepends.h | 1 + Source/cmExportFileGenerator.cxx | 6 +-- Source/cmTarget.cxx | 34 +++++++++++++--- Source/cmTarget.h | 3 ++ Source/cmTargetLinkLibrariesCommand.cxx | 45 +++++++++++++-------- Source/cmTargetLinkLibrariesCommand.h | 12 ++++-- Source/cmake.cxx | 51 ++++++++++++++++++++++++ Source/cmake.h | 5 +++ Tests/ExportImport/Export/CMakeLists.txt | 4 ++ Tests/ExportImport/Import/CMakeLists.txt | 9 ++++- 11 files changed, 140 insertions(+), 49 deletions(-) diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index cc60e0929..7b768dc05 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -188,6 +188,7 @@ cmComputeLinkDepends // The configuration being linked. this->Config = (config && *config)? config : 0; + this->LinkType = this->Target->ComputeLinkType(this->Config); // Enable debug mode if requested. this->DebugMode = this->Makefile->IsOn("CMAKE_LINK_DEPENDS_DEBUG_MODE"); @@ -446,13 +447,6 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, std::vector deplist; cmSystemTools::ExpandListArgument(value, deplist); - // Compute which library configuration to link. - cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED; - if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG") - { - linkType = cmTarget::DEBUG; - } - // Look for entries meant for this configuration. std::vector actual_libs; cmTarget::LinkLibraryType llt = cmTarget::GENERAL; @@ -500,7 +494,7 @@ void cmComputeLinkDepends::AddVarLinkEntries(int depender_index, } // If the library is meant for this link type then use it. - if(llt == cmTarget::GENERAL || llt == linkType) + if(llt == cmTarget::GENERAL || llt == this->LinkType) { actual_libs.push_back(*di); } @@ -524,19 +518,12 @@ void cmComputeLinkDepends::AddTargetLinkEntries(int depender_index, LinkLibraryVectorType const& libs) { - // Compute which library configuration to link. - cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED; - if(this->Config && cmSystemTools::UpperCase(this->Config) == "DEBUG") - { - linkType = cmTarget::DEBUG; - } - // Look for entries meant for this configuration. std::vector actual_libs; for(cmTarget::LinkLibraryVectorType::const_iterator li = libs.begin(); li != libs.end(); ++li) { - if(li->second == cmTarget::GENERAL || li->second == linkType) + if(li->second == cmTarget::GENERAL || li->second == this->LinkType) { actual_libs.push_back(li->first); } diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index 3cbb99a90..47fa6489e 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -72,6 +72,7 @@ private: // Configuration information. const char* Config; + cmTarget::LinkLibraryType LinkType; // Output information. EntryVector FinalLinkEntries; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index e1bbe29d9..dc2efc53f 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -177,11 +177,7 @@ cmExportFileGenerator cmTarget* target, ImportPropertyMap& properties) { // Compute which library configuration to link. - cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED; - if(config && cmSystemTools::UpperCase(config) == "DEBUG") - { - linkType = cmTarget::DEBUG; - } + cmTarget::LinkLibraryType linkType = target->ComputeLinkType(config); // Construct the list of libs linked for this configuration. std::vector actual_libs; diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 0fbae69b8..177db54d7 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -1256,6 +1256,34 @@ const std::vector& cmTarget::GetLinkDirectories() return this->LinkDirectories; } +//---------------------------------------------------------------------------- +cmTarget::LinkLibraryType cmTarget::ComputeLinkType(const char* config) +{ + // No configuration is always optimized. + if(!(config && *config)) + { + return cmTarget::OPTIMIZED; + } + + // Get the list of configurations considered to be DEBUG. + std::vector const& debugConfigs = + this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + + // Check if any entry in the list matches this configuration. + std::string configUpper = cmSystemTools::UpperCase(config); + for(std::vector::const_iterator i = debugConfigs.begin(); + i != debugConfigs.end(); ++i) + { + if(*i == configUpper) + { + return cmTarget::DEBUG; + } + } + + // The current configuration is not a debug configuration. + return cmTarget::OPTIMIZED; +} + //---------------------------------------------------------------------------- void cmTarget::ClearDependencyInformation( cmMakefile& mf, const char* target ) @@ -3620,11 +3648,7 @@ cmTargetLinkInterface* cmTarget::ComputeLinkInterface(const char* config) } // Compute which library configuration to link. - cmTarget::LinkLibraryType linkType = cmTarget::OPTIMIZED; - if(config && cmSystemTools::UpperCase(config) == "DEBUG") - { - linkType = cmTarget::DEBUG; - } + cmTarget::LinkLibraryType linkType = this->ComputeLinkType(config); // Construct the list of libs linked for this configuration. cmTarget::LinkLibraryVectorType const& llibs = diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 695d9e81e..dce4feb25 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -186,6 +186,9 @@ public: const LinkLibraryVectorType &GetOriginalLinkLibraries() const {return this->OriginalLinkLibraries;} + /** Compute the link type to use for the given configuration. */ + LinkLibraryType ComputeLinkType(const char* config); + /** * Clear the dependency information recorded for this target, if any. */ diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0bccd27d7..d84e14440 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -188,28 +188,39 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, return; } - // Include this library in the link interface for the target. - if(llt == cmTarget::DEBUG) - { - // Put in only the DEBUG configuration interface. - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES_DEBUG", lib); - } - else if(llt == cmTarget::OPTIMIZED) - { - // Put in only the non-DEBUG configuration interface. - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib); + // Get the list of configurations considered to be DEBUG. + std::vector const& debugConfigs = + this->Makefile->GetCMakeInstance()->GetDebugConfigs(); + std::string prop; - // Make sure the DEBUG configuration interface exists so that this - // one will not be used as a fall-back. - if(!this->Target->GetProperty("LINK_INTERFACE_LIBRARIES_DEBUG")) + // Include this library in the link interface for the target. + if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL) + { + // Put in the DEBUG configuration interfaces. + for(std::vector::const_iterator i = debugConfigs.begin(); + i != debugConfigs.end(); ++i) { - this->Target->SetProperty("LINK_INTERFACE_LIBRARIES_DEBUG", ""); + prop = "LINK_INTERFACE_LIBRARIES_"; + prop += *i; + this->Target->AppendProperty(prop.c_str(), lib); } } - else + if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL) { - // Put in both the DEBUG and non-DEBUG configuration interfaces. + // Put in the non-DEBUG configuration interfaces. this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib); - this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES_DEBUG", lib); + + // Make sure the DEBUG configuration interfaces exist so that the + // general one will not be used as a fall-back. + for(std::vector::const_iterator i = debugConfigs.begin(); + i != debugConfigs.end(); ++i) + { + prop = "LINK_INTERFACE_LIBRARIES_"; + prop += *i; + if(!this->Target->GetProperty(prop.c_str())) + { + this->Target->SetProperty(prop.c_str(), ""); + } + } } } diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index cc37608b7..e18ed4d35 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -74,7 +74,9 @@ public: "A \"debug\", \"optimized\", or \"general\" keyword indicates that " "the library immediately following it is to be used only for the " "corresponding build configuration. " - "The \"debug\" keyword corresponds to the Debug configuration. " + "The \"debug\" keyword corresponds to the Debug configuration " + "(or to configurations named in the DEBUG_CONFIGURATIONS global " + "property if it is set). " "The \"optimized\" keyword corresponds to all other configurations. " "The \"general\" keyword corresponds to all configurations, and is " "purely optional (assumed if omitted). " @@ -93,14 +95,16 @@ public: " target_link_libraries( LINK_INTERFACE_LIBRARIES\n" " [[debug|optimized|general] ] ...)\n" "The LINK_INTERFACE_LIBRARIES mode appends the libraries " - "to the LINK_INTERFACE_LIBRARIES and LINK_INTERFACE_LIBRARIES_DEBUG " + "to the LINK_INTERFACE_LIBRARIES and its per-configuration equivalent " "target properties instead of using them for linking. " "Libraries specified as \"debug\" are appended to the " - "the LINK_INTERFACE_LIBRARIES_DEBUG property. " + "the LINK_INTERFACE_LIBRARIES_DEBUG property (or to the properties " + "corresponding to configurations listed in the DEBUG_CONFIGURATIONS " + "global property if it is set). " "Libraries specified as \"optimized\" are appended to the " "the LINK_INTERFACE_LIBRARIES property. " "Libraries specified as \"general\" (or without any keyword) are " - "appended to both properties." + "treated as if specified for both \"debug\" and \"optimized\"." ; } diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 0fde39644..b053fb56d 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -3363,6 +3363,19 @@ void cmake::DefineProperties(cmake *cm) "Internal property", "Used to detect compiler changes, Do not set."); + cm->DefineProperty( + "DEBUG_CONFIGURATIONS", cmProperty::GLOBAL, + "Specify which configurations are for debugging.", + "The value must be a semi-colon separated list of configuration names. " + "Currently this property is used only by the target_link_libraries " + "command (see its documentation for details). " + "Additional uses may be defined in the future. " + "\n" + "This property must be set at the top level of the project and before " + "the first target_link_libraries command invocation. " + "If any entry in the list does not match a valid configuration for " + "the project the behavior is undefined."); + cm->DefineProperty( "GLOBAL_DEPENDS_DEBUG_MODE", cmProperty::GLOBAL, "Enable global target dependency graph debug mode.", @@ -3551,6 +3564,12 @@ void cmake::SetProperty(const char* prop, const char* value) return; } + // Special hook to invalidate cached value. + if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0) + { + this->DebugConfigs.clear(); + } + this->Properties.SetProperty(prop, value, cmProperty::GLOBAL); } @@ -3560,6 +3579,13 @@ void cmake::AppendProperty(const char* prop, const char* value) { return; } + + // Special hook to invalidate cached value. + if(strcmp(prop, "DEBUG_CONFIGURATIONS") == 0) + { + this->DebugConfigs.clear(); + } + this->Properties.AppendProperty(prop, value, cmProperty::GLOBAL); } @@ -4270,3 +4296,28 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, cmSystemTools::Message(msg.str().c_str(), "Warning"); } } + +//---------------------------------------------------------------------------- +std::vector const& cmake::GetDebugConfigs() +{ + // Compute on-demand. + if(this->DebugConfigs.empty()) + { + if(const char* config_list = this->GetProperty("DEBUG_CONFIGURATIONS")) + { + // Expand the specified list and convert to upper-case. + cmSystemTools::ExpandListArgument(config_list, this->DebugConfigs); + for(std::vector::iterator i = this->DebugConfigs.begin(); + i != this->DebugConfigs.end(); ++i) + { + *i = cmSystemTools::UpperCase(*i); + } + } + // If no configurations were specified, use a default list. + if(this->DebugConfigs.empty()) + { + this->DebugConfigs.push_back("DEBUG"); + } + } + return this->DebugConfigs; +} diff --git a/Source/cmake.h b/Source/cmake.h index 8d030c73a..eca9064f1 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -332,6 +332,10 @@ class cmake bool IsPropertyDefined(const char *name, cmProperty::ScopeType scope); bool IsPropertyChained(const char *name, cmProperty::ScopeType scope); + /** Get the list of configurations (in upper case) considered to be + debugging configurations.*/ + std::vector const& GetDebugConfigs(); + // record accesses of properties and variables void RecordPropertyAccess(const char *name, cmProperty::ScopeType scope); void ReportUndefinedPropertyAccesses(const char *filename); @@ -456,6 +460,7 @@ private: bool DebugTryCompile; cmFileTimeComparison* FileComparison; std::string GraphVizFile; + std::vector DebugConfigs; void UpdateConversionPathTable(); }; diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index 595530795..26687b1c3 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -6,6 +6,10 @@ if(CMAKE_ANSI_CFLAGS) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ANSI_CFLAGS}") endif(CMAKE_ANSI_CFLAGS) +# Pretend that RelWithDebInfo should link to debug libraries to test +# the DEBUG_CONFIGURATIONS property. +set_property(GLOBAL PROPERTY DEBUG_CONFIGURATIONS Debug RelWithDebInfo) + add_library(testExe1lib STATIC testExe1lib.c) # not exported add_executable(testExe1 testExe1.c) target_link_libraries(testExe1 testExe1lib) diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt index 1ac9d3a57..27f291028 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -32,7 +32,6 @@ add_executable(imp_testExe1 # Try linking to a library imported from the install tree. target_link_libraries(imp_testExe1 exp_testLib2 exp_testLib3 exp_testLib4) -set_property(TARGET imp_testExe1 PROPERTY COMPILE_DEFINITIONS_DEBUG EXE_DBG) # Try building a plugin to an executable imported from the install tree. add_library(imp_mod1 MODULE imp_mod1.c) @@ -58,8 +57,14 @@ add_executable(imp_testExe1b # Try linking to a library imported from the build tree. target_link_libraries(imp_testExe1b bld_testLib2 bld_testLib3 bld_testLib4) -set_property(TARGET imp_testExe1b PROPERTY COMPILE_DEFINITIONS_DEBUG EXE_DBG) # Try building a plugin to an executable imported from the build tree. add_library(imp_mod1b MODULE imp_mod1.c) target_link_libraries(imp_mod1b bld_testExe2) + +# Export/CMakeLists.txt pretends the RelWithDebInfo (as well as Debug) +# configuration should link to debug libs. +foreach(c DEBUG RELWITHDEBINFO) + set_property(TARGET imp_testExe1 PROPERTY COMPILE_DEFINITIONS_${c} EXE_DBG) + set_property(TARGET imp_testExe1b PROPERTY COMPILE_DEFINITIONS_${c} EXE_DBG) +endforeach(c)