The Dude
The Dude

Reputation: 340

Undefined Python references in C++ using CMake

I am trying to compile a c++ project referencing Python using CMake. I am using Cygwin and I have Python2.7 source files in Cygwin.

For example:

PyObject *l = PyList_New(0);

Online help suggested I add the -lpython2.7 linker flag. Am I not adding this correctly in CMake? Otherwise why can I still not use the Python library and how might I fix this?

The compile line:

C:\cygwin64\bin\cmake.exe --build "C:\Users\...\.clion10\system\cmake\generated\3e6845d6\3e6845d6\Release" --target projectname -- -j 4

The CMakeList.txt file:

cmake_minimum_required(VERSION 2.8.4)
project(projectname)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -lpython2.7")

set(SOURCE_FILES
    src/cpp/...
    src/cpp/...
    src/cpp/..
    src/cpp/...
    src/cpp/...)

add_executable(projectname ${SOURCE_FILES})

The errors...

CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaeb4): undefined reference to `PyDict_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaeb4): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `PyDict_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaec4): undefined reference to `PyList_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaec4): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `PyList_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaf0d): undefined reference to `PyDict_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaf0d): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `PyDict_New'
CMakeFiles/spot.dir/src/cpp/OBwrapper.cpp.o:OBwrapper.cpp:(.text+0xaf25): undefined reference to `PyString_FromString'

...and so on....

Upvotes: 0

Views: 4235

Answers (1)

zaufi
zaufi

Reputation: 7129

You misunderstand CMake's way: before use something you ought to find it! I.e. make sure that everything you need to build your package is available and usable at build host. Otherwise that would be not good to waste a (compile) time (say 2 hours) and then get an error that some header/library/executable not found. So, at CMake run time you'd better to be sure that everything you need is here. To do so, CMake have a lot of tools.

Consider your particular case: you need to find Python libraries otherwise build is not possible. To do so, you ought to use find_package like this:

find_package(PythonLibs REQUIRED)

Take a look to documentation and provide other options (like version) if you need. You shouldn't use hardcoded paths in your CMakeLists.txt, otherwise your project wouldn't be really portable (and most probably you'll be the only who can build it w/o a lot of problems). Instead Python libs finder module will provide variables you need to use later, or failed w/ error if nothing has found.

If CMake ends w/o errors, you may use found Python libs. First of all you need to update #include paths:

 include_directories(${PYTHON_INCLUDE_DIRS})

Then tell to linker that your executable projectname needs to be linked w/ Python libs:

add_executable(projectname ${SOURCE_FILES})
target_link_libraries(projectname ${PYTHON_LIBRARIES})

And again, try to avoid to modify CMAKE_CXX_FLAGS (and others) directly -- there are bunch of calls to do that globally and/or per target. Some of them are:

Upvotes: 4

Related Questions