【问题标题】:Using CMake to create an executable that can run independently on other machines使用CMake创建可以在其他机器上独立运行的可执行文件
【发布时间】:2020-02-18 23:00:21
【问题描述】:

我正在将 LibTorch 和 OpenCV 用于 Cpp 中的程序。编译和构建是在 Linux 上使用 CMake 完成的。程序按预期构建和运行。

我想使用 CMake 在另一台 Linux 机器上创建的可执行文件。 问题是我不想在另一台机器上安装 LibTorch 或 OpenCV。如果可能的话,我宁愿为用户提供一个可执行文件。

CMake 如何创建一个独立的可执行文件? 如果只制作一个文件无关紧要,CMake 如何将所有需要的库复制到一个目录?

当前的 CMake 文件:

    cmake_minimum_required(VERSION 2.8)
    project(prediction)
    list(APPEND CMAKE_PREFIX_PATH “libtorch”) # the folder where libtorch in found
    set(CMAKE_BUILD_TYPE Release)

    find_package( OpenCV REQUIRED )
    find_package( Torch REQUIRED )

    if(NOT Torch_FOUND)
    message(FATAL_ERROR “Pytorch Not Found!”)
    endif(NOT Torch_FOUND)

    message(STATUS “Pytorch status:”)
    message(STATUS " libraries: ${TORCH_LIBRARIES}")

    message(STATUS “OpenCV library status:”)
    message(STATUS " version: ${OpenCV_VERSION}")
    message(STATUS " libraries: ${OpenCV_LIBS}")
    message(STATUS " include path: ${OpenCV_INCLUDE_DIRS}")

    file(GLOB SOURCES ".h" ".cpp") # Link all headers and sources in root dir

    include_directories( ${OpenCV_INCLUDE_DIRS} )
    add_executable(entrypoint ${SOURCES})
    target_link_libraries(entrypoint ${TORCH_LIBRARIES} ${OpenCV_LIBS})
    set_property(TARGET entrypoint PROPERTY CXX_STANDARD 14)
####### 编辑

感谢您的回答。 在下面的 Phesho_T 回答之后,我得到了 LibTorch 的静态编译,但它不会使用 set() 指令进行编译。它抛出 C10_LIBRARY NOTFOUND。

我想我会尝试使用共享库。如何指示 CMake 将相关共享库复制到“build”文件夹,以便我可以将所有内容打包到 .zip 文件中并将其发送给用户。

【问题讨论】:

  • 为您不自己构建/维护的模块提供共享库通常是个坏主意。它们可能依赖于其他共享库,这些可能依赖于其他共享库等等 - 您不能将所有依赖项发送给您的最终用户或保证他们将安装所需的包。
  • 知道了。因此,为了在另一台机器上运行可执行文件: 1. 在另一台机器上安装 LibTorch 和 OpenCV 库。 2. 再次运行 CMake。对吗?
  • 在机器 A 上构建应用程序后,您可以将可执行文件复制到已经安装了 LibTorch 和 OpenCV 的机器 B 上,并且您可以在不再次运行 CMake 的情况下运行它,假设:1) A 和B 使用相同的指令集(即 x86)和 2)它们具有相同版本的两个库,或者它们具有 API 和 ABI 兼容的两个不同版本。
  • @Pesho_T 谢谢!

标签: c++ cmake


【解决方案1】:

就像另一个答案所说,您需要在可执行文件中链接 Torch 和 OpenCV 的静态库。

这有几个先决条件:

  1. 这两个库需要在您的系统上安装静态 (.a) 库。如果没有,您可能必须手动构建它们。不同包的步骤不同。

  2. 您需要告诉 CMake 搜索静态库。这是通过CMAKE_FIND_LIBRARY_SUFFIXES 变量完成的。可能默认为.so;.a,这意味着它将首先找到共享库。

set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")

您在 target_link_libraries 命令中使用变量而不是 imported libraries(现代 CMake 方式)这一事实让我认为这应该足够了 - 这些变量应该扩展到静态库的完整路径,然后应该将其添加到您的链接器命令中。

如果使用了导入的目标,解释起来会有点复杂,但这可能超出了这个问题的范围。

试一试,告诉我们你的进展情况。

【讨论】:

  • “如果使用了导入的目标,解释起来有点复杂” - 如果 find 配置为更喜欢静态库而不是共享库,那么导入的目标和变量都是如此。此外,如果FindXXX.cmake 脚本同时提供变量和导入目标,则变量通常会扩展为导入目标的名称。 “机会是默认的.so.a” - 你可能是指.so;.a:这是一个数组的字符串表示,包含.so.a 元素。
  • @Tsyvarev 在我的沙箱中,add_library 将无法使用 IMPORTED 选项,除非您指定库类型。如果模块未配置为提供正确的类型怎么办?或者,例如,您使用了 SHARED 并提供了指向静态库的 IMPORT_LOCATION?回复:默认值,是的,没错——我打错了。会修复的。
  • 感谢您的回答。我编辑了原始帖子。
【解决方案2】:

要创建单个可执行文件,您需要将依赖项静态链接到可执行文件中。检查您的库以查看它们是否提供静态库,否则您需要重新编译 libtorch 或 opencv 以制作静态库。

【讨论】:

  • 首先感谢您的回答。我有两个库的 .so 。怎么做静态链​​接?
  • @Arbok .so 文件是共享库。检查您的库中是否有 .a 文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 2017-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多