Add includes and compile definitions with target_link_libraries.

This establishes that linking is used to propagate usage-requirements
between targets in CMake code. The use of the target_link_libraries
command as the API for this is chosen because introducing a new command
would introduce confusion due to multiple commands which differ only in
a subtle way.
This commit is contained in:
Stephen Kelly 2012-11-05 12:43:28 +01:00
parent 0b92602b81
commit 77cecb778f
14 changed files with 213 additions and 56 deletions

View File

@ -514,6 +514,9 @@ public:
const char *GetLinkInterfaceDependentStringProperty(const std::string &p, const char *GetLinkInterfaceDependentStringProperty(const std::string &p,
const char *config); const char *config);
std::string GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt);
private: private:
/** /**
* A list of direct dependencies. Use in conjunction with DependencyMap. * A list of direct dependencies. Use in conjunction with DependencyMap.
@ -659,9 +662,6 @@ private:
void ProcessSourceExpression(std::string const& expr); void ProcessSourceExpression(std::string const& expr);
std::string GetDebugGeneratorExpressions(const std::string &value,
cmTarget::LinkLibraryType llt);
// The cmMakefile instance that owns this target. This should // The cmMakefile instance that owns this target. This should
// always be set. // always be set.
cmMakefile* Makefile; cmMakefile* Makefile;

View File

@ -249,11 +249,52 @@ cmTargetLinkLibrariesCommand
this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str());
} }
//----------------------------------------------------------------------------
static std::string compileProperty(cmTarget *tgt, const std::string &lib,
bool isGenex,
const std::string &property,
cmTarget::LinkLibraryType llt)
{
std::string value = !isGenex ? "$<LINKED:" + lib + ">"
: "$<$<TARGET_DEFINED:" + lib + ">:" +
"$<TARGET_PROPERTY:" + lib +
",INTERFACE_" + property + ">"
">";
return tgt->GetDebugGeneratorExpressions(value, llt);
}
//----------------------------------------------------------------------------
static bool isGeneratorExpression(const std::string &lib)
{
const std::string::size_type openpos = lib.find("$<");
return (openpos != std::string::npos)
&& (lib.find(">", openpos) != std::string::npos);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void void
cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
cmTarget::LinkLibraryType llt) cmTarget::LinkLibraryType llt)
{ {
const bool isGenex = isGeneratorExpression(lib);
cmsys::RegularExpression targetNameValidator;
targetNameValidator.compile("^[A-Za-z0-9_.:-]+$");
const bool potentialTargetName = targetNameValidator.find(lib);
if (potentialTargetName || isGenex)
{
this->Target->AppendProperty("INCLUDE_DIRECTORIES",
compileProperty(this->Target, lib,
isGenex,
"INCLUDE_DIRECTORIES", llt).c_str());
this->Target->AppendProperty("COMPILE_DEFINITIONS",
compileProperty(this->Target, lib,
isGenex,
"COMPILE_DEFINITIONS", llt).c_str());
}
// Handle normal case first. // Handle normal case first.
if(this->CurrentProcessingState != ProcessingLinkInterface) if(this->CurrentProcessingState != ProcessingLinkInterface)
{ {
@ -266,6 +307,18 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
} }
} }
if (potentialTargetName || isGenex)
{
this->Target->AppendProperty("INTERFACE_COMPILE_DEFINITIONS",
compileProperty(this->Target, lib,
isGenex,
"COMPILE_DEFINITIONS", llt).c_str());
this->Target->AppendProperty("INTERFACE_INCLUDE_DIRECTORIES",
compileProperty(this->Target, lib,
isGenex,
"INCLUDE_DIRECTORIES", llt).c_str());
}
// Get the list of configurations considered to be DEBUG. // Get the list of configurations considered to be DEBUG.
std::vector<std::string> const& debugConfigs = std::vector<std::string> const& debugConfigs =
this->Makefile->GetCMakeInstance()->GetDebugConfigs(); this->Makefile->GetCMakeInstance()->GetDebugConfigs();

View File

@ -97,6 +97,15 @@ public:
"Calls to other signatures of this command may set the property " "Calls to other signatures of this command may set the property "
"making any libraries linked exclusively by this signature private." "making any libraries linked exclusively by this signature private."
"\n" "\n"
"Target usage requirements are also consumed by this command. If the "
"<target> is linked to another target which has "
"a populated INTERFACE_INCLUDE_DIRECTORIES, the content of it is "
"appended to the INCLUDE_DIRECTORIES of <target>. Similarly, the "
"INTERFACE_COMPILE_DEFINITONS of a dependee are added to the "
"COMPILE_DEFINITONS of <target>, and the "
"INTERFACE_POSITION_INDEPENDENT_CODE property is used to determine the "
"POSITION_INDEPENDENT_CODE property of <target>."
"\n"
" target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n" " target_link_libraries(<target> LINK_INTERFACE_LIBRARIES\n"
" [[debug|optimized|general] <lib>] ...)\n" " [[debug|optimized|general] <lib>] ...)\n"
"The LINK_INTERFACE_LIBRARIES mode appends the libraries " "The LINK_INTERFACE_LIBRARIES mode appends the libraries "

View File

@ -62,10 +62,6 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "")
add_subdirectory(subdir) add_subdirectory(subdir)
target_link_libraries(targetA subdirlib) target_link_libraries(targetA subdirlib)
set_property(TARGET targetA APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:subdirlib,INTERFACE_INCLUDE_DIRECTORIES>
)
target_link_libraries(targetA depB depC) target_link_libraries(targetA depB depC)
@ -87,3 +83,24 @@ set_property(TARGET depD APPEND PROPERTY
add_executable(targetB targetB.cpp) add_executable(targetB targetB.cpp)
target_link_libraries(targetB depD) target_link_libraries(targetB depD)
macro(create_header _name)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/${_name}")
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_name}/${_name}.h" "//${_name}.h\n")
endmacro()
create_header(foo)
create_header(bar)
add_library(depG SHARED depG.cpp)
generate_export_header(depG)
target_include_directories(depG INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/foo"
"${CMAKE_CURRENT_BINARY_DIR}/bar"
)
target_compile_definitions(depG INTERFACE
TEST_DEF
)
add_executable(targetC targetC.cpp)
target_link_libraries(targetC depG)

View File

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

View File

@ -0,0 +1,7 @@
#include "depg_export.h"
struct DEPG_EXPORT DepG
{
int foo();
};

View File

@ -0,0 +1,16 @@
#include "depG.h"
#include "foo.h"
#include "bar.h"
#ifndef TEST_DEF
#error Expected TEST_DEF definition
#endif
int main(int argc, char **argv)
{
DepG g;
return g.foo();
}

View File

@ -90,23 +90,7 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
# Test exporting dependent libraries into different exports # Test exporting dependent libraries into different exports
add_library(testLibRequired testLibRequired.c) add_library(testLibRequired testLibRequired.c)
add_library(testLibDepends testLibDepends.c) add_library(testLibDepends testLibDepends.c)
set_property(TARGET testLibDepends APPEND PROPERTY target_link_libraries(testLibDepends LINK_PUBLIC testLibRequired)
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET testLibDepends APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
)
set_property(TARGET testLibDepends APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:testLibRequired,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET testLibDepends APPEND PROPERTY
INTERFACE_COMPILE_DEFINITIONS
$<TARGET_PROPERTY:testLibRequired,INTERFACE_COMPILE_DEFINITIONS>
)
target_link_libraries(testLibDepends testLibRequired)
macro(add_include_lib _libName) macro(add_include_lib _libName)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_libName}.c" "// no content\n")
@ -239,6 +223,25 @@ install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredTargets.cmake DES
install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib ) install(TARGETS testLibDepends testSharedLibDepends EXPORT DependsExp DESTINATION lib )
install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends) install(EXPORT DependsExp FILE testLibDependsTargets.cmake DESTINATION lib/cmake/testLibDepends)
file(WRITE
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
"
if(\${CMAKE_FIND_PACKAGE_NAME}_FIND_VERSION VERSION_LESS 2.3 AND NOT \${CMAKE_FIND_PACKAGE_NAME}_INTERFACES)
set(\${CMAKE_FIND_PACKAGE_NAME}_NO_INTERFACES 1)
endif()
include(\"\${CMAKE_CURRENT_LIST_DIR}/testLibRequiredTargets.cmake\")
set(\${CMAKE_FIND_PACKAGE_NAME}_INCLUDE_DIRS \"${CMAKE_CURRENT_BINARY_DIR}\" \"${CMAKE_CURRENT_SOURCE_DIR}\" )
"
)
include(CMakePackageConfigHelpers)
write_basic_package_version_file( testLibRequiredConfigVersion.cmake VERSION 2.5 COMPATIBILITY AnyNewerVersion)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfig.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/testLibRequiredConfigVersion.cmake"
DESTINATION lib/cmake/testLibRequired
)
# Install and export from install tree. # Install and export from install tree.
install( install(

View File

@ -159,18 +159,11 @@ endif()
add_executable(deps_iface deps_iface.c) add_executable(deps_iface deps_iface.c)
target_link_libraries(deps_iface testLibDepends) target_link_libraries(deps_iface testLibDepends)
target_include_directories(deps_iface PRIVATE $<TARGET_PROPERTY:testLibDepends,INTERFACE_INCLUDE_DIRECTORIES>)
target_compile_definitions(deps_iface PRIVATE $<TARGET_PROPERTY:testLibDepends,INTERFACE_COMPILE_DEFINITIONS>)
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
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(deps_shared_iface target_compile_definitions(deps_shared_iface
PRIVATE PRIVATE
$<TARGET_PROPERTY:testSharedLibDepends,INTERFACE_COMPILE_DEFINITIONS>
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON> $<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON> $<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH> $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>
@ -200,13 +193,8 @@ endif()
add_executable(deps_shared_iface2 deps_shared_iface.cpp) add_executable(deps_shared_iface2 deps_shared_iface.cpp)
target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib) target_link_libraries(deps_shared_iface2 bld_testSharedLibDepends bld_subdirlib)
target_include_directories(deps_shared_iface2
PRIVATE
$<TARGET_PROPERTY:bld_testSharedLibDepends,INTERFACE_INCLUDE_DIRECTORIES>
$<TARGET_PROPERTY:bld_subdirlib,INTERFACE_INCLUDE_DIRECTORIES>
)
target_compile_definitions(deps_shared_iface2 target_compile_definitions(deps_shared_iface2
PRIVATE $<TARGET_PROPERTY:bld_testSharedLibDepends,INTERFACE_COMPILE_DEFINITIONS> TEST_SUBDIR_LIB PRIVATE TEST_SUBDIR_LIB
$<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON> $<$<BOOL:$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>>:PIC_PROPERTY_IS_ON>
$<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON> $<$<BOOL:$<TARGET_PROPERTY:CUSTOM_PROP>>:CUSTOM_PROPERTY_IS_ON>
$<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH> $<$<STREQUAL:$<TARGET_PROPERTY:CUSTOM_STRING>,testcontent>:CUSTOM_STRING_IS_MATCH>

View File

@ -17,3 +17,8 @@ add_executable(imp_testTransExe1 imp_testTransExe1.c)
target_link_libraries(imp_testTransExe1 imp_lib1) target_link_libraries(imp_testTransExe1 imp_lib1)
add_executable(imp_testTransExe1b imp_testTransExe1.c) add_executable(imp_testTransExe1b imp_testTransExe1.c)
target_link_libraries(imp_testTransExe1b imp_lib1b) target_link_libraries(imp_testTransExe1b imp_lib1b)
# Test package INTERFACE controls
add_subdirectory(package_old_old)
add_subdirectory(package_new_old)
add_subdirectory(package_new_new)

View File

@ -0,0 +1,23 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.5 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if (NOT prop)
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
endif()
add_executable(new_new_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(new_new_test Req::testSharedLibRequired)

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.5 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if ("${prop}" STREQUAL "")
message(SEND_ERROR "Interface of Req::testSharedLibRequired should not be empty")
endif()
add_executable(new_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(new_old_test Req::testSharedLibRequired)
include_directories(${testLibRequired_INCLUDE_DIRS})

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8)
find_package(testLibRequired 2.1 REQUIRED)
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
"
#include \"testSharedLibRequired.h\"
int main(int argc, char **argv)
{
TestSharedLibRequired req;
return req.foo();
}
"
)
get_target_property(prop Req::testSharedLibRequired INTERFACE_INCLUDE_DIRECTORIES)
if (prop)
message(SEND_ERROR "Interface of Req::testSharedLibRequired should be empty, but is ${prop}")
endif()
add_executable(old_old_test "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
target_link_libraries(old_old_test Req::testSharedLibRequired)
include_directories(${testLibRequired_INCLUDE_DIRS})

View File

@ -12,29 +12,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(Qt4Targets WIN32 main.cpp) add_executable(Qt4Targets WIN32 main.cpp)
target_link_libraries(Qt4Targets Qt4::QtGui) target_link_libraries(Qt4Targets Qt4::QtGui)
set_property(TARGET Qt4Targets APPEND PROPERTY
INCLUDE_DIRECTORIES
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_INCLUDE_DIRECTORIES>
)
set_property(TARGET Qt4Targets APPEND PROPERTY
COMPILE_DEFINITIONS
$<TARGET_PROPERTY:Qt4::QtGui,INTERFACE_COMPILE_DEFINITIONS>
)
if (WIN32) if (WIN32)
if (TARGET Qt4::QAxServer) if (TARGET Qt4::QAxServer)
add_executable(activeqtexe WIN32 activeqtexe.cpp) add_executable(activeqtexe WIN32 activeqtexe.cpp)
set_property(TARGET activeqtexe PROPERTY QT4_NO_LINK_QTMAIN ON) set_property(TARGET activeqtexe PROPERTY QT4_NO_LINK_QTMAIN ON)
target_link_libraries(activeqtexe Qt4::QAxServer Qt4::QtGui) 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()
endif() endif()