Merge branch 'master' into sublime-text-2-generator

This commit is contained in:
Robert Maynard 2013-02-11 17:20:00 -05:00 committed by Brad King
commit 674bd6e778
125 changed files with 2302 additions and 507 deletions

View File

@ -9,6 +9,8 @@
# configure_file() command when creating the <Name>Config.cmake or <Name>-config.cmake # configure_file() command when creating the <Name>Config.cmake or <Name>-config.cmake
# file for installing a project or library. It helps making the resulting package # file for installing a project or library. It helps making the resulting package
# relocatable by avoiding hardcoded paths in the installed Config.cmake file. # relocatable by avoiding hardcoded paths in the installed Config.cmake file.
# <Name>Config.cmake files installed under UNIX into /lib(64) or /usr/lib(64) are
# considered system packages and are not relocatable.
# #
# In a FooConfig.cmake file there may be code like this to make the # In a FooConfig.cmake file there may be code like this to make the
# install destinations know to the using project: # install destinations know to the using project:
@ -173,17 +175,33 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
else() else()
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}") set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
endif() endif()
# with the /usr-move, /lib(64) is a symlink to /usr/lib on Fedora, ArchLinux, Mageira and others.
# If we are installed to such a location, force using absolute paths.
set(forceAbsolutePaths FALSE)
if("${absInstallDir}" MATCHES "^(/usr)?/lib(64)?/.+")
set(forceAbsolutePaths TRUE)
endif()
file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" ) file(RELATIVE_PATH PACKAGE_RELATIVE_PATH "${absInstallDir}" "${CMAKE_INSTALL_PREFIX}" )
foreach(var ${CCF_PATH_VARS}) foreach(var ${CCF_PATH_VARS})
if(NOT DEFINED ${var}) if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} does not exist") message(FATAL_ERROR "Variable ${var} does not exist")
else() else()
if(IS_ABSOLUTE "${${var}}") if(forceAbsolutePaths)
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}" if(IS_ABSOLUTE "${${var}}")
PACKAGE_${var} "${${var}}") set(PACKAGE_${var} "${${var}}")
else()
set(PACKAGE_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif()
else() else()
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}") if(IS_ABSOLUTE "${${var}}")
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
PACKAGE_${var} "${${var}}")
else()
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
endif()
endif() endif()
endif() endif()
endforeach() endforeach()

View File

@ -1558,8 +1558,11 @@ function(_ep_add_configure_command name)
set(file_deps) set(file_deps)
get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS) get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
foreach(dep IN LISTS deps) foreach(dep IN LISTS deps)
_ep_get_step_stampfile(${dep} "done" done_stamp_file) get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
list(APPEND file_deps ${done_stamp_file}) if(is_ep)
_ep_get_step_stampfile(${dep} "done" done_stamp_file)
list(APPEND file_deps ${done_stamp_file})
endif()
endforeach() endforeach()
get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET) get_property(cmd_set TARGET ${name} PROPERTY _EP_CONFIGURE_COMMAND SET)

View File

@ -65,6 +65,12 @@
# is much more flexible, but requires that FindQt4.cmake is executed before # is much more flexible, but requires that FindQt4.cmake is executed before
# such an exported dependency file is processed. # such an exported dependency file is processed.
# #
# Note that if using IMPORTED targets, the qtmain.lib static library is
# automatically linked on Windows. To disable that globally, set the
# QT4_NO_LINK_QTMAIN variable before finding Qt4. To disable that for a
# particular executable, set the QT4_NO_LINK_QTMAIN target property to
# True on the executable.
#
# QT_INCLUDE_DIRS_NO_SYSTEM # QT_INCLUDE_DIRS_NO_SYSTEM
# If this variable is set to TRUE, the Qt include directories # If this variable is set to TRUE, the Qt include directories
# in the QT_USE_FILE will NOT have the SYSTEM keyword set. # in the QT_USE_FILE will NOT have the SYSTEM keyword set.
@ -1009,7 +1015,14 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
# platform dependent libraries # platform dependent libraries
if(Q_WS_WIN) if(Q_WS_WIN)
_QT4_ADJUST_LIB_VARS(qtmain) _QT4_ADJUST_LIB_VARS(qtmain)
_QT4_ADJUST_LIB_VARS(QAxServer) _QT4_ADJUST_LIB_VARS(QAxServer)
set_property(TARGET Qt4::QAxServer PROPERTY
INTERFACE_QT4_NO_LINK_QTMAIN ON
)
set_property(TARGET Qt4::QAxServer APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL QT4_NO_LINK_QTMAIN)
_QT4_ADJUST_LIB_VARS(QAxContainer) _QT4_ADJUST_LIB_VARS(QAxContainer)
endif() endif()
@ -1049,6 +1062,21 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
_qt4_add_target_private_depends(phonon DBus) _qt4_add_target_private_depends(phonon DBus)
endif() endif()
if (WIN32 AND NOT QT4_NO_LINK_QTMAIN)
set(_isExe $<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>)
set(_isWin32 $<BOOL:$<TARGET_PROPERTY:WIN32_EXECUTABLE>>)
set(_isNotExcluded $<NOT:$<BOOL:$<TARGET_PROPERTY:QT4_NO_LINK_QTMAIN>>>)
set(_isPolicyNEW $<TARGET_POLICY:CMP0020>)
set_property(TARGET Qt4::QtCore APPEND PROPERTY
IMPORTED_LINK_INTERFACE_LIBRARIES
$<$<AND:${_isExe},${_isWin32},${_isNotExcluded},${_isPolicyNEW}>:Qt4::qtmain>
)
unset(_isExe)
unset(_isWin32)
unset(_isNotExcluded)
unset(_isPolicyNEW)
endif()
####################################### #######################################
# #
# Check the executables of Qt # Check the executables of Qt

View File

@ -2,5 +2,5 @@
set(CMake_VERSION_MAJOR 2) set(CMake_VERSION_MAJOR 2)
set(CMake_VERSION_MINOR 8) set(CMake_VERSION_MINOR 8)
set(CMake_VERSION_PATCH 10) set(CMake_VERSION_PATCH 10)
set(CMake_VERSION_TWEAK 20130110) set(CMake_VERSION_TWEAK 20130129)
#set(CMake_VERSION_RC 1) #set(CMake_VERSION_RC 1)

View File

@ -37,6 +37,7 @@
"target in the same buildsystem. Expands to the empty string " \ "target in the same buildsystem. Expands to the empty string " \
"otherwise.\n" \ "otherwise.\n" \
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \ " $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
" $<TARGET_DEFINED:tgt> = '1' if tgt is a target, else '0'\n" \
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \ " $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \ " $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
"where \"tgt\" is the name of a target. " \ "where \"tgt\" is the name of a target. " \
@ -46,9 +47,14 @@
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \ " $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \ " $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
"\n" \ "\n" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \ " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \
"on the target tgt. Note that tgt is not added as a dependency of\n" \ "on the target tgt.\n" \
"the target this expression is evaluated on.\n" \ "Note that tgt is not added as a dependency of the target this " \
"expression is evaluated on.\n" \
" $<TARGET_POLICY:pol> = '1' if the policy was NEW when " \
"the 'head' target was created, else '0'. If the policy was not " \
"set, the warning message for the policy will be emitted. This " \
"generator expression only works for a subset of policies.\n" \
"Boolean expressions:\n" \ "Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \ " $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \ " $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
@ -59,7 +65,7 @@
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \ #define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \ CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"Expressions with an implicit 'this' target:\n" \ "Expressions with an implicit 'this' target:\n" \
" $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \ " $<TARGET_PROPERTY:prop> = The value of the property prop on " \
"the target on which the generator expression is evaluated.\n" \ "the target on which the generator expression is evaluated.\n" \
"" ""

View File

@ -62,6 +62,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
cmTarget* te = *tei; cmTarget* te = *tei;
this->GenerateImportTargetCode(os, te); this->GenerateImportTargetCode(os, te);
te->AppendBuildInterfaceIncludes();
ImportPropertyMap properties; ImportPropertyMap properties;
this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te, this->PopulateInterfaceProperty("INTERFACE_INCLUDE_DIRECTORIES", te,
@ -70,20 +72,23 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te, this->PopulateInterfaceProperty("INTERFACE_COMPILE_DEFINITIONS", te,
cmGeneratorExpression::BuildInterface, cmGeneratorExpression::BuildInterface,
properties, missingTargets); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties); this->GenerateInterfaceProperties(te, os, properties);
} }
this->GenerateMissingTargetsCheckCode(os, missingTargets);
// Generate import file content for each configuration. // Generate import file content for each configuration.
for(std::vector<std::string>::const_iterator for(std::vector<std::string>::const_iterator
ci = this->Configurations.begin(); ci = this->Configurations.begin();
ci != this->Configurations.end(); ++ci) ci != this->Configurations.end(); ++ci)
{ {
this->GenerateImportConfig(os, ci->c_str()); this->GenerateImportConfig(os, ci->c_str(), missingTargets);
} }
this->GenerateMissingTargetsCheckCode(os, missingTargets);
return true; return true;
} }
@ -91,7 +96,8 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
void void
cmExportBuildFileGenerator cmExportBuildFileGenerator
::GenerateImportTargetsConfig(std::ostream& os, ::GenerateImportTargetsConfig(std::ostream& os,
const char* config, std::string const& suffix) const char* config, std::string const& suffix,
std::vector<std::string> &missingTargets)
{ {
for(std::vector<cmTarget*>::const_iterator for(std::vector<cmTarget*>::const_iterator
tei = this->Exports->begin(); tei = this->Exports->begin();
@ -104,9 +110,12 @@ cmExportBuildFileGenerator
if(!properties.empty()) if(!properties.empty())
{ {
// Get the rest of the target details. // Get the rest of the target details.
std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix, this->SetImportDetailProperties(config, suffix,
target, properties, missingTargets); target, properties, missingTargets);
this->SetImportLinkInterface(config, suffix,
cmGeneratorExpression::BuildInterface,
target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION // TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff // This should wait until the build feature propagation stuff
@ -115,7 +124,6 @@ cmExportBuildFileGenerator
// properties); // properties);
// Generate code in the export file. // Generate code in the export file.
this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, target, properties); this->GenerateImportPropertyCode(os, config, target, properties);
} }
} }

View File

@ -44,7 +44,8 @@ protected:
virtual bool GenerateMainFile(std::ostream& os); virtual bool GenerateMainFile(std::ostream& os);
virtual void GenerateImportTargetsConfig(std::ostream& os, virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config, const char* config,
std::string const& suffix); std::string const& suffix,
std::vector<std::string> &missingTargets);
virtual void HandleMissingTarget(std::string& link_libs, virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets, std::vector<std::string>& missingTargets,
cmMakefile* mf, cmMakefile* mf,

View File

@ -21,6 +21,7 @@
#include "cmTarget.h" #include "cmTarget.h"
#include "cmTargetExport.h" #include "cmTargetExport.h"
#include "cmVersion.h" #include "cmVersion.h"
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx> #include <cmsys/auto_ptr.hxx>
@ -81,16 +82,16 @@ bool cmExportFileGenerator::GenerateImportFile()
// Protect that file against use with older CMake versions. // Protect that file against use with older CMake versions.
os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n"; os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n" os << "if(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
<< " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n" << " message(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "ENDIF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"; << "endif()\n";
// Isolate the file policy level. // Isolate the file policy level.
// We use 2.6 here instead of the current version because newer // We use 2.6 here instead of the current version because newer
// versions of CMake should be able to export files imported by 2.6 // versions of CMake should be able to export files imported by 2.6
// until the import format changes. // until the import format changes.
os << "CMAKE_POLICY(PUSH)\n" os << "cmake_policy(PUSH)\n"
<< "CMAKE_POLICY(VERSION 2.6)\n"; << "cmake_policy(VERSION 2.6)\n";
// Start with the import file header. // Start with the import file header.
this->GenerateImportHeaderCode(os); this->GenerateImportHeaderCode(os);
@ -100,14 +101,15 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer. // End with the import file footer.
this->GenerateImportFooterCode(os); this->GenerateImportFooterCode(os);
os << "CMAKE_POLICY(POP)\n"; os << "cmake_policy(POP)\n";
return result; return result;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os, void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
const char* config) const char* config,
std::vector<std::string> &missingTargets)
{ {
// Construct the property configuration suffix. // Construct the property configuration suffix.
std::string suffix = "_"; std::string suffix = "_";
@ -121,7 +123,19 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
} }
// Generate the per-config target information. // Generate the per-config target information.
this->GenerateImportTargetsConfig(os, config, suffix); this->GenerateImportTargetsConfig(os, config, suffix, missingTargets);
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
cmTarget *target,
ImportPropertyMap &properties)
{
const char *input = target->GetProperty(propName);
if (input)
{
properties[propName] = input;
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -164,6 +178,85 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
properties, missingTargets); properties, missingTargets);
} }
//----------------------------------------------------------------------------
void getPropertyContents(cmTarget *tgt, const char *prop,
std::set<std::string> &ifaceProperties)
{
const char *p = tgt->GetProperty(prop);
if (!p)
{
return;
}
std::vector<std::string> content;
cmSystemTools::ExpandListArgument(p, content);
for (std::vector<std::string>::const_iterator ci = content.begin();
ci != content.end(); ++ci)
{
ifaceProperties.insert(*ci);
}
}
//----------------------------------------------------------------------------
void getCompatibleInterfaceProperties(cmTarget *target,
std::set<std::string> &ifaceProperties,
const char *config)
{
cmComputeLinkInformation *info = target->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
getPropertyContents(li->Target,
"COMPATIBLE_INTERFACE_BOOL",
ifaceProperties);
getPropertyContents(li->Target,
"COMPATIBLE_INTERFACE_STRING",
ifaceProperties);
}
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
cmTarget *target,
ImportPropertyMap &properties)
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
target, properties);
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_STRING",
target, properties);
std::set<std::string> ifaceProperties;
getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", ifaceProperties);
getPropertyContents(target, "COMPATIBLE_INTERFACE_STRING", ifaceProperties);
getCompatibleInterfaceProperties(target, ifaceProperties, 0);
std::vector<std::string> configNames;
target->GetMakefile()->GetConfigurations(configNames);
for (std::vector<std::string>::const_iterator ci = configNames.begin();
ci != configNames.end(); ++ci)
{
getCompatibleInterfaceProperties(target, ifaceProperties, ci->c_str());
}
for (std::set<std::string>::const_iterator it = ifaceProperties.begin();
it != ifaceProperties.end(); ++it)
{
this->PopulateInterfaceProperty(("INTERFACE_" + *it).c_str(),
target, properties);
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target, void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
std::ostream& os, std::ostream& os,
@ -173,7 +266,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
{ {
std::string targetName = this->Namespace; std::string targetName = this->Namespace;
targetName += target->GetName(); targetName += target->GetName();
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin(); for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi) pi != properties.end(); ++pi)
{ {
@ -183,9 +276,89 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
} }
} }
//----------------------------------------------------------------------------
bool
cmExportFileGenerator::AddTargetNamespace(std::string &input,
cmTarget* target,
std::vector<std::string> &missingTargets)
{
cmMakefile *mf = target->GetMakefile();
cmTarget *tgt = mf->FindTargetToUse(input.c_str());
if (!tgt)
{
return false;
}
if(tgt->IsImported())
{
return true;
}
if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
input = this->Namespace + input;
}
else
{
std::string namespacedTarget;
this->HandleMissingTarget(namespacedTarget, missingTargets,
mf, target, tgt);
if (!namespacedTarget.empty())
{
input = namespacedTarget;
}
}
return true;
}
//----------------------------------------------------------------------------
static bool isGeneratorExpression(const std::string &lib)
{
const std::string::size_type openpos = lib.find("$<");
return (openpos != std::string::npos)
&& (lib.find(">", openpos) != std::string::npos);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmExportFileGenerator::ResolveTargetsInGeneratorExpressions( cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
std::string &input,
cmTarget* target,
std::vector<std::string> &missingTargets,
FreeTargetsReplace replace)
{
if (replace == NoReplaceFreeTargets)
{
this->ResolveTargetsInGeneratorExpression(input, target, missingTargets);
return;
}
std::vector<std::string> parts;
cmGeneratorExpression::Split(input, parts);
std::string sep;
input = "";
for(std::vector<std::string>::iterator li = parts.begin();
li != parts.end(); ++li)
{
if (!isGeneratorExpression(*li))
{
this->AddTargetNamespace(*li, target, missingTargets);
}
else
{
this->ResolveTargetsInGeneratorExpression(
*li,
target,
missingTargets);
}
input += sep + *li;
sep = ";";
}
}
//----------------------------------------------------------------------------
void
cmExportFileGenerator::ResolveTargetsInGeneratorExpression(
std::string &input, std::string &input,
cmTarget* target, cmTarget* target,
std::vector<std::string> &missingTargets) std::vector<std::string> &missingTargets)
@ -212,45 +385,17 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
continue; continue;
} }
const std::string targetName = input.substr(nameStartPos, std::string targetName = input.substr(nameStartPos,
commaPos - nameStartPos); commaPos - nameStartPos);
pos = nameStartPos; // We're not going to replace the entire expression, if (!this->AddTargetNamespace(targetName, target, missingTargets))
// but only the target parameter.
if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
{
if(tgt->IsImported())
{
pos += targetName.size();
}
else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
input.replace(pos, targetName.size(),
this->Namespace + targetName);
pos += this->Namespace.size() + targetName.size();
}
else
{
std::string namespacedTarget;
this->HandleMissingTarget(namespacedTarget, missingTargets,
mf, target, tgt);
if (!namespacedTarget.empty())
{
input.replace(pos, targetName.size(), namespacedTarget);
pos += namespacedTarget.size();
}
}
}
else
{ {
errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires " errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
"its first parameter to be a reachable target."; "its first parameter to be a reachable target.";
}
lastPos = pos;
if (!errorString.empty())
{
break; break;
} }
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
lastPos = pos + targetName.size();
} }
if (!errorString.empty()) if (!errorString.empty())
{ {
@ -267,51 +412,24 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
if (endPos == input.npos) if (endPos == input.npos)
{ {
errorString = "$<TARGET_NAME:...> expression incomplete"; errorString = "$<TARGET_NAME:...> expression incomplete";
break;
} }
const std::string targetName = input.substr(nameStartPos, std::string targetName = input.substr(nameStartPos,
endPos - nameStartPos); endPos - nameStartPos);
if(targetName.find("$<", lastPos) != input.npos) if(targetName.find("$<") != input.npos)
{ {
errorString = "$<TARGET_NAME:...> requires its parameter to be a " errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"literal."; "literal.";
break;
} }
if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str())) if (!this->AddTargetNamespace(targetName, target, missingTargets))
{
if(tgt->IsImported())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
targetName);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
this->Namespace + targetName);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
else
{
std::string namespacedTarget;
this->HandleMissingTarget(namespacedTarget, missingTargets,
mf, target, tgt);
if (!namespacedTarget.empty())
{
input.replace(pos, sizeof("$<TARGET_NAME:") + targetName.size(),
namespacedTarget);
pos += sizeof("$<TARGET_NAME:") + targetName.size();
}
}
}
else
{ {
errorString = "$<TARGET_NAME:...> requires its parameter to be a " errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"reachable target."; "reachable target.";
}
lastPos = pos;
if (!errorString.empty())
{
break; break;
} }
input.replace(pos, endPos - pos + 1, targetName);
lastPos = endPos;
} }
if (!errorString.empty()) if (!errorString.empty())
{ {
@ -319,6 +437,64 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
} }
} }
//----------------------------------------------------------------------------
void
cmExportFileGenerator
::SetImportLinkInterface(const char* config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
cmTarget* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets)
{
// Add the transitive link dependencies for this configuration.
cmTarget::LinkInterface const* iface = target->GetLinkInterface(config,
target);
if (!iface)
{
return;
}
if (iface->ImplementationIsInterface)
{
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
return;
}
const char *propContent;
if (const char *prop_suffixed = target->GetProperty(
("LINK_INTERFACE_LIBRARIES" + suffix).c_str()))
{
propContent = prop_suffixed;
}
else if (const char *prop = target->GetProperty(
"LINK_INTERFACE_LIBRARIES"))
{
propContent = prop;
}
else
{
return;
}
if (!*propContent)
{
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = "";
return;
}
std::string prepro = cmGeneratorExpression::Preprocess(propContent,
preprocessRule);
if (!prepro.empty())
{
this->ResolveTargetsInGeneratorExpressions(prepro, target,
missingTargets,
ReplaceFreeTargets);
properties["IMPORTED_LINK_INTERFACE_LIBRARIES" + suffix] = prepro;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmExportFileGenerator cmExportFileGenerator
@ -363,9 +539,7 @@ cmExportFileGenerator
this->SetImportLinkProperty(suffix, target, this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES", "IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets); iface->Languages, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
this->SetImportLinkProperty(suffix, target, this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES", "IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties, missingTargets); iface->SharedDeps, properties, missingTargets);
@ -397,9 +571,6 @@ cmExportFileGenerator
return; return;
} }
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->GetMakefile();
// Construct the property value. // Construct the property value.
std::string link_libs; std::string link_libs;
const char* sep = ""; const char* sep = "";
@ -410,33 +581,9 @@ cmExportFileGenerator
link_libs += sep; link_libs += sep;
sep = ";"; sep = ";";
// Append this entry. std::string temp = *li;
if(cmTarget* tgt = mf->FindTargetToUse(li->c_str())) this->AddTargetNamespace(temp, target, missingTargets);
{ link_libs += temp;
// This is a target.
if(tgt->IsImported())
{
// The target is imported (and therefore is not in the
// export). Append the raw name.
link_libs += *li;
}
else if(this->ExportedTargets.find(tgt) != this->ExportedTargets.end())
{
// The target is in the export. Append it with the export
// namespace.
link_libs += this->Namespace;
link_libs += *li;
}
else
{
this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
}
}
else
{
// Append the raw name.
link_libs += *li;
}
} }
// Store the property. // Store the property.
@ -469,7 +616,7 @@ void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os) void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{ {
os << "# Commands beyond this point should not need to know the version.\n" os << "# Commands beyond this point should not need to know the version.\n"
<< "SET(CMAKE_IMPORT_FILE_VERSION)\n"; << "set(CMAKE_IMPORT_FILE_VERSION)\n";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -478,7 +625,7 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
// Store an import file format version. This will let us change the // Store an import file format version. This will let us change the
// format later while still allowing old import files to work. // format later while still allowing old import files to work.
os << "# Commands may need to know the format version.\n" os << "# Commands may need to know the format version.\n"
<< "SET(CMAKE_IMPORT_FILE_VERSION 1)\n" << "set(CMAKE_IMPORT_FILE_VERSION 1)\n"
<< "\n"; << "\n";
} }
@ -486,31 +633,31 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os, void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
const std::string &expectedTargets) const std::string &expectedTargets)
{ {
os << "SET(_targetsDefined)\n" os << "set(_targetsDefined)\n"
"SET(_targetsNotDefined)\n" "set(_targetsNotDefined)\n"
"SET(_expectedTargets)\n" "set(_expectedTargets)\n"
"FOREACH(_expectedTarget " << expectedTargets << ")\n" "foreach(_expectedTarget " << expectedTargets << ")\n"
" LIST(APPEND _expectedTargets ${_expectedTarget})\n" " list(APPEND _expectedTargets ${_expectedTarget})\n"
" IF(NOT TARGET ${_expectedTarget})\n" " if(NOT TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsNotDefined ${_expectedTarget})\n" " list(APPEND _targetsNotDefined ${_expectedTarget})\n"
" ENDIF(NOT TARGET ${_expectedTarget})\n" " endif()\n"
" IF(TARGET ${_expectedTarget})\n" " if(TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsDefined ${_expectedTarget})\n" " list(APPEND _targetsDefined ${_expectedTarget})\n"
" ENDIF(TARGET ${_expectedTarget})\n" " endif()\n"
"ENDFOREACH(_expectedTarget)\n" "endforeach()\n"
"IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" "if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
" SET(CMAKE_IMPORT_FILE_VERSION)\n" " set(CMAKE_IMPORT_FILE_VERSION)\n"
" CMAKE_POLICY(POP)\n" " cmake_policy(POP)\n"
" RETURN()\n" " return()\n"
"ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n" "endif()\n"
"IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" "if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
" MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export " " message(FATAL_ERROR \"Some (but not all) targets in this export "
"set were already defined.\\nTargets Defined: ${_targetsDefined}\\n" "set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
"Targets not yet defined: ${_targetsNotDefined}\\n\")\n" "Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
"ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n" "endif()\n"
"UNSET(_targetsDefined)\n" "unset(_targetsDefined)\n"
"UNSET(_targetsNotDefined)\n" "unset(_targetsNotDefined)\n"
"UNSET(_expectedTargets)\n" "unset(_expectedTargets)\n"
"\n\n"; "\n\n";
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -527,16 +674,16 @@ cmExportFileGenerator
switch(target->GetType()) switch(target->GetType())
{ {
case cmTarget::EXECUTABLE: case cmTarget::EXECUTABLE:
os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n"; os << "add_executable(" << targetName << " IMPORTED)\n";
break; break;
case cmTarget::STATIC_LIBRARY: case cmTarget::STATIC_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n"; os << "add_library(" << targetName << " STATIC IMPORTED)\n";
break; break;
case cmTarget::SHARED_LIBRARY: case cmTarget::SHARED_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n"; os << "add_library(" << targetName << " SHARED IMPORTED)\n";
break; break;
case cmTarget::MODULE_LIBRARY: case cmTarget::MODULE_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n"; os << "add_library(" << targetName << " MODULE IMPORTED)\n";
break; break;
default: // should never happen default: // should never happen
break; break;
@ -545,27 +692,27 @@ cmExportFileGenerator
// Mark the imported executable if it has exports. // Mark the imported executable if it has exports.
if(target->IsExecutableWithExports()) if(target->IsExecutableWithExports())
{ {
os << "SET_PROPERTY(TARGET " << targetName os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n"; << " PROPERTY ENABLE_EXPORTS 1)\n";
} }
// Mark the imported library if it is a framework. // Mark the imported library if it is a framework.
if(target->IsFrameworkOnApple()) if(target->IsFrameworkOnApple())
{ {
os << "SET_PROPERTY(TARGET " << targetName os << "set_property(TARGET " << targetName
<< " PROPERTY FRAMEWORK 1)\n"; << " PROPERTY FRAMEWORK 1)\n";
} }
// Mark the imported executable if it is an application bundle. // Mark the imported executable if it is an application bundle.
if(target->IsAppBundleOnApple()) if(target->IsAppBundleOnApple())
{ {
os << "SET_PROPERTY(TARGET " << targetName os << "set_property(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n"; << " PROPERTY MACOSX_BUNDLE 1)\n";
} }
if (target->IsCFBundleOnApple()) if (target->IsCFBundleOnApple())
{ {
os << "SET_PROPERTY(TARGET " << targetName os << "set_property(TARGET " << targetName
<< " PROPERTY BUNDLE 1)\n"; << " PROPERTY BUNDLE 1)\n";
} }
os << "\n"; os << "\n";
@ -585,7 +732,7 @@ cmExportFileGenerator
// Set the import properties. // Set the import properties.
os << "# Import target \"" << targetName << "\" for configuration \"" os << "# Import target \"" << targetName << "\" for configuration \""
<< config << "\"\n"; << config << "\"\n";
os << "SET_PROPERTY(TARGET " << targetName os << "set_property(TARGET " << targetName
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS "; << " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
if(config && *config) if(config && *config)
{ {
@ -596,7 +743,7 @@ cmExportFileGenerator
os << "NOCONFIG"; os << "NOCONFIG";
} }
os << ")\n"; os << ")\n";
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n"; os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin(); for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi) pi != properties.end(); ++pi)
{ {
@ -611,21 +758,29 @@ cmExportFileGenerator
void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os, void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets) const std::vector<std::string>& missingTargets)
{ {
if (missingTargets.empty())
{
return;
}
os << "# Make sure the targets which have been exported in some other \n" os << "# Make sure the targets which have been exported in some other \n"
"# export set exist.\n"; "# export set exist.\n";
std::set<std::string> emitted;
for(unsigned int i=0; i<missingTargets.size(); ++i) for(unsigned int i=0; i<missingTargets.size(); ++i)
{ {
os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n" if (emitted.insert(missingTargets[i]).second)
<< " IF(CMAKE_FIND_PACKAGE_NAME)\n" {
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n" os << "if(NOT TARGET \"" << missingTargets[i] << "\" )\n"
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE " << " if(CMAKE_FIND_PACKAGE_NAME)\n"
<< "\"Required imported target \\\"" << missingTargets[i] << " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
<< "\\\" not found ! \")\n" << " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
<< " ELSE()\n" << "\"Required imported target \\\"" << missingTargets[i]
<< " MESSAGE(FATAL_ERROR \"Required imported target \\\"" << "\\\" not found ! \")\n"
<< missingTargets[i] << "\\\" not found ! \")\n" << " else()\n"
<< " ENDIF()\n" << " message(FATAL_ERROR \"Required imported target \\\""
<< "ENDIF()\n"; << missingTargets[i] << "\\\" not found ! \")\n"
<< " endif()\n"
<< "endif()\n";
}
} }
os << "\n"; os << "\n";
} }
@ -643,10 +798,10 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
// on SUSE with a mysql pkg-config file, which claimed everything is fine, // on SUSE with a mysql pkg-config file, which claimed everything is fine,
// but the development package was not installed.). // but the development package was not installed.).
os << "# Loop over all imported files and verify that they actually exist\n" os << "# Loop over all imported files and verify that they actually exist\n"
"FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n" "foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
" FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n" " foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
" IF(NOT EXISTS \"${file}\" )\n" " if(NOT EXISTS \"${file}\" )\n"
" MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\"" " message(FATAL_ERROR \"The imported target \\\"${target}\\\""
" references the file\n" " references the file\n"
" \\\"${file}\\\"\n" " \\\"${file}\\\"\n"
"but this file does not exist. Possible reasons include:\n" "but this file does not exist. Possible reasons include:\n"
@ -656,11 +811,11 @@ cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
" \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n" " \\\"${CMAKE_CURRENT_LIST_FILE}\\\"\n"
"but not all the files it references.\n" "but not all the files it references.\n"
"\")\n" "\")\n"
" ENDIF()\n" " endif()\n"
" ENDFOREACH()\n" " endforeach()\n"
" UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n" " unset(_IMPORT_CHECK_FILES_FOR_${target})\n"
"ENDFOREACH()\n" "endforeach()\n"
"UNSET(_IMPORT_CHECK_TARGETS)\n" "unset(_IMPORT_CHECK_TARGETS)\n"
"\n"; "\n";
} }
@ -676,8 +831,8 @@ cmExportFileGenerator
std::string targetName = this->Namespace; std::string targetName = this->Namespace;
targetName += target->GetName(); targetName += target->GetName();
os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n" os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " "; "list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
for(std::set<std::string>::const_iterator li = importedLocations.begin(); for(std::set<std::string>::const_iterator li = importedLocations.begin();
li != importedLocations.end(); li != importedLocations.end();

View File

@ -47,7 +47,8 @@ protected:
// Generate per-configuration target information to the given output // Generate per-configuration target information to the given output
// stream. // stream.
void GenerateImportConfig(std::ostream& os, const char* config); void GenerateImportConfig(std::ostream& os, const char* config,
std::vector<std::string> &missingTargets);
// Methods to implement export file code generation. // Methods to implement export file code generation.
void GenerateImportHeaderCode(std::ostream& os, const char* config = 0); void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
@ -85,7 +86,8 @@ protected:
/** Each subclass knows where the target files are located. */ /** Each subclass knows where the target files are located. */
virtual void GenerateImportTargetsConfig(std::ostream& os, virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config, const char* config,
std::string const& suffix) = 0; std::string const& suffix,
std::vector<std::string> &missingTargets) = 0;
/** Each subclass knows how to deal with a target that is missing from an /** Each subclass knows how to deal with a target that is missing from an
* export set. */ * export set. */
@ -99,12 +101,27 @@ protected:
cmGeneratorExpression::PreprocessContext, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties, ImportPropertyMap &properties,
std::vector<std::string> &missingTargets); std::vector<std::string> &missingTargets);
void PopulateInterfaceProperty(const char *propName, cmTarget *target,
ImportPropertyMap &properties);
void PopulateCompatibleInterfaceProperties(cmTarget *target,
ImportPropertyMap &properties);
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties); const ImportPropertyMap &properties);
void SetImportLinkInterface(const char* config, std::string const& suffix,
cmGeneratorExpression::PreprocessContext preprocessRule,
cmTarget* target, ImportPropertyMap& properties,
std::vector<std::string>& missingTargets);
enum FreeTargetsReplace {
ReplaceFreeTargets,
NoReplaceFreeTargets
};
void ResolveTargetsInGeneratorExpressions(std::string &input, void ResolveTargetsInGeneratorExpressions(std::string &input,
cmTarget* target, cmTarget* target,
std::vector<std::string> &missingTargets); std::vector<std::string> &missingTargets,
FreeTargetsReplace replace = NoReplaceFreeTargets);
// The namespace in which the exports are placed in the generated file. // The namespace in which the exports are placed in the generated file.
std::string Namespace; std::string Namespace;
@ -128,6 +145,13 @@ private:
cmGeneratorExpression::PreprocessContext, cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties, ImportPropertyMap &properties,
std::vector<std::string> &missingTargets); std::vector<std::string> &missingTargets);
bool AddTargetNamespace(std::string &input, cmTarget* target,
std::vector<std::string> &missingTargets);
void ResolveTargetsInGeneratorExpression(std::string &input,
cmTarget* target,
std::vector<std::string> &missingTargets);
}; };
#endif #endif

View File

@ -57,7 +57,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
else else
{ {
cmOStringStream e; cmOStringStream e;
e << "INSTALL(EXPORT \"" e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName() << this->IEGen->GetExportSet()->GetName()
<< "\" ...) " << "includes target \"" << te->Target->GetName() << "\" ...) " << "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set."; << "\" more than once in the export set.";
@ -89,39 +89,47 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
te, te,
cmGeneratorExpression::InstallInterface, cmGeneratorExpression::InstallInterface,
properties, missingTargets); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties); this->GenerateInterfaceProperties(te, os, properties);
} }
this->GenerateMissingTargetsCheckCode(os, missingTargets);
// Now load per-configuration properties for them. // Now load per-configuration properties for them.
os << "# Load information for each installed configuration.\n" os << "# Load information for each installed configuration.\n"
<< "GET_FILENAME_COMPONENT(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n" << "get_filename_component(_DIR \"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"
<< "FILE(GLOB CONFIG_FILES \"${_DIR}/" << "file(GLOB CONFIG_FILES \"${_DIR}/"
<< this->GetConfigImportFileGlob() << "\")\n" << this->GetConfigImportFileGlob() << "\")\n"
<< "FOREACH(f ${CONFIG_FILES})\n" << "foreach(f ${CONFIG_FILES})\n"
<< " INCLUDE(${f})\n" << " include(${f})\n"
<< "ENDFOREACH(f)\n" << "endforeach()\n"
<< "\n"; << "\n";
this->GenerateImportedFileCheckLoop(os);
// Generate an import file for each configuration. // Generate an import file for each configuration.
bool result = true; bool result = true;
for(std::vector<std::string>::const_iterator for(std::vector<std::string>::const_iterator
ci = this->Configurations.begin(); ci = this->Configurations.begin();
ci != this->Configurations.end(); ++ci) ci != this->Configurations.end(); ++ci)
{ {
if(!this->GenerateImportFileConfig(ci->c_str())) if(!this->GenerateImportFileConfig(ci->c_str(), missingTargets))
{ {
result = false; result = false;
} }
} }
this->GenerateMissingTargetsCheckCode(os, missingTargets);
return result; return result;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool bool
cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config) cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config,
std::vector<std::string> &missingTargets)
{ {
// Skip configurations not enabled for this export. // Skip configurations not enabled for this export.
if(!this->IEGen->InstallsForConfig(config)) if(!this->IEGen->InstallsForConfig(config))
@ -161,7 +169,7 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
this->GenerateImportHeaderCode(os, config); this->GenerateImportHeaderCode(os, config);
// Generate the per-config target information. // Generate the per-config target information.
this->GenerateImportConfig(os, config); this->GenerateImportConfig(os, config, missingTargets);
// End with the import file footer. // End with the import file footer.
this->GenerateImportFooterCode(os); this->GenerateImportFooterCode(os);
@ -176,7 +184,8 @@ cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
void void
cmExportInstallFileGenerator cmExportInstallFileGenerator
::GenerateImportTargetsConfig(std::ostream& os, ::GenerateImportTargetsConfig(std::ostream& os,
const char* config, std::string const& suffix) const char* config, std::string const& suffix,
std::vector<std::string> &missingTargets)
{ {
// Add code to compute the installation prefix relative to the // Add code to compute the installation prefix relative to the
// import file location. // import file location.
@ -185,12 +194,12 @@ cmExportInstallFileGenerator
{ {
std::string dest = installDest; std::string dest = installDest;
os << "# Compute the installation prefix relative to this file.\n" os << "# Compute the installation prefix relative to this file.\n"
<< "GET_FILENAME_COMPONENT(_IMPORT_PREFIX " << "get_filename_component(_IMPORT_PREFIX "
<< "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n"; << "\"${CMAKE_CURRENT_LIST_FILE}\" PATH)\n";
while(!dest.empty()) while(!dest.empty())
{ {
os << os <<
"GET_FILENAME_COMPONENT(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n"; "get_filename_component(_IMPORT_PREFIX \"${_IMPORT_PREFIX}\" PATH)\n";
dest = cmSystemTools::GetFilenamePath(dest); dest = cmSystemTools::GetFilenamePath(dest);
} }
os << "\n"; os << "\n";
@ -225,10 +234,13 @@ cmExportInstallFileGenerator
if(!properties.empty()) if(!properties.empty())
{ {
// Get the rest of the target details. // Get the rest of the target details.
std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix, this->SetImportDetailProperties(config, suffix,
te->Target, properties, missingTargets); te->Target, properties, missingTargets);
this->SetImportLinkInterface(config, suffix,
cmGeneratorExpression::InstallInterface,
te->Target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION // TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff // This should wait until the build feature propagation stuff
// is done. Then this can be a propagated include directory. // is done. Then this can be a propagated include directory.
@ -236,20 +248,17 @@ cmExportInstallFileGenerator
// properties); // properties);
// Generate code in the export file. // Generate code in the export file.
this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, te->Target, properties); this->GenerateImportPropertyCode(os, config, te->Target, properties);
this->GenerateImportedFileChecksCode(os, te->Target, properties, this->GenerateImportedFileChecksCode(os, te->Target, properties,
importedLocations); importedLocations);
} }
} }
this->GenerateImportedFileCheckLoop(os);
// Cleanup the import prefix variable. // Cleanup the import prefix variable.
if(!this->ImportPrefix.empty()) if(!this->ImportPrefix.empty())
{ {
os << "# Cleanup temporary variables.\n" os << "# Cleanup temporary variables.\n"
<< "SET(_IMPORT_PREFIX)\n" << "set(_IMPORT_PREFIX)\n"
<< "\n"; << "\n";
} }
} }
@ -419,7 +428,7 @@ cmExportInstallFileGenerator
{ {
const char* installDest = this->IEGen->GetDestination(); const char* installDest = this->IEGen->GetDestination();
cmOStringStream e; cmOStringStream e;
e << "INSTALL(EXPORT \"" e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName() << this->IEGen->GetExportSet()->GetName()
<< "\") given absolute " << "\") given absolute "
<< "DESTINATION \"" << installDest << "\" but the export " << "DESTINATION \"" << installDest << "\" but the export "
@ -437,7 +446,7 @@ cmExportInstallFileGenerator
int occurrences) int occurrences)
{ {
cmOStringStream e; cmOStringStream e;
e << "INSTALL(EXPORT \"" e << "install(EXPORT \""
<< this->IEGen->GetExportSet()->GetName() << this->IEGen->GetExportSet()->GetName()
<< "\" ...) " << "\" ...) "
<< "includes target \"" << depender->GetName() << "includes target \"" << depender->GetName()

View File

@ -56,7 +56,8 @@ protected:
virtual bool GenerateMainFile(std::ostream& os); virtual bool GenerateMainFile(std::ostream& os);
virtual void GenerateImportTargetsConfig(std::ostream& os, virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config, const char* config,
std::string const& suffix); std::string const& suffix,
std::vector<std::string> &missingTargets);
virtual void HandleMissingTarget(std::string& link_libs, virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets, std::vector<std::string>& missingTargets,
cmMakefile* mf, cmMakefile* mf,
@ -72,7 +73,8 @@ protected:
/** Generate a per-configuration file for the targets. */ /** Generate a per-configuration file for the targets. */
bool GenerateImportFileConfig(const char* config); bool GenerateImportFileConfig(const char* config,
std::vector<std::string> &missingTargets);
/** Fill in properties indicating installed file locations. */ /** Fill in properties indicating installed file locations. */
void SetImportLocationProperty(const char* config, void SetImportLocationProperty(const char* config,

View File

@ -621,7 +621,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
->GetGeneratorTarget(target); ->GetGeneratorTarget(target);
// the compilerdefines for this target // the compilerdefines for this target
std::string cdefs = gtgt->GetCompileDefinitions(); std::string cdefs = target->GetCompileDefinitions();
if(!cdefs.empty()) if(!cdefs.empty())
{ {

View File

@ -37,9 +37,13 @@ bool cmFLTKWrapUICommand
// get the list of GUI files from which .cxx and .h will be generated // get the list of GUI files from which .cxx and .h will be generated
std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory(); std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory();
{
// Some of the generated files are *.h so the directory "GUI" // Some of the generated files are *.h so the directory "GUI"
// where they are created have to be added to the include path // where they are created have to be added to the include path
this->Makefile->AddIncludeDirectory( outputDirectory.c_str() ); std::vector<std::string> outputDirectories;
outputDirectories.push_back(outputDirectory);
this->Makefile->AddIncludeDirectories( outputDirectories );
}
for(std::vector<std::string>::iterator i = (newArgs.begin() + 1); for(std::vector<std::string>::iterator i = (newArgs.begin() + 1);
i != newArgs.end(); i++) i != newArgs.end(); i++)

View File

@ -147,6 +147,38 @@ cmCompiledGeneratorExpression::~cmCompiledGeneratorExpression()
} }
} }
//----------------------------------------------------------------------------
static std::string stripEmptyListElements(const std::string &input)
{
std::string result;
const char *c = input.c_str();
bool skipSemiColons = true;
for ( ; *c; ++c)
{
if(c[0] == ';')
{
if(skipSemiColons)
{
continue;
}
skipSemiColons = true;
}
else
{
skipSemiColons = false;
}
result += *c;
}
if (!result.empty() && *(result.end() - 1) == ';')
{
result.resize(result.size() - 1);
}
return result;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static std::string stripAllGeneratorExpressions(const std::string &input) static std::string stripAllGeneratorExpressions(const std::string &input)
{ {
@ -186,7 +218,7 @@ static std::string stripAllGeneratorExpressions(const std::string &input)
lastPos = pos; lastPos = pos;
} }
result += input.substr(lastPos); result += input.substr(lastPos);
return result; return stripEmptyListElements(result);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -247,7 +279,68 @@ static std::string stripExportInterface(const std::string &input,
} }
result += input.substr(lastPos); result += input.substr(lastPos);
return result; return stripEmptyListElements(result);
}
//----------------------------------------------------------------------------
void cmGeneratorExpression::Split(const std::string &input,
std::vector<std::string> &output)
{
std::string::size_type pos = 0;
std::string::size_type lastPos = pos;
while((pos = input.find("$<", lastPos)) != input.npos)
{
std::string part = input.substr(lastPos, pos - lastPos);
std::string preGenex;
if (!part.empty())
{
std::string::size_type startPos = input.rfind(";", pos);
if (startPos != pos - 1 && startPos >= lastPos)
{
part = input.substr(lastPos, startPos - lastPos);
preGenex = input.substr(startPos + 1, pos - startPos - 1);
}
cmSystemTools::ExpandListArgument(part.c_str(), output);
}
pos += 2;
int nestingLevel = 1;
const char *c = input.c_str() + pos;
const char * const cStart = c;
for ( ; *c; ++c)
{
if(c[0] == '$' && c[1] == '<')
{
++nestingLevel;
++c;
continue;
}
if(c[0] == '>')
{
--nestingLevel;
if (nestingLevel == 0)
{
break;
}
}
}
for ( ; *c; ++c)
{
// Capture the part after the genex and before the next ';'
if(c[0] == ';')
{
--c;
break;
}
}
const std::string::size_type traversed = (c - cStart) + 1;
output.push_back(preGenex + "$<" + input.substr(pos, traversed));
pos += traversed;
lastPos = pos;
}
if (lastPos < input.size())
{
cmSystemTools::ExpandListArgument(input.substr(lastPos), output);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -59,6 +59,9 @@ public:
static std::string Preprocess(const std::string &input, static std::string Preprocess(const std::string &input,
PreprocessContext context); PreprocessContext context);
static void Split(const std::string &input,
std::vector<std::string> &output);
private: private:
cmGeneratorExpression(const cmGeneratorExpression &); cmGeneratorExpression(const cmGeneratorExpression &);
void operator=(const cmGeneratorExpression &); void operator=(const cmGeneratorExpression &);

View File

@ -106,3 +106,22 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
} }
return DAG; return DAG;
} }
//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
while (parent)
{
top = parent;
parent = parent->Parent;
}
const char *prop = top->Property.c_str();
return (strcmp(prop, "LINK_LIBRARIES") == 0
|| strcmp(prop, "LINK_INTERFACE_LIBRARIES") == 0
|| strcmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES") == 0
|| strncmp(prop, "LINK_INTERFACE_LIBRARIES_", 26) == 0
|| strncmp(prop, "IMPORTED_LINK_INTERFACE_LIBRARIES_", 35) == 0);
}

View File

@ -35,6 +35,9 @@ struct cmGeneratorExpressionDAGChecker
void reportError(cmGeneratorExpressionContext *context, void reportError(cmGeneratorExpressionContext *context,
const std::string &expr); const std::string &expr);
bool EvaluatingLinkLibraries();
private: private:
Result checkGraph() const; Result checkGraph() const;

View File

@ -289,6 +289,22 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode; } configurationTestNode;
static const struct TargetDefinedNode : public cmGeneratorExpressionNode
{
TargetDefinedNode() {}
virtual int NumExpectedParameters() const { return 1; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
const GeneratorExpressionContent *,
cmGeneratorExpressionDAGChecker *) const
{
return context->Makefile->FindTargetToUse(parameters.front().c_str())
? "1" : "0";
}
} targetDefinedNode;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static const char* targetPropertyTransitiveWhitelist[] = { static const char* targetPropertyTransitiveWhitelist[] = {
"INTERFACE_INCLUDE_DIRECTORIES" "INTERFACE_INCLUDE_DIRECTORIES"
@ -426,6 +442,34 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
const char *prop = target->GetProperty(propertyName.c_str()); const char *prop = target->GetProperty(propertyName.c_str());
if (!prop) if (!prop)
{ {
if (target->IsImported())
{
return std::string();
}
if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
{
return std::string();
}
if (propertyName == "POSITION_INDEPENDENT_CODE")
{
return target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config))
{
return target->GetLinkInterfaceDependentBoolProperty(
propertyName,
context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentStringProperty(propertyName,
context->Config))
{
return target->GetLinkInterfaceDependentStringProperty(
propertyName,
context->Config);
}
return std::string(); return std::string();
} }
@ -471,6 +515,105 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} targetNameNode; } targetNameNode;
//----------------------------------------------------------------------------
static const char* targetPolicyWhitelist[] = {
"CMP0003"
, "CMP0004"
, "CMP0008"
, "CMP0020"
};
cmPolicies::PolicyStatus statusForTarget(cmTarget *tgt, const char *policy)
{
#define RETURN_POLICY(POLICY) \
if (strcmp(policy, #POLICY) == 0) \
{ \
return tgt->GetPolicyStatus ## POLICY (); \
} \
RETURN_POLICY(CMP0003)
RETURN_POLICY(CMP0004)
RETURN_POLICY(CMP0008)
RETURN_POLICY(CMP0020)
#undef RETURN_POLICY
assert("!Unreachable code. Not a valid policy");
return cmPolicies::WARN;
}
cmPolicies::PolicyID policyForString(const char *policy_id)
{
#define RETURN_POLICY_ID(POLICY_ID) \
if (strcmp(policy_id, #POLICY_ID) == 0) \
{ \
return cmPolicies:: POLICY_ID; \
} \
RETURN_POLICY_ID(CMP0003)
RETURN_POLICY_ID(CMP0004)
RETURN_POLICY_ID(CMP0008)
RETURN_POLICY_ID(CMP0020)
#undef RETURN_POLICY_ID
assert("!Unreachable code. Not a valid policy");
return cmPolicies::CMP0002;
}
//----------------------------------------------------------------------------
static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
TargetPolicyNode() {}
virtual int NumExpectedParameters() const { return 1; }
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context ,
const GeneratorExpressionContent *content,
cmGeneratorExpressionDAGChecker *) const
{
if (!context->HeadTarget)
{
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with targets. It may not "
"be used with add_custom_command.");
return std::string();
}
for (size_t i = 0;
i < (sizeof(targetPolicyWhitelist) /
sizeof(*targetPolicyWhitelist));
++i)
{
const char *policy = targetPolicyWhitelist[i];
if (parameters.front() == policy)
{
cmMakefile *mf = context->HeadTarget->GetMakefile();
switch(statusForTarget(context->HeadTarget, policy))
{
case cmPolicies::WARN:
mf->IssueMessage(cmake::AUTHOR_WARNING,
mf->GetPolicies()->
GetPolicyWarning(policyForString(policy)));
case cmPolicies::REQUIRED_IF_USED:
case cmPolicies::REQUIRED_ALWAYS:
case cmPolicies::OLD:
return "0";
case cmPolicies::NEW:
return "1";
}
}
}
reportError(context, content->GetOriginalExpression(),
"$<TARGET_POLICY:prop> may only be used with a limited number of "
"policies. Currently it may be used with policies CMP0003, CMP0004, "
"CMP0008 and CMP0020."
);
return std::string();
}
} targetPolicyNode;
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
template<bool linker, bool soname> template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator struct TargetFilesystemArtifactResultCreator
@ -698,10 +841,14 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetPropertyNode; return &targetPropertyNode;
else if (identifier == "TARGET_NAME") else if (identifier == "TARGET_NAME")
return &targetNameNode; return &targetNameNode;
else if (identifier == "TARGET_POLICY")
return &targetPolicyNode;
else if (identifier == "BUILD_INTERFACE") else if (identifier == "BUILD_INTERFACE")
return &buildInterfaceNode; return &buildInterfaceNode;
else if (identifier == "INSTALL_INTERFACE") else if (identifier == "INSTALL_INTERFACE")
return &installInterfaceNode; return &installInterfaceNode;
else if (identifier == "TARGET_DEFINED")
return &targetDefinedNode;
return 0; return 0;
} }

View File

@ -254,32 +254,3 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
{ {
return this->Target->GetIncludeDirectories(config); return this->Target->GetIncludeDirectories(config);
} }
//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
{
std::string defPropName = "COMPILE_DEFINITIONS";
if (config)
{
defPropName += "_" + cmSystemTools::UpperCase(config);
}
const char *prop = this->Target->GetProperty(defPropName.c_str());
if (!prop)
{
return "";
}
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
defPropName, 0, 0);
return ge.Parse(prop)->Evaluate(this->Makefile,
config,
false,
this->Target,
&dagChecker);
}

View File

@ -68,8 +68,6 @@ public:
/** Get the include directories for this target. */ /** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories(const char *config); std::vector<std::string> GetIncludeDirectories(const char *config);
std::string GetCompileDefinitions(const char *config = 0);
private: private:
void ClassifySources(); void ClassifySources();
void LookupObjectLibraries(); void LookupObjectLibraries();

View File

@ -941,19 +941,7 @@ void cmGlobalGenerator::Generate()
for ( tit = targets->begin(); tit != targets->end(); ++ tit ) for ( tit = targets->begin(); tit != targets->end(); ++ tit )
{ {
if (mf->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES")) tit->second.AppendBuildInterfaceIncludes();
{
const char *binDir = mf->GetStartOutputDirectory();
const char *srcDir = mf->GetStartDirectory();
const std::string dirs = std::string(binDir ? binDir : "")
+ std::string(binDir ? ";" : "")
+ std::string(srcDir ? srcDir : "");
if (!dirs.empty())
{
tit->second.AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
}
}
} }
} }
@ -992,6 +980,7 @@ void cmGlobalGenerator::Generate()
// Generate project files // Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i) for (i = 0; i < this->LocalGenerators.size(); ++i)
{ {
this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
this->SetCurrentLocalGenerator(this->LocalGenerators[i]); this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
this->LocalGenerators[i]->Generate(); this->LocalGenerators[i]->Generate();
this->LocalGenerators[i]->GenerateInstallRules(); this->LocalGenerators[i]->GenerateInstallRules();
@ -1075,7 +1064,8 @@ void cmGlobalGenerator::CreateAutomocTargets()
if(target.GetType() == cmTarget::EXECUTABLE || if(target.GetType() == cmTarget::EXECUTABLE ||
target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::STATIC_LIBRARY ||
target.GetType() == cmTarget::SHARED_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY ||
target.GetType() == cmTarget::MODULE_LIBRARY) target.GetType() == cmTarget::MODULE_LIBRARY ||
target.GetType() == cmTarget::OBJECT_LIBRARY)
{ {
if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported()) if(target.GetPropertyAsBool("AUTOMOC") && !target.IsImported())
{ {

View File

@ -1367,16 +1367,18 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// This function removes each occurence of the flag and returns the last one // This function removes each occurrence of the flag and returns the last one
// (i.e., the dominant flag in GCC) // (i.e., the dominant flag in GCC)
std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag, std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
std::string& flags) std::string& flags)
{ {
std::string retFlag; std::string retFlag;
std::string::size_type pos = flags.rfind(flag); std::string::size_type lastOccurancePos = flags.rfind(flag);
bool saved = false; bool saved = false;
while(pos != flags.npos) while(lastOccurancePos != flags.npos)
{ {
//increment pos, we use lastOccurancePos to reduce search space on next inc
std::string::size_type pos = lastOccurancePos;
if(pos == 0 || flags[pos-1]==' ') if(pos == 0 || flags[pos-1]==' ')
{ {
while(pos < flags.size() && flags[pos] != ' ') while(pos < flags.size() && flags[pos] != ' ')
@ -1388,9 +1390,12 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
flags[pos] = ' '; flags[pos] = ' ';
pos++; pos++;
} }
}
saved = true; saved = true;
pos = flags.rfind(flag); }
//decrement lastOccurancePos while making sure we don't loop around
//and become a very large positive number since size_type is unsigned
lastOccurancePos = lastOccurancePos == 0 ? 0 : lastOccurancePos-1;
lastOccurancePos = flags.rfind(flag,lastOccurancePos);
} }
return retFlag; return retFlag;
} }
@ -1676,11 +1681,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->AppendDefines(ppDefs, exportMacro); this->AppendDefines(ppDefs, exportMacro);
} }
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target); cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str()); this->AppendDefines(ppDefs, target.GetCompileDefinitions().c_str());
if(configName) if(configName)
{ {
this->AppendDefines(ppDefs, this->AppendDefines(ppDefs,
gtgt->GetCompileDefinitions(configName).c_str()); target.GetCompileDefinitions(configName).c_str());
} }
buildSettings->AddAttribute buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList()); ("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());

View File

@ -36,6 +36,10 @@ bool cmIncludeDirectoryCommand
++i; ++i;
} }
std::vector<std::string> beforeIncludes;
std::vector<std::string> afterIncludes;
std::set<cmStdString> systemIncludes;
for(; i != args.end(); ++i) for(; i != args.end(); ++i)
{ {
if(*i == "SYSTEM") if(*i == "SYSTEM")
@ -49,9 +53,37 @@ bool cmIncludeDirectoryCommand
return false; return false;
} }
this->AddDirectory(i->c_str(),before,system); std::vector<std::string> includes;
GetIncludes(*i, includes);
if (before)
{
beforeIncludes.insert(beforeIncludes.end(),
includes.begin(),
includes.end());
}
else
{
afterIncludes.insert(afterIncludes.end(),
includes.begin(),
includes.end());
}
if (system)
{
for (std::vector<std::string>::const_iterator li = includes.begin();
li != includes.end(); ++li)
{
systemIncludes.insert(*li);
}
}
} }
std::reverse(beforeIncludes.begin(), beforeIncludes.end());
this->Makefile->AddIncludeDirectories(afterIncludes);
this->Makefile->AddIncludeDirectories(beforeIncludes, before);
this->Makefile->AddSystemIncludeDirectories(systemIncludes);
return true; return true;
} }
@ -72,57 +104,49 @@ static bool StartsWithGeneratorExpression(const std::string &input)
// output from a program and passing it into a command the cleanup doesn't // output from a program and passing it into a command the cleanup doesn't
// always happen // always happen
// //
void cmIncludeDirectoryCommand::AddDirectory(const char *i, void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg,
bool before, std::vector<std::string> &incs)
bool system)
{ {
// break apart any line feed arguments // break apart any line feed arguments
std::string ret = i;
std::string::size_type pos = 0; std::string::size_type pos = 0;
if((pos = ret.find('\n', pos)) != std::string::npos) std::string::size_type lastPos = 0;
while((pos = arg.find('\n', lastPos)) != std::string::npos)
{ {
if (pos) if (pos)
{ {
this->AddDirectory(ret.substr(0,pos).c_str(), before, system); std::string inc = arg.substr(lastPos,pos);
NormalizeInclude(inc);
incs.push_back(inc);
} }
if (ret.size()-pos-1) lastPos = pos + 1;
{ }
this->AddDirectory(ret.substr(pos+1,ret.size()-pos-1).c_str(), std::string inc = arg.substr(lastPos);
before, system); NormalizeInclude(inc);
} incs.push_back(inc);
return; }
void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
{
std::string::size_type b = inc.find_first_not_of(" \r");
std::string::size_type e = inc.find_last_not_of(" \r");
if ((b!=inc.npos) && (e!=inc.npos))
{
inc.assign(inc, b, 1+e-b); // copy the remaining substring
} }
// remove any leading or trailing spaces and \r if (!cmSystemTools::IsOff(inc.c_str()))
std::string::size_type b = ret.find_first_not_of(" \r");
std::string::size_type e = ret.find_last_not_of(" \r");
if ((b!=ret.npos) && (e!=ret.npos))
{ {
ret.assign(ret, b, 1+e-b); // copy the remaining substring cmSystemTools::ConvertToUnixSlashes(inc);
}
else
{
return; // if we get here, we had only whitespace in the string
}
if (!cmSystemTools::IsOff(ret.c_str())) if(!cmSystemTools::FileIsFullPath(inc.c_str()))
{
cmSystemTools::ConvertToUnixSlashes(ret);
if(!cmSystemTools::FileIsFullPath(ret.c_str()))
{ {
if(!StartsWithGeneratorExpression(ret)) if(!StartsWithGeneratorExpression(inc))
{ {
std::string tmp = this->Makefile->GetStartDirectory(); std::string tmp = this->Makefile->GetStartDirectory();
tmp += "/"; tmp += "/";
tmp += ret; tmp += inc;
ret = tmp; inc = tmp;
} }
} }
} }
this->Makefile->AddIncludeDirectory(ret.c_str(), before);
if(system)
{
this->Makefile->AddSystemIncludeDirectory(ret.c_str());
}
} }

View File

@ -84,7 +84,8 @@ public:
protected: protected:
// used internally // used internally
void AddDirectory(const char *arg, bool before, bool system); void GetIncludes(const std::string &arg, std::vector<std::string> &incs);
void NormalizeInclude(std::string &inc);
}; };

View File

@ -1697,25 +1697,21 @@ void cmLocalVisualStudio6Generator
std::set<std::string> minsizeDefinesSet; std::set<std::string> minsizeDefinesSet;
std::set<std::string> debugrelDefinesSet; std::set<std::string> debugrelDefinesSet;
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
this->AppendDefines( this->AppendDefines(
definesSet, definesSet,
gt->GetCompileDefinitions()); target.GetCompileDefinitions());
this->AppendDefines( this->AppendDefines(
debugDefinesSet, debugDefinesSet,
gt->GetCompileDefinitions("DEBUG")); target.GetCompileDefinitions("DEBUG"));
this->AppendDefines( this->AppendDefines(
releaseDefinesSet, releaseDefinesSet,
gt->GetCompileDefinitions("RELEASE")); target.GetCompileDefinitions("RELEASE"));
this->AppendDefines( this->AppendDefines(
minsizeDefinesSet, minsizeDefinesSet,
gt->GetCompileDefinitions("MINSIZEREL")); target.GetCompileDefinitions("MINSIZEREL"));
this->AppendDefines( this->AppendDefines(
debugrelDefinesSet, debugrelDefinesSet,
gt->GetCompileDefinitions("RELWITHDEBINFO")); target.GetCompileDefinitions("RELWITHDEBINFO"));
std::string defines = " "; std::string defines = " ";
std::string debugDefines = " "; std::string debugDefines = " ";

View File

@ -745,8 +745,8 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.ParseFinish(); targetOptions.ParseFinish();
cmGeneratorTarget* gt = cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target); this->GlobalGenerator->GetGeneratorTarget(&target);
targetOptions.AddDefines(gt->GetCompileDefinitions().c_str()); targetOptions.AddDefines(target.GetCompileDefinitions().c_str());
targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str()); targetOptions.AddDefines(target.GetCompileDefinitions(configName).c_str());
targetOptions.SetVerboseMakefile( targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

View File

@ -99,6 +99,7 @@ cmMakefile::cmMakefile(): Internal(new Internals)
this->AddDefaultDefinitions(); this->AddDefaultDefinitions();
this->Initialize(); this->Initialize();
this->PreOrder = false; this->PreOrder = false;
this->GeneratingBuildSystem = false;
} }
cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals) cmMakefile::cmMakefile(const cmMakefile& mf): Internal(new Internals)
@ -1616,20 +1617,31 @@ void cmMakefile::AddSubDirectory(const char* srcPath, const char *binPath,
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmMakefile::AddIncludeDirectory(const char* inc, bool before) void cmMakefile::AddIncludeDirectories(const std::vector<std::string> &incs,
bool before)
{ {
if (!inc) if (incs.empty())
{ {
return; return;
} }
std::string incString;
std::string sep;
for(std::vector<std::string>::const_iterator li = incs.begin();
li != incs.end(); ++li)
{
incString += sep + *li;
sep = ";";
}
std::vector<IncludeDirectoriesEntry>::iterator position = std::vector<IncludeDirectoriesEntry>::iterator position =
before ? this->IncludeDirectoriesEntries.begin() before ? this->IncludeDirectoriesEntries.begin()
: this->IncludeDirectoriesEntries.end(); : this->IncludeDirectoriesEntries.end();
cmListFileBacktrace lfbt; cmListFileBacktrace lfbt;
this->GetBacktrace(lfbt); this->GetBacktrace(lfbt);
IncludeDirectoriesEntry entry(inc, lfbt); IncludeDirectoriesEntry entry(incString, lfbt);
this->IncludeDirectoriesEntries.insert(position, entry); this->IncludeDirectoriesEntries.insert(position, entry);
// Property on each target: // Property on each target:
@ -1642,9 +1654,14 @@ void cmMakefile::AddIncludeDirectory(const char* inc, bool before)
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmMakefile::AddSystemIncludeDirectory(const char* dir) void
cmMakefile::AddSystemIncludeDirectories(const std::set<cmStdString> &incs)
{ {
this->SystemIncludeDirectories.insert(dir); for(std::set<cmStdString>::const_iterator li = incs.begin();
li != incs.end(); ++li)
{
this->SystemIncludeDirectories.insert(*li);
}
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2243,7 +2260,7 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
{ {
return true; return true;
} }
// If we are doing an in-source build, than the test will always fail // If we are doing an in-source build, then the test will always fail
if ( cmSystemTools::SameFile(this->GetHomeDirectory(), if ( cmSystemTools::SameFile(this->GetHomeDirectory(),
this->GetHomeOutputDirectory()) ) this->GetHomeOutputDirectory()) )
{ {
@ -2254,8 +2271,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
return true; return true;
} }
// Check if this is subdirectory of the source tree but not a // Check if this is a subdirectory of the source tree but not a
// subdirectory of a build tree // subdirectory of the build tree
if ( cmSystemTools::IsSubDirectory(fileName, if ( cmSystemTools::IsSubDirectory(fileName,
this->GetHomeDirectory()) && this->GetHomeDirectory()) &&
!cmSystemTools::IsSubDirectory(fileName, !cmSystemTools::IsSubDirectory(fileName,

View File

@ -287,7 +287,8 @@ public:
/** /**
* Add an include directory to the build. * Add an include directory to the build.
*/ */
void AddIncludeDirectory(const char*, bool before = false); void AddIncludeDirectories(const std::vector<std::string> &incs,
bool before = false);
/** /**
* Add a variable definition to the build. This variable * Add a variable definition to the build. This variable
@ -545,7 +546,7 @@ public:
/** /**
* Mark include directories as system directories. * Mark include directories as system directories.
*/ */
void AddSystemIncludeDirectory(const char* dir); void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
bool IsSystemIncludeDirectory(const char* dir); bool IsSystemIncludeDirectory(const char* dir);
/** Expand out any arguements in the vector that have ; separated /** Expand out any arguements in the vector that have ; separated
@ -869,6 +870,9 @@ public:
return this->IncludeDirectoriesEntries; return this->IncludeDirectoriesEntries;
} }
bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
protected: protected:
// add link libraries and directories to the target // add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target); void AddGlobalLinkInformation(const char* name, cmTarget& target);
@ -1018,6 +1022,9 @@ private:
// Enforce rules about CMakeLists.txt files. // Enforce rules about CMakeLists.txt files.
void EnforceDirectoryLevelRules(); void EnforceDirectoryLevelRules();
bool GeneratingBuildSystem;
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -303,10 +303,10 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
// Add preprocessor definitions for this target and configuration. // Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions()); (defines, this->Target->GetCompileDefinitions());
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions( (defines, this->Target->GetCompileDefinitions(
this->LocalGenerator->ConfigurationName.c_str())); this->LocalGenerator->ConfigurationName.c_str()));
std::string definesString; std::string definesString;

View File

@ -228,7 +228,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
// Add preprocessor definitions for this target and configuration. // Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, (defines,
this->GeneratorTarget->GetCompileDefinitions()); this->Target->GetCompileDefinitions());
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, (defines,
source->GetProperty("COMPILE_DEFINITIONS")); source->GetProperty("COMPILE_DEFINITIONS"));
@ -237,7 +237,7 @@ ComputeDefines(cmSourceFile *source, const std::string& language)
defPropName += cmSystemTools::UpperCase(this->GetConfigName()); defPropName += cmSystemTools::UpperCase(this->GetConfigName());
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, (defines,
this->GeneratorTarget->GetCompileDefinitions(this->GetConfigName())); this->Target->GetCompileDefinitions(this->GetConfigName()));
this->LocalGenerator->AppendDefines this->LocalGenerator->AppendDefines
(defines, (defines,
source->GetProperty(defPropName.c_str())); source->GetProperty(defPropName.c_str()));

View File

@ -508,6 +508,27 @@ cmPolicies::cmPolicies()
"for strict compatibility. " "for strict compatibility. "
"The NEW behavior for this policy is to leave the values untouched.", "The NEW behavior for this policy is to leave the values untouched.",
2,8,11,0, cmPolicies::WARN); 2,8,11,0, cmPolicies::WARN);
this->DefinePolicy(
CMP0020, "CMP0020",
"Automatically link Qt executables to qtmain target on Windows.",
"CMake 2.8.10 and lower required users of Qt to always specify a link "
"dependency to the qtmain.lib static library manually on Windows. CMake "
"2.8.11 gained the ability to evaluate generator expressions while "
"determining the link dependencies from IMPORTED targets. This allows "
"CMake itself to automatically link executables which link to Qt to the "
"qtmain.lib library when using IMPORTED Qt targets. For applications "
"already linking to qtmain.lib, this should have little impact. For "
"applications which supply their own alternative WinMain implementation "
"and for applications which use the QAxServer library, this automatic "
"linking will need to be disabled as per the documentation."
"\n"
"The OLD behavior for this policy is not to link executables to "
"qtmain.lib automatically when they link to the QtCore IMPORTED"
"target. "
"The NEW behavior for this policy is to link executables to "
"qtmain.lib automatically when they link to QtCore IMPORTED target.",
2,8,11,0, cmPolicies::WARN);
} }
cmPolicies::~cmPolicies() cmPolicies::~cmPolicies()

View File

@ -69,6 +69,7 @@ public:
/// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C} /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C}
/// instead. /// instead.
CMP0019, ///< No variable re-expansion in include and link info CMP0019, ///< No variable re-expansion in include and link info
CMP0020, ///< Automatically link Qt executables to qtmain target
/** \brief Always the last entry. /** \brief Always the last entry.
* *

View File

@ -229,7 +229,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
} }
const char* tmp = target->GetProperty("COMPILE_DEFINITIONS"); const char* tmp = target->GetProperty("COMPILE_DEFINITIONS");
std::string _moc_compile_defs = (tmp!=0 ? tmp : ""); std::string _moc_compile_defs;
if (tmp)
{
_moc_compile_defs = target->GetCompileDefinitions();
}
tmp = makefile->GetProperty("COMPILE_DEFINITIONS"); tmp = makefile->GetProperty("COMPILE_DEFINITIONS");
if (tmp) if (tmp)
{ {

View File

@ -145,11 +145,14 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0003 = cmPolicies::WARN; this->PolicyStatusCMP0003 = cmPolicies::WARN;
this->PolicyStatusCMP0004 = cmPolicies::WARN; this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN; this->PolicyStatusCMP0008 = cmPolicies::WARN;
this->PolicyStatusCMP0020 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false; this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false; this->HaveInstallRule = false;
this->DLLPlatform = false; this->DLLPlatform = false;
this->IsApple = false; this->IsApple = false;
this->IsImportedTarget = false; this->IsImportedTarget = false;
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -891,6 +894,30 @@ void cmTarget::DefineProperties(cmake *cm)
"must ensure that the targets that they link to have a consistent " "must ensure that the targets that they link to have a consistent "
"requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property."); "requirement for their INTERFACE_POSITION_INDEPENDENT_CODE property.");
cm->DefineProperty
("COMPATIBLE_INTERFACE_BOOL", cmProperty::TARGET,
"Properties which must be compatible with their link interface",
"The COMPATIBLE_INTERFACE_BOOL property may contain a list of properties"
"for this target which must be consistent when evaluated as a boolean "
"in the INTERFACE of all linked dependencies. For example, if a "
"property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" "
"property content in all dependencies must be consistent with each "
"other, and with the \"FOO\" property in this target. "
"Consistency in this sense has the meaning that if the property is set,"
"then it must have the same boolean value as all others, and if the "
"property is not set, then it is ignored.");
cm->DefineProperty
("COMPATIBLE_INTERFACE_STRING", cmProperty::TARGET,
"Properties which must be string-compatible with their link interface",
"The COMPATIBLE_INTERFACE_STRING property may contain a list of "
"properties for this target which must be the same when evaluated as "
"a string in the INTERFACE of all linked dependencies. For example, "
"if a property \"FOO\" appears in the list, then the \"INTERFACE_FOO\" "
"property content in all dependencies must be equal with each "
"other, and with the \"FOO\" property in this target. If the "
"property is not set, then it is ignored.");
cm->DefineProperty cm->DefineProperty
("POST_INSTALL_SCRIPT", cmProperty::TARGET, ("POST_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.", "Deprecated install support.",
@ -1485,6 +1512,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004); this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 = this->PolicyStatusCMP0008 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0008); this->Makefile->GetPolicyStatus(cmPolicies::CMP0008);
this->PolicyStatusCMP0020 =
this->Makefile->GetPolicyStatus(cmPolicies::CMP0020);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1506,6 +1535,13 @@ void cmTarget::ClearLinkMaps()
this->Internal->LinkImplMap.clear(); this->Internal->LinkImplMap.clear();
this->Internal->LinkInterfaceMap.clear(); this->Internal->LinkInterfaceMap.clear();
this->Internal->LinkClosureMap.clear(); this->Internal->LinkClosureMap.clear();
for (cmTargetLinkInformationMap::const_iterator it
= this->LinkInformation.begin();
it != this->LinkInformation.end(); ++it)
{
delete it->second;
}
this->LinkInformation.clear();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2232,6 +2268,14 @@ static std::string targetNameGenex(const char *lib)
return std::string("$<TARGET_NAME:") + lib + ">"; return std::string("$<TARGET_NAME:") + lib + ">";
} }
//----------------------------------------------------------------------------
static bool isGeneratorExpression(const std::string &lib)
{
const std::string::size_type openpos = lib.find("$<");
return (openpos != std::string::npos)
&& (lib.find(">", openpos) != std::string::npos);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::AddLinkLibrary(cmMakefile& mf, void cmTarget::AddLinkLibrary(cmMakefile& mf,
const char *target, const char* lib, const char *target, const char* lib,
@ -2247,13 +2291,19 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
cmTarget *tgt = this->Makefile->FindTargetToUse(lib); cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
const bool isNonImportedTarget = tgt && !tgt->IsImported(); const bool isNonImportedTarget = tgt && !tgt->IsImported();
std::string libName = isNonImportedTarget ? targetNameGenex(lib) const std::string libName = (isNonImportedTarget && llt != GENERAL)
: std::string(lib); ? targetNameGenex(lib)
: std::string(lib);
this->AppendProperty("LINK_LIBRARIES", this->AppendProperty("LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(libName, this->GetDebugGeneratorExpressions(libName,
llt).c_str()); llt).c_str());
} }
if (isGeneratorExpression(lib))
{
return;
}
cmTarget::LibraryID tmp; cmTarget::LibraryID tmp;
tmp.first = lib; tmp.first = lib;
tmp.second = llt; tmp.second = llt;
@ -2654,6 +2704,30 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
this->MaybeInvalidatePropertyCache(prop); this->MaybeInvalidatePropertyCache(prop);
} }
//----------------------------------------------------------------------------
void cmTarget::AppendBuildInterfaceIncludes()
{
if (this->BuildInterfaceIncludesAppended)
{
return;
}
this->BuildInterfaceIncludesAppended = true;
if (this->Makefile->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES"))
{
const char *binDir = this->Makefile->GetStartOutputDirectory();
const char *srcDir = this->Makefile->GetStartDirectory();
const std::string dirs = std::string(binDir ? binDir : "")
+ std::string(binDir ? ";" : "")
+ std::string(srcDir ? srcDir : "");
if (!dirs.empty())
{
this->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
("$<BUILD_INTERFACE:" + dirs + ">").c_str());
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, void cmTarget::InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
bool before) bool before)
@ -2688,11 +2762,17 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmSystemTools::ExpandListArgument(debugProp, debugProperties); cmSystemTools::ExpandListArgument(debugProp, debugProperties);
} }
bool debugIncludes = std::find(debugProperties.begin(), bool debugIncludes = !this->DebugIncludesDone
&& std::find(debugProperties.begin(),
debugProperties.end(), debugProperties.end(),
"INCLUDE_DIRECTORIES") "INCLUDE_DIRECTORIES")
!= debugProperties.end(); != debugProperties.end();
if (this->Makefile->IsGeneratingBuildSystem())
{
this->DebugIncludesDone = true;
}
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
it = this->Internal->IncludeDirectoriesEntries.begin(), it = this->Internal->IncludeDirectoriesEntries.begin(),
end = this->Internal->IncludeDirectoriesEntries.end(); end = this->Internal->IncludeDirectoriesEntries.end();
@ -2727,13 +2807,42 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
if (!usedIncludes.empty()) if (!usedIncludes.empty())
{ {
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG, this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG,
"Used includes:\n" + usedIncludes, "Used includes for target " + this->Name + ":\n"
(*it)->ge->GetBacktrace()); + usedIncludes, (*it)->ge->GetBacktrace());
} }
} }
return includes; return includes;
} }
//----------------------------------------------------------------------------
std::string cmTarget::GetCompileDefinitions(const char *config)
{
std::string defPropName = "COMPILE_DEFINITIONS";
if (config)
{
defPropName += "_" + cmSystemTools::UpperCase(config);
}
const char *prop = this->GetProperty(defPropName.c_str());
if (!prop)
{
return "";
}
cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
defPropName, 0, 0);
return ge.Parse(prop)->Evaluate(this->Makefile,
config,
false,
this,
&dagChecker);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop) void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{ {
@ -4431,22 +4540,69 @@ void cmTarget::AddLinkDependentTargetsForProperties(
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p, template<typename PropertyType>
const char *config) PropertyType getTypedProperty(cmTarget *tgt, const char *prop,
PropertyType *);
//----------------------------------------------------------------------------
template<>
bool getTypedProperty<bool>(cmTarget *tgt, const char *prop, bool *)
{ {
bool propContent = this->GetPropertyAsBool(p.c_str()); return tgt->GetPropertyAsBool(prop);
const bool explicitlySet = this->GetProperties() }
//----------------------------------------------------------------------------
template<>
const char *getTypedProperty<const char *>(cmTarget *tgt, const char *prop,
const char **)
{
return tgt->GetProperty(prop);
}
//----------------------------------------------------------------------------
template<typename PropertyType>
bool consistentProperty(PropertyType lhs, PropertyType rhs);
//----------------------------------------------------------------------------
template<>
bool consistentProperty(bool lhs, bool rhs)
{
return lhs == rhs;
}
//----------------------------------------------------------------------------
template<>
bool consistentProperty(const char *lhs, const char *rhs)
{
if (!lhs && !rhs)
return true;
if (!lhs || !rhs)
return false;
return strcmp(lhs, rhs) == 0;
}
//----------------------------------------------------------------------------
template<typename PropertyType>
PropertyType checkInterfacePropertyCompatibility(cmTarget *tgt,
const std::string &p,
const char *config,
const char *defaultValue,
PropertyType *)
{
PropertyType propContent = getTypedProperty<PropertyType>(tgt, p.c_str(),
0);
const bool explicitlySet = tgt->GetProperties()
.find(p.c_str()) .find(p.c_str())
!= this->GetProperties().end(); != tgt->GetProperties().end();
std::set<std::string> dependentTargets; std::set<std::string> dependentTargets;
this->GetLinkDependentTargetsForProperty(p, tgt->GetLinkDependentTargetsForProperty(p,
dependentTargets); dependentTargets);
const bool impliedByUse = const bool impliedByUse =
this->IsNullImpliedByLinkLibraries(p); tgt->IsNullImpliedByLinkLibraries(p);
assert((impliedByUse ^ explicitlySet) assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet)); || (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = this->GetLinkInformation(config); cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems(); const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet; bool propInitialized = explicitlySet;
@ -4468,20 +4624,22 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const bool ifaceIsSet = li->Target->GetProperties() const bool ifaceIsSet = li->Target->GetProperties()
.find("INTERFACE_" + p) .find("INTERFACE_" + p)
!= li->Target->GetProperties().end(); != li->Target->GetProperties().end();
const bool ifacePropContent = li->Target->GetPropertyAsBool( PropertyType ifacePropContent =
("INTERFACE_" + p).c_str()); getTypedProperty<PropertyType>(li->Target,
("INTERFACE_" + p).c_str(), 0);
if (explicitlySet) if (explicitlySet)
{ {
if (ifaceIsSet) if (ifaceIsSet)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "Property " << p << " on target \"" e << "Property " << p << " on target \""
<< this->GetName() << "\" does\nnot match the " << tgt->GetName() << "\" does\nnot match the "
"INTERFACE_" << p << " property requirement\nof " "INTERFACE_" << p << " property requirement\nof "
"dependency \"" << li->Target->GetName() << "\".\n"; "dependency \"" << li->Target->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
break;
} }
else else
{ {
@ -4499,15 +4657,16 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{ {
if (ifaceIsSet) if (ifaceIsSet)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "Property " << p << " on target \"" e << "Property " << p << " on target \""
<< this->GetName() << "\" is\nimplied to be FALSE because it " << tgt->GetName() << "\" is\nimplied to be " << defaultValue
"was used to determine the link libraries\nalready. The " << " because it was used to determine the link libraries\n"
"INTERFACE_" << p << " property on\ndependency \"" "already. The INTERFACE_" << p << " property on\ndependency \""
<< li->Target->GetName() << "\" is in conflict.\n"; << li->Target->GetName() << "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
break;
} }
else else
{ {
@ -4527,14 +4686,15 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{ {
if (propInitialized) if (propInitialized)
{ {
if (propContent != ifacePropContent) if (!consistentProperty(propContent, ifacePropContent))
{ {
cmOStringStream e; cmOStringStream e;
e << "The INTERFACE_" << p << " property of \"" e << "The INTERFACE_" << p << " property of \""
<< li->Target->GetName() << "\" does\nnot agree with the value " << li->Target->GetName() << "\" does\nnot agree with the value "
"of " << p << " already determined\nfor \"" "of " << p << " already determined\nfor \""
<< this->GetName() << "\".\n"; << tgt->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str()); cmSystemTools::Error(e.str().c_str());
break;
} }
else else
{ {
@ -4558,6 +4718,80 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
return propContent; return propContent;
} }
//----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
{
return checkInterfacePropertyCompatibility<bool>(this, p, config, "FALSE",
0);
}
//----------------------------------------------------------------------------
const char * cmTarget::GetLinkInterfaceDependentStringProperty(
const std::string &p,
const char *config)
{
return checkInterfacePropertyCompatibility<const char *>(this,
p,
config,
"empty", 0);
}
//----------------------------------------------------------------------------
bool isLinkDependentProperty(cmTarget *tgt, const std::string &p,
const char *interfaceProperty,
const char *config)
{
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
const char *prop = li->Target->GetProperty(interfaceProperty);
if (!prop)
{
continue;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (*pi == p)
{
return true;
}
}
}
return false;
}
//----------------------------------------------------------------------------
bool cmTarget::IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
{
return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_BOOL",
config);
}
//----------------------------------------------------------------------------
bool cmTarget::IsLinkInterfaceDependentStringProperty(const std::string &p,
const char *config)
{
return isLinkDependentProperty(this, p, "COMPATIBLE_INTERFACE_STRING",
config);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
{ {
@ -4896,16 +5130,30 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
{ {
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES"; std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
linkProp += suffix; linkProp += suffix;
if(const char* config_libs = this->GetProperty(linkProp.c_str()))
const char *propertyLibs = this->GetProperty(linkProp.c_str());
if(!propertyLibs)
{ {
cmSystemTools::ExpandListArgument(config_libs, linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
info.LinkInterface.Libraries); propertyLibs = this->GetProperty(linkProp.c_str());
} }
else if(const char* libs = if(propertyLibs)
this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
{ {
cmSystemTools::ExpandListArgument(libs, cmListFileBacktrace lfbt;
info.LinkInterface.Libraries); cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
linkProp, 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(propertyLibs)
->Evaluate(this->Makefile,
desired_config.c_str(),
false,
headTarget,
this,
&dagChecker),
info.LinkInterface.Libraries);
} }
} }
@ -5019,18 +5267,20 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// An explicit list of interface libraries may be set for shared // An explicit list of interface libraries may be set for shared
// libraries and executables that export symbols. // libraries and executables that export symbols.
const char* explicitLibraries = 0; const char* explicitLibraries = 0;
std::string linkIfaceProp;
if(this->GetType() == cmTarget::SHARED_LIBRARY || if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports()) this->IsExecutableWithExports())
{ {
// Lookup the per-configuration property. // Lookup the per-configuration property.
std::string propName = "LINK_INTERFACE_LIBRARIES"; linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
propName += suffix; linkIfaceProp += suffix;
explicitLibraries = this->GetProperty(propName.c_str()); explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
// If not set, try the generic property. // If not set, try the generic property.
if(!explicitLibraries) if(!explicitLibraries)
{ {
explicitLibraries = this->GetProperty("LINK_INTERFACE_LIBRARIES"); linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
} }
} }
@ -5048,7 +5298,16 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
if(explicitLibraries) if(explicitLibraries)
{ {
// The interface libraries have been explicitly set. // The interface libraries have been explicitly set.
cmSystemTools::ExpandListArgument(explicitLibraries, iface.Libraries); cmListFileBacktrace lfbt;
cmGeneratorExpression ge(lfbt);
cmGeneratorExpressionDAGChecker dagChecker(lfbt, this->GetName(),
linkIfaceProp, 0, 0);
cmSystemTools::ExpandListArgument(ge.Parse(explicitLibraries)->Evaluate(
this->Makefile,
config,
false,
headTarget,
this, &dagChecker), iface.Libraries);
if(this->GetType() == cmTarget::SHARED_LIBRARY) if(this->GetType() == cmTarget::SHARED_LIBRARY)
{ {
@ -5091,6 +5350,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// The link implementation is the default link interface. // The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config, LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget); headTarget);
iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries; iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries; iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY) if(this->GetType() == cmTarget::STATIC_LIBRARY)
@ -5272,6 +5532,107 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
return lib; return lib;
} }
template<typename PropertyType>
PropertyType getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config,
PropertyType *);
template<>
bool getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config, bool *)
{
return tgt->GetLinkInterfaceDependentBoolProperty(prop, config);
}
template<>
const char * getLinkInterfaceDependentProperty(cmTarget *tgt,
const std::string prop,
const char *config,
const char **)
{
return tgt->GetLinkInterfaceDependentStringProperty(prop, config);
}
//----------------------------------------------------------------------------
template<typename PropertyType>
void checkPropertyConsistency(cmTarget *depender, cmTarget *dependee,
const char *propName,
std::set<cmStdString> &emitted,
const char *config,
PropertyType *)
{
const char *prop = dependee->GetProperty(propName);
if (!prop)
{
return;
}
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(prop, props);
for(std::vector<std::string>::iterator pi = props.begin();
pi != props.end(); ++pi)
{
if (depender->GetMakefile()->GetCMakeInstance()
->GetIsPropertyDefined(pi->c_str(),
cmProperty::TARGET))
{
cmOStringStream e;
e << "Target \"" << dependee->GetName() << "\" has property \""
<< *pi << "\" listed in its " << propName << " property. "
"This is not allowed. Only user-defined properties may appear "
"listed in the " << propName << " property.";
depender->GetMakefile()->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
if(emitted.insert(*pi).second)
{
getLinkInterfaceDependentProperty<PropertyType>(depender, *pi, config,
0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
}
}
//----------------------------------------------------------------------------
void cmTarget::CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config)
{
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
std::set<cmStdString> emitted;
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
checkPropertyConsistency<bool>(this, li->Target,
"COMPATIBLE_INTERFACE_BOOL",
emitted, config, 0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
checkPropertyConsistency<const char *>(this, li->Target,
"COMPATIBLE_INTERFACE_STRING",
emitted, config, 0);
if (cmSystemTools::GetErrorOccuredFlag())
{
return;
}
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
cmComputeLinkInformation* cmComputeLinkInformation*
cmTarget::GetLinkInformation(const char* config, cmTarget *head) cmTarget::GetLinkInformation(const char* config, cmTarget *head)
@ -5296,6 +5657,11 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
// Store the information for this configuration. // Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info); cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first; i = this->LinkInformation.insert(entry).first;
if (info)
{
this->CheckPropertyCompatibility(info, config);
}
} }
return i->second; return i->second;
} }

View File

@ -102,6 +102,10 @@ public:
cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const cmPolicies::PolicyStatus GetPolicyStatusCMP0008() const
{ return this->PolicyStatusCMP0008; } { return this->PolicyStatusCMP0008; }
/** Get the status of policy CMP0020 when the target was created. */
cmPolicies::PolicyStatus GetPolicyStatusCMP0020() const
{ return this->PolicyStatusCMP0020; }
/** /**
* Get the list of the custom commands for this target * Get the list of the custom commands for this target
*/ */
@ -258,7 +262,9 @@ public:
// Needed only for OLD behavior of CMP0003. // Needed only for OLD behavior of CMP0003.
std::vector<std::string> WrongConfigLibraries; std::vector<std::string> WrongConfigLibraries;
LinkInterface(): Multiplicity(0) {} bool ImplementationIsInterface;
LinkInterface(): Multiplicity(0), ImplementationIsInterface(false) {}
}; };
/** Get the link interface for the given configuration. Returns 0 /** Get the link interface for the given configuration. Returns 0
@ -424,6 +430,8 @@ public:
If no macro should be defined null is returned. */ If no macro should be defined null is returned. */
const char* GetExportMacro(); const char* GetExportMacro();
std::string GetCompileDefinitions(const char *config = 0);
// Compute the set of languages compiled by the target. This is // Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change // computed every time it is called because the languages can change
// when source file properties are changed and we do not have enough // when source file properties are changed and we do not have enough
@ -488,15 +496,24 @@ public:
void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry, void InsertInclude(const cmMakefileIncludeDirectoriesEntry &entry,
bool before = false); bool before = false);
void AppendBuildInterfaceIncludes();
void GetLinkDependentTargetsForProperty(const std::string &p, void GetLinkDependentTargetsForProperty(const std::string &p,
std::set<std::string> &targets); std::set<std::string> &targets);
bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
bool IsLinkInterfaceDependentStringProperty(const std::string &p,
const char *config);
void AddLinkDependentTargetsForProperties( void AddLinkDependentTargetsForProperties(
const std::map<cmStdString, cmStdString> &map); const std::map<cmStdString, cmStdString> &map);
bool GetLinkInterfaceDependentBoolProperty(const std::string &p, bool GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config); const char *config);
const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
const char *config);
private: private:
/** /**
* A list of direct dependencies. Use in conjunction with DependencyMap. * A list of direct dependencies. Use in conjunction with DependencyMap.
@ -606,9 +623,11 @@ private:
bool DLLPlatform; bool DLLPlatform;
bool IsApple; bool IsApple;
bool IsImportedTarget; bool IsImportedTarget;
bool DebugIncludesDone;
mutable std::map<cmStdString, std::set<std::string> > mutable std::map<cmStdString, std::set<std::string> >
LinkDependentProperties; LinkDependentProperties;
mutable std::set<std::string> LinkImplicitNullProperties; mutable std::set<std::string> LinkImplicitNullProperties;
bool BuildInterfaceIncludesAppended;
// Cache target output paths for each configuration. // Cache target output paths for each configuration.
struct OutputInfo; struct OutputInfo;
@ -624,6 +643,8 @@ private:
cmTarget *head); cmTarget *head);
cmTargetLinkInformationMap LinkInformation; cmTargetLinkInformationMap LinkInformation;
void CheckPropertyCompatibility(cmComputeLinkInformation *info,
const char* config);
bool ComputeLinkInterface(const char* config, LinkInterface& iface, bool ComputeLinkInterface(const char* config, LinkInterface& iface,
cmTarget *head); cmTarget *head);
@ -649,6 +670,7 @@ private:
cmPolicies::PolicyStatus PolicyStatusCMP0003; cmPolicies::PolicyStatus PolicyStatusCMP0003;
cmPolicies::PolicyStatus PolicyStatusCMP0004; cmPolicies::PolicyStatus PolicyStatusCMP0004;
cmPolicies::PolicyStatus PolicyStatusCMP0008; cmPolicies::PolicyStatus PolicyStatusCMP0008;
cmPolicies::PolicyStatus PolicyStatusCMP0020;
// Internal representation details. // Internal representation details.
friend class cmTargetInternals; friend class cmTargetInternals;

View File

@ -20,13 +20,11 @@ bool cmTargetCompileDefinitionsCommand
} }
void cmTargetCompileDefinitionsCommand void cmTargetCompileDefinitionsCommand
::HandleImportedTargetInvalidScope(const std::string &scope, ::HandleImportedTarget(const std::string &tgt)
const std::string &tgt)
{ {
cmOStringStream e; cmOStringStream e;
e << "Cannot specify " << scope << " compile definitions for imported " e << "Cannot specify compile definitions for imported target \""
"target \"" << tgt << "\". Compile definitions can only be " << tgt << "\".";
"specified for an imported target in the INTERFACE mode.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
} }

View File

@ -59,7 +59,7 @@ public:
"Specify compile definitions or targets to use when compiling a given " "Specify compile definitions or targets to use when compiling a given "
"target. " "target. "
"The named <target> must have been created by a command such as " "The named <target> must have been created by a command such as "
"add_executable or add_library. " "add_executable or add_library and must not be an IMPORTED target. "
"The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
"the scope of the following arguments. PRIVATE and PUBLIC items will " "the scope of the following arguments. PRIVATE and PUBLIC items will "
"populate the COMPILE_DEFINITIONS property of <target>. PUBLIC and " "populate the COMPILE_DEFINITIONS property of <target>. PUBLIC and "
@ -69,14 +69,16 @@ public:
"INTERFACE_COMPILE_DEFINITIONS from. " "INTERFACE_COMPILE_DEFINITIONS from. "
"Repeated calls for the same <target> append items in the order called." "Repeated calls for the same <target> append items in the order called."
"\n" "\n"
"Arguments to target_compile_definitions may use \"generator "
"expressions\" with the syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
; ;
} }
cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand); cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand);
private: private:
virtual void HandleImportedTargetInvalidScope(const std::string &scope, virtual void HandleImportedTarget(const std::string &tgt);
const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual bool HandleNonTargetArg(std::string &content, virtual bool HandleNonTargetArg(std::string &content,

View File

@ -22,13 +22,11 @@ bool cmTargetIncludeDirectoriesCommand
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand void cmTargetIncludeDirectoriesCommand
::HandleImportedTargetInvalidScope(const std::string &tgt, ::HandleImportedTarget(const std::string &tgt)
const std::string &scope)
{ {
cmOStringStream e; cmOStringStream e;
e << "Cannot specify " << scope << " include directories for imported " e << "Cannot specify include directories for imported target \""
"target \"" << tgt << "\". Include directories can only be " << tgt << "\".";
"specified for an imported target in the INTERFACE mode.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
} }

View File

@ -60,7 +60,7 @@ public:
"Specify include directories or targets to use when compiling a given " "Specify include directories or targets to use when compiling a given "
"target. " "target. "
"The named <target> must have been created by a command such as " "The named <target> must have been created by a command such as "
"add_executable or add_library.\n" "add_executable or add_library and must not be an IMPORTED target.\n"
"If BEFORE is specified, the content will be prepended to the property " "If BEFORE is specified, the content will be prepended to the property "
"instead of being appended.\n" "instead of being appended.\n"
"The INTERFACE, PUBLIC and PRIVATE keywords are required to specify " "The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
@ -73,14 +73,16 @@ public:
"directories must be absolute paths, not relative paths. " "directories must be absolute paths, not relative paths. "
"Repeated calls for the same <target> append items in the order called." "Repeated calls for the same <target> append items in the order called."
"\n" "\n"
"Arguments to target_include_directories may use \"generator "
"expressions\" with the syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
; ;
} }
cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand); cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand);
private: private:
virtual void HandleImportedTargetInvalidScope(const std::string &tgt, virtual void HandleImportedTarget(const std::string &tgt);
const std::string &scope);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual bool HandleNonTargetArg(std::string &content, virtual bool HandleNonTargetArg(std::string &content,

View File

@ -33,10 +33,6 @@ bool cmTargetLinkLibrariesCommand
this->Target = this->Target =
this->Makefile->GetCMakeInstance() this->Makefile->GetCMakeInstance()
->GetGlobalGenerator()->FindTarget(0, args[0].c_str()); ->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
if(!this->Target)
{
this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
}
if(!this->Target) if(!this->Target)
{ {
cmake::MessageType t = cmake::FATAL_ERROR; // fail by default cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
@ -261,16 +257,6 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
// Handle normal case first. // Handle normal case first.
if(this->CurrentProcessingState != ProcessingLinkInterface) if(this->CurrentProcessingState != ProcessingLinkInterface)
{ {
if (this->Target->IsImported())
{
cmOStringStream e;
e << "Imported targets may only be used with the "
"LINK_INTERFACE_LIBRARIES specifier to target_link_libraries.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
this->Makefile this->Makefile
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
if (this->CurrentProcessingState != ProcessingPublicInterface) if (this->CurrentProcessingState != ProcessingPublicInterface)

View File

@ -13,6 +13,7 @@
#define cmTargetLinkLibrariesCommand_h #define cmTargetLinkLibrariesCommand_h
#include "cmCommand.h" #include "cmCommand.h"
#include "cmDocumentGeneratorExpressions.h"
/** \class cmTargetLinkLibrariesCommand /** \class cmTargetLinkLibrariesCommand
* \brief Specify a list of libraries to link into executables. * \brief Specify a list of libraries to link into executables.
@ -92,7 +93,9 @@ public:
"linked to this target will appear on the link line for the other " "linked to this target will appear on the link line for the other "
"target too. " "target too. "
"See the LINK_INTERFACE_LIBRARIES target property to override the " "See the LINK_INTERFACE_LIBRARIES target property to override the "
"set of transitive link dependencies for a target." "set of transitive link dependencies for a target. "
"Calls to other signatures of this command may set the property "
"making any libraries linked exclusively by this signature private."
"\n" "\n"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n" " target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n" " [[debug|optimized|general] <lib>] ...)\n"
@ -141,6 +144,12 @@ public:
"However, if two archives are really so interdependent they should " "However, if two archives are really so interdependent they should "
"probably be combined into a single archive." "probably be combined into a single archive."
")" ")"
"\n"
"Arguments to target_link_libraries may use \"generator expressions\" "
"with the syntax \"$<...>\". Note however, that generator expressions "
"will not be used in OLD handling of CMP0003 or CMP0004."
"\n"
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
; ;
} }

View File

@ -65,6 +65,14 @@ bool cmTargetPropCommandBase
return true; return true;
} }
//----------------------------------------------------------------------------
static bool isGeneratorExpression(const std::string &lib)
{
const std::string::size_type openpos = lib.find("$<");
return (openpos != std::string::npos)
&& (lib.find(">", openpos) != std::string::npos);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool cmTargetPropCommandBase bool cmTargetPropCommandBase
::ProcessContentArgs(std::vector<std::string> const& args, ::ProcessContentArgs(std::vector<std::string> const& args,
@ -80,9 +88,9 @@ bool cmTargetPropCommandBase
return false; return false;
} }
if(this->Target->IsImported() && scope != "INTERFACE") if(this->Target->IsImported())
{ {
this->HandleImportedTargetInvalidScope(args[0], scope); this->HandleImportedTarget(args[0]);
return false; return false;
} }
@ -105,6 +113,10 @@ bool cmTargetPropCommandBase
content += sep + "$<TARGET_PROPERTY:" + args[i] content += sep + "$<TARGET_PROPERTY:" + args[i]
+ ",INTERFACE_" + this->Property + ">"; + ",INTERFACE_" + this->Property + ">";
} }
else if(isGeneratorExpression(args[i]))
{
content += sep + args[i];
}
else if (!this->HandleNonTargetArg(content, sep, args[i], args[0])) else if (!this->HandleNonTargetArg(content, sep, args[i], args[0]))
{ {
return false; return false;

View File

@ -14,6 +14,7 @@
#define cmTargetPropCommandBase_h #define cmTargetPropCommandBase_h
#include "cmCommand.h" #include "cmCommand.h"
#include "cmDocumentGeneratorExpressions.h"
class cmTarget; class cmTarget;
@ -31,8 +32,7 @@ public:
const char *prop, ArgumentFlags flags = NO_FLAGS); const char *prop, ArgumentFlags flags = NO_FLAGS);
private: private:
virtual void HandleImportedTargetInvalidScope(const std::string &tgt, virtual void HandleImportedTarget(const std::string &tgt) = 0;
const std::string &scope) = 0;
virtual void HandleMissingTarget(const std::string &name) = 0; virtual void HandleMissingTarget(const std::string &name) = 0;
virtual bool HandleNonTargetArg(std::string &content, virtual bool HandleNonTargetArg(std::string &content,

View File

@ -1221,8 +1221,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.Parse(flags.c_str()); clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str()); clOptions.Parse(defineFlags.c_str());
clOptions.AddDefines( clOptions.AddDefines(
this->GeneratorTarget->GetCompileDefinitions().c_str()); this->Target->GetCompileDefinitions().c_str());
clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions( clOptions.AddDefines(this->Target->GetCompileDefinitions(
configName.c_str()).c_str()); configName.c_str()).c_str());
clOptions.SetVerboseMakefile( clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE")); this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));

View File

@ -3302,6 +3302,12 @@ int cmake::ExecuteLinkScript(std::vector<std::string>& args)
int result = 0; int result = 0;
while(result == 0 && cmSystemTools::GetLineFromStream(fin, command)) while(result == 0 && cmSystemTools::GetLineFromStream(fin, command))
{ {
// Skip empty command lines.
if(command.find_first_not_of(" \t") == command.npos)
{
continue;
}
// Setup this command line. // Setup this command line.
const char* cmd[2] = {command.c_str(), 0}; const char* cmd[2] = {command.c_str(), 0};
cmsysProcess_SetCommand(cp, cmd); cmsysProcess_SetCommand(cp, cmd);
@ -3555,6 +3561,13 @@ void cmake::DefineProperty(const char *name, cmProperty::ScopeType scope,
chained); chained);
} }
bool cmake::GetIsPropertyDefined(const char *name,
cmProperty::ScopeType scope)
{
return this->PropertyDefinitions[scope].find(name) !=
this->PropertyDefinitions[scope].end();
}
cmPropertyDefinition *cmake cmPropertyDefinition *cmake
::GetPropertyDefinition(const char *name, ::GetPropertyDefinition(const char *name,
cmProperty::ScopeType scope) cmProperty::ScopeType scope)
@ -4384,6 +4397,10 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text,
isError = true; isError = true;
msg << "CMake Internal Error (please report a bug)"; msg << "CMake Internal Error (please report a bug)";
} }
else if(t == cmake::LOG)
{
msg << "CMake Debug Log";
}
else else
{ {
msg << "CMake Warning"; msg << "CMake Warning";

View File

@ -341,6 +341,8 @@ class cmake
bool chain = false, bool chain = false,
const char *variableGroup = 0); const char *variableGroup = 0);
bool GetIsPropertyDefined(const char *name, cmProperty::ScopeType scope);
// get property definition // get property definition
cmPropertyDefinition *GetPropertyDefinition cmPropertyDefinition *GetPropertyDefinition
(const char *name, cmProperty::ScopeType scope); (const char *name, cmProperty::ScopeType scope);

View File

@ -574,6 +574,8 @@ IF(KWSYS_USE_SystemTools)
ENDIF() ENDIF()
IF(KWSYS_USE_SystemInformation) IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P})
IF(NOT CYGWIN) IF(NOT CYGWIN)
INCLUDE(CheckIncludeFiles) INCLUDE(CheckIncludeFiles)
CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H) CHECK_INCLUDE_FILES("sys/types.h;ifaddrs.h" KWSYS_SYS_HAS_IFADDRS_H)
@ -603,6 +605,13 @@ IF(KWSYS_USE_SystemInformation)
COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1) COMPILE_DEFINITIONS KWSYS_SYS_HAS_MPCTL_H=1)
ENDIF() ENDIF()
ENDIF() ENDIF()
IF(CMAKE_SYSTEM MATCHES "BSD")
CHECK_INCLUDE_FILES("machine/cpu.h" KWSYS_SYS_HAS_MACHINE_CPU_H)
IF(KWSYS_SYS_HAS_MACHINE_CPU_H)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_SYS_HAS_MACHINE_CPU_H=1)
ENDIF()
ENDIF()
IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE) IF(KWSYS_LFS_AVAILABLE AND NOT KWSYS_LFS_DISABLE)
SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1) SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
ENDIF() ENDIF()
@ -631,6 +640,20 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1) COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
ENDIF() ENDIF()
IF(BORLAND)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM
"Checking whether Borland CXX compiler supports assembler instructions" DIRECT)
IF(KWSYS_CXX_HAS_BORLAND_ASM)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM=1)
KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_BORLAND_ASM_CPUID
"Checking whether Borland CXX compiler supports CPUID assembler instruction" DIRECT)
IF(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS_BORLAND_ASM_CPUID=1)
ENDIF()
ENDIF()
ENDIF()
IF(KWSYS_USE___INT64) IF(KWSYS_USE___INT64)
SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_USE___INT64=1) COMPILE_DEFINITIONS KWSYS_USE___INT64=1)

View File

@ -418,9 +418,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
parse it. */ parse it. */
newCommands[cp->NumberOfCommands] = newCommands[cp->NumberOfCommands] =
kwsysSystem_Parse_CommandForUnix(*command, 0); kwsysSystem_Parse_CommandForUnix(*command, 0);
if(!newCommands[cp->NumberOfCommands]) if(!newCommands[cp->NumberOfCommands] ||
!newCommands[cp->NumberOfCommands][0])
{ {
/* Out of memory. */ /* Out of memory or no command parsed. */
free(newCommands); free(newCommands);
return 0; return 0;
} }

View File

@ -91,6 +91,10 @@ typedef int siginfo_t;
# include <sys/sysctl.h> # include <sys/sysctl.h>
#endif #endif
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
# include <machine/cpu.h>
#endif
#if defined(__DragonFly__) #if defined(__DragonFly__)
# include <sys/sysctl.h> # include <sys/sysctl.h>
#endif #endif
@ -198,7 +202,7 @@ typedef struct rlimit ResourceLimitType;
#define USE_CPUID_INTRINSICS 0 #define USE_CPUID_INTRINSICS 0
#endif #endif
#if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS #if USE_ASM_INSTRUCTIONS || USE_CPUID_INTRINSICS || defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
# define USE_CPUID 1 # define USE_CPUID 1
#else #else
# define USE_CPUID 0 # define USE_CPUID 0
@ -220,6 +224,7 @@ static bool call_cpuid(int select, int result[4])
return true; return true;
#else #else
int tmp[4]; int tmp[4];
#if defined(_MSC_VER)
// Use SEH to determine CPUID presence // Use SEH to determine CPUID presence
__try { __try {
_asm { _asm {
@ -258,7 +263,24 @@ static bool call_cpuid(int select, int result[4])
return false; return false;
} }
memcpy(result, tmp, sizeof(tmp)); memcpy(result, tmp, sizeof(tmp));
#elif defined(KWSYS_CXX_HAS_BORLAND_ASM_CPUID)
unsigned int a, b, c, d;
__asm {
mov EAX, select;
cpuid
mov a, EAX;
mov b, EBX;
mov c, ECX;
mov d, EDX;
}
result[0] = a;
result[1] = b;
result[2] = c;
result[3] = d;
#endif
// The cpuid instruction succeeded. // The cpuid instruction succeeded.
return true; return true;
#endif #endif
@ -428,7 +450,7 @@ protected:
int CPUCount(); int CPUCount();
unsigned char LogicalCPUPerPhysicalCPU(); unsigned char LogicalCPUPerPhysicalCPU();
unsigned char GetAPICId(); unsigned char GetAPICId();
unsigned int IsHyperThreadingSupported(); bool IsHyperThreadingSupported();
static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int); static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int);
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different // For Linux and Cygwin, /proc/cpuinfo formats are slightly different
@ -452,7 +474,8 @@ protected:
kwsys_stl::string SysCtlBuffer; kwsys_stl::string SysCtlBuffer;
// For Solaris // For Solaris
bool QuerySolarisInfo(); bool QuerySolarisMemory();
bool QuerySolarisProcessor();
kwsys_stl::string ParseValueFromKStat(const char* arguments); kwsys_stl::string ParseValueFromKStat(const char* arguments);
kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args); kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args);
@ -477,9 +500,11 @@ protected:
//For AIX //For AIX
bool QueryAIXMemory(); bool QueryAIXMemory();
bool QueryProcessorBySysconf();
bool QueryProcessor(); bool QueryProcessor();
// Evaluate the memory information. // Evaluate the memory information.
bool QueryMemoryBySysconf();
bool QueryMemory(); bool QueryMemory();
size_t TotalVirtualMemory; size_t TotalVirtualMemory;
size_t AvailableVirtualMemory; size_t AvailableVirtualMemory;
@ -1283,7 +1308,7 @@ void SystemInformationImplementation::RunCPUCheck()
#elif defined(__APPLE__) #elif defined(__APPLE__)
this->ParseSysCtl(); this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun) #elif defined (__SVR4) && defined (__sun)
this->QuerySolarisInfo(); this->QuerySolarisProcessor();
#elif defined(__HAIKU__) #elif defined(__HAIKU__)
this->QueryHaikuInfo(); this->QueryHaikuInfo();
#elif defined(__QNX__) #elif defined(__QNX__)
@ -1309,7 +1334,7 @@ void SystemInformationImplementation::RunMemoryCheck()
#if defined(__APPLE__) #if defined(__APPLE__)
this->ParseSysCtl(); this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun) #elif defined (__SVR4) && defined (__sun)
this->QuerySolarisInfo(); this->QuerySolarisMemory();
#elif defined(__HAIKU__) #elif defined(__HAIKU__)
this->QueryHaikuInfo(); this->QueryHaikuInfo();
#elif defined(__QNX__) #elif defined(__QNX__)
@ -3012,7 +3037,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
return true; return true;
} }
bool SystemInformationImplementation::QueryProcessor() bool SystemInformationImplementation::QueryProcessorBySysconf()
{ {
#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN) #if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
// IRIX names this slightly different // IRIX names this slightly different
@ -3026,7 +3051,7 @@ bool SystemInformationImplementation::QueryProcessor()
return false; return false;
} }
this->NumberOfPhysicalCPU = c; this->NumberOfPhysicalCPU = static_cast<unsigned int>(c);
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
return true; return true;
@ -3035,6 +3060,11 @@ bool SystemInformationImplementation::QueryProcessor()
#endif #endif
} }
bool SystemInformationImplementation::QueryProcessor()
{
return this->QueryProcessorBySysconf();
}
/** /**
Get total system RAM in units of KiB. Get total system RAM in units of KiB.
*/ */
@ -3555,8 +3585,7 @@ bool SystemInformationImplementation::QueryAIXMemory()
#endif #endif
} }
/** Query for the memory status */ bool SystemInformationImplementation::QueryMemoryBySysconf()
bool SystemInformationImplementation::QueryMemory()
{ {
#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE) #if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
// Assume the mmap() granularity as returned by _SC_PAGESIZE is also // Assume the mmap() granularity as returned by _SC_PAGESIZE is also
@ -3593,6 +3622,12 @@ bool SystemInformationImplementation::QueryMemory()
#endif #endif
} }
/** Query for the memory status */
bool SystemInformationImplementation::QueryMemory()
{
return this->QueryMemoryBySysconf();
}
/** */ /** */
size_t SystemInformationImplementation::GetTotalVirtualMemory() size_t SystemInformationImplementation::GetTotalVirtualMemory()
{ {
@ -3725,8 +3760,13 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
/** Works only for windows */ /** Works only for windows */
unsigned int SystemInformationImplementation::IsHyperThreadingSupported() bool SystemInformationImplementation::IsHyperThreadingSupported()
{ {
if (this->Features.ExtendedFeatures.SupportsHyperthreading)
{
return true;
}
#if USE_CPUID #if USE_CPUID
int Regs[4] = { 0, 0, 0, 0 }, int Regs[4] = { 0, 0, 0, 0 },
VendorId[4] = { 0, 0, 0, 0 }; VendorId[4] = { 0, 0, 0, 0 };
@ -3744,13 +3784,15 @@ unsigned int SystemInformationImplementation::IsHyperThreadingSupported()
if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID)) if (((Regs[0] & FAMILY_ID) == PENTIUM4_ID) || (Regs[0] & EXT_FAMILY_ID))
{ {
if (VendorId[1] == 'uneG') if (VendorId[1] == 0x756e6547) // 'uneG'
{ {
if (VendorId[3] == 'Ieni') if (VendorId[3] == 0x49656e69) // 'Ieni'
{ {
if (VendorId[2] == 'letn') if (VendorId[2] == 0x6c65746e) // 'letn'
{ {
return(Regs[3] & HT_BIT); // Genuine Intel with hyper-Threading technology // Genuine Intel with hyper-Threading technology
this->Features.ExtendedFeatures.SupportsHyperthreading = ((Regs[3] & HT_BIT) != 0);
return this->Features.ExtendedFeatures.SupportsHyperthreading;
} }
} }
} }
@ -4000,6 +4042,81 @@ bool SystemInformationImplementation::ParseSysCtl()
len = sizeof(value); len = sizeof(value);
err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0); err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0);
this->ChipID.Model = static_cast< int >( value ); this->ChipID.Model = static_cast< int >( value );
// Chip Stepping
len = sizeof(value);
value = 0;
err = sysctlbyname("machdep.cpu.stepping", &value, &len, NULL, 0);
if (!err)
{
this->ChipID.Revision = static_cast< int >( value );
}
// feature string
char *buf = 0;
size_t allocSize = 128;
err = 0;
len = 0;
// sysctlbyname() will return with err==0 && len==0 if the buffer is too small
while (err == 0 && len == 0)
{
delete[] buf;
allocSize *= 2;
buf = new char[allocSize];
if (!buf)
{
break;
}
buf[0] = ' ';
len = allocSize - 2; // keep space for leading and trailing space
err = sysctlbyname("machdep.cpu.features", buf + 1, &len, NULL, 0);
}
if (!err && buf && len)
{
// now we can match every flags as space + flag + space
buf[len + 1] = ' ';
kwsys_stl::string cpuflags(buf, len + 2);
if ((cpuflags.find(" FPU ")!=kwsys_stl::string::npos))
{
this->Features.HasFPU = true;
}
if ((cpuflags.find(" TSC ")!=kwsys_stl::string::npos))
{
this->Features.HasTSC = true;
}
if ((cpuflags.find(" MMX ")!=kwsys_stl::string::npos))
{
this->Features.HasMMX = true;
}
if ((cpuflags.find(" SSE ")!=kwsys_stl::string::npos))
{
this->Features.HasSSE = true;
}
if ((cpuflags.find(" SSE2 ")!=kwsys_stl::string::npos))
{
this->Features.HasSSE2 = true;
}
if ((cpuflags.find(" APIC ")!=kwsys_stl::string::npos))
{
this->Features.HasAPIC = true;
}
if ((cpuflags.find(" CMOV ")!=kwsys_stl::string::npos))
{
this->Features.HasCMOV = true;
}
if ((cpuflags.find(" MTRR ")!=kwsys_stl::string::npos))
{
this->Features.HasMTRR = true;
}
if ((cpuflags.find(" ACPI ")!=kwsys_stl::string::npos))
{
this->Features.HasACPI = true;
}
}
delete[] buf;
} }
// brand string // brand string
@ -4059,13 +4176,12 @@ kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<
char* data = NULL; char* data = NULL;
int length; int length;
double timeout = 255; double timeout = 255;
int pipe; // pipe id as returned by kwsysProcess_WaitForData()
while(kwsysProcess_WaitForData(gp,&data,&length,&timeout)) // wait for 1s while( ( pipe = kwsysProcess_WaitForData(gp,&data,&length,&timeout),
(pipe == kwsysProcess_Pipe_STDOUT || pipe == kwsysProcess_Pipe_STDERR) ) ) // wait for 1s
{ {
for(int i=0;i<length;i++) buffer.append(data, length);
{
buffer += data[i];
}
} }
kwsysProcess_WaitForExit(gp, 0); kwsysProcess_WaitForExit(gp, 0);
@ -4173,16 +4289,40 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
return value; return value;
} }
/** Querying for system information from Solaris */ /** Querying for system information from Solaris */
bool SystemInformationImplementation::QuerySolarisInfo() bool SystemInformationImplementation::QuerySolarisMemory()
{ {
// Parse values #if defined (__SVR4) && defined (__sun)
this->NumberOfPhysicalCPU = static_cast<unsigned int>( // Solaris allows querying this value by sysconf, but if this is
atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str())); // a 32 bit process on a 64 bit host the returned memory will be
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU; // limited to 4GiB. So if this is a 32 bit process or if the sysconf
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1; // method fails use the kstat interface.
#if SIZEOF_VOID_P == 8
if (this->QueryMemoryBySysconf())
{
return true;
}
#endif
char* tail;
unsigned long totalMemory =
strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0);
this->TotalPhysicalMemory = totalMemory/128;
return true;
#else
return false;
#endif
}
bool SystemInformationImplementation::QuerySolarisProcessor()
{
if (!this->QueryProcessorBySysconf())
{
return false;
}
// Parse values
this->CPUSpeedInMHz = static_cast<float>(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str())); this->CPUSpeedInMHz = static_cast<float>(atoi(this->ParseValueFromKStat("-s clock_MHz").c_str()));
// Chip family // Chip family
@ -4199,20 +4339,6 @@ bool SystemInformationImplementation::QuerySolarisInfo()
this->FindManufacturer(); this->FindManufacturer();
} }
// Cache size
this->Features.L1CacheSize = 0;
this->Features.L2CacheSize = 0;
char* tail;
unsigned long totalMemory =
strtoul(this->ParseValueFromKStat("-s physmem").c_str(),&tail,0);
this->TotalPhysicalMemory = totalMemory/128;
// Undefined values (for now at least)
this->TotalVirtualMemory = 0;
this->AvailablePhysicalMemory = 0;
this->AvailableVirtualMemory = 0;
return true; return true;
} }
@ -4424,6 +4550,45 @@ bool SystemInformationImplementation::QueryBSDProcessor()
this->CPUSpeedInMHz = (float) k; this->CPUSpeedInMHz = (float) k;
#endif #endif
#if defined(CPU_SSE)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE;
if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
{
return false;
}
this->Features.HasSSE = (k > 0);
#endif
#if defined(CPU_SSE2)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_SSE2;
if (sysctl(ctrl, 2, &k, &sz, NULL, 0) != 0)
{
return false;
}
this->Features.HasSSE2 = (k > 0);
#endif
#if defined(CPU_CPUVENDOR)
ctrl[0] = CTL_MACHDEP;
ctrl[1] = CPU_CPUVENDOR;
char vbuf[25];
::memset(vbuf, 0, sizeof(vbuf));
sz = sizeof(vbuf) - 1;
if (sysctl(ctrl, 2, vbuf, &sz, NULL, 0) != 0)
{
return false;
}
this->ChipID.Vendor = vbuf;
this->FindManufacturer();
#endif
return true; return true;
#else #else
return false; return false;

View File

@ -580,3 +580,30 @@ int main()
} }
} }
#endif #endif
#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM
int main()
{
int a = 1;
__asm {
xor EBX, EBX;
mov a, EBX;
}
return a;
}
#endif
#ifdef TEST_KWSYS_CXX_HAS_BORLAND_ASM_CPUID
int main()
{
int a = 0;
__asm {
xor EAX, EAX;
cpuid;
mov a, EAX;
}
return a;
}
#endif

View File

@ -12,15 +12,12 @@ target_compile_definitions(target_compile_definitions
INTERFACE MY_INTERFACE_DEFINE INTERFACE MY_INTERFACE_DEFINE
) )
add_library(importedlib UNKNOWN IMPORTED)
target_compile_definitions(importedlib
INTERFACE MY_IMPORTEDINTERFACE_DEFINE
)
add_executable(consumer add_executable(consumer
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
) )
target_compile_definitions(consumer target_compile_definitions(consumer
PRIVATE target_compile_definitions importedlib PRIVATE target_compile_definitions importedlib
$<$<TARGET_DEFINED:notdefined>:SHOULD_NOT_BE_DEFINED>
$<$<TARGET_DEFINED:target_compile_definitions>:SHOULD_BE_DEFINED>
) )

View File

@ -11,8 +11,12 @@
#error Expected MY_INTERFACE_DEFINE #error Expected MY_INTERFACE_DEFINE
#endif #endif
#ifndef MY_IMPORTEDINTERFACE_DEFINE #ifdef SHOULD_NOT_BE_DEFINED
#error Expected MY_IMPORTEDINTERFACE_DEFINE #error Unexpected SHOULD_NOT_BE_DEFINED
#endif
#ifndef SHOULD_BE_DEFINED
#error Expected SHOULD_BE_DEFINED
#endif #endif
int main() { return 0; } int main() { return 0; }

View File

@ -11,9 +11,6 @@ file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/publicinclude/publicinclude.h" "#define
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/interfaceinclude/interfaceinclude.h" "#define INTERFACEINCLUDE_DEFINE\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude/importedinterfaceinclude.h" "#define IMPORTEDINTERFACEINCLUDE_DEFINE\n")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison") file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/poison")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/poison/common.h" "#error Should not be included\n")
@ -33,12 +30,12 @@ target_include_directories(target_include_directories
PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison" PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/poison"
) )
target_include_directories(target_include_directories target_include_directories(target_include_directories
BEFORE PUBLIC "${CMAKE_CURRENT_BINARY_DIR}/cure" BEFORE PUBLIC "$<$<TARGET_DEFINED:target_include_directories>:${CMAKE_CURRENT_BINARY_DIR}/cure>"
) )
add_library(importedlib UNKNOWN IMPORTED) # Has no effect because the target is not defined:
target_include_directories(importedlib target_include_directories(target_include_directories
INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude" BEFORE PUBLIC "$<$<TARGET_DEFINED:notdefined>:${CMAKE_CURRENT_BINARY_DIR}/poison>"
) )
add_executable(consumer add_executable(consumer
@ -46,5 +43,5 @@ add_executable(consumer
) )
target_include_directories(consumer target_include_directories(consumer
PRIVATE target_include_directories importedlib PRIVATE target_include_directories
) )

View File

@ -2,7 +2,6 @@
#include "common.h" #include "common.h"
#include "publicinclude.h" #include "publicinclude.h"
#include "interfaceinclude.h" #include "interfaceinclude.h"
#include "importedinterfaceinclude.h"
#ifdef PRIVATEINCLUDE_DEFINE #ifdef PRIVATEINCLUDE_DEFINE
#error Unexpected PRIVATEINCLUDE_DEFINE #error Unexpected PRIVATEINCLUDE_DEFINE
@ -16,10 +15,6 @@
#error Expected INTERFACEINCLUDE_DEFINE #error Expected INTERFACEINCLUDE_DEFINE
#endif #endif
#ifndef IMPORTEDINTERFACEINCLUDE_DEFINE
#error Expected IMPORTEDINTERFACEINCLUDE_DEFINE
#endif
#ifndef CURE_DEFINE #ifndef CURE_DEFINE
#error Expected CURE_DEFINE #error Expected CURE_DEFINE
#endif #endif

View File

@ -29,9 +29,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(depA SHARED depA.cpp) add_library(depA SHARED depA.cpp)
generate_export_header(depA) generate_export_header(depA)
add_library(importedlib UNKNOWN IMPORTED)
target_link_libraries(importedlib LINK_INTERFACE_LIBRARIES depA)
add_library(depB SHARED depB.cpp) add_library(depB SHARED depB.cpp)
generate_export_header(depB) generate_export_header(depB)
@ -80,3 +77,13 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp) add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
generate_export_header(depIfaceOnly) generate_export_header(depIfaceOnly)
set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly) set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly)
add_library(depD SHARED depD.cpp)
generate_export_header(depD)
set_property(TARGET depD APPEND PROPERTY
LINK_INTERFACE_LIBRARIES
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depA>
)
add_executable(targetB targetB.cpp)
target_link_libraries(targetB depD)

View File

@ -0,0 +1,13 @@
#include "depD.h"
int DepD::foo()
{
return 0;
}
DepA DepD::getA()
{
DepA a;
return a;
}

View File

@ -0,0 +1,11 @@
#include "depd_export.h"
#include "depA.h"
struct DEPD_EXPORT DepD
{
int foo();
DepA getA();
};

View File

@ -0,0 +1,10 @@
#include "depD.h"
int main(int argc, char **argv)
{
DepD d;
DepA a = d.getA();
return d.foo() + a.foo();
}

View File

@ -216,6 +216,7 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(PolicyScope PolicyScope) ADD_TEST_MACRO(PolicyScope PolicyScope)
ADD_TEST_MACRO(EmptyLibrary EmptyLibrary) ADD_TEST_MACRO(EmptyLibrary EmptyLibrary)
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions) ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
set_tests_properties(EmptyLibrary PROPERTIES set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test") PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test")
ADD_TEST_MACRO(CrossCompile CrossCompile) ADD_TEST_MACRO(CrossCompile CrossCompile)

View File

@ -4,7 +4,8 @@ set(CMAKE_EXECUTABLE "${CMake_BIN_DIR}/cmake")
macro(AddCMakeTest TestName PreArgs) macro(AddCMakeTest TestName PreArgs)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TestName}Test.cmake.in" configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TestName}Test.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" @ONLY IMMEDIATE) "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" @ONLY IMMEDIATE)
add_test(CMake.${TestName} ${CMAKE_EXECUTABLE} ${PreArgs} add_test(NAME CMake.${TestName}
COMMAND ${CMAKE_EXECUTABLE} ${PreArgs}
-P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN}) -P "${CMAKE_CURRENT_BINARY_DIR}/${TestName}Test.cmake" ${ARGN})
endmacro() endmacro()
@ -28,7 +29,7 @@ AddCMakeTest(String "")
AddCMakeTest(Math "") AddCMakeTest(Math "")
AddCMakeTest(CMakeMinimumRequired "") AddCMakeTest(CMakeMinimumRequired "")
AddCMakeTest(CompilerIdVendor "") AddCMakeTest(CompilerIdVendor "")
AddCMakeTest(ProcessorCount "") AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
AddCMakeTest(PushCheckState "") AddCMakeTest(PushCheckState "")
AddCMakeTest(While "") AddCMakeTest(While "")

View File

@ -9,10 +9,17 @@ message("### 3. ProcessorCount(...) function call is emitting output that it sho
message("processor_count='${processor_count}'") message("processor_count='${processor_count}'")
execute_process( execute_process(
COMMAND "@CMAKE_BINARY_DIR@/Source/kwsys/$ENV{CMAKE_CONFIG_TYPE}/cmsysTestsCxx" COMMAND "${KWSYS_TEST_EXE}"
testSystemInformation testSystemInformation
OUTPUT_VARIABLE tsi_out OUTPUT_VARIABLE tsi_out
ERROR_VARIABLE tsi_err) ERROR_VARIABLE tsi_err
RESULT_VARIABLE tsi_res
)
if (tsi_res)
message("executing \"${KWSYS_TEST_EXE}\" failed")
message(FATAL_ERROR "output: ${tsi_res}")
endif ()
string(REGEX REPLACE "(.*)GetNumberOfPhysicalCPU:.([0-9]*)(.*)" "\\2" string(REGEX REPLACE "(.*)GetNumberOfPhysicalCPU:.([0-9]*)(.*)" "\\2"
system_info_processor_count "${tsi_out}") system_info_processor_count "${tsi_out}")

View File

@ -0,0 +1,57 @@
cmake_minimum_required(VERSION 2.8)
project(CompatibleInterface)
include(GenerateExportHeader)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(iface1 empty.cpp)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
BOOL_PROP1
BOOL_PROP2
BOOL_PROP3
BOOL_PROP4
)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING
STRING_PROP1
STRING_PROP2
STRING_PROP3
)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP1 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP2 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP1 prop1)
set_property(TARGET iface1 PROPERTY INTERFACE_STRING_PROP2 prop2)
add_executable(CompatibleInterface main.cpp)
target_link_libraries(CompatibleInterface iface1)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP2 ON)
set_property(TARGET CompatibleInterface PROPERTY BOOL_PROP3 ON)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP2 prop2)
set_property(TARGET CompatibleInterface PROPERTY STRING_PROP3 prop3)
target_compile_definitions(CompatibleInterface
PRIVATE
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP1>>:BOOL_PROP1>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP2>>:BOOL_PROP2>
$<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP3>>:BOOL_PROP3>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP1>,prop1>:STRING_PROP1>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP2>,prop2>:STRING_PROP2>
$<$<STREQUAL:$<TARGET_PROPERTY:STRING_PROP3>,prop3>:STRING_PROP3>
)
add_library(iface2 SHARED iface2.cpp)
generate_export_header(iface2)
# For the LINK_LIBRARIES and related properties, we should not evaluate
# properties defined only in the interface - they should be implicitly zero
set_property(TARGET iface2
APPEND PROPERTY
LINK_INTERFACE_LIBRARIES $<$<BOOL:$<TARGET_PROPERTY:BOOL_PROP4>>:nonexistant>
)
target_link_libraries(CompatibleInterface iface2)

View File

@ -0,0 +1 @@
// no content

View File

@ -0,0 +1,7 @@
#include "iface2.h"
int Iface2::foo()
{
return 0;
}

View File

@ -0,0 +1,13 @@
#ifndef IFACE2_H
#define IFACE2_H
#include "iface2_export.h"
class IFACE2_EXPORT Iface2
{
public:
int foo();
};
#endif

View File

@ -0,0 +1,32 @@
#ifndef BOOL_PROP1
#error Expected BOOL_PROP1
#endif
#ifndef BOOL_PROP2
#error Expected BOOL_PROP2
#endif
#ifndef BOOL_PROP3
#error Expected BOOL_PROP3
#endif
#ifndef STRING_PROP1
#error Expected STRING_PROP1
#endif
#ifndef STRING_PROP2
#error Expected STRING_PROP2
#endif
#ifndef STRING_PROP3
#error Expected STRING_PROP3
#endif
#include "iface2.h"
int main(int argc, char **argv)
{
Iface2 if2;
return if2.foo();
}

View File

@ -158,6 +158,56 @@ set_property(TARGET testLibRequired APPEND PROPERTY
$<INSTALL_INTERFACE:InstallOnly_DEFINE> $<INSTALL_INTERFACE:InstallOnly_DEFINE>
) )
include(GenerateExportHeader)
add_library(testSharedLibRequired SHARED testSharedLibRequired.cpp)
generate_export_header(testSharedLibRequired)
set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_POSITION_INDEPENDENT_CODE ON
)
set_property(TARGET testSharedLibRequired APPEND PROPERTY
INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
)
set_property(TARGET testSharedLibRequired APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_DIR}"
)
set_property(TARGET testSharedLibRequired
APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL CUSTOM_PROP
)
set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_CUSTOM_PROP ON
)
set_property(TARGET testSharedLibRequired
APPEND PROPERTY
COMPATIBLE_INTERFACE_STRING CUSTOM_STRING
)
set_property(TARGET testSharedLibRequired
PROPERTY
INTERFACE_CUSTOM_STRING testcontent
)
add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
)
generate_export_header(testSharedLibDepends)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testSharedLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET testSharedLibDepends APPEND PROPERTY
LINK_INTERFACE_LIBRARIES
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:$<TARGET_NAME:testSharedLibRequired>>
)
# LINK_PRIVATE because the LINK_INTERFACE_LIBRARIES is specified above.
target_link_libraries(testSharedLibDepends LINK_PRIVATE testSharedLibRequired)
install(TARGETS testLibRequired install(TARGETS testLibRequired
testLibIncludeRequired1 testLibIncludeRequired1
testLibIncludeRequired2 testLibIncludeRequired2
@ -165,10 +215,11 @@ install(TARGETS testLibRequired
testLibIncludeRequired4 testLibIncludeRequired4
testLibIncludeRequired5 testLibIncludeRequired5
testLibIncludeRequired6 testLibIncludeRequired6
testSharedLibRequired
EXPORT RequiredExp DESTINATION lib ) EXPORT RequiredExp DESTINATION lib )
install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired) install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib ) install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends) install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
@ -216,9 +267,12 @@ if(WIN32)
install(TARGETS testLib5 RUNTIME DESTINATION bin) install(TARGETS testLib5 RUNTIME DESTINATION bin)
endif() endif()
add_subdirectory(sublib) # For CMAKE_BUILD_INTERFACE_INCLUDES test.
# Export from build tree. # Export from build tree.
export(TARGETS testExe1 testLib1 testLib2 testLib3 export(TARGETS testExe1 testLib1 testLib2 testLib3
testExe2libImp testLib3Imp testLib3ImpDep testExe2libImp testLib3Imp testLib3ImpDep subdirlib
testSharedLibRequired testSharedLibDepends
NAMESPACE bld_ NAMESPACE bld_
FILE ExportBuildTree.cmake FILE ExportBuildTree.cmake
) )

View File

@ -0,0 +1,6 @@
set(CMAKE_BUILD_INTERFACE_INCLUDES ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(subdirlib SHARED subdir.cpp)
generate_export_header(subdirlib)

View File

@ -0,0 +1,7 @@
#include "subdir.h"
int SubDirObject::foo()
{
return 0;
}

View File

@ -0,0 +1,12 @@
#ifndef SUBDIR_H
#define SUBDIR_H
#include "subdirlib_export.h"
struct SUBDIRLIB_EXPORT SubDirObject
{
int foo();
};
#endif

View File

@ -0,0 +1,8 @@
#include "testSharedLibDepends.h"
int TestSharedLibDepends::foo()
{
TestSharedLibRequired req;
return req.foo();
}

View File

@ -0,0 +1,14 @@
#ifndef TESTSHAREDLIBDEPENDS_H
#define TESTSHAREDLIBDEPENDS_H
#include "testsharedlibdepends_export.h"
#include "testSharedLibRequired.h"
struct TESTSHAREDLIBDEPENDS_EXPORT TestSharedLibDepends
{
int foo();
};
#endif

View File

@ -0,0 +1,7 @@
#include "testSharedLibRequired.h"
int TestSharedLibRequired::foo()
{
return 0;
}

View File

@ -0,0 +1,12 @@
#ifndef TESTSHAREDLIBREQUIRED_H
#define TESTSHAREDLIBREQUIRED_H
#include "testsharedlibrequired_export.h"
struct TESTSHAREDLIBREQUIRED_EXPORT TestSharedLibRequired
{
int foo();
};
#endif

View File

@ -157,13 +157,50 @@ endif()
# Test that dependent imported targets have usable # Test that dependent imported targets have usable
# INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES # INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES
add_library(deps_iface deps_iface.cpp) add_executable(deps_iface deps_iface.c)
target_link_libraries(deps_iface testLibsDepends) target_link_libraries(deps_iface testLibDepends)
set_property(TARGET deps_iface APPEND PROPERTY target_include_directories(deps_iface PRIVATE testLibDepends)
COMPILE_DEFINITIONS target_compile_definitions(deps_iface PRIVATE testLibDepends)
$<TARGET_PROPERTY:testLibDepends,INTERFACE_COMPILE_DEFINITIONS>
add_executable(deps_shared_iface deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface testSharedLibDepends)
target_include_directories(deps_shared_iface PRIVATE testSharedLibDepends)
target_compile_definitions(deps_shared_iface
PRIVATE
testSharedLibDepends
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
) )
set_property(TARGET deps_iface APPEND PROPERTY
INCLUDE_DIRECTORIES if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
$<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES> include(CheckCXXCompilerFlag)
check_cxx_compiler_flag(-fPIE run_pic_test)
else()
if (CMAKE_CXX_COMPILER_ID MATCHES "PGI"
OR CMAKE_CXX_COMPILER_ID MATCHES "PathScale"
OR CMAKE_SYSTEM_NAME MATCHES "IRIX64"
OR CMAKE_CXX_COMPILER_ID MATCHES "Intel")
set(run_pic_test 0)
else()
set(run_pic_test 1)
endif()
endif()
if (run_pic_test)
target_compile_definitions(deps_shared_iface PRIVATE CHECK_PIC_WORKS)
endif()
#-----------------------------------------------------------------------------
# Test that targets imported from the build tree have their dependencies
# evaluated correctly. The above already tests the same for the install tree.
add_executable(deps_shared_iface2 deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib)
target_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends bld_subdirlib)
target_compile_definitions(deps_shared_iface2
PRIVATE bld_testSharedLibDepends TEST_SUBDIR_LIB
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
) )

View File

@ -18,7 +18,7 @@
extern int testLibDepends(void); extern int testLibDepends(void);
int main(int,char **) int main()
{ {
return testLibDepends(); return testLibDepends();
} }

View File

@ -0,0 +1,41 @@
#include "testSharedLibDepends.h"
#ifdef CHECK_PIC_WORKS
#if defined(__ELF__) && !defined(__PIC__) && !defined(__PIE__)
#error Expected by INTERFACE_POSITION_INDEPENDENT_CODE property of dependency
#endif
#endif
#ifndef PIC_PROPERTY_IS_ON
#error Expected PIC_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_PROPERTY_IS_ON
#error Expected CUSTOM_PROPERTY_IS_ON
#endif
#ifndef CUSTOM_STRING_IS_MATCH
#error Expected CUSTOM_STRING_IS_MATCH
#endif
#ifdef TEST_SUBDIR_LIB
#include "subdir.h"
#endif
int main(int,char **)
{
TestSharedLibDepends dep;
TestSharedLibRequired req;
#ifdef TEST_SUBDIR_LIB
SubDirObject sdo;
#endif
return dep.foo() + req.foo()
#ifdef TEST_SUBDIR_LIB
+ sdo.foo()
#endif
;
}

View File

@ -50,6 +50,8 @@ if(NOT DEFINED can_build_tutorial_step5)
endif() endif()
endif() endif()
add_custom_target(NonExternalProjectTarget
COMMAND ${CMAKE_COMMAND} -E echo NonExternalProjectTarget)
# Empty projects that test all the known ExternalProject_Add argument key words: # Empty projects that test all the known ExternalProject_Add argument key words:
# #
@ -94,7 +96,7 @@ ExternalProject_Add(${proj}
CVS_REPOSITORY "" CVS_REPOSITORY ""
CVS_MODULE "" CVS_MODULE ""
CVS_TAG "" CVS_TAG ""
DEPENDS "MinimalNoOpProject" DEPENDS "MinimalNoOpProject" NonExternalProjectTarget
DOWNLOAD_COMMAND "" DOWNLOAD_COMMAND ""
INSTALL_COMMAND "" INSTALL_COMMAND ""
PATCH_COMMAND "" PATCH_COMMAND ""

View File

@ -2,15 +2,16 @@ cmake_minimum_required(VERSION 2.8)
project(Qt4Targets) project(Qt4Targets)
cmake_policy(SET CMP0020 NEW)
find_package(Qt4 REQUIRED) find_package(Qt4 REQUIRED)
set(CMAKE_AUTOMOC ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(Qt4Targets WIN32 main.cpp) add_executable(Qt4Targets WIN32 main.cpp)
target_link_libraries(Qt4Targets Qt4::QtGui) target_link_libraries(Qt4Targets Qt4::QtGui)
if (WIN32)
target_link_libraries(Qt4Targets Qt4::qtmain)
endif()
set_property(TARGET Qt4Targets APPEND PROPERTY set_property(TARGET Qt4Targets APPEND PROPERTY
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES> $<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
@ -19,3 +20,21 @@ set_property(TARGET Qt4Targets APPEND PROPERTY
COMPILE_DEFINITIONS COMPILE_DEFINITIONS
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS> $<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
) )
if (WIN32)
if (TARGET Qt4::QAxServer)
add_executable(activeqtexe WIN32 activeqtexe.cpp)
set_property(TARGET activeqtexe PROPERTY QT4_NO_LINK_QTMAIN ON)
target_link_libraries(activeqtexe Qt4::QAxServer Qt4::QtGui)
set_property(TARGET activeqtexe APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET activeqtexe APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:Qt4::QAxServer,INTERFACE_COMPILE_DEFINITIONS>
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
)
endif()
endif()

View File

@ -0,0 +1,36 @@
#include <QApplication>
#ifndef QT_QAXSERVER_LIB
#error Expected QT_QAXSERVER_LIB
#endif
#include <QAxFactory>
class MyObject : public QObject
{
Q_OBJECT
public:
MyObject(QObject *parent = 0)
: QObject(parent)
{
}
};
QAXFACTORY_DEFAULT(MyObject,
"{4dc3f340-a6f7-44e4-a79b-3e9217685fbd}",
"{9ee49617-7d5c-441a-b833-4b068d41d751}",
"{13eca64b-ee2a-4f3c-aa04-5d9d975779a7}",
"{ce947ee3-0403-4fdc-895a-4fe779344b46}",
"{8de435ce-8d2a-46ac-b3b3-cb800d0547c7}");
int main(int argc, char **argv)
{
QApplication app(argc, argv);
QAxFactory::isServer();
return app.exec();
}
#include "activeqtexe.moc"

View File

@ -13,11 +13,14 @@ add_definitions(-DFOO -DSomeDefine="Barx")
# enable relaxed mode so automoc can handle all the special cases: # enable relaxed mode so automoc can handle all the special cases:
set(CMAKE_AUTOMOC_RELAXED_MODE TRUE) set(CMAKE_AUTOMOC_RELAXED_MODE TRUE)
# create an executable and a library target, both requiring automoc: # create an executable and two library targets, each requiring automoc:
add_library(codeeditorLib STATIC codeeditor.cpp) add_library(codeeditorLib STATIC codeeditor.cpp)
add_executable(foo main.cpp calwidget.cpp foo.cpp blub.cpp bar.cpp abc.cpp xyz.cpp yaf.cpp private_slot.cpp) add_library(privateSlot OBJECT private_slot.cpp)
set_target_properties(foo codeeditorLib PROPERTIES AUTOMOC TRUE) add_executable(foo main.cpp calwidget.cpp foo.cpp blub.cpp bar.cpp abc.cpp
xyz.cpp yaf.cpp $<TARGET_OBJECTS:privateSlot>)
set_target_properties(foo codeeditorLib privateSlot PROPERTIES AUTOMOC TRUE)
target_link_libraries(foo codeeditorLib ${QT_LIBRARIES} ) target_link_libraries(foo codeeditorLib ${QT_LIBRARIES} )

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "foo" links to item " bar " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,9 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 NEW)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
target_link_libraries(foo "$<1: bar >")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "bat" links to item " bar " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 OLD)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
add_library(bing SHARED empty.cpp)
add_library(bung SHARED empty.cpp)
cmake_policy(SET CMP0004 NEW)
add_library(bat SHARED empty.cpp)
target_link_libraries(foo "$<1: bar >")
target_link_libraries(bing "$<$<NOT:$<TARGET_POLICY:CMP0004>>: bar >")
target_link_libraries(bung "$<$<TARGET_POLICY:CMP0004>: bar >")
# The line below causes the error because the policy is NEW when bat
# is created.
target_link_libraries(bat "$<1: bar >")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
Target "foo" links to item " bat " which has leading or trailing
whitespace. This is now an error according to policy CMP0004.

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8)
cmake_policy(SET CMP0004 NEW)
add_library(foo SHARED empty.cpp)
add_library(bar SHARED empty.cpp)
add_library(bat SHARED empty.cpp)
# The negation here avoids the error.
target_link_libraries(foo "$<$<NOT:$<TARGET_POLICY:CMP0004>>: bar >")
# The below line causes the error.
target_link_libraries(foo "$<$<TARGET_POLICY:CMP0004>: bat >")

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} NONE)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,5 @@
include(RunCMake)
run_cmake(CMP0004-OLD)
run_cmake(CMP0004-NEW)
run_cmake(CMP0004-policy-genex)

View File

View File

@ -53,12 +53,14 @@ add_RunCMake_test(ObjectLibrary)
if(NOT WIN32) if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode) add_RunCMake_test(PositionIndependentCode)
endif() endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(build_command) add_RunCMake_test(build_command)
add_RunCMake_test(find_package) add_RunCMake_test(find_package)
add_RunCMake_test(include) add_RunCMake_test(include)
add_RunCMake_test(include_directories) add_RunCMake_test(include_directories)
add_RunCMake_test(list) add_RunCMake_test(list)
add_RunCMake_test(CMP0004)
if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]") if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
add_RunCMake_test(include_external_msproject) add_RunCMake_test(include_external_msproject)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 2.8)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,5 @@
CMake Error in CMakeLists.txt:
Target "foo" has property "INCLUDE_DIRECTORIES" listed in its
COMPATIBLE_INTERFACE_BOOL property. This is not allowed. Only
user-defined properties may appear listed in the COMPATIBLE_INTERFACE_BOOL
property.

View File

@ -0,0 +1,11 @@
add_library(foo UNKNOWN IMPORTED)
add_library(bar UNKNOWN IMPORTED)
set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL INCLUDE_DIRECTORIES)
set_property(TARGET foo PROPERTY INTERFACE_INCLUDE_DIRECTORIES ON)
set_property(TARGET bar PROPERTY INTERFACE_INCLUDE_DIRECTORIES ON)
add_executable(user main.cpp)
set_property(TARGET user PROPERTY INCLUDE_DIRECTORIES OFF)
target_link_libraries(user foo bar)

Some files were not shown because too many files have changed in this diff Show More