2011-10-07 04:41:37 +04:00
|
|
|
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)
|
|
|
|
|
2012-12-06 15:14:03 +04:00
|
|
|
add_library(libgenex SHARED libgenex.cpp)
|
|
|
|
generate_export_header(libgenex)
|
|
|
|
|
|
|
|
set_property(TARGET depB APPEND PROPERTY
|
|
|
|
LINK_LIBRARIES $<1:libgenex>
|
|
|
|
)
|
|
|
|
|
2011-10-07 04:41:37 +04:00
|
|
|
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 "")
|
|
|
|
|
2012-11-25 04:15:44 +04:00
|
|
|
add_subdirectory(subdir)
|
|
|
|
target_link_libraries(targetA subdirlib)
|
|
|
|
|
2011-10-07 04:41:37 +04:00
|
|
|
target_link_libraries(targetA depB depC)
|
|
|
|
|
|
|
|
assert_property(targetA LINK_INTERFACE_LIBRARIES "")
|
2012-12-26 13:58:21 +04:00
|
|
|
|
|
|
|
# Exclude depIfaceOnly from ALL so that it will only be built if something
|
|
|
|
# depends on it. As it is in the link interface of depB, targetA
|
|
|
|
# will depend on it. That dependency is what is being tested here.
|
|
|
|
add_library(depIfaceOnly SHARED EXCLUDE_FROM_ALL depIfaceOnly.cpp)
|
|
|
|
generate_export_header(depIfaceOnly)
|
|
|
|
set_property(TARGET depB APPEND PROPERTY LINK_INTERFACE_LIBRARIES depIfaceOnly)
|
Allow generator expressions in LINK_INTERFACE_LIBRARIES.
The Config and IMPORTED_ variants may also contain generator
expressions.
If 'the implementation is the interface', then the result of
evaluating the expressions at generate time is used to populate
the IMPORTED_LINK_INTERFACE_LIBRARIES property.
1) In the case of non-static libraries, this is fine because the
user still has the option to populate the LINK_INTERFACE_LIBRARIES
with generator expressions if that is what is wanted.
2) In the case of static libraries, this prevents a footgun,
enforcing that the interface and the implementation are really
the same.
Otherwise, the LINK_LIBRARIES could contain a generator
expression which is evaluated with a different context at build
time, and when used as an imported target. That would mean that the
result of evaluating the INTERFACE_LINK_LIBRARIES property for
a static library would not necessarily be the 'link implementation'.
For example:
add_library(libone STATIC libone.cpp)
add_library(libtwo STATIC libtwo.cpp)
add_library(libthree STATIC libthree.cpp)
target_link_libraries(libtwo
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,STATIC_LIBRARY>:libone>)
target_link_libraries(libthree libtwo)
If the LINK_LIBRARIES content was simply copied to the
IMPORTED_LINK_INTERFACE_LIBRARIES, then libthree links to libone, but
executables linking to libthree will not link to libone.
3) As the 'implementation is the interface' concept is to be
deprecated in the future anyway, this should be fine.
2013-01-04 16:36:18 +04:00
|
|
|
|
|
|
|
add_library(depD SHARED depD.cpp)
|
|
|
|
generate_export_header(depD)
|
|
|
|
set_property(TARGET depD APPEND PROPERTY
|
|
|
|
LINK_INTERFACE_LIBRARIES
|
|
|
|
$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depA>
|
|
|
|
)
|
|
|
|
|
|
|
|
add_executable(targetB targetB.cpp)
|
|
|
|
target_link_libraries(targetB depD)
|
2012-11-05 15:43:28 +04:00
|
|
|
|
|
|
|
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)
|
2013-02-07 15:33:20 +04:00
|
|
|
# Creates a generator expression for include directories like
|
|
|
|
# $<$<TARGET_DEFINED:$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depG>>:\
|
|
|
|
# $<TARGET_PROPERTY:$<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depG>,INTERFACE_INCLUDE_DIRECTORIES>>
|
|
|
|
target_link_libraries(targetC $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:depG>)
|