我有一个令人费解的问题。我有第三方依赖,它是静态的(libthird.a
)和共享的pic形式(libthird.so
)。
我有一个库util
,它取决于libthird
。
我的应用程序依赖于util
想要静态链接libthird
的应用程序,并且我需要生成一些依赖于util
并需要链接{{}的共享库1}}动态。
我目前的(工作)方法如下:
libthird
这很有效。但是我正在构建add_library(third INTERFACE)
target_link_libraries(third INTERFACE /path/to/libthird.a)
add_library(third_shared INTERFACE)
target_link_libraries(third_shared INTERFACE /path/to/libthird.so)
add_library(util ${UTIL_SOURCES})
add_library(util_shared ${UTIL_SOURCES}) # same sources again!!
target_link_libraries(util PUBLIC third)
target_link_libraries(util_shared PUBLIC third_shared)
add_executable(some_app ...)
target_link_libraries(some_app PRIVATE util)
add_library(some_shared_object ...)
target_link_libraries(some_shared_object PUBLIC util_shared)
(实际上,另外还有六十几个库)两次......只是为了获得不同的链接器依赖性。在cmake中有更好的方法吗?
如果我只是在util
和target_link_libraries()
上some_app
,我会以错误的顺序发出链接器标志,因为some_shared_object
确实依赖于{{ 1}}。
答案 0 :(得分:1)
你所采取的方法绝对是我见过的,也是以前用过的。如果它用于小型存档和/或一次性使用,则可以。
对于以下示例,我假设一个项目结构如下:
foo/
CMakeLists.txt
include/
foo.h
src/
foo.c
所以,我(天真地?)使用以下方法,基于您可以从静态存档创建(在基于Unix的系统上)共享库的知识。
project(foo C)
set(SOURCES
"src/foo.c")
set(LIBNAME "foo")
add_library(${LIBNAME} STATIC ${SOURCES})
target_include_directories(${LIBNAME} PUBLIC "include")
target_compile_options(${LIBNAME} PUBLIC "-fPIC")
#
get_property(CUR_PREFIX TARGET ${LIBNAME} PROPERTY PREFIX)
get_property(CUR_SUFFIX TARGET ${LIBNAME} PROPERTY SUFFIX)
get_property(CUR_NAME TARGET ${LIBNAME} PROPERTY NAME)
get_property(CUR_OUTPUT_NAME TARGET ${LIBNAME} PROPERTY OUTPUT_NAME)
get_property(CUR_ARCHIVE_OUTPUT_NAME TARGET ${LIBNAME} PROPERTY ARCHIVE_OUTPUT_NAME)
message(STATUS "prefix: ${CUR_PREFIX}")
message(STATUS "suffix: ${CUR_SUFFIX}")
message(STATUS "name: ${CUR_NAME}")
message(STATUS "output name: ${CUR_OUTPUT_NAME}")
message(STATUS "archive name: ${CUR_ARCHIVE_OUTPUT_NAME}")
add_custom_command(TARGET ${LIBNAME} POST_BUILD
COMMAND ${CMAKE_C_COMPILER} -shared -o libfoo.so -Wl,--whole-archive libfoo.a -Wl,--no-whole-archive
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
这种方法我未解决的问题是我没有找到一种可靠且可移植的方法来获取静态存档的名称(libfoo.a
)。因此,target properties的所有message
命令;他们可能会在您的平台上表现不同。
cmake
支持得最有效的方法是使用object library:
# cmake file
cmake_minimum_required(VERSION 3.2)
project(foo C)
set(SOURCES
"src/foo.c")
set(LIBNAME "foo")
set(LIBNAME_OBJ "${LIBNAME}_obj")
add_library(${LIBNAME_OBJ} OBJECT ${SOURCES})
target_include_directories(${LIBNAME_OBJ} PUBLIC "include")
target_compile_options(${LIBNAME_OBJ} PUBLIC "-fPIC")
#
add_library(${LIBNAME} SHARED $<TARGET_OBJECTS:${LIBNAME_OBJ}>)
add_library(${LIBNAME}_static STATIC $<TARGET_OBJECTS:${LIBNAME_OBJ}>)
所有示例均使用cmake版本3.6.1进行测试。
希望这会有所帮助。如果您找到了更好的方法,请告诉我们。