summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Kelly <steveire@gmail.com>2011-10-07 00:41:37 (GMT)
committerBrad King <brad.king@kitware.com>2011-11-22 21:52:35 (GMT)
commit914382224d34cfb86a67c8191b6e7b3a3e918f88 (patch)
treef5796b3ff7095e8e0fad805fe219aead007b57d3
parentcf64218eeb7dbe8a0d71292c42df63c4cb982fed (diff)
downloadCMake-914382224d34cfb86a67c8191b6e7b3a3e918f88.zip
CMake-914382224d34cfb86a67c8191b6e7b3a3e918f88.tar.gz
CMake-914382224d34cfb86a67c8191b6e7b3a3e918f88.tar.bz2
target_link_libraries: Add LINK_(PUBLIC|PRIVATE) options
Makes it possible to specify the link dependencies and link interfaces in one command without repetition.
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx52
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h21
-rw-r--r--Tests/CMakeCommands/target_link_libraries/CMakeLists.txt58
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depA.cpp7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depA.h7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depB.cpp11
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depB.h7
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depC.cpp13
-rw-r--r--Tests/CMakeCommands/target_link_libraries/depC.h12
-rw-r--r--Tests/CMakeCommands/target_link_libraries/targetA.cpp12
-rw-r--r--Tests/CMakeLists.txt2
11 files changed, 191 insertions, 11 deletions
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index 805959d..0db5943 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 a9b5d8b..e91c46d 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(<target>\n"
+ " <LINK_PRIVATE|LINK_PUBLIC>\n"
+ " [[debug|optimized|general] <lib>] ...\n"
+ " [<LINK_PRIVATE|LINK_PUBLIC>\n"
+ " [[debug|optimized|general] <lib>] ...])\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 0000000..1faa888
--- /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 0000000..c2e8e7b
--- /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 0000000..7a85948
--- /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 0000000..97e5be2
--- /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 0000000..e617813
--- /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 0000000..93410a8
--- /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 0000000..4d65c9e
--- /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 0000000..3c6472e
--- /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 78db39d..44ed2f5 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"