cmake - 链接静态库pytorch在构建期间找不到其内部函数

cmake - linking static library pytorch cannot find its internal functions during build

我正在尝试使用 cmake 构建程序。由于几个原因,程序必须使用静态库而不是动态库来构建,我需要使用 PyTorch 所以这就是我所做的:

  1. 已下载并安装 PyTorch 静态库(我在 /home/me/pytorch/torch/lib 的正确路径中找到了 libtorch.a
  2. 制作 CMakeLists.txt 内容如下:
cmake_minimum_required(VERSION 3.5.1 FATAL_ERROR)
project(example-app LANGUAGES CXX)
find_package(Torch REQUIRED)
add_executable(example-app example-app.cpp argparse/argparse.cpp)
target_link_libraries(example-app "${TORCH_LIBRARIES}" -static -fopenmp)
set_property(TARGET example-app PROPERTY CXX_STANDARD 14)

仅供参考,example-app.cpp 是具有主要功能的文件,argparse/ 是一个目录,其中包含一些在 example-app.cpp

中调用的函数的源代码

cmake -DCMAKE_PREFIX_PATH=/home/me/pytorch/torch ..都有效,但是后面的build会报错,说找不到对某些函数的引用,即以fbgemm::开头的函数。 fbgemm 是(据我所知)用于实现 PyTorch 的某种 GEMM 库。

在我看来,在链接静态 PyTorch 库时,它的内部库 fbgemm 之类的东西没有正确链接,但我不是 cmake 方面的专家,老实说也不完全是当然。

我是不是做错了什么,或者是否有解决此问题的方法?任何帮助或推动正确的方向将不胜感激。

P.S.

  1. 确切的错误尚未 post 编辑,因为它太长了,但它主要由 undefined reference to ~ 错误组成。如果查看错误消息可能对某些人有帮助,我很乐意编辑问题并post它。

  2. building 和 运行 如果我从代码 without 中删除需要库函数的部分,文件工作正常从 example-app.cpp.

  3. 注释掉 #include <torch/torch.h>

最近通过 PyTorch 的静态链接经历了类似的过程,老实说它不太漂亮。

我将概述我已采取的步骤(您可以在 torchlambda, here is CMakeLists.txt (it also includes AWS SDK and AWS Lambda static builds), here 中找到确切的源代码是一个从源代码构建 pytorch 的脚本(通过 /scripts/build_mobile.sh 克隆和构建仅 CPU支持)), 虽然它只有 CPU 支持(如果你需要 CUDA,类似的步骤应该没问题,它至少会让你开始)。

Pytorch 静态库

预建静态 PyTorch

首先,你需要预建静态库文件(所有都需要是静态的,因此没有.so,只有[=19] =] 扩展是合适的)。

Tbh 我一直在寻找 PyTorchinstallation page 上提供的那些,但只有 shared 版本。 在一个 GitHub 问题中,我找到了一种下载它们的方法,如下所示:

而不是下载(此处通过 wget)共享库:

$ wget https://download.pytorch.org/libtorch/cu101/libtorch-shared-with-deps-1.4.0.zip

您将 shared 重命名为 static(如 in this issue 所述),因此它将变为:

$ wget https://download.pytorch.org/libtorch/cu101/libtorch-static-with-deps-1.4.0.zip

然而,当你下载它时,lib文件夹下没有libtorch.a(也没有找到libcaffe2.a,如this issue所示),所以我剩下的是从源代码明确构建。

如果您以某种方式拥有这些文件(如果有,请提供您从哪里获得它们),您可以跳过下一步。

从源代码构建

对于 CPU 版本,我使用了 /pytorch/scripts/build_mobile.sh 文件,如果需要 GPU 支持,您可以基于此版本(也许您只需要将 -DUSE_CUDA=ON 传递给此脚本, 虽然不确定)。

最重要的是 cmake-DBUILD_SHARED_LIBS=OFF,以便将所有内容构建为 static 库。您还可以检查 script from my tool 也将参数传递给 build_mobile.sh

运行 默认情况下会在 /pytorch/build_mobile/install 中为您提供静态文件,其中包含您需要的一切。

CMake

现在您可以将上述构建文件复制到 /usr/local(最好不要复制,除非您将 Docker 用作 torchlambda)或从您的 CMakeLists.txt 中设置它的路径] 像这样:

set(LIBTORCH "/path/to/pytorch/build_mobile/install")

# Below will append libtorch to path so CMake can see files
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};${LIBTORCH}")

现在其余的都很好 除了 target_link_libraries,应该使用(如 this issue 所示,请参阅此处列出的相关问题以获取更多参考)使用 -Wl,--whole-archive 链接器标志,这让我想到了这个:

target_link_libraries(example-app PRIVATE -lm
        -Wl,--whole-archive "${TORCH_LIBRARIES}"
        -Wl,--no-whole-archive
        -lpthread
        ${CMAKE_DL_LIBS})

您可能不需要 -lm-lpthread${CMAKE_DL_LIBS},尽管我在 Amazon Linux AMI.

上构建时需要它

建筑

现在您可以开始构建您的应用程序了。标准 libtorch 方式应该没问题,但这是我使用的另一个命令:

mkdir build && \
  cd build &&  \
  cmake .. && \
  cmake --build . --config Release

上面将创建 build 文件夹,现在应该安全地放置 example-app 二进制文件。

最后使用 ld build/example-app 验证 PyTorch 中的所有内容都是静态链接的,参见 aforementioned issue5.,您的输出应该看起来相似。