Merge topic 'fix-COMPATIBLE_INTERFACE-properties'

830246e Export the COMPATIBLE_INTERFACE_BOOL content properties
bd82bb4 Clear the link information in ClearLinkMaps.
e987991 Make INTERFACE determined properties readable in generator expressions.
d9afacc Exit early if we find an inconsistent property.
1800f70 Populate the link information cache before checking dependent properties.
This commit is contained in:
Brad King 2013-01-23 15:11:15 -05:00 committed by CMake Topic Stage
commit bf2e4e8cb1
32 changed files with 325 additions and 5 deletions

View File

@ -74,6 +74,7 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties);
}

View File

@ -21,6 +21,7 @@
#include "cmTarget.h"
#include "cmTargetExport.h"
#include "cmVersion.h"
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx>
@ -177,6 +178,79 @@ 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);
}
}
//----------------------------------------------------------------------------
void cmExportFileGenerator::PopulateCompatibleInterfaceProperties(
cmTarget *target,
ImportPropertyMap &properties)
{
this->PopulateInterfaceProperty("COMPATIBLE_INTERFACE_BOOL",
target, properties);
std::set<std::string> ifaceProperties;
getPropertyContents(target, "COMPATIBLE_INTERFACE_BOOL", 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,

View File

@ -103,6 +103,8 @@ protected:
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);

View File

@ -91,6 +91,7 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties);
}

View File

@ -106,3 +106,16 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
}
return DAG;
}
//----------------------------------------------------------------------------
bool cmGeneratorExpressionDAGChecker::EvaluatingLinkLibraries()
{
const cmGeneratorExpressionDAGChecker *top = this;
const cmGeneratorExpressionDAGChecker *parent = this->Parent;
while (parent)
{
parent = parent->Parent;
top = parent;
}
return top->Property == "LINK_LIBRARIES";
}

View File

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

View File

@ -442,6 +442,27 @@ 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";
}
return std::string();
}

View File

@ -1520,6 +1520,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();
}
//----------------------------------------------------------------------------
@ -4533,6 +4540,7 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
"INTERFACE_" << p << " property requirement\nof "
"dependency \"" << li->Target->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4559,6 +4567,7 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
"INTERFACE_" << p << " property on\ndependency \""
<< li->Target->GetName() << "\" is in conflict.\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4586,6 +4595,7 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
"of " << p << " already determined\nfor \""
<< this->GetName() << "\".\n";
cmSystemTools::Error(e.str().c_str());
break;
}
else
{
@ -4609,6 +4619,53 @@ bool cmTarget::GetLinkInterfaceDependentBoolProperty(const std::string &p,
return propContent;
}
//----------------------------------------------------------------------------
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);
}
//----------------------------------------------------------------------------
void cmTarget::GetLanguages(std::set<cmStdString>& languages) const
{
@ -5422,14 +5479,14 @@ cmTarget::GetLinkInformation(const char* config, cmTarget *head)
info = 0;
}
// Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
if (info)
{
this->CheckPropertyCompatibility(info, config);
}
// Store the information for this configuration.
cmTargetLinkInformationMap::value_type entry(key, info);
i = this->LinkInformation.insert(entry).first;
}
return i->second;
}

View File

@ -495,6 +495,8 @@ public:
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);
void AddLinkDependentTargetsForProperties(
const std::map<cmStdString, cmStdString> &map);

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

@ -0,0 +1,28 @@
cmake_minimum_required(VERSION 2.8)
project(CompatibleInterface)
add_library(iface1 empty.cpp)
set_property(TARGET iface1 APPEND PROPERTY
COMPATIBLE_INTERFACE_BOOL
BOOL_PROP1
BOOL_PROP2
BOOL_PROP3
)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP1 ON)
set_property(TARGET iface1 PROPERTY INTERFACE_BOOL_PROP2 ON)
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)
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>
)

View File

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

View File

@ -0,0 +1,17 @@
#ifndef BOOL_PROP1
#error Expected BOOL_PROP1
#endif
#ifndef BOOL_PROP2
#error Expected BOOL_PROP2
#endif
#ifndef BOOL_PROP3
#error Expected BOOL_PROP3
#endif
int main(int argc, char **argv)
{
return 0;
}

View File

@ -173,6 +173,15 @@ 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
)
add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
set_property(TARGET testSharedLibDepends APPEND PROPERTY

View File

@ -165,7 +165,12 @@ 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)
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>
)
if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
include(CheckCXXCompilerFlag)
@ -194,4 +199,6 @@ 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>
)

View File

@ -8,6 +8,14 @@
#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
#ifdef TEST_SUBDIR_LIB
#include "subdir.h"
#endif

View File

@ -53,6 +53,7 @@ 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)

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)

View File

@ -0,0 +1,3 @@
CMake Error: Property SOMEPROP on target "user" does
not match the INTERFACE_SOMEPROP property requirement
of dependency "foo".

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 SOMEPROP)
set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP ON)
set_property(TARGET bar PROPERTY INTERFACE_SOMEPROP ON)
add_executable(user main.cpp)
set_property(TARGET user PROPERTY SOMEPROP OFF)
target_link_libraries(user foo bar)

View File

@ -0,0 +1,3 @@
CMake Error: The INTERFACE_SOMEPROP property of "bar" does
not agree with the value of SOMEPROP already determined
for "user".

View File

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

View File

@ -0,0 +1,4 @@
CMake Error: Property SOMEPROP on target "user" is
implied to be FALSE because it was used to determine the link libraries
already. The INTERFACE_SOMEPROP property on
dependency "foo" is in conflict.

View File

@ -0,0 +1,9 @@
add_library(foo UNKNOWN IMPORTED)
add_library(bar UNKNOWN IMPORTED)
set_property(TARGET foo APPEND PROPERTY COMPATIBLE_INTERFACE_BOOL SOMEPROP)
set_property(TARGET foo PROPERTY INTERFACE_SOMEPROP ON)
add_executable(user main.cpp)
target_link_libraries(user foo $<$<STREQUAL:$<TARGET_PROPERTY:SOMEPROP>,prop>:bar>)

View File

@ -0,0 +1,6 @@
include(RunCMake)
run_cmake(InterfaceBool-mismatch-depends)
run_cmake(InterfaceBool-mismatch-depend-self)
run_cmake(InterfaceBool-mismatched-use)
run_cmake(InterfaceBool-builtin-prop)

View File

@ -0,0 +1,5 @@
int main(int argc, char **argv)
{
return 0;
}