首页 > 解决方案 > 我如何分发使用 cmake 构建的静态库

问题描述

我有一个 cmake 项目,它是一个静态库,我必须与我公司的其他团队共享,但只有 .lib 文件而不是源代码。这个库依赖于 Boost。

现在我构建库并将安装文件夹转移到另一台电脑(exe_pc)并在exe项目中使用它(这个exe也依赖于boost)。现在在编译时我收到一个链接错误,说E:/Development/vcpkg/installed/x64-windows/lib/boost_system-vc140-mt.lib无法打开。

所以我打开并检查生成的 LibTargets.cmake,它包含构建库的 pc 的 boost 库的绝对路径。

# The installation prefix configured by this project.
set(_IMPORT_PREFIX "C:/Program Files/cpp_licensing")

# Create imported target Licensing::liblicensing
add_library(Licensing::liblicensing STATIC IMPORTED)

set_target_properties(Licensing::liblicensing PROPERTIES
  INTERFACE_COMPILE_DEFINITIONS "_LICENSING_DEBUG=0"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "\$<\$<NOT:\$<CONFIG:DEBUG>>:E:/Development/vcpkg/installed/x64-windows/lib/boost_system-vc140-mt.lib>;\$<\$<CONFIG:DEBUG>:E:/Development/vcpkg/installed/x64-windows/debug/lib/boost_system-vc140-mt-gd.lib>;\$<\$<NOT:\$<CONFIG:DEBUG>>:E:/Development/vcpkg/installed/x64-windows/lib/boost_filesystem-vc140-mt.lib>;\$<\$<CONFIG:DEBUG>:E:/Development/vcpkg/installed/x64-windows/debug/lib/boost_filesystem-vc140-mt-gd.lib>;cryptopp-static;wbemuuid"
)

LibLicensingTargets-release.cmake

et_target_properties(Licensing::liblicensing PROPERTIES
  IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX"
  IMPORTED_LOCATION_RELEASE "C:/Program Files/cpp_licensing/lib/licensing.lib"
  )

list(APPEND _IMPORT_CHECK_TARGETS Licensing::liblicensing )
list(APPEND _IMPORT_CHECK_FILES_FOR_Licensing::liblicensing "C:/Program Files/cpp_licensing/lib/licensing.lib" )

用户应该安装了 boost,我唯一的问题是,因为目标文件中使用了绝对路径,所以用户必须在他的 pc 上的目标文件中手动更改它们。

我对 cmake 做了哪些更改,以便可以共享库构建的文件夹。我如何分发使用 cmake 构建的库?

这是图书馆项目的cmake

cmake_minimum_required(VERSION 3.10)
project(liblicensing)

message("~~ Project: " ${PROJECT_NAME})

set(LIB_NAME "${PROJECT_NAME}")
set(PROJECT_VERSION 1.0)

include_directories(
        ${PROJECT_SOURCE_DIR}/include
)

if (WIN32)
    find_package(Boost REQUIRED system filesystem)
    find_package(cryptopp REQUIRED)
    find_package(unofficial-date REQUIRED)
    include_directories(
            ${Boost_INCLUDE_DIR}
    )

else()
    find_package(date REQUIRED)
endif ()

file(GLOB_RECURSE HEADER_FILES include/*.h include/*.hpp)
file(GLOB_RECURSE SOURCES src/*.cpp)

add_library(${LIB_NAME} STATIC ${SOURCES} ${HEADER_FILES} )

set_target_properties(
        ${LIB_NAME}
        PROPERTIES
        OUTPUT_NAME "licensing"
        POSITION_INDEPENDENT_CODE ON
        CXX_STANDARD 14
        CXX_STANDARD_REQUIRED YES
        CXX_EXTENSIONS NO
        LINKER_LANGUAGE CXX
)

if (MSVC)
    set_target_properties(${LIB_NAME} PROPERTIES DEBUG_POSTFIX "_d")
endif()

add_library(Licensing::liblicensing ALIAS ${LIB_NAME})

set(INSTALLATION_DIR "${CMAKE_INSTALL_PREFIX}")
set(CMAKE_INSTALL_LIBDIR "${INSTALLATION_DIR}/lib")
set(CMAKE_INSTALL_BINDIR "${INSTALLATION_DIR}/bin")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB_NAME})

target_include_directories(${LIB_NAME}
        PUBLIC
        $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
        )

if (WIN32)
    target_link_libraries(
            ${LIB_NAME}
            ${Boost_LIBRARIES}
            cryptopp-static
            wbemuuid
    )

else()
    target_link_libraries(
            ${LIB_NAME}
            cryptopp
            boost_system
            boost_filesystem
    )
endif ()

if(CMAKE_BUILD_TYPE MATCHES Debug)
    target_compile_definitions(${LIB_NAME} PUBLIC _LICENSING_DEBUG=1)
elseif(CMAKE_BUILD_TYPE MATCHES Release)
    target_compile_definitions(${LIB_NAME} PUBLIC _LICENSING_DEBUG=0)
endif()

# Expose Projects's public includes to other subprojects through cache variable.
set(${PROJECT_NAME}_INCLUDE_DIRS ${PROJECT_SOURCE_DIR}/include CACHE INTERNAL "${PROJECT_NAME}: Include Directories" FORCE)


###############
# Installation
##

install(TARGETS ${LIB_NAME}
        EXPORT LibLicensingTargets
        LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
        ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
        RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
#        INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

install(DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/
        DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/${LIB_NAME}
        FILES_MATCHING PATTERN "*.h*")

install(EXPORT LibLicensingTargets
        FILE LibLicensingTargets.cmake
        NAMESPACE Licensing::
        DESTINATION ${INSTALL_CONFIGDIR}
        )


#####################
# ConfigVersion file
##
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
        ${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfigVersion.cmake
        VERSION ${PROJECT_VERSION}
        COMPATIBILITY AnyNewerVersion
)

configure_package_config_file(
        ${CMAKE_CURRENT_LIST_DIR}/CMake/LibLicensingConfig.cmake.in
        ${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfig.cmake
        INSTALL_DESTINATION ${INSTALL_CONFIGDIR}
)

## Install all the helper files
install(
        FILES
        ${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfig.cmake
        ${CMAKE_CURRENT_BINARY_DIR}/LibLicensingConfigVersion.cmake
        DESTINATION ${INSTALL_CONFIGDIR}
)

标签: c++cmake

解决方案


不是一个完整的答案,但太多的评论:

如果您LibLicensingTargets.cmake仔细检查您的文件,您会看到cryptopp-staticwbemuuid没有解析到库级别。

查看您如何引用 Boost,您会使用${Boost_LIBRARIES}解析到库级别的旧式版本 ( )。

尝试使用 FindBoost.cmake 模块提供的目标,如下所示:

if (WIN32)
    target_link_libraries(
            ${LIB_NAME}
            Boost::system
            Boost::filesystem
            cryptopp-static
            wbemuuid
    )

else()
    target_link_libraries(
            ${LIB_NAME}
            cryptopp
            Boost::system
            Boost::filesystem
    )
endif()

令我困惑的另一件事是为什么您添加了ALIAS

add_library(Licensing::liblicensing ALIAS ${LIB_NAME})

ALIAS是在文件中正确创建的LibLicensingTargets.cmake,因此您不需要自己创建它。

另一件事是,您正在为您的 INSTALL 命令提供绝对路径。要使包完全可重定位,您需要使用相对路径(相对于CMAKE_INSTALL_PREFIX安装目录)。

因此,应将以下命令更改为:

set(CMAKE_INSTALL_LIBDIR "lib")
set(CMAKE_INSTALL_BINDIR "bin")
set(CMAKE_INSTALL_INCLUDEDIR "include")
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/${LIB_NAME})

如果您进一步添加该行:

export(TARGETS liblicensing NAMESPACE LibLicensing:: FILE LibLicensingTargets.cmake)

到您的 CMakeLists.txt,外部项目能够从您的构建树文件夹中导入目标,因为 liblicensing 已安装在其中。请参阅导出命令的 CMake文档。


推荐阅读