Merge topic 'fix-COMPATIBLE_INTERFACE-properties'
830246e
Export the COMPATIBLE_INTERFACE_BOOL content propertiesbd82bb4
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:
commit
bf2e4e8cb1
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -35,6 +35,9 @@ struct cmGeneratorExpressionDAGChecker
|
|||
|
||||
void reportError(cmGeneratorExpressionContext *context,
|
||||
const std::string &expr);
|
||||
|
||||
bool EvaluatingLinkLibraries();
|
||||
|
||||
private:
|
||||
Result checkGraph() const;
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
)
|
|
@ -0,0 +1 @@
|
|||
// no content
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(${RunCMake_TEST} CXX)
|
||||
include(${RunCMake_TEST}.cmake)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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.
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,3 @@
|
|||
CMake Error: Property SOMEPROP on target "user" does
|
||||
not match the INTERFACE_SOMEPROP property requirement
|
||||
of dependency "foo".
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -0,0 +1,3 @@
|
|||
CMake Error: The INTERFACE_SOMEPROP property of "bar" does
|
||||
not agree with the value of SOMEPROP already determined
|
||||
for "user".
|
|
@ -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)
|
|
@ -0,0 +1 @@
|
|||
1
|
|
@ -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.
|
|
@ -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>)
|
|
@ -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)
|
|
@ -0,0 +1,5 @@
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue