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
# file for installing a project or library. It helps making the resulting package
# 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
# install destinations know to the using project:
@ -173,11 +175,26 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
else()
set(absInstallDir "${CMAKE_INSTALL_PREFIX}/${CCF_INSTALL_DESTINATION}")
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}" )
foreach(var ${CCF_PATH_VARS})
if(NOT DEFINED ${var})
message(FATAL_ERROR "Variable ${var} does not exist")
else()
if(forceAbsolutePaths)
if(IS_ABSOLUTE "${${var}}")
set(PACKAGE_${var} "${${var}}")
else()
set(PACKAGE_${var} "${CMAKE_INSTALL_PREFIX}/${${var}}")
endif()
else()
if(IS_ABSOLUTE "${${var}}")
string(REPLACE "${CMAKE_INSTALL_PREFIX}" "\${PACKAGE_PREFIX_DIR}"
@ -186,6 +203,7 @@ function(CONFIGURE_PACKAGE_CONFIG_FILE _inputFile _outputFile)
set(PACKAGE_${var} "\${PACKAGE_PREFIX_DIR}/${${var}}")
endif()
endif()
endif()
endforeach()
get_filename_component(inputFileName "${_inputFile}" NAME)

View File

@ -1558,8 +1558,11 @@ function(_ep_add_configure_command name)
set(file_deps)
get_property(deps TARGET ${name} PROPERTY _EP_DEPENDS)
foreach(dep IN LISTS deps)
get_property(is_ep TARGET ${dep} PROPERTY _EP_IS_EXTERNAL_PROJECT)
if(is_ep)
_ep_get_step_stampfile(${dep} "done" done_stamp_file)
list(APPEND file_deps ${done_stamp_file})
endif()
endforeach()
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
# 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
# If this variable is set to TRUE, the Qt include directories
# 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
if(Q_WS_WIN)
_QT4_ADJUST_LIB_VARS(qtmain)
_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)
endif()
@ -1049,6 +1062,21 @@ if (QT_QMAKE_EXECUTABLE AND QTVERSION)
_qt4_add_target_private_depends(phonon DBus)
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

View File

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

View File

@ -37,6 +37,7 @@
"target in the same buildsystem. Expands to the empty string " \
"otherwise.\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_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
"where \"tgt\" is the name of a target. " \
@ -46,9 +47,14 @@
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
"\n" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
"on the target tgt. Note that tgt is not added as a dependency of\n" \
"the target this expression is evaluated on.\n" \
" $<TARGET_PROPERTY:tgt,prop> = The value of the property prop " \
"on the target tgt.\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" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
@ -59,7 +65,7 @@
#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"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" \
""

View File

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

View File

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

View File

@ -21,6 +21,7 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmVersion.h"
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx>
@ -81,16 +82,16 @@ bool cmExportFileGenerator::GenerateImportFile()
// Protect that file against use with older CMake versions.
os << "# Generated by CMake " << cmVersion::GetCMakeVersion() << "\n\n";
os << "IF(\"${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}\" LESS 2.5)\n"
<< " MESSAGE(FATAL_ERROR \"CMake >= 2.6.0 required\")\n"
<< "ENDIF(\"${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"
<< "endif()\n";
// Isolate the file policy level.
// 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
// until the import format changes.
os << "CMAKE_POLICY(PUSH)\n"
<< "CMAKE_POLICY(VERSION 2.6)\n";
os << "cmake_policy(PUSH)\n"
<< "cmake_policy(VERSION 2.6)\n";
// Start with the import file header.
this->GenerateImportHeaderCode(os);
@ -100,14 +101,15 @@ bool cmExportFileGenerator::GenerateImportFile()
// End with the import file footer.
this->GenerateImportFooterCode(os);
os << "CMAKE_POLICY(POP)\n";
os << "cmake_policy(POP)\n";
return result;
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
const char* config)
const char* config,
std::vector<std::string> &missingTargets)
{
// Construct the property configuration suffix.
std::string suffix = "_";
@ -121,7 +123,19 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
}
// 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);
}
//----------------------------------------------------------------------------
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,
std::ostream& os,
@ -173,7 +266,7 @@ void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
{
std::string targetName = this->Namespace;
targetName += target->GetName();
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin();
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
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,
cmTarget* target,
std::vector<std::string> &missingTargets)
@ -212,45 +385,17 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
continue;
}
const std::string targetName = input.substr(nameStartPos,
std::string targetName = input.substr(nameStartPos,
commaPos - nameStartPos);
pos = nameStartPos; // We're not going to replace the entire expression,
// 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
if (!this->AddTargetNamespace(targetName, target, missingTargets))
{
errorString = "$<TARGET_PROPERTY:" + targetName + ",prop> requires "
"its first parameter to be a reachable target.";
}
lastPos = pos;
if (!errorString.empty())
{
break;
}
input.replace(nameStartPos, commaPos - nameStartPos, targetName);
lastPos = pos + targetName.size();
}
if (!errorString.empty())
{
@ -267,51 +412,24 @@ cmExportFileGenerator::ResolveTargetsInGeneratorExpressions(
if (endPos == input.npos)
{
errorString = "$<TARGET_NAME:...> expression incomplete";
break;
}
const std::string targetName = input.substr(nameStartPos,
std::string targetName = input.substr(nameStartPos,
endPos - nameStartPos);
if(targetName.find("$<", lastPos) != input.npos)
if(targetName.find("$<") != input.npos)
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"literal.";
break;
}
if (cmTarget *tgt = mf->FindTargetToUse(targetName.c_str()))
{
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
if (!this->AddTargetNamespace(targetName, target, missingTargets))
{
errorString = "$<TARGET_NAME:...> requires its parameter to be a "
"reachable target.";
}
lastPos = pos;
if (!errorString.empty())
{
break;
}
input.replace(pos, endPos - pos + 1, targetName);
lastPos = endPos;
}
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
cmExportFileGenerator
@ -363,9 +539,7 @@ cmExportFileGenerator
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
iface->Languages, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
iface->Libraries, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
iface->SharedDeps, properties, missingTargets);
@ -397,9 +571,6 @@ cmExportFileGenerator
return;
}
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->GetMakefile();
// Construct the property value.
std::string link_libs;
const char* sep = "";
@ -410,33 +581,9 @@ cmExportFileGenerator
link_libs += sep;
sep = ";";
// Append this entry.
if(cmTarget* tgt = mf->FindTargetToUse(li->c_str()))
{
// 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;
}
std::string temp = *li;
this->AddTargetNamespace(temp, target, missingTargets);
link_libs += temp;
}
// Store the property.
@ -469,7 +616,7 @@ void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
void cmExportFileGenerator::GenerateImportFooterCode(std::ostream& os)
{
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
// format later while still allowing old import files to work.
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";
}
@ -486,31 +633,31 @@ void cmExportFileGenerator::GenerateImportVersionCode(std::ostream& os)
void cmExportFileGenerator::GenerateExpectedTargetsCode(std::ostream& os,
const std::string &expectedTargets)
{
os << "SET(_targetsDefined)\n"
"SET(_targetsNotDefined)\n"
"SET(_expectedTargets)\n"
"FOREACH(_expectedTarget " << expectedTargets << ")\n"
" LIST(APPEND _expectedTargets ${_expectedTarget})\n"
" IF(NOT TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsNotDefined ${_expectedTarget})\n"
" ENDIF(NOT TARGET ${_expectedTarget})\n"
" IF(TARGET ${_expectedTarget})\n"
" LIST(APPEND _targetsDefined ${_expectedTarget})\n"
" ENDIF(TARGET ${_expectedTarget})\n"
"ENDFOREACH(_expectedTarget)\n"
"IF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
" SET(CMAKE_IMPORT_FILE_VERSION)\n"
" CMAKE_POLICY(POP)\n"
" RETURN()\n"
"ENDIF(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
"IF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
" MESSAGE(FATAL_ERROR \"Some (but not all) targets in this export "
os << "set(_targetsDefined)\n"
"set(_targetsNotDefined)\n"
"set(_expectedTargets)\n"
"foreach(_expectedTarget " << expectedTargets << ")\n"
" list(APPEND _expectedTargets ${_expectedTarget})\n"
" if(NOT TARGET ${_expectedTarget})\n"
" list(APPEND _targetsNotDefined ${_expectedTarget})\n"
" endif()\n"
" if(TARGET ${_expectedTarget})\n"
" list(APPEND _targetsDefined ${_expectedTarget})\n"
" endif()\n"
"endforeach()\n"
"if(\"${_targetsDefined}\" STREQUAL \"${_expectedTargets}\")\n"
" set(CMAKE_IMPORT_FILE_VERSION)\n"
" cmake_policy(POP)\n"
" return()\n"
"endif()\n"
"if(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
" message(FATAL_ERROR \"Some (but not all) targets in this export "
"set were already defined.\\nTargets Defined: ${_targetsDefined}\\n"
"Targets not yet defined: ${_targetsNotDefined}\\n\")\n"
"ENDIF(NOT \"${_targetsDefined}\" STREQUAL \"\")\n"
"UNSET(_targetsDefined)\n"
"UNSET(_targetsNotDefined)\n"
"UNSET(_expectedTargets)\n"
"endif()\n"
"unset(_targetsDefined)\n"
"unset(_targetsNotDefined)\n"
"unset(_expectedTargets)\n"
"\n\n";
}
//----------------------------------------------------------------------------
@ -527,16 +674,16 @@ cmExportFileGenerator
switch(target->GetType())
{
case cmTarget::EXECUTABLE:
os << "ADD_EXECUTABLE(" << targetName << " IMPORTED)\n";
os << "add_executable(" << targetName << " IMPORTED)\n";
break;
case cmTarget::STATIC_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " STATIC IMPORTED)\n";
os << "add_library(" << targetName << " STATIC IMPORTED)\n";
break;
case cmTarget::SHARED_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " SHARED IMPORTED)\n";
os << "add_library(" << targetName << " SHARED IMPORTED)\n";
break;
case cmTarget::MODULE_LIBRARY:
os << "ADD_LIBRARY(" << targetName << " MODULE IMPORTED)\n";
os << "add_library(" << targetName << " MODULE IMPORTED)\n";
break;
default: // should never happen
break;
@ -545,27 +692,27 @@ cmExportFileGenerator
// Mark the imported executable if it has exports.
if(target->IsExecutableWithExports())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY ENABLE_EXPORTS 1)\n";
}
// Mark the imported library if it is a framework.
if(target->IsFrameworkOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY FRAMEWORK 1)\n";
}
// Mark the imported executable if it is an application bundle.
if(target->IsAppBundleOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY MACOSX_BUNDLE 1)\n";
}
if (target->IsCFBundleOnApple())
{
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " PROPERTY BUNDLE 1)\n";
}
os << "\n";
@ -585,7 +732,7 @@ cmExportFileGenerator
// Set the import properties.
os << "# Import target \"" << targetName << "\" for configuration \""
<< config << "\"\n";
os << "SET_PROPERTY(TARGET " << targetName
os << "set_property(TARGET " << targetName
<< " APPEND PROPERTY IMPORTED_CONFIGURATIONS ";
if(config && *config)
{
@ -596,7 +743,7 @@ cmExportFileGenerator
os << "NOCONFIG";
}
os << ")\n";
os << "SET_TARGET_PROPERTIES(" << targetName << " PROPERTIES\n";
os << "set_target_properties(" << targetName << " PROPERTIES\n";
for(ImportPropertyMap::const_iterator pi = properties.begin();
pi != properties.end(); ++pi)
{
@ -611,21 +758,29 @@ cmExportFileGenerator
void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
const std::vector<std::string>& missingTargets)
{
if (missingTargets.empty())
{
return;
}
os << "# Make sure the targets which have been exported in some other \n"
"# export set exist.\n";
std::set<std::string> emitted;
for(unsigned int i=0; i<missingTargets.size(); ++i)
{
os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
<< " IF(CMAKE_FIND_PACKAGE_NAME)\n"
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
<< " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
if (emitted.insert(missingTargets[i]).second)
{
os << "if(NOT TARGET \"" << missingTargets[i] << "\" )\n"
<< " if(CMAKE_FIND_PACKAGE_NAME)\n"
<< " set( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
<< " set( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
<< "\"Required imported target \\\"" << missingTargets[i]
<< "\\\" not found ! \")\n"
<< " ELSE()\n"
<< " MESSAGE(FATAL_ERROR \"Required imported target \\\""
<< " else()\n"
<< " message(FATAL_ERROR \"Required imported target \\\""
<< missingTargets[i] << "\\\" not found ! \")\n"
<< " ENDIF()\n"
<< "ENDIF()\n";
<< " endif()\n"
<< "endif()\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,
// but the development package was not installed.).
os << "# Loop over all imported files and verify that they actually exist\n"
"FOREACH(target ${_IMPORT_CHECK_TARGETS} )\n"
" FOREACH(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
" IF(NOT EXISTS \"${file}\" )\n"
" MESSAGE(FATAL_ERROR \"The imported target \\\"${target}\\\""
"foreach(target ${_IMPORT_CHECK_TARGETS} )\n"
" foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )\n"
" if(NOT EXISTS \"${file}\" )\n"
" message(FATAL_ERROR \"The imported target \\\"${target}\\\""
" references the file\n"
" \\\"${file}\\\"\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"
"but not all the files it references.\n"
"\")\n"
" ENDIF()\n"
" ENDFOREACH()\n"
" UNSET(_IMPORT_CHECK_FILES_FOR_${target})\n"
"ENDFOREACH()\n"
"UNSET(_IMPORT_CHECK_TARGETS)\n"
" endif()\n"
" endforeach()\n"
" unset(_IMPORT_CHECK_FILES_FOR_${target})\n"
"endforeach()\n"
"unset(_IMPORT_CHECK_TARGETS)\n"
"\n";
}
@ -676,8 +831,8 @@ cmExportFileGenerator
std::string targetName = this->Namespace;
targetName += target->GetName();
os << "LIST(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"LIST(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
os << "list(APPEND _IMPORT_CHECK_TARGETS " << targetName << " )\n"
"list(APPEND _IMPORT_CHECK_FILES_FOR_" << targetName << " ";
for(std::set<std::string>::const_iterator li = importedLocations.begin();
li != importedLocations.end();

View File

@ -47,7 +47,8 @@ protected:
// Generate per-configuration target information to the given output
// 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.
void GenerateImportHeaderCode(std::ostream& os, const char* config = 0);
@ -85,7 +86,8 @@ protected:
/** Each subclass knows where the target files are located. */
virtual void GenerateImportTargetsConfig(std::ostream& os,
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
* export set. */
@ -99,12 +101,27 @@ protected:
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties,
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,
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,
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.
std::string Namespace;
@ -128,6 +145,13 @@ private:
cmGeneratorExpression::PreprocessContext,
ImportPropertyMap &properties,
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

View File

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

View File

@ -56,7 +56,8 @@ protected:
virtual bool GenerateMainFile(std::ostream& os);
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
std::string const& suffix);
std::string const& suffix,
std::vector<std::string> &missingTargets);
virtual void HandleMissingTarget(std::string& link_libs,
std::vector<std::string>& missingTargets,
cmMakefile* mf,
@ -72,7 +73,8 @@ protected:
/** 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. */
void SetImportLocationProperty(const char* config,

View File

@ -621,7 +621,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
->GetGeneratorTarget(target);
// the compilerdefines for this target
std::string cdefs = gtgt->GetCompileDefinitions();
std::string cdefs = target->GetCompileDefinitions();
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
std::string outputDirectory = this->Makefile->GetCurrentOutputDirectory();
{
// Some of the generated files are *.h so the directory "GUI"
// 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);
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)
{
@ -186,7 +218,7 @@ static std::string stripAllGeneratorExpressions(const std::string &input)
lastPos = pos;
}
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);
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,
PreprocessContext context);
static void Split(const std::string &input,
std::vector<std::string> &output);
private:
cmGeneratorExpression(const cmGeneratorExpression &);
void operator=(const cmGeneratorExpression &);

View File

@ -106,3 +106,22 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
}
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,
const std::string &expr);
bool EvaluatingLinkLibraries();
private:
Result checkGraph() const;

View File

@ -289,6 +289,22 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} 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[] = {
"INTERFACE_INCLUDE_DIRECTORIES"
@ -426,6 +442,34 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
const char *prop = target->GetProperty(propertyName.c_str());
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();
}
@ -471,6 +515,105 @@ static const struct TargetNameNode : public cmGeneratorExpressionNode
} 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>
struct TargetFilesystemArtifactResultCreator
@ -698,10 +841,14 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetPropertyNode;
else if (identifier == "TARGET_NAME")
return &targetNameNode;
else if (identifier == "TARGET_POLICY")
return &targetPolicyNode;
else if (identifier == "BUILD_INTERFACE")
return &buildInterfaceNode;
else if (identifier == "INSTALL_INTERFACE")
return &installInterfaceNode;
else if (identifier == "TARGET_DEFINED")
return &targetDefinedNode;
return 0;
}

View File

@ -254,32 +254,3 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories(
{
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. */
std::vector<std::string> GetIncludeDirectories(const char *config);
std::string GetCompileDefinitions(const char *config = 0);
private:
void ClassifySources();
void LookupObjectLibraries();

View File

@ -941,19 +941,7 @@ void cmGlobalGenerator::Generate()
for ( tit = targets->begin(); tit != targets->end(); ++ tit )
{
if (mf->IsOn("CMAKE_BUILD_INTERFACE_INCLUDES"))
{
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());
}
}
tit->second.AppendBuildInterfaceIncludes();
}
}
@ -992,6 +980,7 @@ void cmGlobalGenerator::Generate()
// Generate project files
for (i = 0; i < this->LocalGenerators.size(); ++i)
{
this->LocalGenerators[i]->GetMakefile()->SetGeneratingBuildSystem();
this->SetCurrentLocalGenerator(this->LocalGenerators[i]);
this->LocalGenerators[i]->Generate();
this->LocalGenerators[i]->GenerateInstallRules();
@ -1075,7 +1064,8 @@ void cmGlobalGenerator::CreateAutomocTargets()
if(target.GetType() == cmTarget::EXECUTABLE ||
target.GetType() == cmTarget::STATIC_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())
{

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)
std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
std::string& flags)
{
std::string retFlag;
std::string::size_type pos = flags.rfind(flag);
std::string::size_type lastOccurancePos = flags.rfind(flag);
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]==' ')
{
while(pos < flags.size() && flags[pos] != ' ')
@ -1388,9 +1390,12 @@ std::string cmGlobalXCodeGenerator::ExtractFlag(const char* flag,
flags[pos] = ' ';
pos++;
}
}
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;
}
@ -1676,11 +1681,11 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
this->AppendDefines(ppDefs, exportMacro);
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str());
this->AppendDefines(ppDefs, target.GetCompileDefinitions().c_str());
if(configName)
{
this->AppendDefines(ppDefs,
gtgt->GetCompileDefinitions(configName).c_str());
target.GetCompileDefinitions(configName).c_str());
}
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());

View File

@ -36,6 +36,10 @@ bool cmIncludeDirectoryCommand
++i;
}
std::vector<std::string> beforeIncludes;
std::vector<std::string> afterIncludes;
std::set<cmStdString> systemIncludes;
for(; i != args.end(); ++i)
{
if(*i == "SYSTEM")
@ -49,9 +53,37 @@ bool cmIncludeDirectoryCommand
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;
}
@ -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
// always happen
//
void cmIncludeDirectoryCommand::AddDirectory(const char *i,
bool before,
bool system)
void cmIncludeDirectoryCommand::GetIncludes(const std::string &arg,
std::vector<std::string> &incs)
{
// break apart any line feed arguments
std::string ret = i;
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)
{
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)
{
this->AddDirectory(ret.substr(pos+1,ret.size()-pos-1).c_str(),
before, system);
lastPos = pos + 1;
}
return;
std::string inc = arg.substr(lastPos);
NormalizeInclude(inc);
incs.push_back(inc);
}
// remove any leading or trailing spaces and \r
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))
void cmIncludeDirectoryCommand::NormalizeInclude(std::string &inc)
{
ret.assign(ret, b, 1+e-b); // copy the remaining substring
}
else
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))
{
return; // if we get here, we had only whitespace in the string
inc.assign(inc, b, 1+e-b); // copy the remaining substring
}
if (!cmSystemTools::IsOff(ret.c_str()))
if (!cmSystemTools::IsOff(inc.c_str()))
{
cmSystemTools::ConvertToUnixSlashes(ret);
if(!cmSystemTools::FileIsFullPath(ret.c_str()))
cmSystemTools::ConvertToUnixSlashes(inc);
if(!cmSystemTools::FileIsFullPath(inc.c_str()))
{
if(!StartsWithGeneratorExpression(ret))
if(!StartsWithGeneratorExpression(inc))
{
std::string tmp = this->Makefile->GetStartDirectory();
tmp += "/";
tmp += ret;
ret = tmp;
tmp += inc;
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:
// 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> debugrelDefinesSet;
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
this->AppendDefines(
definesSet,
gt->GetCompileDefinitions());
target.GetCompileDefinitions());
this->AppendDefines(
debugDefinesSet,
gt->GetCompileDefinitions("DEBUG"));
target.GetCompileDefinitions("DEBUG"));
this->AppendDefines(
releaseDefinesSet,
gt->GetCompileDefinitions("RELEASE"));
target.GetCompileDefinitions("RELEASE"));
this->AppendDefines(
minsizeDefinesSet,
gt->GetCompileDefinitions("MINSIZEREL"));
target.GetCompileDefinitions("MINSIZEREL"));
this->AppendDefines(
debugrelDefinesSet,
gt->GetCompileDefinitions("RELWITHDEBINFO"));
target.GetCompileDefinitions("RELWITHDEBINFO"));
std::string defines = " ";
std::string debugDefines = " ";

View File

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

View File

@ -99,6 +99,7 @@ cmMakefile::cmMakefile(): Internal(new Internals)
this->AddDefaultDefinitions();
this->Initialize();
this->PreOrder = false;
this->GeneratingBuildSystem = false;
}
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;
}
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 =
before ? this->IncludeDirectoriesEntries.begin()
: this->IncludeDirectoriesEntries.end();
cmListFileBacktrace lfbt;
this->GetBacktrace(lfbt);
IncludeDirectoriesEntry entry(inc, lfbt);
IncludeDirectoriesEntry entry(incString, lfbt);
this->IncludeDirectoriesEntries.insert(position, entry);
// 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;
}
// 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(),
this->GetHomeOutputDirectory()) )
{
@ -2254,8 +2271,8 @@ bool cmMakefile::CanIWriteThisFile(const char* fileName)
return true;
}
// Check if this is subdirectory of the source tree but not a
// subdirectory of a build tree
// Check if this is a subdirectory of the source tree but not a
// subdirectory of the build tree
if ( cmSystemTools::IsSubDirectory(fileName,
this->GetHomeDirectory()) &&
!cmSystemTools::IsSubDirectory(fileName,

View File

@ -287,7 +287,8 @@ public:
/**
* 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
@ -545,7 +546,7 @@ public:
/**
* Mark include directories as system directories.
*/
void AddSystemIncludeDirectory(const char* dir);
void AddSystemIncludeDirectories(const std::set<cmStdString> &incs);
bool IsSystemIncludeDirectory(const char* dir);
/** Expand out any arguements in the vector that have ; separated
@ -869,6 +870,9 @@ public:
return this->IncludeDirectoriesEntries;
}
bool IsGeneratingBuildSystem(){ return this->GeneratingBuildSystem; }
void SetGeneratingBuildSystem(){ this->GeneratingBuildSystem = true; }
protected:
// add link libraries and directories to the target
void AddGlobalLinkInformation(const char* name, cmTarget& target);
@ -1018,6 +1022,9 @@ private:
// Enforce rules about CMakeLists.txt files.
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.
this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions());
(defines, this->Target->GetCompileDefinitions());
this->LocalGenerator->AppendDefines
(defines, this->GeneratorTarget->GetCompileDefinitions(
(defines, this->Target->GetCompileDefinitions(
this->LocalGenerator->ConfigurationName.c_str()));
std::string definesString;

View File

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

View File

@ -508,6 +508,27 @@ cmPolicies::cmPolicies()
"for strict compatibility. "
"The NEW behavior for this policy is to leave the values untouched.",
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()

View File

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

View File

@ -229,7 +229,11 @@ void cmQtAutomoc::SetupAutomocTarget(cmTarget* target)
}
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");
if (tmp)
{

View File

@ -145,11 +145,14 @@ cmTarget::cmTarget()
this->PolicyStatusCMP0003 = cmPolicies::WARN;
this->PolicyStatusCMP0004 = cmPolicies::WARN;
this->PolicyStatusCMP0008 = cmPolicies::WARN;
this->PolicyStatusCMP0020 = cmPolicies::WARN;
this->LinkLibrariesAnalyzed = false;
this->HaveInstallRule = false;
this->DLLPlatform = false;
this->IsApple = 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 "
"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
("POST_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
@ -1485,6 +1512,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->Makefile->GetPolicyStatus(cmPolicies::CMP0004);
this->PolicyStatusCMP0008 =
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->LinkInterfaceMap.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 + ">";
}
//----------------------------------------------------------------------------
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,
const char *target, const char* lib,
@ -2247,13 +2291,19 @@ void cmTarget::AddLinkLibrary(cmMakefile& mf,
cmTarget *tgt = this->Makefile->FindTargetToUse(lib);
const bool isNonImportedTarget = tgt && !tgt->IsImported();
std::string libName = isNonImportedTarget ? targetNameGenex(lib)
const std::string libName = (isNonImportedTarget && llt != GENERAL)
? targetNameGenex(lib)
: std::string(lib);
this->AppendProperty("LINK_LIBRARIES",
this->GetDebugGeneratorExpressions(libName,
llt).c_str());
}
if (isGeneratorExpression(lib))
{
return;
}
cmTarget::LibraryID tmp;
tmp.first = lib;
tmp.second = llt;
@ -2654,6 +2704,30 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
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,
bool before)
@ -2688,11 +2762,17 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
}
bool debugIncludes = std::find(debugProperties.begin(),
bool debugIncludes = !this->DebugIncludesDone
&& std::find(debugProperties.begin(),
debugProperties.end(),
"INCLUDE_DIRECTORIES")
!= debugProperties.end();
if (this->Makefile->IsGeneratingBuildSystem())
{
this->DebugIncludesDone = true;
}
for (std::vector<cmTargetInternals::IncludeDirectoriesEntry*>::const_iterator
it = this->Internal->IncludeDirectoriesEntries.begin(),
end = this->Internal->IncludeDirectoriesEntries.end();
@ -2727,13 +2807,42 @@ std::vector<std::string> cmTarget::GetIncludeDirectories(const char *config)
if (!usedIncludes.empty())
{
this->Makefile->GetCMakeInstance()->IssueMessage(cmake::LOG,
"Used includes:\n" + usedIncludes,
(*it)->ge->GetBacktrace());
"Used includes for target " + this->Name + ":\n"
+ usedIncludes, (*it)->ge->GetBacktrace());
}
}
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)
{
@ -4431,22 +4540,69 @@ void cmTarget::AddLinkDependentTargetsForProperties(
}
//----------------------------------------------------------------------------
bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config)
template<typename PropertyType>
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());
const bool explicitlySet = this->GetProperties()
return tgt->GetPropertyAsBool(prop);
}
//----------------------------------------------------------------------------
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())
!= this->GetProperties().end();
!= tgt->GetProperties().end();
std::set<std::string> dependentTargets;
this->GetLinkDependentTargetsForProperty(p,
tgt->GetLinkDependentTargetsForProperty(p,
dependentTargets);
const bool impliedByUse =
this->IsNullImpliedByLinkLibraries(p);
tgt->IsNullImpliedByLinkLibraries(p);
assert((impliedByUse ^ explicitlySet)
|| (!impliedByUse && !explicitlySet));
cmComputeLinkInformation *info = this->GetLinkInformation(config);
cmComputeLinkInformation *info = tgt->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
bool propInitialized = explicitlySet;
@ -4468,20 +4624,22 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
const bool ifaceIsSet = li->Target->GetProperties()
.find("INTERFACE_" + p)
!= li->Target->GetProperties().end();
const bool ifacePropContent = li->Target->GetPropertyAsBool(
("INTERFACE_" + p).c_str());
PropertyType ifacePropContent =
getTypedProperty<PropertyType>(li->Target,
("INTERFACE_" + p).c_str(), 0);
if (explicitlySet)
{
if (ifaceIsSet)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "Property " << p << " on target \""
<< this->GetName() << "\" does\nnot match the "
<< tgt->GetName() << "\" does\nnot match the "
"INTERFACE_" << p << " property requirement\nof "
"dependency \"" << li->Target->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4499,15 +4657,16 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{
if (ifaceIsSet)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "Property " << p << " on target \""
<< this->GetName() << "\" is\nimplied to be FALSE because it "
"was used to determine the link libraries\nalready. The "
"INTERFACE_" << p << " property on\ndependency \""
<< tgt->GetName() << "\" is\nimplied to be " << defaultValue
<< " because it was used to determine the link libraries\n"
"already. The INTERFACE_" << p << " property on\ndependency \""
<< li->Target->GetName() << "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4527,14 +4686,15 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
{
if (propInitialized)
{
if (propContent != ifacePropContent)
if (!consistentProperty(propContent, ifacePropContent))
{
cmOStringStream e;
e << "The INTERFACE_" << p << " property of \""
<< li->Target->GetName() << "\" does\nnot agree with the value "
"of " << p << " already determined\nfor \""
<< this->GetName() << "\".\n";
<< tgt->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4558,6 +4718,80 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
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
{
@ -4896,15 +5130,29 @@ void cmTarget::ComputeImportInfo(std::string const& desired_config,
{
std::string linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
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,
info.LinkInterface.Libraries);
linkProp = "IMPORTED_LINK_INTERFACE_LIBRARIES";
propertyLibs = this->GetProperty(linkProp.c_str());
}
else if(const char* libs =
this->GetProperty("IMPORTED_LINK_INTERFACE_LIBRARIES"))
if(propertyLibs)
{
cmSystemTools::ExpandListArgument(libs,
cmListFileBacktrace lfbt;
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
// libraries and executables that export symbols.
const char* explicitLibraries = 0;
std::string linkIfaceProp;
if(this->GetType() == cmTarget::SHARED_LIBRARY ||
this->IsExecutableWithExports())
{
// Lookup the per-configuration property.
std::string propName = "LINK_INTERFACE_LIBRARIES";
propName += suffix;
explicitLibraries = this->GetProperty(propName.c_str());
linkIfaceProp = "LINK_INTERFACE_LIBRARIES";
linkIfaceProp += suffix;
explicitLibraries = this->GetProperty(linkIfaceProp.c_str());
// If not set, try the generic property.
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)
{
// 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)
{
@ -5091,6 +5350,7 @@ bool cmTarget::ComputeLinkInterface(const char* config, LinkInterface& iface,
// The link implementation is the default link interface.
LinkImplementation const* impl = this->GetLinkImplementation(config,
headTarget);
iface.ImplementationIsInterface = true;
iface.Libraries = impl->Libraries;
iface.WrongConfigLibraries = impl->WrongConfigLibraries;
if(this->GetType() == cmTarget::STATIC_LIBRARY)
@ -5272,6 +5532,107 @@ std::string cmTarget::CheckCMP0004(std::string const& item)
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*
cmTarget::GetLinkInformation(const char* config, cmTarget *head)
@ -5296,6 +5657,11 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
// Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
if (info)
{
this->CheckPropertyCompatibility(info, config);
}
}
return i->second;
}

View File

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

View File

@ -20,13 +20,11 @@ bool cmTargetCompileDefinitionsCommand
}
void cmTargetCompileDefinitionsCommand
::HandleImportedTargetInvalidScope(const std::string &scope,
const std::string &tgt)
::HandleImportedTarget(const std::string &tgt)
{
cmOStringStream e;
e << "Cannot specify " << scope << " compile definitions for imported "
"target \"" << tgt << "\". Compile definitions can only be "
"specified for an imported target in the INTERFACE mode.";
e << "Cannot specify compile definitions for imported target \""
<< tgt << "\".";
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 "
"target. "
"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 scope of the following arguments. PRIVATE and PUBLIC items will "
"populate the COMPILE_DEFINITIONS property of <target>. PUBLIC and "
@ -69,14 +69,16 @@ public:
"INTERFACE_COMPILE_DEFINITIONS from. "
"Repeated calls for the same <target> append items in the order called."
"\n"
"Arguments to target_compile_definitions may use \"generator "
"expressions\" with the syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
;
}
cmTypeMacro(cmTargetCompileDefinitionsCommand, cmCommand);
private:
virtual void HandleImportedTargetInvalidScope(const std::string &scope,
const std::string &tgt);
virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name);
virtual bool HandleNonTargetArg(std::string &content,

View File

@ -22,13 +22,11 @@ bool cmTargetIncludeDirectoriesCommand
//----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand
::HandleImportedTargetInvalidScope(const std::string &tgt,
const std::string &scope)
::HandleImportedTarget(const std::string &tgt)
{
cmOStringStream e;
e << "Cannot specify " << scope << " include directories for imported "
"target \"" << tgt << "\". Include directories can only be "
"specified for an imported target in the INTERFACE mode.";
e << "Cannot specify include directories for imported target \""
<< tgt << "\".";
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 "
"target. "
"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 "
"instead of being appended.\n"
"The INTERFACE, PUBLIC and PRIVATE keywords are required to specify "
@ -73,14 +73,16 @@ public:
"directories must be absolute paths, not relative paths. "
"Repeated calls for the same <target> append items in the order called."
"\n"
"Arguments to target_include_directories may use \"generator "
"expressions\" with the syntax \"$<...>\". "
CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
;
}
cmTypeMacro(cmTargetIncludeDirectoriesCommand, cmCommand);
private:
virtual void HandleImportedTargetInvalidScope(const std::string &tgt,
const std::string &scope);
virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name);
virtual bool HandleNonTargetArg(std::string &content,

View File

@ -33,10 +33,6 @@ bool cmTargetLinkLibrariesCommand
this->Target =
this->Makefile->GetCMakeInstance()
->GetGlobalGenerator()->FindTarget(0, args[0].c_str());
if(!this->Target)
{
this->Target = this->Makefile->FindTargetToUse(args[0].c_str());
}
if(!this->Target)
{
cmake::MessageType t = cmake::FATAL_ERROR; // fail by default
@ -261,16 +257,6 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
// Handle normal case first.
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
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
if (this->CurrentProcessingState != ProcessingPublicInterface)

View File

@ -13,6 +13,7 @@
#define cmTargetLinkLibrariesCommand_h
#include "cmCommand.h"
#include "cmDocumentGeneratorExpressions.h"
/** \class cmTargetLinkLibrariesCommand
* \brief Specify a list of libraries to link into executables.
@ -93,6 +94,8 @@ public:
"target too. "
"See the LINK_INTERFACE_LIBRARIES target property to override the "
"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"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n"
@ -141,6 +144,12 @@ public:
"However, if two archives are really so interdependent they should "
"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;
}
//----------------------------------------------------------------------------
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
::ProcessContentArgs(std::vector<std::string> const& args,
@ -80,9 +88,9 @@ bool cmTargetPropCommandBase
return false;
}
if(this->Target->IsImported() && scope != "INTERFACE")
if(this->Target->IsImported())
{
this->HandleImportedTargetInvalidScope(args[0], scope);
this->HandleImportedTarget(args[0]);
return false;
}
@ -105,6 +113,10 @@ bool cmTargetPropCommandBase
content += sep + "$<TARGET_PROPERTY:" + args[i]
+ ",INTERFACE_" + this->Property + ">";
}
else if(isGeneratorExpression(args[i]))
{
content += sep + args[i];
}
else if (!this->HandleNonTargetArg(content, sep, args[i], args[0]))
{
return false;

View File

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

View File

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

View File

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

View File

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

View File

@ -574,6 +574,8 @@ IF(KWSYS_USE_SystemTools)
ENDIF()
IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS SIZEOF_VOID_P=${CMAKE_SIZEOF_VOID_P})
IF(NOT CYGWIN)
INCLUDE(CheckIncludeFiles)
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)
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)
SET(KWSYS_PLATFORM_CXX_TEST_DEFINES -DKWSYS_HAS_LFS=1)
ENDIF()
@ -631,6 +640,20 @@ IF(KWSYS_USE_SystemInformation)
SET_PROPERTY(SOURCE SystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_CXX_HAS__ATOI64=1)
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)
SET_PROPERTY(SOURCE SystemInformation.cxx testSystemInformation.cxx APPEND PROPERTY
COMPILE_DEFINITIONS KWSYS_USE___INT64=1)

View File

@ -418,9 +418,10 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
parse it. */
newCommands[cp->NumberOfCommands] =
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);
return 0;
}

View File

@ -91,6 +91,10 @@ typedef int siginfo_t;
# include <sys/sysctl.h>
#endif
#if defined(KWSYS_SYS_HAS_MACHINE_CPU_H)
# include <machine/cpu.h>
#endif
#if defined(__DragonFly__)
# include <sys/sysctl.h>
#endif
@ -198,7 +202,7 @@ typedef struct rlimit ResourceLimitType;
#define USE_CPUID_INTRINSICS 0
#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
#else
# define USE_CPUID 0
@ -220,6 +224,7 @@ static bool call_cpuid(int select, int result[4])
return true;
#else
int tmp[4];
#if defined(_MSC_VER)
// Use SEH to determine CPUID presence
__try {
_asm {
@ -259,6 +264,23 @@ static bool call_cpuid(int select, int result[4])
}
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.
return true;
#endif
@ -428,7 +450,7 @@ protected:
int CPUCount();
unsigned char LogicalCPUPerPhysicalCPU();
unsigned char GetAPICId();
unsigned int IsHyperThreadingSupported();
bool IsHyperThreadingSupported();
static LongLong GetCyclesDifference(DELAY_FUNC, unsigned int);
// For Linux and Cygwin, /proc/cpuinfo formats are slightly different
@ -452,7 +474,8 @@ protected:
kwsys_stl::string SysCtlBuffer;
// For Solaris
bool QuerySolarisInfo();
bool QuerySolarisMemory();
bool QuerySolarisProcessor();
kwsys_stl::string ParseValueFromKStat(const char* arguments);
kwsys_stl::string RunProcess(kwsys_stl::vector<const char*> args);
@ -477,9 +500,11 @@ protected:
//For AIX
bool QueryAIXMemory();
bool QueryProcessorBySysconf();
bool QueryProcessor();
// Evaluate the memory information.
bool QueryMemoryBySysconf();
bool QueryMemory();
size_t TotalVirtualMemory;
size_t AvailableVirtualMemory;
@ -1283,7 +1308,7 @@ void SystemInformationImplementation::RunCPUCheck()
#elif defined(__APPLE__)
this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun)
this->QuerySolarisInfo();
this->QuerySolarisProcessor();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
@ -1309,7 +1334,7 @@ void SystemInformationImplementation::RunMemoryCheck()
#if defined(__APPLE__)
this->ParseSysCtl();
#elif defined (__SVR4) && defined (__sun)
this->QuerySolarisInfo();
this->QuerySolarisMemory();
#elif defined(__HAIKU__)
this->QueryHaikuInfo();
#elif defined(__QNX__)
@ -3012,7 +3037,7 @@ bool SystemInformationImplementation::RetreiveInformationFromCpuInfoFile()
return true;
}
bool SystemInformationImplementation::QueryProcessor()
bool SystemInformationImplementation::QueryProcessorBySysconf()
{
#if defined(_SC_NPROC_ONLN) && !defined(_SC_NPROCESSORS_ONLN)
// IRIX names this slightly different
@ -3026,7 +3051,7 @@ bool SystemInformationImplementation::QueryProcessor()
return false;
}
this->NumberOfPhysicalCPU = c;
this->NumberOfPhysicalCPU = static_cast<unsigned int>(c);
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
return true;
@ -3035,6 +3060,11 @@ bool SystemInformationImplementation::QueryProcessor()
#endif
}
bool SystemInformationImplementation::QueryProcessor()
{
return this->QueryProcessorBySysconf();
}
/**
Get total system RAM in units of KiB.
*/
@ -3555,8 +3585,7 @@ bool SystemInformationImplementation::QueryAIXMemory()
#endif
}
/** Query for the memory status */
bool SystemInformationImplementation::QueryMemory()
bool SystemInformationImplementation::QueryMemoryBySysconf()
{
#if defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
// Assume the mmap() granularity as returned by _SC_PAGESIZE is also
@ -3593,6 +3622,12 @@ bool SystemInformationImplementation::QueryMemory()
#endif
}
/** Query for the memory status */
bool SystemInformationImplementation::QueryMemory()
{
return this->QueryMemoryBySysconf();
}
/** */
size_t SystemInformationImplementation::GetTotalVirtualMemory()
{
@ -3725,8 +3760,13 @@ unsigned char SystemInformationImplementation::LogicalCPUPerPhysicalCPU(void)
/** Works only for windows */
unsigned int SystemInformationImplementation::IsHyperThreadingSupported()
bool SystemInformationImplementation::IsHyperThreadingSupported()
{
if (this->Features.ExtendedFeatures.SupportsHyperthreading)
{
return true;
}
#if USE_CPUID
int Regs[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 (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);
err = sysctlbyname("machdep.cpu.model", &value, &len, NULL, 0);
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
@ -4059,13 +4176,12 @@ kwsys_stl::string SystemInformationImplementation::RunProcess(kwsys_stl::vector<
char* data = NULL;
int length;
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 += data[i];
}
buffer.append(data, length);
}
kwsysProcess_WaitForExit(gp, 0);
@ -4173,16 +4289,40 @@ kwsys_stl::string SystemInformationImplementation::ParseValueFromKStat(const cha
return value;
}
/** Querying for system information from Solaris */
bool SystemInformationImplementation::QuerySolarisInfo()
bool SystemInformationImplementation::QuerySolarisMemory()
{
// Parse values
this->NumberOfPhysicalCPU = static_cast<unsigned int>(
atoi(this->ParseValueFromKStat("-n syste_misc -s ncpus").c_str()));
this->NumberOfLogicalCPU = this->NumberOfPhysicalCPU;
this->Features.ExtendedFeatures.LogicalProcessorsPerPhysical = 1;
#if defined (__SVR4) && defined (__sun)
// Solaris allows querying this value by sysconf, but if this is
// a 32 bit process on a 64 bit host the returned memory will be
// limited to 4GiB. So if this is a 32 bit process or if the sysconf
// 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()));
// Chip family
@ -4199,20 +4339,6 @@ bool SystemInformationImplementation::QuerySolarisInfo()
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;
}
@ -4424,6 +4550,45 @@ bool SystemInformationImplementation::QueryBSDProcessor()
this->CPUSpeedInMHz = (float) k;
#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;
#else
return false;

View File

@ -580,3 +580,30 @@ int main()
}
}
#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
)
add_library(importedlib UNKNOWN IMPORTED)
target_compile_definitions(importedlib
INTERFACE MY_IMPORTEDINTERFACE_DEFINE
)
add_executable(consumer
"${CMAKE_CURRENT_SOURCE_DIR}/consumer.cpp"
)
target_compile_definitions(consumer
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
#endif
#ifndef MY_IMPORTEDINTERFACE_DEFINE
#error Expected MY_IMPORTEDINTERFACE_DEFINE
#ifdef SHOULD_NOT_BE_DEFINED
#error Unexpected SHOULD_NOT_BE_DEFINED
#endif
#ifndef SHOULD_BE_DEFINED
#error Expected SHOULD_BE_DEFINED
#endif
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(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(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"
)
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)
target_include_directories(importedlib
INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/importedinterfaceinclude"
# Has no effect because the target is not defined:
target_include_directories(target_include_directories
BEFORE PUBLIC "$<$<TARGET_DEFINED:notdefined>:${CMAKE_CURRENT_BINARY_DIR}/poison>"
)
add_executable(consumer
@ -46,5 +43,5 @@ add_executable(consumer
)
target_include_directories(consumer
PRIVATE target_include_directories importedlib
PRIVATE target_include_directories
)

View File

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

View File

@ -29,9 +29,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_library(depA SHARED depA.cpp)
generate_export_header(depA)
add_library(importedlib UNKNOWN IMPORTED)
target_link_libraries(importedlib LINK_INTERFACE_LIBRARIES depA)
add_library(depB SHARED depB.cpp)
generate_export_header(depB)
@ -80,3 +77,13 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
generate_export_header(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(EmptyLibrary EmptyLibrary)
ADD_TEST_MACRO(CompileDefinitions CompileDefinitions)
ADD_TEST_MACRO(CompatibleInterface CompatibleInterface)
set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target:test")
ADD_TEST_MACRO(CrossCompile CrossCompile)

View File

@ -4,7 +4,8 @@ set(CMAKE_EXECUTABLE "${CMake_BIN_DIR}/cmake")
macro(AddCMakeTest TestName PreArgs)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/${TestName}Test.cmake.in"
"${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})
endmacro()
@ -28,7 +29,7 @@ AddCMakeTest(String "")
AddCMakeTest(Math "")
AddCMakeTest(CMakeMinimumRequired "")
AddCMakeTest(CompilerIdVendor "")
AddCMakeTest(ProcessorCount "")
AddCMakeTest(ProcessorCount "-DKWSYS_TEST_EXE=$<TARGET_FILE:cmsysTestsCxx>")
AddCMakeTest(PushCheckState "")
AddCMakeTest(While "")

View File

@ -9,10 +9,17 @@ message("### 3. ProcessorCount(...) function call is emitting output that it sho
message("processor_count='${processor_count}'")
execute_process(
COMMAND "@CMAKE_BINARY_DIR@/Source/kwsys/$ENV{CMAKE_CONFIG_TYPE}/cmsysTestsCxx"
COMMAND "${KWSYS_TEST_EXE}"
testSystemInformation
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"
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>
)
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
testLibIncludeRequired1
testLibIncludeRequired2
@ -165,10 +215,11 @@ install(TARGETS testLibRequired
testLibIncludeRequired4
testLibIncludeRequired5
testLibIncludeRequired6
testSharedLibRequired
EXPORT RequiredExp DESTINATION lib )
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)
@ -216,9 +267,12 @@ if(WIN32)
install(TARGETS testLib5 RUNTIME DESTINATION bin)
endif()
add_subdirectory(sublib) # For CMAKE_BUILD_INTERFACE_INCLUDES test.
# Export from build tree.
export(TARGETS testExe1 testLib1 testLib2 testLib3
testExe2libImp testLib3Imp testLib3ImpDep
testExe2libImp testLib3Imp testLib3ImpDep subdirlib
testSharedLibRequired testSharedLibDepends
NAMESPACE bld_
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
# INTERFACE_COMPILE_DEFINITIONS and INTERFACE_INCLUDE_DIRECTORIES
add_library(deps_iface deps_iface.cpp)
target_link_libraries(deps_iface testLibsDepends)
set_property(TARGET deps_iface APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:testLibDepends,INTERFACE_COMPILE_DEFINITIONS>
add_executable(deps_iface deps_iface.c)
target_link_libraries(deps_iface testLibDepends)
target_include_directories(deps_iface PRIVATE testLibDepends)
target_compile_definitions(deps_iface PRIVATE testLibDepends)
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
$<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
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);
int main(int,char **)
int main()
{
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()
add_custom_target(NonExternalProjectTarget
COMMAND ${CMAKE_COMMAND} -E echo NonExternalProjectTarget)
# Empty projects that test all the known ExternalProject_Add argument key words:
#
@ -94,7 +96,7 @@ ExternalProject_Add(${proj}
CVS_REPOSITORY ""
CVS_MODULE ""
CVS_TAG ""
DEPENDS "MinimalNoOpProject"
DEPENDS "MinimalNoOpProject" NonExternalProjectTarget
DOWNLOAD_COMMAND ""
INSTALL_COMMAND ""
PATCH_COMMAND ""

View File

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

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)
add_RunCMake_test(PositionIndependentCode)
endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(build_command)
add_RunCMake_test(find_package)
add_RunCMake_test(include)
add_RunCMake_test(include_directories)
add_RunCMake_test(list)
add_RunCMake_test(CMP0004)
if("${CMAKE_TEST_GENERATOR}" MATCHES "Visual Studio [^6]")
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