I'm writing a python module using pybind11
with CMake
3.9.4.
As it is convenience, I wish to download pybind11
source files using ExternalProject_Add
in my CMakeLists.txt
.
When I run cmake .
, it does not download pybind11
source files, and throws an error.
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".
There is a workaround:
cmake .
make
(then, it downloads pybind11
source files)cmake .
make
However, this is not smart... Is there any way to download pybind11
using ExternalProject_Add
without commenting the lines out and restoring them (and without running cmake
and make
twice)?
/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");
}
With CMake's FetchContent module (version 3.11+), you can do this:
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()
This will download pybind11 at configure time, and add_subdirectory
it. Then you're ready to call pybind11_add_module
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With