From 77cecb778ff1882d87401c1055ec06585462f787 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 5 Nov 2012 12:43:28 +0100 Subject: 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. --- Source/cmTarget.h | 6 +-- Source/cmTargetLinkLibrariesCommand.cxx | 53 ++++++++++++++++++++++ Source/cmTargetLinkLibrariesCommand.h | 9 ++++ .../target_link_libraries/CMakeLists.txt | 25 ++++++++-- Tests/CMakeCommands/target_link_libraries/depG.cpp | 7 +++ Tests/CMakeCommands/target_link_libraries/depG.h | 7 +++ .../target_link_libraries/targetC.cpp | 16 +++++++ Tests/ExportImport/Export/CMakeLists.txt | 37 ++++++++------- Tests/ExportImport/Import/A/CMakeLists.txt | 14 +----- Tests/ExportImport/Import/CMakeLists.txt | 5 ++ .../Import/package_new_new/CMakeLists.txt | 23 ++++++++++ .../Import/package_new_old/CMakeLists.txt | 24 ++++++++++ .../Import/package_old_old/CMakeLists.txt | 24 ++++++++++ Tests/Qt4Targets/CMakeLists.txt | 19 -------- 14 files changed, 213 insertions(+), 56 deletions(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/depG.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depG.h create mode 100644 Tests/CMakeCommands/target_link_libraries/targetC.cpp create mode 100644 Tests/ExportImport/Import/package_new_new/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/package_new_old/CMakeLists.txt create mode 100644 Tests/ExportImport/Import/package_old_old/CMakeLists.txt diff --git a/Source/cmTarget.h b/Source/cmTarget.h index cf2d4c4..7577a59 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -514,6 +514,9 @@ public: const char *GetLinkInterfaceDependentStringProperty(const std::string &p, const char *config); + + std::string GetDebugGeneratorExpressions(const std::string &value, + cmTarget::LinkLibraryType llt); private: /** * A list of direct dependencies. Use in conjunction with DependencyMap. @@ -659,9 +662,6 @@ private: 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 // always be set. cmMakefile* Makefile; diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index f42b0f6..cb913f5 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -250,10 +250,51 @@ cmTargetLinkLibrariesCommand } //---------------------------------------------------------------------------- +static std::string compileProperty(cmTarget *tgt, const std::string &lib, + bool isGenex, + const std::string &property, + cmTarget::LinkLibraryType llt) +{ + std::string value = !isGenex ? "$" + : "$<$:" + + "$" + ">"; + + 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 cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, 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. 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. std::vector const& debugConfigs = this->Makefile->GetCMakeInstance()->GetDebugConfigs(); diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index 3da3950..aaabdfa 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -97,6 +97,15 @@ public: "Calls to other signatures of this command may set the property " "making any libraries linked exclusively by this signature private." "\n" + "Target usage requirements are also consumed by this command. If the " + " is linked to another target which has " + "a populated INTERFACE_INCLUDE_DIRECTORIES, the content of it is " + "appended to the INCLUDE_DIRECTORIES of . Similarly, the " + "INTERFACE_COMPILE_DEFINITONS of a dependee are added to the " + "COMPILE_DEFINITONS of , and the " + "INTERFACE_POSITION_INDEPENDENT_CODE property is used to determine the " + "POSITION_INDEPENDENT_CODE property of ." + "\n" " target_link_libraries( LINK_INTERFACE_LIBRARIES\n" " [[debug|optimized|general] ] ...)\n" "The LINK_INTERFACE_LIBRARIES mode appends the libraries " diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt index 1d0e342..cd0fe11 100644 --- a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -62,10 +62,6 @@ assert_property(targetA LINK_INTERFACE_LIBRARIES "") add_subdirectory(subdir) target_link_libraries(targetA subdirlib) -set_property(TARGET targetA APPEND PROPERTY - INCLUDE_DIRECTORIES - $ -) target_link_libraries(targetA depB depC) @@ -87,3 +83,24 @@ set_property(TARGET depD APPEND PROPERTY add_executable(targetB targetB.cpp) 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) diff --git a/Tests/CMakeCommands/target_link_libraries/depG.cpp b/Tests/CMakeCommands/target_link_libraries/depG.cpp new file mode 100644 index 0000000..65b9655 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depG.cpp @@ -0,0 +1,7 @@ + +#include "depG.h" + +int DepG::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depG.h b/Tests/CMakeCommands/target_link_libraries/depG.h new file mode 100644 index 0000000..1a36589 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depG.h @@ -0,0 +1,7 @@ + +#include "depg_export.h" + +struct DEPG_EXPORT DepG +{ + int foo(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/targetC.cpp b/Tests/CMakeCommands/target_link_libraries/targetC.cpp new file mode 100644 index 0000000..ff6ba66 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/targetC.cpp @@ -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(); +} diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt index ae44c28..ae938cd 100644 --- a/Tests/ExportImport/Export/CMakeLists.txt +++ b/Tests/ExportImport/Export/CMakeLists.txt @@ -90,23 +90,7 @@ set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3) # Test exporting dependent libraries into different exports add_library(testLibRequired testLibRequired.c) add_library(testLibDepends testLibDepends.c) -set_property(TARGET testLibDepends APPEND PROPERTY - INCLUDE_DIRECTORIES - $ -) -set_property(TARGET testLibDepends APPEND PROPERTY - COMPILE_DEFINITIONS - $ -) -set_property(TARGET testLibDepends APPEND PROPERTY - INTERFACE_INCLUDE_DIRECTORIES - $ -) -set_property(TARGET testLibDepends APPEND PROPERTY - INTERFACE_COMPILE_DEFINITIONS - $ -) -target_link_libraries(testLibDepends testLibRequired) +target_link_libraries(testLibDepends LINK_PUBLIC testLibRequired) macro(add_include_lib _libName) 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(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( diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt index 0675594..0337130 100644 --- a/Tests/ExportImport/Import/A/CMakeLists.txt +++ b/Tests/ExportImport/Import/A/CMakeLists.txt @@ -159,18 +159,11 @@ endif() add_executable(deps_iface deps_iface.c) target_link_libraries(deps_iface testLibDepends) -target_include_directories(deps_iface PRIVATE $) -target_compile_definitions(deps_iface PRIVATE $) add_executable(deps_shared_iface deps_shared_iface.cpp) target_link_libraries(deps_shared_iface testSharedLibDepends) -target_include_directories(deps_shared_iface - PRIVATE - $ -) target_compile_definitions(deps_shared_iface PRIVATE - $ $<$>:PIC_PROPERTY_IS_ON> $<$>:CUSTOM_PROPERTY_IS_ON> $<$,testcontent>:CUSTOM_STRING_IS_MATCH> @@ -200,13 +193,8 @@ endif() 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 - $ - $ -) target_compile_definitions(deps_shared_iface2 - PRIVATE $ TEST_SUBDIR_LIB + PRIVATE TEST_SUBDIR_LIB $<$>:PIC_PROPERTY_IS_ON> $<$>:CUSTOM_PROPERTY_IS_ON> $<$,testcontent>:CUSTOM_STRING_IS_MATCH> diff --git a/Tests/ExportImport/Import/CMakeLists.txt b/Tests/ExportImport/Import/CMakeLists.txt index 3fc78a2..237f8fa 100644 --- a/Tests/ExportImport/Import/CMakeLists.txt +++ b/Tests/ExportImport/Import/CMakeLists.txt @@ -17,3 +17,8 @@ add_executable(imp_testTransExe1 imp_testTransExe1.c) target_link_libraries(imp_testTransExe1 imp_lib1) add_executable(imp_testTransExe1b imp_testTransExe1.c) 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) diff --git a/Tests/ExportImport/Import/package_new_new/CMakeLists.txt b/Tests/ExportImport/Import/package_new_new/CMakeLists.txt new file mode 100644 index 0000000..4e6f642 --- /dev/null +++ b/Tests/ExportImport/Import/package_new_new/CMakeLists.txt @@ -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) diff --git a/Tests/ExportImport/Import/package_new_old/CMakeLists.txt b/Tests/ExportImport/Import/package_new_old/CMakeLists.txt new file mode 100644 index 0000000..e675d64 --- /dev/null +++ b/Tests/ExportImport/Import/package_new_old/CMakeLists.txt @@ -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}) diff --git a/Tests/ExportImport/Import/package_old_old/CMakeLists.txt b/Tests/ExportImport/Import/package_old_old/CMakeLists.txt new file mode 100644 index 0000000..3b27330 --- /dev/null +++ b/Tests/ExportImport/Import/package_old_old/CMakeLists.txt @@ -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}) diff --git a/Tests/Qt4Targets/CMakeLists.txt b/Tests/Qt4Targets/CMakeLists.txt index d3aba74..d0c9c66 100644 --- a/Tests/Qt4Targets/CMakeLists.txt +++ b/Tests/Qt4Targets/CMakeLists.txt @@ -12,29 +12,10 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) add_executable(Qt4Targets WIN32 main.cpp) target_link_libraries(Qt4Targets Qt4::QtGui) -set_property(TARGET Qt4Targets APPEND PROPERTY - INCLUDE_DIRECTORIES - $ -) -set_property(TARGET Qt4Targets APPEND PROPERTY - 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 - $ - $ - ) - set_property(TARGET activeqtexe APPEND PROPERTY - COMPILE_DEFINITIONS - $ - $ - ) endif() endif() -- cgit v0.12