使用CMake/CPack打包带有Boost库的C++程序

14

我编写了一个使用boost的简单C++程序,我想在具有任何Linux版本(目前)的相同体系结构的机器上部署它,这些机器可能已经安装了一些boost版本。我对部署很陌生,但尝试阅读文档并编写了一个类似于以下内容的CMakeLists.txt:

cmake_minimum_required(VERSION 2.8)
project( myprog )
FIND_PACKAGE( Boost 1.50 COMPONENTS thread system chrono program_options REQUIRED )
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIR} )
add_executable( myprog myprog.cpp )
target_link_libraries( myprog -lpthread -lboost_system -lboost_chrono -lboost_program_options )

INSTALL( TARGETS myprog DESTINATION . )
SET( CPACK_GENERATOR "TGZ")
INCLUDE( CPack )

一切都编译和运行正常,但打包(make package)只打包了可执行文件而没有依赖的boost库".so"

当我运行:ldd myprog时,它告诉我它依赖于:linux-vdso.so,libpthread.so,libboost_system.so,libboost_chrono.so,libboost_program_options.so libstdc++.so libgcc_s.so libc.so librt.so libm.so

这些是我想要打包的共享库(也许我不需要打包标准库)

如何告诉cmake抓取正确的共享对象库,并将它们放在可执行文件旁边,以便用户只需解压文件夹并启动可执行文件而无需安装?

静态链接在这里不是一个选项,因为我会有一堆将使用相同boost库的可执行文件,并且还可能存在与静态链接到libgcc存在许可问题。


1
我找到了一个脚本来复制所需的依赖项 http://h3manth.com/content/copying-shared-library-dependencies 手动部署(将so文件放在可执行文件旁边),但启动不容易。首先,我们必须删除标准依赖项,然后chmod 711 *,然后将ld_library_path设置为应用程序和共享库所在的文件夹。最终程序可以运行,但不够用户友好。有人能提供用户友好的部署建议吗? - darkblue
1
回答部分我的评论,通过使用set(CMAKE_EXE_LINKER_FLAGS“-Wl,-rpath ='$ ORIGIN'”),似乎不再需要设置ld_library_path,我仍然需要删除linux-vdso.so,libpthread.so,libstdc ++ .so libgcc_s.so libc.so librt.so libm.so才能使其运行。虽然它在我的机器上工作(ubuntu 12.04和ubuntu 14.04),但我不确定它是否适用于任何相同架构的Linux版本。 - darkblue
似乎除了 set(CMAKE_EXE_LINKER_FLAGS "-Wl,-rpath='$ORIGIN' ") 之外,还需要添加 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) 这一行。 - Guillaume Pascal
3个回答

1

0

尝试在分发包中包含所需库是完全有效的。

我在cmake文件中的做法是,通过使用ldd从可执行文件中提取库名称,然后解析链接,将结果复制到我的包中:

从可执行文件中提取库名称

execute_process(  # Get interesting dynamic libraries from binary
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/bin
    COMMAND ldd ${APPLICATION_NAME}
    COMMAND nawk "{print $3}"
    COMMAND sort -u
    COMMAND egrep "std|boost|ssl|crypto|z|mysql|sqlite" # Only libs I want to copy
    OUTPUT_VARIABLE INSTALL_FILES
    ERROR_VARIABLE INSTALL_FILES_ERROR
    OUTPUT_STRIP_TRAILING_WHITESPACE
    )

string(REGEX REPLACE "\n" ";" INSTALL_FILES "${INSTALL_FILES}") # Convert into list

message(" ----> ${INSTALL_FILES}")

if (${INSTALL_FILES_ERROR})
    message("----> ${INSTALL_FILES_ERROR}")
endif (${INSTALL_FILES_ERROR})

解析链接

foreach (_file ${INSTALL_FILES}) # Resolve links
    get_filename_component(_resolvedFile "${_file}" REALPATH)
    list (APPEND INSTALL_RESOLVED_FILES ${_resolvedFile} )
endforeach()

将库复制到包中

install(FILES                               # Copy all libraries and symlinks pointing to real paths
    ${INSTALL_FILES}
    DESTINATION "${PROJECT_VERSION}/lib/"
    COMPONENT core
    )
install(FILES                               # Copy all libraries real paths
    ${INSTALL_RESOLVED_FILES}
    DESTINATION "${PROJECT_VERSION}/lib/"
    COMPONENT core
    )

-1
你需要添加一个安装规则,将库文件复制到软件包中。否则,.so 文件将不会被复制到目标位置。
因此,请尝试以下操作(根据您的需求进行调整):
install(TARGETS targets... RUNTIME_DEPENDENCIES DIRECTORIES ${Boost_LIBRARIES})

更多信息:阅读有关CMake安装规则的内容


1
你好ASOD99,欢迎来到StackOverfow!提醒一下,仅有代码的答案并不是高质量的。虽然这段代码可能很有用,但你可以通过解释它的原理、使用场景、限制等方面来改进它。请编辑你的回答,加入解释和相关文档链接。 - mingaleg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接