Unable to link against Boost.Python on OS X
Asked Answered
P

3

4

I am trying to build a really trivial example with Boost.Python. I have installed boost and boost-python with homebrew. I am using python 3.4.3 and boost 1.59. My OS is El Capitan.

Boost.Python was installed with python3 like this:

brew install boost-python --with-python3

I have 3 files:

/* greet.hpp */
#ifndef BOOSTPYTHONHELLOWORLD_GREET_HPP
#define BOOSTPYTHONHELLOWORLD_GREET_HPP

char const* greet();

#endif //BOOSTPYTHONHELLOWORLD_GREET_HPP



/* greet.cpp */    
#include "greet.hpp"

char const* greet()
{
    return "Hello world";
}



/* greet_ext.cpp */
#include "greet.hpp"
#include <boost/python.hpp>

BOOST_PYTHON_MODULE(greet_ext)
{
    using namespace boost::python;
    def("greet", greet);
}

My CMakeLists.txt file looks like this:

cmake_minimum_required(VERSION 3.3)
project(BoostPythonHelloWorld)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(PYTHON_LIBRARY "/usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/lib/libpython3.4m.dylib")
set(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.4.3/Frameworks/Python.framework/Versions/3.4/include/python3.4m")
FIND_PACKAGE(PythonLibs 3.4 REQUIRED)
FIND_PACKAGE(Boost COMPONENTS python)
if(NOT WIN32)
    add_definitions(-DBOOST_ALL_DYN_LINK=1)
    add_definitions(-DBOOST_TEST_DYN_LINK)
endif()
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS})
add_library(greet SHARED greet.cpp)
add_library(greet_ext SHARED greet_ext.cpp)
target_link_libraries(greet_ext greet)
target_link_libraries(greet_ext ${PYTHON_LIBRARIES})
target_link_libraries(greet_ext ${Boost_LIBRARIES})
set_target_properties(greet_ext PROPERTIES PREFIX "")

When I run CMake it finds all the correct python libraries (because I specified them manually as you can see in the file above).

During build I get the following link error:

Scanning dependencies of target greet
[ 25%] Building CXX object CMakeFiles/greet.dir/greet.cpp.o
[ 50%] Linking CXX shared library libgreet.dylib
[ 50%] Built target greet
Scanning dependencies of target greet_ext
[ 75%] Building CXX object CMakeFiles/greet_ext.dir/greet_ext.cpp.o
[100%] Linking CXX shared library greet_ext.dylib
Undefined symbols for architecture x86_64:
  "boost::python::detail::init_module(PyModuleDef&, void (*)())", referenced from:
      _PyInit_greet_ext in greet_ext.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [greet_ext.dylib] Error 1
make[1]: *** [CMakeFiles/greet_ext.dir/all] Error 2
make: *** [all] Error 2

Anyone have any idea why this is happening?

EDIT

If I link against Python 2.7 it works, which means boost-python was built against python 2.7 instead of 3.4, even though I specified the --with-python3 options..

So, the questions is, how to build boost-python against python 3.4?

Penzance answered 11/11, 2015 at 14:45 Comment(2)
You can check the library name, should be boost_python_3 and boost_python_2.7 or something like that. But I don't know whether FindBoost will help you there. Do you mind removing your edits and make a proper answer? Then you can accept your answer as your actual problem was solved and might help others.Rationality
Can you add the cmake output? I have the suspicion that CMake picks up the old python version. The meaning of BOOST_PYTHON_MODULE is different for python 2 and 3. It seems during compilation the python 2 variety is built.Map
P
1

The solution I am currently using is to reinstall boost-python without python 2.7 support.

The steps I took were:

  1. Uninstall boost-python if already installed: brew uninstall boost-python.
  2. Install boost-python with python3 support but without python 2.7 support: brew install boost-python --with-python3 --without-python.
Penzance answered 15/11, 2015 at 18:58 Comment(2)
I executed brew install boost-python --with-python3 --without-python, cmake can't locate the boost (it works with brew install boost-python) + cmake .. <...ominited content...> -- Could NOT find BoostImmaterial
Clear cache folder/restart MAC if you have installed boost-python before. Cache folder: \Library\Caches , Otherwise cmake will fail to locate to boost library.Immaterial
S
1

In order to use boost-python with python 3 you need to change this in your CMakeLists.txt:

FIND_PACKAGE(Boost COMPONENTS python)

to this:

FIND_PACKAGE(Boost COMPONENTS python3)

That way you can recompile boost with python 2 support and still use python 3.

Suh answered 28/12, 2015 at 16:42 Comment(0)
M
1

I'd suggest installing boost-python3 via brew.

You still need to give the minor version number as well and possibly the library path. The following worked for me:

BOOST_LIBRARYDIR=/usr/local/Cellar/boost-python3/1.67.0/lib cmake ..

with CMakeLists.txt (located in ..) containing

FIND_PACKAGE(Boost COMPONENTS python36)

(for Boost 1.67.0 and Python 3.6, obviously).

Map answered 14/6, 2018 at 18:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.