ExternalProject_Add 使用 pybind11 进行 CMake 项目的智能方法

Posted

技术标签:

【中文标题】ExternalProject_Add 使用 pybind11 进行 CMake 项目的智能方法【英文标题】:Smart way to CMake a project using pybind11 by ExternalProject_Add 【发布时间】:2017-10-31 04:07:38 【问题描述】:

我正在使用pybind11CMake 3.9.4 编写一个python 模块。 为方便起见,我希望在我的CMakeLists.txt 中使用ExternalProject_Add 下载pybind11 源文件。

当我运行cmake .时,它没有下载pybind11源文件,并抛出错误。

CMake Error at CMakeLists.txt:21 (add_subdirectory):
  The source directory
    /Users/me/foo/pybind11_external-prefix/src/pybind11_external
  does not contain a CMakeLists.txt file.

CMake Error at CMakeLists.txt:22 (pybind11_add_module):
  Unknown CMake command "pybind11_add_module".

有一个解决方法:

    注释掉 CMakeLists.txt 中的最后 3 行 运行cmake . 运行make(然后,它会下载pybind11源文件) 恢复 CMakeLists.txt 的最后 3 行 运行cmake . 运行make

但是,这并不聪明...有没有办法使用ExternalProject_Add 下载pybind11 而无需注释掉并恢复它们(并且无需运行cmakemake 两次)?

/Users/me/foo/CMakeLists.txt

cmake_minimum_required(VERSION 3.8)
project(foo)
set(CMAKE_CXX_STANDARD 14)

include(ExternalProject)
ExternalProject_Add(
        pybind11_external
        GIT_REPOSITORY https://github.com/pybind/pybind11.git
        GIT_TAG v2.2.1
        CONFIGURE_COMMAND ""
        BUILD_COMMAND ""
        INSTALL_COMMAND ""
)
set(PYBIND11_CPP_STANDARD -std=c++14)
ExternalProject_Get_Property(pybind11_external source_dir)
include_directories($source_dir/include)

add_subdirectory($source_dir)             # comment out, then restore this line
pybind11_add_module(foo SHARED foo.cpp)     # comment out, then restore this line
add_dependencies(foo pybind11_external)     # comment out, then restore this line

/Users/me/foo/foo.hpp

#ifndef FOO_LIBRARY_H
#define FOO_LIBRARY_H

#include<pybind11/pybind11.h>

int add(int i, int j);

#endif

/Users/me/foo/foo.cpp

#include "foo.hpp"

int add(int i, int j) 
    return i + j;


PYBIND11_MODULE(example, m) 
    m.doc() = "pybind11 example plugin";
    m.def("add", &add, "A function which adds two numbers");

【问题讨论】:

您的问题是 ExternalProject 仅在主项目的 build stage 构建。所以add_subdirectory() 进入 ExternalProject 是行不通的,因为它是在配置阶段处理的。 That question 描述了在配置阶段构建 ExternalProject。 【参考方案1】:

使用 CMake 的 FetchContent 模块(版本 3.11+),您可以这样做:

include(FetchContent)
FetchContent_Declare(
    pybind11
    GIT_REPOSITORY https://github.com/pybind/pybind11
    GIT_TAG        v2.2.3
)

FetchContent_GetProperties(pybind11)
if(NOT pybind11_POPULATED)
    FetchContent_Populate(pybind11)
    add_subdirectory($pybind11_SOURCE_DIR $pybind11_BINARY_DIR)
endif()

这将在配置时下载 pybind11,并add_subdirectory 它。然后你就可以打电话给pybind11_add_module了。

【讨论】:

以上是关于ExternalProject_Add 使用 pybind11 进行 CMake 项目的智能方法的主要内容,如果未能解决你的问题,请参考以下文章

ExternalProject_Add 使用 pybind11 进行 CMake 项目的智能方法

CMake ExternalProject_Add() 和 FindPackage()

如何将环境变量传递给 ExternalProject_Add CONFIGURE_COMMAND?

cmake:ExternalProject_Add() 不应用 cmake 参数

CMake 使 add_library 依赖于 ExternalProject_Add

CMake ExternalProject_Add 中的 URL 问题