From cf64218eeb7dbe8a0d71292c42df63c4cb982fed Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 2 Nov 2011 12:43:01 +0100 Subject: [PATCH 1/4] target_link_libraries: Trim trailing whitespace --- Source/cmTargetLinkLibrariesCommand.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index ce57df7f2..a9b5d8bb7 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -19,7 +19,7 @@ * * cmTargetLinkLibrariesCommand is used to specify a list of libraries to link * into executable(s) or shared objects. The names of the libraries - * should be those defined by the LIBRARY(library) command(s). + * should be those defined by the LIBRARY(library) command(s). */ class cmTargetLinkLibrariesCommand : public cmCommand { @@ -27,7 +27,7 @@ public: /** * This is a virtual constructor for the command. */ - virtual cmCommand* Clone() + virtual cmCommand* Clone() { return new cmTargetLinkLibrariesCommand; } @@ -47,12 +47,12 @@ public: /** * Succinct documentation. */ - virtual const char* GetTerseDocumentation() + virtual const char* GetTerseDocumentation() { - return + return "Link a target to given libraries."; } - + /** * More documentation. */ @@ -130,7 +130,7 @@ public: ")" ; } - + cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand); private: void LinkLibraryTypeSpecifierWarning(int left, int right); From 914382224d34cfb86a67c8191b6e7b3a3e918f88 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Fri, 7 Oct 2011 02:41:37 +0200 Subject: [PATCH 2/4] target_link_libraries: Add LINK_(PUBLIC|PRIVATE) options Makes it possible to specify the link dependencies and link interfaces in one command without repetition. --- Source/cmTargetLinkLibrariesCommand.cxx | 52 +++++++++++++---- Source/cmTargetLinkLibrariesCommand.h | 21 ++++++- .../target_link_libraries/CMakeLists.txt | 58 +++++++++++++++++++ .../target_link_libraries/depA.cpp | 7 +++ .../target_link_libraries/depA.h | 7 +++ .../target_link_libraries/depB.cpp | 11 ++++ .../target_link_libraries/depB.h | 7 +++ .../target_link_libraries/depC.cpp | 13 +++++ .../target_link_libraries/depC.h | 12 ++++ .../target_link_libraries/targetA.cpp | 12 ++++ Tests/CMakeLists.txt | 2 + 11 files changed, 191 insertions(+), 11 deletions(-) create mode 100644 Tests/CMakeCommands/target_link_libraries/CMakeLists.txt create mode 100644 Tests/CMakeCommands/target_link_libraries/depA.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depA.h create mode 100644 Tests/CMakeCommands/target_link_libraries/depB.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depB.h create mode 100644 Tests/CMakeCommands/target_link_libraries/depC.cpp create mode 100644 Tests/CMakeCommands/target_link_libraries/depC.h create mode 100644 Tests/CMakeCommands/target_link_libraries/targetA.cpp diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 805959def..0db5943bb 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -95,8 +95,8 @@ bool cmTargetLinkLibrariesCommand bool haveLLT = false; // Start with primary linking and switch to link interface - // specification when the keyword is encountered. - this->DoingInterface = false; + // specification if the keyword is encountered as the first argument. + this->CurrentProcessingState = ProcessingLinkLibraries; // add libraries, nothe that there is an optional prefix // of debug and optimized than can be used @@ -104,7 +104,7 @@ bool cmTargetLinkLibrariesCommand { if(args[i] == "LINK_INTERFACE_LIBRARIES") { - this->DoingInterface = true; + this->CurrentProcessingState = ProcessingLinkInterface; if(i != 1) { this->Makefile->IssueMessage( @@ -115,6 +115,32 @@ bool cmTargetLinkLibrariesCommand return true; } } + else if(args[i] == "LINK_PUBLIC") + { + if(i != 1 && this->CurrentProcessingState != ProcessingPrivateInterface) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " + "argument, just after the target name." + ); + return true; + } + this->CurrentProcessingState = ProcessingPublicInterface; + } + else if(args[i] == "LINK_PRIVATE") + { + if(i != 1 && this->CurrentProcessingState != ProcessingPublicInterface) + { + this->Makefile->IssueMessage( + cmake::FATAL_ERROR, + "The LINK_PUBLIC or LINK_PRIVATE option must appear as the second " + "argument, just after the target name." + ); + return true; + } + this->CurrentProcessingState = ProcessingPrivateInterface; + } else if(args[i] == "debug") { if(haveLLT) @@ -186,11 +212,13 @@ bool cmTargetLinkLibrariesCommand cmSystemTools::SetFatalErrorOccured(); } - // If the INTERFACE option was given, make sure the - // LINK_INTERFACE_LIBRARIES property exists. This allows the - // command to be used to specify an empty link interface. - if(this->DoingInterface && - !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) + // If any of the LINK_ options were given, make sure the + // LINK_INTERFACE_LIBRARIES target property exists. + // Use of any of the new keywords implies awareness of + // this property. And if no libraries are named, it should + // result in an empty link interface. + if((this->CurrentProcessingState != ProcessingLinkLibraries) + && !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) { this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); } @@ -217,11 +245,15 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt) { // Handle normal case first. - if(!this->DoingInterface) + if(this->CurrentProcessingState != ProcessingLinkInterface) { this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); - return; + if (this->CurrentProcessingState != ProcessingPublicInterface + || this->CurrentProcessingState == ProcessingPrivateInterface) + { + return; + } } // Get the list of configurations considered to be DEBUG. diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index a9b5d8bb7..e91c46dfe 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -107,6 +107,18 @@ public: "Libraries specified as \"general\" (or without any keyword) are " "treated as if specified for both \"debug\" and \"optimized\"." "\n" + " target_link_libraries(\n" + " \n" + " [[debug|optimized|general] ] ...\n" + " [\n" + " [[debug|optimized|general] ] ...])\n" + "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both the" + "link dependencies and the link interface in one command. " + "Libraries and targets following LINK_PUBLIC are linked to, and are " + "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets " + "following LINK_PRIVATE are linked to, but are not made part of the " + "LINK_INTERFACE_LIBRARIES. " + "\n" "The library dependency graph is normally acyclic (a DAG), but in the " "case of mutually-dependent STATIC libraries CMake allows the graph " "to contain cycles (strongly connected components). " @@ -137,7 +149,14 @@ private: static const char* LinkLibraryTypeNames[3]; cmTarget* Target; - bool DoingInterface; + enum ProcessingState { + ProcessingLinkLibraries, + ProcessingLinkInterface, + ProcessingPublicInterface, + ProcessingPrivateInterface + }; + + ProcessingState CurrentProcessingState; void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt); }; diff --git a/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt new file mode 100644 index 000000000..1faa88848 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 2.8) + +project(target_link_libraries) + +file(WRITE + "${CMAKE_CURRENT_BINARY_DIR}/main.cxx" + "int main() { return 0; } +" +) + +add_executable( + target_link_libraries + "${CMAKE_CURRENT_BINARY_DIR}/main.cxx" +) + +macro(ASSERT_PROPERTY _target _property _value) + get_target_property(_out ${_target} ${_property}) + if (NOT _out) + set(_out "") + endif() + if (NOT "${_out}" STREQUAL "${_value}") + message(SEND_ERROR "Target ${_target} does not have property ${_property} with value ${_value}. Actual value: ${_out}") + endif() +endmacro() + +include(GenerateExportHeader) +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +add_library(depA SHARED depA.cpp) +generate_export_header(depA) + +add_library(depB SHARED depB.cpp) +generate_export_header(depB) + +target_link_libraries(depB LINK_PRIVATE depA) + +add_library(depC SHARED depC.cpp) +generate_export_header(depC) + +target_link_libraries(depC LINK_PUBLIC depA) + +assert_property(depA LINK_INTERFACE_LIBRARIES "") +assert_property(depB LINK_INTERFACE_LIBRARIES "") +assert_property(depC LINK_INTERFACE_LIBRARIES "depA") + +add_executable(targetA targetA.cpp) + +target_link_libraries(targetA LINK_INTERFACE_LIBRARIES depA depB) + +assert_property(targetA LINK_INTERFACE_LIBRARIES "depA;depB") + +set_target_properties(targetA PROPERTIES LINK_INTERFACE_LIBRARIES "") + +assert_property(targetA LINK_INTERFACE_LIBRARIES "") + +target_link_libraries(targetA depB depC) + +assert_property(targetA LINK_INTERFACE_LIBRARIES "") diff --git a/Tests/CMakeCommands/target_link_libraries/depA.cpp b/Tests/CMakeCommands/target_link_libraries/depA.cpp new file mode 100644 index 000000000..c2e8e7b9a --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depA.cpp @@ -0,0 +1,7 @@ + +#include "depA.h" + +int DepA::foo() +{ + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depA.h b/Tests/CMakeCommands/target_link_libraries/depA.h new file mode 100644 index 000000000..7a859488b --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depA.h @@ -0,0 +1,7 @@ + +#include "depa_export.h" + +struct DEPA_EXPORT DepA +{ + int foo(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/depB.cpp b/Tests/CMakeCommands/target_link_libraries/depB.cpp new file mode 100644 index 000000000..97e5be274 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depB.cpp @@ -0,0 +1,11 @@ + +#include "depB.h" + +#include "depA.h" + +int DepB::foo() +{ + DepA a; + + return 0; +} diff --git a/Tests/CMakeCommands/target_link_libraries/depB.h b/Tests/CMakeCommands/target_link_libraries/depB.h new file mode 100644 index 000000000..e617813ba --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depB.h @@ -0,0 +1,7 @@ + +#include "depb_export.h" + +struct DEPB_EXPORT DepB +{ + int foo(); +}; diff --git a/Tests/CMakeCommands/target_link_libraries/depC.cpp b/Tests/CMakeCommands/target_link_libraries/depC.cpp new file mode 100644 index 000000000..93410a8f2 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depC.cpp @@ -0,0 +1,13 @@ + +#include "depC.h" + +int DepC::foo() +{ + return 0; +} + +DepA DepC::getA() +{ + DepA a; + return a; +} \ No newline at end of file diff --git a/Tests/CMakeCommands/target_link_libraries/depC.h b/Tests/CMakeCommands/target_link_libraries/depC.h new file mode 100644 index 000000000..4d65c9eb3 --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/depC.h @@ -0,0 +1,12 @@ + +#include "depc_export.h" + +#include "depA.h" + +struct DEPC_EXPORT DepC +{ + int foo(); + + DepA getA(); + +}; diff --git a/Tests/CMakeCommands/target_link_libraries/targetA.cpp b/Tests/CMakeCommands/target_link_libraries/targetA.cpp new file mode 100644 index 000000000..3c6472e9a --- /dev/null +++ b/Tests/CMakeCommands/target_link_libraries/targetA.cpp @@ -0,0 +1,12 @@ + +#include "depB.h" +#include "depC.h" + +int main(int argc, char **argv) +{ + DepA a; + DepB b; + DepC c; + + return a.foo() + b.foo() + c.foo(); +} diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index 78db39d6f..44ed2f594 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -1574,6 +1574,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/ -P "${CMake_SOURCE_DIR}/Tests/CMakeCommands/build_command/RunCMake.cmake" ) + ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries) + CONFIGURE_FILE( "${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in" "${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake" From 5fc95dff464b08c83df2c904a281bb4c45278a35 Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 22 Nov 2011 17:19:04 -0500 Subject: [PATCH 3/4] target_link_libraries: Add missing space in documentation Change "thelink" to "the link". --- Source/cmTargetLinkLibrariesCommand.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h index e91c46dfe..8df4ac0e8 100644 --- a/Source/cmTargetLinkLibrariesCommand.h +++ b/Source/cmTargetLinkLibrariesCommand.h @@ -112,8 +112,8 @@ public: " [[debug|optimized|general] ] ...\n" " [\n" " [[debug|optimized|general] ] ...])\n" - "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both the" - "link dependencies and the link interface in one command. " + "The LINK_PUBLIC and LINK_PRIVATE modes can be used to specify both " + "the link dependencies and the link interface in one command. " "Libraries and targets following LINK_PUBLIC are linked to, and are " "made part of the LINK_INTERFACE_LIBRARIES. Libraries and targets " "following LINK_PRIVATE are linked to, but are not made part of the " From b1f12f8042ef0d7b190c04644905d3b3a325d4ae Mon Sep 17 00:00:00 2001 From: Brad King Date: Tue, 22 Nov 2011 17:20:23 -0500 Subject: [PATCH 4/4] target_link_libraries: Simplify argument processing state tests Remove extra parens in test for not handling LINK_INTERFACE_LIBRARIES. Remove redundant test for equality with ProcessingPrivateInterface subsumed by test for inequality with ProcessingPublicInterface. --- Source/cmTargetLinkLibrariesCommand.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 0db5943bb..36c4ca8bd 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -217,8 +217,8 @@ bool cmTargetLinkLibrariesCommand // Use of any of the new keywords implies awareness of // this property. And if no libraries are named, it should // result in an empty link interface. - if((this->CurrentProcessingState != ProcessingLinkLibraries) - && !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) + if(this->CurrentProcessingState != ProcessingLinkLibraries && + !this->Target->GetProperty("LINK_INTERFACE_LIBRARIES")) { this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", ""); } @@ -249,9 +249,9 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib, { this->Makefile ->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt); - if (this->CurrentProcessingState != ProcessingPublicInterface - || this->CurrentProcessingState == ProcessingPrivateInterface) + if (this->CurrentProcessingState != ProcessingPublicInterface) { + // Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface. return; } }