Reputation: 67
I was trying to compile this example.cpp
from a pybind11 tutorial called pybind11_examples
on GitHub
#include <pybind11/pybind11.h>
#include <pybind11/eigen.h>
#include <Eigen/LU>
#include <iostream>
// ----------------
// regular C++ code
// ----------------
Eigen::MatrixXd mul(const Eigen::MatrixXd &xs, double fac)
{
std::cout << "Double" << std::endl;
return fac*xs;
}
Eigen::MatrixXi mul(const Eigen::MatrixXi &xs, int fac)
{
std::cout << "Int" << std::endl;
return fac*xs;
}
// ----------------
// Python interface
// ----------------
namespace py = pybind11;
PYBIND11_MODULE(example,m)
{
m.doc() = "pybind11 example plugin";
// N.B. the order here is crucial, in the reversed order every "int" is converted to a "double"
m.def("mul", py::overload_cast<const Eigen::MatrixXi &,int >(&mul) );
m.def("mul", py::overload_cast<const Eigen::MatrixXd &,double>(&mul) );
}
and the corresponding CMakeLists.txt
file is
cmake_minimum_required(VERSION 2.8.12)
project(example)
set (CMAKE_CXX_STANDARD 14)
find_package( PkgConfig )
pkg_check_modules( EIGEN3 REQUIRED eigen3 )
include_directories( ${EIGEN3_INCLUDE_DIRS} )
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
One confusion I have is why do we not need to link Eigen
with example
. Is it because Eigen
is a header-only library so include_directories
is enough? Then what should I do for non-header-only libraries?
Thanks in advance!
Upvotes: 0
Views: 590
Reputation: 67
More on the target_link_library
problem, I tried the following CMakeLists.txt
cmake_minimum_required(VERSION 2.8.12)
project(example)
set (CMAKE_CXX_STANDARD 14)
find_package(Eigen3 3.3)
add_subdirectory(pybind11)
pybind11_add_module(example example.cpp)
target_link_libraries(example Eigen3::Eigen)
And it gives me the following error:
CMake Error at CMakeLists.txt:14 (target_link_libraries):
The keyword signature for target_link_libraries has already been used with
the target "example". All uses of target_link_libraries with a target must
be either all-keyword or all-plain.
The uses of the keyword signature are here:
* pybind11/tools/pybind11Tools.cmake:179 (target_link_libraries)
* pybind11/tools/pybind11Tools.cmake:211 (target_link_libraries)
This is because the two lines mentioned above are calling target_link_libraries
as
179: target_link_libraries(${target_name} PRIVATE pybind11::module)
211: target_link_libraries(${target_name} PRIVATE pybind11::lto)
This causes an error because, as mentioned in the error message:
all uses of
target_link_libraries
with a target must be eitherall-keyword
orall-plain
.
all-keyword
refers to including PRIVATE|PUBLIC|INTERFACE
in the target_link_libraries
call as in the above two lines.
all-plain
refers to not including PRIVATE|PUBLIC|INTERFACE
in the target_link_libraries
command, for example:
target_link_libraries(example Eigen3::Eigen)
We must pick one of the above ways to use the target_link_libraries
command within a single CMakeLists.txt
file. Since pybind11
made that choice for us using a keyword call, we must also do the same. So if we use
target_link_libraries(example PRIVATE Eigen3::Eigen)
it will successfully compile. If we use PUBLIC
instead of PRIVATE
, it will also successfully compile.
Upvotes: 1
Reputation: 1638
EDIT: To answer your question regarding what to do with non-header-only libraries:
Pybind11's pybind11_add_module
works the same way as CMakes add_executable
or add_library
it defines a target (first argument) that you can then link against. In your case:
#Rest of the CMakeLists.txt...
pybind11_add_module(example example.cpp)
target_link_libraries(example my_library)
#Rest of the CMakeLists.txt...
As was already posted by @user253751 in the comments. Eigen is a header only library. You can see for yourself on their homepage:
Requirements
Eigen doesn't have any dependencies other than the C++ standard library.
We use the CMake build system, but only to build the documentation and unit-tests, and to automate installation. If you just want to use Eigen, you can use the header files right away. There is no binary library to link to, and no configured header file. Eigen is a pure template library defined in the headers.
Upvotes: 1