CMake:导入的库作为另一个自定义命令或目标的OUTPUT或BYPRODUCTS

时间:2015-12-23 15:35:32

标签: cmake shared-libraries static-libraries

我想从ZIP文件中提取静态库并链接到它。

具有以下设置:

add_library(COMSDK_LIB STATIC IMPORTED GLOBAL)
set_property(TARGET COMSDK_LIB PROPERTY IMPORTED_LOCATION "/tmp/lib/libRTSClientSdk.a")

导入的库在另一个CMakeLists.txt中使用:

target_link_libraries(mylib COMSDK_LIB)

导入的库是否可能由其他add_custom_commandadd_custom_target生成?

我尝试了以下操作,但确实工作:

add_custom_command(
    OUTPUT "/tmp/lib/libRTSClientSdk.a"
    COMMAND unzip -x client_sdk.zip -o /tmp
    DEPENDS client_sdk.zip
)

给出的错误消息是:

$ ninja
ninja: error: '/tmp/lib/libRTSClientSdk.a', needed by 'mylib.dll', missing and no known rule to make it

1 个答案:

答案 0 :(得分:1)

问题在于您的自定义命令正在make步骤中执行,并且它期望在cmake执行期间更早地提取依赖关系。所以,基本上,你需要从SDK 获取静态库你在CMake规则中或在连接过程中使用它。

CMake mailing list中列出了两种可能的解决方案。

解决方案#1 :(在CMake端执行)

重新编写其中一个代码段,在CMake执行期间正在进行下载和解压缩:

set(CLIENTSDK_ZIP "cliendsdk.zip")
set(CLIENTSDK_URL "http://example.com/${CLIENTSDK_ZIP}")
set(CLIENTSDK_LIB "libRTSClientSdk.a")
set(CLIENTSDK_OUTPUT_DIR "/tmp/sdk/dir")

# Basically just downloading zip file:
message(STATUS "Downloading ${CLIENTSDK_URL}")
execute_process(COMMAND wget ${CLIENTSDK_URL}
  WORKING_DIRECTORY ${CLIENTSDK_OUTPUT_DIR}
  RESULT_VARIABLE errno
  ERROR_VARIABLE err)

if (NOT ${errno} EQUAL 0)
  message(ERROR "Failed downloading ${CLIENTSDK_URL}. Code: ${err}")
endif()

# Extracting downloaded zip file:
message(STATUS "Extracting ${CLIENTSDK_ZIP})
execute_process(COMMAND unzip ${CLIENTSDK_ZIP}
  WORKING_DIRECTORY ${CLIENTSDK_OUTPUT_DIR}
  RESULT_VARIABLE errno
  ERROR_VARIABLE err)

if (NOT ${errno} EQUAL 0)
  message(ERROR "Failed extracting ${CLIENTSDK_ZIP}. Code: ${err}")
endif()

# Importing into CMake scope one library from extracted zip:
add_library(specific_sdk_lib STATIC IMPORTED)
set_target_properties(specific_sdk_lib
  PROPERTIES IMPORTED_LOCATION ${CLIENTSDK_OUTPUT_DIR}/lib/${CLIENTSDK_LIB})

# Adding rule for linking to specific static library from extracted zip:
target_link_libraries(mylib specific_sdk_lib)

解决方案#2 (在制作方执行):

# We must include ExternalProject CMake module first!
include("ExternalProject")

set(CLIENTSDK_URL "http://example.com/clientsdk.zip")
set(CLIENTSDK_LIB "libRTSClientSdk.a")
set(CLIENTSDK_PREFIX "3rd_party")
set(CLIENTSDK_EXTRACTED_DIR
    "${CMAKE_CURRENT_BINARY_DIR}/${CLIENTSDK_PREFIX}/src/DownloadClientSDK/")

ExternalProject_Add("DownloadClientSDK"
    PREFIX ${CLIENTSDK_PREFIX}
    URL "${CLIENTSDK_URL}"
    # Suppress ExternalProject configure/build/install targets:
    CONFIGURE_COMMAND ""
    BUILD_COMMAND ""
    INSTALL_COMMAND "")

add_library(COMSDK_LIB STATIC IMPORTED)
set_target_properties(COMSDK_LIB PROPERTIES IMPORTED_LOCATION
    ${CLIENTSDK_EXTRACTED_DIR}/${CLIENTSDK_LIB})

# Require all that download/unzip mumbojumbo only for COMSDK_LIB:
add_dependencies(COMSDK_LIB DownloadClientSDK)

target_link_libraries(my_library COMSDK_LIB)

基本上,CMake及其ExternalProject模块负责(生成适当的make目标)识别归档格式,解压缩,如果需要 - 配置,构建和安装。