cmakepybind11conan

Cmake: using conan pybind11 package


I'm having trouble understanding how to use pybind11 conan package. I can use some others, but pybind11 is giving me hard time.

My starting point is as follows:

conanfile.txt:

[requires]
pybind11/2.7.1

[generators]
cmake

main.cpp:

#include <pybind11/pybind11.h>

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

PYBIND11_MODULE(cobind, m) {m.def("add", &add);}

CMakeLists.txt

cmake_minimum_required(VERSION 3.21)
project(cobind11 VERSION 1.0 LANGUAGES CXX)

include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

pybind11_add_module(cobind main.cpp)

The log of my suffering trying to make this work:

  1. Starting point

If I try to build as above the project I get the following error:

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

-- Configuring incomplete, errors occurred!
  1. Adding find_package(pybind11 REQUIRED)

If I add a line find_package(pybind11 REQUIRED) I get the following error:

CMake Error at CMakeLists.txt:16 (find_package):
  By not providing "Findpybind11.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "pybind11",
  but CMake did not find one.
  1. Adding include([...]/pybind11Tools.cmake)

If I add a line #include(${CONAN_PYBIND11_ROOT}/lib/cmake/pybind11/pybind11Tools.cmake) I get the following error:

CMake Error at /home/[...]/pybind11Tools.cmake:100 (set_property):
  set_property could not find TARGET pybind11::pybind11.  Perhaps it has not yet been created.

like in this issue https://github.com/pybind/pybind11/issues/3388. Maybe it is fixed in the new release?

  1. Upgrading to 2.8.1

The fresh pybind11 is 2.8.1, let's upgrade

pybind11/2.8.1: Not found in local cache, looking in remotes...
pybind11/2.8.1: Trying with 'conancenter'...
ERROR: Unable to find 'pybind11/2.8.1' in remotes

OK. One can read between the lines, that it used to work, so maybe let's downgrade?

  1. Downgrading to 2.4.3

If I require pybind/2.4.3 instead of pybind/2.7.1 in conanfile.txt I get

fatal error: Python.h: No such file or directory
  112 | #include <Python.h>
      |          ^~~~~~~~~

like in this issue https://github.com/pybind/pybind11/issues/1781. Differently from that issue, installing python*-dev does not help. But whatever, I don't want to use old pybind anyway.

  1. Trying a conanfile from test package

The conancentral recipes contain a test package (https://github.com/conan-io/conan-center-index/tree/master/recipes/pybind11/all/test_package), which is tested automatically when the package is created. Let's try that instead!

CMake Error at CMakeLists.txt:13 (find_package):
  By not providing "Findpybind11.cmake" in CMAKE_MODULE_PATH this project has
  asked CMake to find a package configuration file provided by "pybind11",
  but CMake did not find one.

Am I just hopeless???

Maybe, but! I can:


Solution

  • I have used pybind in the past (two or three years ago) and it worked without problems with conan. However, I tried to install it now and faced similar problems. This might be related to the evolution of conan towards conan 2.0 (an alpha version was released today) and that the recipe was not updated to account changes.

    An alternative that you might consider, is to install pybind with conan using a different generator. More specifically, the CMakeDeps generator. With the CMakeDeps generator conan will create a pybind11-config.cmake file for you and you just need to use find_package(pybind11 REQUIRED) in CMakeLists.txt. That is, there is no "conan specific stuff" in your CMakeLists.txt file.

    conanfile.txt

    [requires]
    pybind11/2.7.1
    
    [generators]
    CMakeDeps
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 3.21)
    project(cobind11 VERSION 1.0 LANGUAGES CXX)
    
    # Tell cmake to also search in the buld folder for the "<library>-config.cmake"
    # files
    list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}")
    find_package(pybind11 REQUIRED)
    
    pybind11_add_module(cobind main.cpp)
    

    main.cpp

    #include <pybind11/pybind11.h>
    
    int add(int i, int j) { return i + j; }
    
    PYBIND11_MODULE(cobind, m) { m.def("add", &add); }
    

    With this I was able to build the library and use it in Python.


    Conan deeper integration with CMake

    You can also use the CMakeToolchain generator in addition to the CMakeDeps generator. It generates a conan_toolchain.cmake file that you pass to the cmake command with --toolchain conan_toolchain.cmake. If you use it, there is no need to add the list(APPEND CMAKE_PREFIX_PATH "${CMAKE_BINARY_DIR}") line to your CMakeLists.txt file. Furthermore, the settings you specify in conan, such as build type and compiler, will impact cmake. That is, you don't need to specify these things in both conan and cmake. This seems to be where conan is going, regarding cmake integration, in the comming 2.0 release.