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); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties); te, properties);
this->PopulateCompatibleInterfaceProperties(te, properties);
this->GenerateInterfaceProperties(te, os, properties); this->GenerateInterfaceProperties(te, os, properties);
} }

View File

@ -21,6 +21,7 @@
#include "cmTarget.h" #include "cmTarget.h"
#include "cmTargetExport.h" #include "cmTargetExport.h"
#include "cmVersion.h" #include "cmVersion.h"
#include "cmComputeLinkInformation.h"
#include <cmsys/auto_ptr.hxx> #include <cmsys/auto_ptr.hxx>
@ -177,6 +178,79 @@ void cmExportFileGenerator::PopulateInterfaceProperty(const char *propName,
properties, missingTargets); properties, missingTargets);
} }
//----------------------------------------------------------------------------
void getPropertyContents(cmTarget *tgt, const char *prop,
std::set<std::string> &ifaceProperties)
{
const char *p = tgt->GetProperty(prop);
if (!p)
{
return;
}
std::vector<std::string> content;
cmSystemTools::ExpandListArgument(p, content);
for (std::vector<std::string>::const_iterator ci = content.begin();
ci != content.end(); ++ci)
{
ifaceProperties.insert(*ci);
}
}
//----------------------------------------------------------------------------
void getCompatibleInterfaceProperties(cmTarget *target,
std::set<std::string> &ifaceProperties,
const char *config)
{
cmComputeLinkInformation *info = target->GetLinkInformation(config);
const cmComputeLinkInformation::ItemVector &deps = info->GetItems();
for(cmComputeLinkInformation::ItemVector::const_iterator li =
deps.begin();
li != deps.end(); ++li)
{
if (!li->Target)
{
continue;
}
getPropertyContents(li->Target,
"COMPATIBLE_INTERFACE_BOOL",
ifaceProperties);
}
}
//----------------------------------------------------------------------------
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, void cmExportFileGenerator::GenerateInterfaceProperties(cmTarget *target,
std::ostream& os, std::ostream& os,

View File

@ -103,6 +103,8 @@ protected:
std::vector<std::string> &missingTargets); std::vector<std::string> &missingTargets);
void PopulateInterfaceProperty(const char *propName, cmTarget *target, void PopulateInterfaceProperty(const char *propName, cmTarget *target,
ImportPropertyMap &properties); ImportPropertyMap &properties);
void PopulateCompatibleInterfaceProperties(cmTarget *target,
ImportPropertyMap &properties);
void GenerateInterfaceProperties(cmTarget *target, std::ostream& os, void GenerateInterfaceProperties(cmTarget *target, std::ostream& os,
const ImportPropertyMap &properties); const ImportPropertyMap &properties);

View File

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

View File

@ -106,3 +106,16 @@ cmGeneratorExpressionDAGChecker::checkGraph() const
} }
return DAG; 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, void reportError(cmGeneratorExpressionContext *context,
const std::string &expr); const std::string &expr);
bool EvaluatingLinkLibraries();
private: private:
Result checkGraph() const; Result checkGraph() const;

View File

@ -442,6 +442,27 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
const char *prop = target->GetProperty(propertyName.c_str()); const char *prop = target->GetProperty(propertyName.c_str());
if (!prop) if (!prop)
{ {
if (target->IsImported())
{
return std::string();
}
if (dagCheckerParent && dagCheckerParent->EvaluatingLinkLibraries())
{
return std::string();
}
if (propertyName == "POSITION_INDEPENDENT_CODE")
{
return target->GetLinkInterfaceDependentBoolProperty(
"POSITION_INDEPENDENT_CODE", context->Config) ? "1" : "0";
}
if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
context->Config))
{
return target->GetLinkInterfaceDependentBoolProperty(
propertyName,
context->Config) ? "1" : "0";
}
return std::string(); return std::string();
} }

View File

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

View File

@ -495,6 +495,8 @@ public:
void GetLinkDependentTargetsForProperty(const std::string &p, void GetLinkDependentTargetsForProperty(const std::string &p,
std::set<std::string> &targets); std::set<std::string> &targets);
bool IsNullImpliedByLinkLibraries(const std::string &p); bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
const char *config);
void AddLinkDependentTargetsForProperties( void AddLinkDependentTargetsForProperties(
const std::map<cmStdString, cmStdString> &map); const std::map<cmStdString, cmStdString> &map);

View File

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

View File

@ -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}" INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}"
"${CMAKE_CURRENT_SOURCE_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) add_library(testSharedLibDepends SHARED testSharedLibDepends.cpp)
set_property(TARGET testSharedLibDepends APPEND PROPERTY 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) add_executable(deps_shared_iface deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface testSharedLibDepends) target_link_libraries(deps_shared_iface testSharedLibDepends)
target_include_directories(deps_shared_iface PRIVATE 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") if (APPLE OR CMAKE_CXX_COMPILER_ID MATCHES "GNU")
include(CheckCXXCompilerFlag) 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_include_directories(deps_shared_iface2 PRIVATE bld_testSharedLibDepends bld_subdirlib)
target_compile_definitions(deps_shared_iface2 target_compile_definitions(deps_shared_iface2
PRIVATE bld_testSharedLibDepends TEST_SUBDIR_LIB 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
#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 #ifdef TEST_SUBDIR_LIB
#include "subdir.h" #include "subdir.h"
#endif #endif

View File

@ -53,6 +53,7 @@ add_RunCMake_test(ObjectLibrary)
if(NOT WIN32) if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode) add_RunCMake_test(PositionIndependentCode)
endif() endif()
add_RunCMake_test(CompatibleInterface)
add_RunCMake_test(build_command) add_RunCMake_test(build_command)
add_RunCMake_test(find_package) add_RunCMake_test(find_package)

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;
}