将 CMake 包与 bazel cmake_external 链接

问题描述

要将 pytorch c++ 库与 CMake 链接,您实际上只需要 find_package(Torch required) 并使用

-DCMAKE_PREFIX_PATH=/absolute/path/to/libtorch

您可以在此处下载源代码https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip CMake 教程在这里https://pytorch.org/cppdocs/installing.html

我的 WORKSPACE 中有以下内容

new_local_repository(
    name = "torch",build_file_content = all_content,path = "third_party/libtorch",)

这在我的 BUILD

cmake_external(
    name = "torch",cache_entries = {
        "CMAKE_PREFIX_PATH": "/home/jackshi/projects/third_party/libtorch",},lib_source = "@torch//:all",)

当我尝试链接到它时,我得到 <dir> does not appear to contain CMakeList.txt 确实如此,但是,当您将其与 find_package(Torch required) 链接时,不需要顶级 CMakeList.txt。 CMake 寻找 TorchConfig.cmake 。 bazel 可以在没有顶级 CMakeList.txt 的情况下为此包创建目标吗?它应该在寻找 TorchConfig.cmake 对吗?

另外,当文件是远程的,通过 CMAKE_PREFIX_PATH 获取时,http_archive 是如何工作的,你使用 ~/.cache/bazel 目录吗?

谢谢!

解决方法

您的链接 (https://download.pytorch.org/libtorch/nightly/cpu/libtorch-shared-with-deps-latest.zip) 不是源代码,而是完全编译的库。因此不需要CMake,因为它已经编译好了。

find_package 是 CMake 的一项功能,它使用搜索最常见安装路径的算法查找已经编译的依赖项。即使在 CMake 中也不必编译您想要查找的库。你不想在这里使用它,因为它是一种解决问题的CMake方式

您可以尝试三种方法:

  • 在 Bazel 中,您可以使用已经构建的库。为此,只需创建一个普通的 cc_library 规则,在其中将编译的库 *.a 添加为 srcs
cc_library(
    name = "torch",srcs = glob(["lib/*.so","lib/*.a"]),hdrs = glob(["include/**/*.h","include/**/*.h"]),includes = ["include"],)

这种方法相当糟糕,因为你无法控制这个库的构建过程。您从源代码编译的越多,您的构建堆栈就越好、越健壮。

# WORKSPACE file
 http_archive(
      name = "pytorch",urls = ["https://github.com/pytorch/pytorch/archive/v1.7.1.tar.gz"],strip_prefix  = "pytorch-1.7.1",)

# and then in your BUILD file

cc_binary(
  name = "my_supper_binary"
  srcs = ["main.cpp"],deps = ["@pytorch//:torch"],)

另外,远程文件时CMAKE_PREFIX_PATH如何工作,通过http_archive获取,你使用~/.cache/bazel目录吗?

不,对于每个操作,Bazel 都使用称为沙箱的功能设置了一个完整的所需环境。当您为例如创建的工作区定义 BUILD 文件时http_archive,那么所有需要的依赖都会在那里,你不应该关心它,因为该位置在操作完成后被删除。通过正确的沙盒实现,您甚至无法读取 /home/jackshi/projects/third_party/libtorch,因为该路径不在您的 deps 中。 Bazel 真的很认真,因为无法跟踪这种偷偷摸摸的依赖项,因此您可以在这里更改一些内容,并且 Bazel 不会重新编译您的目标

但是有时您想向 cmake_external 添加一些依赖项。使用 rules_foreign_cc,您可以执行以下操作:

configure_make(
    name = "apr",lib_source = "@apr//:all",shared_libraries = ["libapr-1.so"],static_libraries = ["libapr-1.a"],)

configure_make(
    name = "apr_util",configure_options = [
        "--with-apr=$$EXT_BUILD_DEPS$$/apr",],lib_source = "@apr_util//:all",shared_libraries = ["libaprutil-1.so"],static_libraries = ["libaprutil-1.a"],deps = [":apr"],)

这是一个autotools的例子,但没关系。 apr_util 目标取决于 apr。因此,在 apr_util 构建期间,apr 构建工件将在 $$EXT_BUILD_DEPS$$/apr 中可用。该路径专为该特定构建而创建,稍后将被删除