首页 > 解决方案 > CMake:正确安装多个构建工件

问题描述

ADD_CUSTOM_TARGET用来构建生成数十个静态库的 make 项目。然后我想install正确地让其他项目能够使用这些构建结果。我到底应该怎么做?

据我了解,我必须为每个库创建目标,然后创建mylib-config.cmake引用这些目标。在看了这里和那里之后,我想出了这样的东西

#... here comes ADD_CUSTOM_TARGET to build my Makefile project...
FILE(WRITE "share/dpdk-config.cmake" "include(CMakeFindDependencyMacro)\n")
FILE(GLOB LIBS ${CMAKE_SOURCE_DIR}/build/lib/*.a)
FOREACH (LIB_FILE_NAME ${LIBS})
    GET_FILENAME_COMPONENT(LIB_NAME ${LIB_FILE_NAME} NAME_WE)
    SET(TARGET_NAME ${LIB_NAME}_target)
    ADD_CUSTOM_TARGET(${TARGET_NAME} DEPENDS ${LIB})
    ADD_LIBRARY(${LIB_NAME} STATIC IMPORTED GLOBAL)
    ADD_DEPENDENCIES(${LIB_NAME} ${TARGET_NAME})
    SET_TARGET_PROPERTIES(${LIB_NAME}
                          PROPERTIES
                          IMPORTED_LOCATION ${LIB_FILE_NAME}
                          INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/include
                          )
    INSTALL(TARGETS ${LIB_NAME}
            EXPORT ${TARGET_NAME}
            ARCHIVE DESTINATION ${CMAKE_SOURCE_DIR}/build/lib
            )

    INSTALL(
            EXPORT ${TARGET_NAME}
            DESTINATION share/dpdk
    )
    FILE(APPEND "share/dpdk-config.cmake" "include(share/dpdk/${TARGET_NAME}.cmake)\n")

    #    MESSAGE(STATUS "Library file: ${LIB_FILE_NAME}")
    #    MESSAGE(STATUS "Library: ${LIB_NAME}")
    #    MESSAGE(STATUS "Library target: ${TARGET_NAME}")
ENDFOREACH ()

INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/build/lib
        DESTINATION ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/)

INSTALL(DIRECTORY ${CMAKE_SOURCE_DIR}/build/include
        DESTINATION ${CMAKE_SOURCE_DIR}/${CMAKE_BUILD_TYPE}/)

首先,我不确定这是正确的方法,其次,它不起作用。任何帮助将不胜感激

编辑:好的,这种方法不起作用,因为无法导出导入的库。请参阅CMake 问题 #14311

标签: cmake

解决方案


好吧,实际上我的赌注已经足够接近了。INSTALL将不起作用,但您可以使用它ConfigXXX.cmake来收集所有必要的信息、创建导出的库、添加必要的属性和瞧。例如,可以拿起英特尔的 TBB,它有类似的问题,他们通过上述方法解决了。我只是根据他们的脚本创建了一个函数

FUNCTION(SET_LIBRARY_TARGET LIB_FILE_NAME INCLUDE_DIR ISDEBUG)
    SET(POSTFIX "_release")
    IF (${ISDEBUG})
        SET(POSTFIX "_debug")
    ENDIF ()

    GET_FILENAME_COMPONENT(LIB_NAME ${LIB_FILE_NAME} NAME_WE)

    STRING(REPLACE "librte_" "" LIB_NAME "${LIB_NAME}")
    STRING(REPLACE "libdpdk" "dpdk" LIB_NAME "${LIB_NAME}")
    STRING(APPEND LIB_NAME "${POSTFIX}")

    ADD_LIBRARY(DPDK::${LIB_NAME} STATIC IMPORTED)
    SET_TARGET_PROPERTIES(DPDK::${LIB_NAME} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIR}")

    IF (${ISDEBUG})
        SET_PROPERTY(TARGET DPDK::${LIB_NAME} APPEND PROPERTY IMPORTED_LOCATION_DEBUG "${LIB_FILE_NAME}")
        SET_PROPERTY(TARGET DPDK::${LIB_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
    ELSE ()
        SET_PROPERTY(TARGET DPDK::${LIB_NAME} APPEND PROPERTY IMPORTED_LOCATION_RELEASE "${LIB_FILE_NAME}")
        SET_PROPERTY(TARGET DPDK::${LIB_NAME} APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
    ENDIF ()

    SET(DPDK_${LIB_NAME}_FOUND 1)
ENDFUNCTION()

我想它可以比这更优雅,做我的客人来改进它

EDIT001:更干净紧凑的版本

FUNCTION(SET_LIBRARY_TARGET NAMESPACE LIB_NAME DEBUG_LIB_FILE_NAME RELEASE_LIB_FILE_NAME INCLUDE_DIR)
    ADD_LIBRARY(${NAMESPACE}::${LIB_NAME} STATIC IMPORTED)
    SET_TARGET_PROPERTIES(${NAMESPACE}::${LIB_NAME} PROPERTIES
                          IMPORTED_CONFIGURATIONS "RELEASE;DEBUG"
                          IMPORTED_LOCATION_RELEASE "${RELEASE_LIB_FILE_NAME}"
                          IMPORTED_LOCATION_DEBUG "${DEBUG_LIB_FILE_NAME}"
                          INTERFACE_INCLUDE_DIRECTORIES "${INCLUDE_DIR}"
                          )
    SET(${NAMESPACE}_${LIB_NAME}_FOUND 1)
ENDFUNCTION()

推荐阅读