Search code examples
cmakesetuptoolspybind11

Building C++ Pybind11 extension with setuptools and CMake generates .so directory


I am trying to use setuptools to install a C++ library with a Pybind11 interface using CMake. For using CMake with setuptools, I am using the code in the following answer: Extending setuptools extension to use CMake in setup.py? I am able to build the library by hand with cmake. Unfortunately however, when executing pip install . in the root directory of my project, the build fails. While the first call to cmake (self.spawn(['cmake', str(cwd)] + cmake_args)) finishes without any error, executing the second call (self.spawn(['cmake', '--build', '.'] + build_args)) gives me the following error:

/users/thoerman/miniconda3/envs/postproc_np_products/bin/../lib/gcc/x86_64-conda_cos6-linux-gnu/7.3.0/../../../../x86_64-conda_cos6-linux-gnu/bin/ld: cannot open output file /users/thoerman/postproc_np_products/build/lib.linux-x86_64-cpython-37/postproc_ops_cpp.cpython-37m-x86_64-linux-gnu.so: Is a directory
      collect2: error: ld returned 1 exit status
      gmake[3]: *** [/users/thoerman/postproc_np_products/build/lib.linux-x86_64-cpython-37/postproc_ops_cpp.cpython-37m-x86_64-linux-gnu.so] Error 1
      gmake[2]: *** [CMakeFiles/postproc_ops_cpp.dir/all] Error 2
      gmake[1]: *** [CMakeFiles/postproc_ops_cpp.dir/rule] Error 2
      gmake: *** [postproc_ops_cpp] Error 2

But when running the exact same commands on the command line inside the build_temp directory, everything works just fine.

Does anyone have a hint for me, what might be going wrong?


Solution

  • After further digging into the problem, I found the solution myself. The problem was with the lines

    extdir = pathlib.Path(self.get_ext_fullpath(ext.name))
    extdir.mkdir(parents=True, exist_ok=True)
    

    This created a directory for the target to be built. Building the target then failed, since there was already a directory with the same name. I was able to solve it by replacing the second line as follows:

    extdir.parent.mkdir(parents=True, exist_ok=True)