Commit 3c5cf1bb authored by Brad King's avatar Brad King
Browse files

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.
parent bf796f14
......@@ -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<std::string> 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<std::string> 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<std::string> 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);
}
......
......@@ -72,6 +72,7 @@ private:
// Configuration information.
const char* Config;
cmTarget::LinkLibraryType LinkType;
// Output information.
EntryVector FinalLinkEntries;
......
......@@ -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<std::string> actual_libs;
......
......@@ -1256,6 +1256,34 @@ const std::vector<std::string>& 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<std::string> 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<std::string>::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 =
......
......@@ -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.
*/
......
......@@ -188,28 +188,39 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
return;
}
// Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs();
std::string prop;
// Include this library in the link interface for the target.
if(llt == cmTarget::DEBUG)
if(llt == cmTarget::DEBUG || llt == cmTarget::GENERAL)
{
// Put in only the DEBUG configuration interface.
this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES_DEBUG", lib);
// Put in the DEBUG configuration interfaces.
for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
i != debugConfigs.end(); ++i)
{
prop = "LINK_INTERFACE_LIBRARIES_";
prop += *i;
this->Target->AppendProperty(prop.c_str(), lib);
}
}
else if(llt == cmTarget::OPTIMIZED)
if(llt == cmTarget::OPTIMIZED || llt == cmTarget::GENERAL)
{
// Put in only the non-DEBUG configuration interface.
// Put in the non-DEBUG configuration interfaces.
this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
// 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"))
// Make sure the DEBUG configuration interfaces exist so that the
// general one will not be used as a fall-back.
for(std::vector<std::string>::const_iterator i = debugConfigs.begin();
i != debugConfigs.end(); ++i)
{
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES_DEBUG", "");
prop = "LINK_INTERFACE_LIBRARIES_";
prop += *i;
if(!this->Target->GetProperty(prop.c_str()))
{
this->Target->SetProperty(prop.c_str(), "");
}
}
}
else
{
// Put in both the DEBUG and non-DEBUG configuration interfaces.
this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES", lib);
this->Target->AppendProperty("LINK_INTERFACE_LIBRARIES_DEBUG", lib);
}
}
......@@ -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(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\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\"."
;
}
......
......@@ -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<std::string> 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<std::string>::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;
}
......@@ -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<std::string> 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<std::string> DebugConfigs;
void UpdateConversionPathTable();
};
......
......@@ -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)
......
......@@ -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)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment