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;
|
||||
|
||||
// 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,10 +212,12 @@ 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 &&
|
||||
// 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)
|
||||
{
|
||||
// Not LINK_INTERFACE_LIBRARIES or LINK_PUBLIC, do not add to interface.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get the list of configurations considered to be DEBUG.
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
@ -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). "
|
||||
|
@ -130,14 +142,21 @@ public:
|
|||
")"
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
cmTypeMacro(cmTargetLinkLibrariesCommand, cmCommand);
|
||||
private:
|
||||
void LinkLibraryTypeSpecifierWarning(int left, int right);
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
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"
|
||||
|
|
Loading…
Reference in New Issue