Merge topic 'target-link-libraries-interfaces'
b1f12f8
target_link_libraries: Simplify argument processing state tests5fc95df
target_link_libraries: Add missing space in documentation9143822
target_link_libraries: Add LINK_(PUBLIC|PRIVATE) optionscf64218
target_link_libraries: Trim trailing whitespace
This commit is contained in:
commit
1ec3801a3a
|
@ -95,8 +95,8 @@ bool cmTargetLinkLibrariesCommand
|
||||||
bool haveLLT = false;
|
bool haveLLT = false;
|
||||||
|
|
||||||
// Start with primary linking and switch to link interface
|
// Start with primary linking and switch to link interface
|
||||||
// specification when the keyword is encountered.
|
// specification if the keyword is encountered as the first argument.
|
||||||
this->DoingInterface = false;
|
this->CurrentProcessingState = ProcessingLinkLibraries;
|
||||||
|
|
||||||
// add libraries, nothe that there is an optional prefix
|
// add libraries, nothe that there is an optional prefix
|
||||||
// of debug and optimized than can be used
|
// of debug and optimized than can be used
|
||||||
|
@ -104,7 +104,7 @@ bool cmTargetLinkLibrariesCommand
|
||||||
{
|
{
|
||||||
if(args[i] == "LINK_INTERFACE_LIBRARIES")
|
if(args[i] == "LINK_INTERFACE_LIBRARIES")
|
||||||
{
|
{
|
||||||
this->DoingInterface = true;
|
this->CurrentProcessingState = ProcessingLinkInterface;
|
||||||
if(i != 1)
|
if(i != 1)
|
||||||
{
|
{
|
||||||
this->Makefile->IssueMessage(
|
this->Makefile->IssueMessage(
|
||||||
|
@ -115,6 +115,32 @@ bool cmTargetLinkLibrariesCommand
|
||||||
return true;
|
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")
|
else if(args[i] == "debug")
|
||||||
{
|
{
|
||||||
if(haveLLT)
|
if(haveLLT)
|
||||||
|
@ -186,10 +212,12 @@ bool cmTargetLinkLibrariesCommand
|
||||||
cmSystemTools::SetFatalErrorOccured();
|
cmSystemTools::SetFatalErrorOccured();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the INTERFACE option was given, make sure the
|
// If any of the LINK_ options were given, make sure the
|
||||||
// LINK_INTERFACE_LIBRARIES property exists. This allows the
|
// LINK_INTERFACE_LIBRARIES target property exists.
|
||||||
// command to be used to specify an empty link interface.
|
// Use of any of the new keywords implies awareness of
|
||||||
if(this->DoingInterface &&
|
// 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->GetProperty("LINK_INTERFACE_LIBRARIES"))
|
||||||
{
|
{
|
||||||
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
|
this->Target->SetProperty("LINK_INTERFACE_LIBRARIES", "");
|
||||||
|
@ -217,11 +245,15 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const char* lib,
|
||||||
cmTarget::LinkLibraryType llt)
|
cmTarget::LinkLibraryType llt)
|
||||||
{
|
{
|
||||||
// Handle normal case first.
|
// Handle normal case first.
|
||||||
if(!this->DoingInterface)
|
if(this->CurrentProcessingState != ProcessingLinkInterface)
|
||||||
{
|
{
|
||||||
this->Makefile
|
this->Makefile
|
||||||
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
|
->AddLinkLibraryForTarget(this->Target->GetName(), lib, llt);
|
||||||
return;
|
if (this->CurrentProcessingState != ProcessingPublicInterface)
|
||||||
|
{
|
||||||
|
// Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the list of configurations considered to be DEBUG.
|
// Get the list of configurations considered to be DEBUG.
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
*
|
*
|
||||||
* cmTargetLinkLibrariesCommand is used to specify a list of libraries to link
|
* cmTargetLinkLibrariesCommand is used to specify a list of libraries to link
|
||||||
* into executable(s) or shared objects. The names of the libraries
|
* 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
|
class cmTargetLinkLibrariesCommand : public cmCommand
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* This is a virtual constructor for the command.
|
* This is a virtual constructor for the command.
|
||||||
*/
|
*/
|
||||||
virtual cmCommand* Clone()
|
virtual cmCommand* Clone()
|
||||||
{
|
{
|
||||||
return new cmTargetLinkLibrariesCommand;
|
return new cmTargetLinkLibrariesCommand;
|
||||||
}
|
}
|
||||||
|
@ -47,12 +47,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* Succinct documentation.
|
* Succinct documentation.
|
||||||
*/
|
*/
|
||||||
virtual const char* GetTerseDocumentation()
|
virtual const char* GetTerseDocumentation()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
"Link a target to given libraries.";
|
"Link a target to given libraries.";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* More documentation.
|
* More documentation.
|
||||||
*/
|
*/
|
||||||
|
@ -107,6 +107,18 @@ public:
|
||||||
"Libraries specified as \"general\" (or without any keyword) are "
|
"Libraries specified as \"general\" (or without any keyword) are "
|
||||||
"treated as if specified for both \"debug\" and \"optimized\"."
|
"treated as if specified for both \"debug\" and \"optimized\"."
|
||||||
"\n"
|
"\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 "
|
"The library dependency graph is normally acyclic (a DAG), but in the "
|
||||||
"case of mutually-dependent STATIC libraries CMake allows the graph "
|
"case of mutually-dependent STATIC libraries CMake allows the graph "
|
||||||
"to contain cycles (strongly connected components). "
|
"to contain cycles (strongly connected components). "
|
||||||
|
@ -130,14 +142,21 @@ public:
|
||||||
")"
|
")"
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand);
|
cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand);
|
||||||
private:
|
private:
|
||||||
void LinkLibraryTypeSpecifierWarning(int left, int right);
|
void LinkLibraryTypeSpecifierWarning(int left, int right);
|
||||||
static const char* LinkLibraryTypeNames[3];
|
static const char* LinkLibraryTypeNames[3];
|
||||||
|
|
||||||
cmTarget* Target;
|
cmTarget* Target;
|
||||||
bool DoingInterface;
|
enum ProcessingState {
|
||||||
|
ProcessingLinkLibraries,
|
||||||
|
ProcessingLinkInterface,
|
||||||
|
ProcessingPublicInterface,
|
||||||
|
ProcessingPrivateInterface
|
||||||
|
};
|
||||||
|
|
||||||
|
ProcessingState CurrentProcessingState;
|
||||||
|
|
||||||
void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
|
void HandleLibrary(const char* lib, cmTarget::LinkLibraryType llt);
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 "")
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "depA.h"
|
||||||
|
|
||||||
|
int DepA::foo()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "depa_export.h"
|
||||||
|
|
||||||
|
struct DEPA_EXPORT DepA
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#include "depB.h"
|
||||||
|
|
||||||
|
#include "depA.h"
|
||||||
|
|
||||||
|
int DepB::foo()
|
||||||
|
{
|
||||||
|
DepA a;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
#include "depb_export.h"
|
||||||
|
|
||||||
|
struct DEPB_EXPORT DepB
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
};
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
#include "depC.h"
|
||||||
|
|
||||||
|
int DepC::foo()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DepA DepC::getA()
|
||||||
|
{
|
||||||
|
DepA a;
|
||||||
|
return a;
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
|
||||||
|
#include "depc_export.h"
|
||||||
|
|
||||||
|
#include "depA.h"
|
||||||
|
|
||||||
|
struct DEPC_EXPORT DepC
|
||||||
|
{
|
||||||
|
int foo();
|
||||||
|
|
||||||
|
DepA getA();
|
||||||
|
|
||||||
|
};
|
|
@ -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();
|
||||||
|
}
|
|
@ -1658,6 +1658,8 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
|
||||||
-P "${CMake_SOURCE_DIR}/Tests/CMakeCommands/build_command/RunCMake.cmake"
|
-P "${CMake_SOURCE_DIR}/Tests/CMakeCommands/build_command/RunCMake.cmake"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
ADD_TEST_MACRO(CMakeCommands.target_link_libraries target_link_libraries)
|
||||||
|
|
||||||
CONFIGURE_FILE(
|
CONFIGURE_FILE(
|
||||||
"${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
|
"${CMake_SOURCE_DIR}/Tests/CTestTestCrash/test.cmake.in"
|
||||||
"${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake"
|
"${CMake_BINARY_DIR}/Tests/CTestTestCrash/test.cmake"
|
||||||
|
|
Loading…
Reference in New Issue