Unable to link against Boost.Python on OS X - cmake

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?

The solution I am currently using is to reinstall boost-python without python 2.7 support.
The steps I took were:
Uninstall boost-python if already installed: brew uninstall boost-python.
Install boost-python with python3 support but without python 2.7 support: brew install boost-python --with-python3 --without-python.

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.

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).

Related

How can I properly tell cmake which CXX compiler to use?

I am trying to build a project from cmake on CentOS 7. The project requires C++ 17 and I'm getting this error from the build:
CMake Error at nvbench/nvbench/CMakeLists.txt:86 (target_compile_features):
target_compile_features The compiler feature "cxx_std_17" is not known to
CXX compiler
"GNU"
version 4.8.5.
L86:
target_compile_features(nvbench PUBLIC cuda_std_17 PRIVATE cxx_std_17)
Naturally, CentOS 7's g++ has version 4.8.5 and doesn't support C++ 17, but I have devtoolset 9 which has g++ version 9.3.1. I've added these lines near the top CMakeLists.txt:
set(CMAKE_C_COMPILER /opt/rh/devtoolset-9/root/bin/gcc)
set(CMAKE_CXX_COMPILER /opt/rh/devtoolset-9/root/bin/g++)
but cmake still references the default compiler and not the one in the devtoolset.
Also made sure to run with scl enable devtoolset-9 'cmake ..' but that didn't work either.
How can I fix this so cmake uses g++ in the devtooset?

How to statically link PROJ to pybind11

I'm interested in statically linking PROJ to a library created with pybind11.
but, I get error by cmake.
Why am I getting this error and how can I fix it?
My CMakeLists.txt is this.
cmake_minimum_required(VERSION 3.4)
project(myearth LANGUAGES CXX)
add_subdirectory(pybind11)
pybind11_add_module(myearth MyEarth.cpp)
include_directories(${CMAKE_SOURCE_DIR}/PROJ/include)
add_library(proj4 STATIC IMPORTED)
set_target_properties(proj4 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/PROJ/lib/libproj.a)
target_link_libraries(myearth PRIVATE proj4)
CMake Error.
I think fPIC option is for shared library. so, libproj.a is not necessary this option because this is static library.
(venv) ~/Projects/LinkLibTest/MySample/build$ make
[ 50%] Building CXX object CMakeFiles/myearth.dir/MyEarth.cpp.o
[100%] Linking CXX shared module myearth.cpython-36m-x86_64-linux-gnu.so
/usr/bin/ld: ../PROJ/lib/libproj.a(proj_4D_api.o): relocation R_X86_64_PC32 against symbol `pj_errno' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: bad value
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/myearth.dir/build.make:98: myearth.cpython-36m-x86_64-linux-gnu.so] Error 1
make[1]: *** [CMakeFiles/Makefile2:100: CMakeFiles/myearth.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
(venv) ~/Projects/LinkLibTest/MySample/build$
I created libproj.a by the following command.
$ ./configure --prefix=/output --disable-shared
$ sudo make
$ sudo make install
Linux Mint 20.3 64bit
CMake v3.22.2
PROJ v5.2.0 (https://proj.org/)
Python v3.6.8
Thank you.
Shared libraries must have position independent code, but your version of PROJ was built without it; you will have to rebuild PROJ with PIC.
$ ./configure --prefix=/output --with-pic

How to properly link libraries from vcpkg in a CMake project

I'm testing vcpkg (on macOS) with a CMake project.
Since not all vcpkg packages have CMake find modules, I'm trying with a package that doesn't have one: libuuid
This is the directory tree relative to libuuid I can see from the vcpkg root:
$ find packages/libuuid_x64-osx
packages/libuuid_x64-osx
packages/libuuid_x64-osx/include
packages/libuuid_x64-osx/include/uuid
packages/libuuid_x64-osx/include/uuid/uuid.h
packages/libuuid_x64-osx/BUILD_INFO
packages/libuuid_x64-osx/lib
packages/libuuid_x64-osx/lib/libuuid.a
packages/libuuid_x64-osx/CONTROL
packages/libuuid_x64-osx/debug
packages/libuuid_x64-osx/debug/lib
packages/libuuid_x64-osx/debug/lib/libuuid.a
packages/libuuid_x64-osx/share
packages/libuuid_x64-osx/share/libuuid
packages/libuuid_x64-osx/share/libuuid/copyright
Example program:
#include <iostream>
#include <uuid/uuid.h>
int main(int argc, char **argv)
{
std::cout << "Hello, world!" << std::endl;
return 0;
}
Example CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
project(vcpkg_example_project)
add_executable(app app.cpp)
target_link_libraries(app uuid)
If I understand correctly, vcpkg's philosophy is not to provide missing CMake find-modules, but to simply have #include <libfoo/foo.h> work out of the box. And in fact the example above compiles fine. But fails to find -luuid:
$ cmake -DCMAKE_TOOCHAIN_FILE=/Users/me/Dev/vcpkg/scripts/buildsystems/vcpkg.cmake ..
...
$ cmake --build .
Scanning dependencies of target app
[ 50%] Building CXX object CMakeFiles/app.dir/app.cpp.o
[100%] Linking CXX executable app
ld: library not found for -luuid
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [app] Error 1
make[1]: *** [CMakeFiles/app.dir/all] Error 2
make: *** [all] Error 2
What am I missing?
Also, I see there is a installed/x64-osx/lib/libuuid.a. Shouldn't installed/x64-osx/lib automatically added as lib path by the toolchain cmake script?
I'd make a target out of uuid. From what you describe, most probably an Interface Library called uuid. You can add_target_include_directories and target_link_libraries for the headers and any libraries, and then add it to the rest of your project.
So something like this:
add_library(uuid INTERFACE)
if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
find_library(LIBUUID uuid "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/lib/")
else()
find_library(LIBUUID uuid "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/debug/lib/")
endif()
target_link_libraries(uuid INTERFACE "${LIBUUID}")
target_include_directories(uuid SYSTEM INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}/packages/libuuid_x64-osx/include")
I'd then do an add_subdirectory to the library's folder and link to uuid

Building FLANN with Cmake fails

I am trying to build FLANN libraries in order to build PCL library afterwards.
I get an error while using CMake to compile the source.
I guess I am missing something very basic. Since I can't find a compiled library for my system I have to build it myself.
With the command
~/flann-1.8.4-src/build> cmake ..
I get
CMake Error at src/cpp/CMakeLists.txt:86 (add_library):
No SOURCES given to target: flann
CMake Error at src/cpp/CMakeLists.txt:32 (add_library):
No SOURCES given to target: flann_cpp
This happens with flann 1.8.4 and 1.9.1 on a SLES11 operating system.
Any hint?
Here a complete transcription of what cmake says:
-- Could NOT find HDF5 (missing: HDF5_LIBRARIES HDF5_INCLUDE_DIRS) (found version "")
CMake Warning at CMakeLists.txt:76 (message):
hdf5 library not found, some tests will not be run
-- Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR GTEST_MAIN_LIBRARY)
CMake Warning at CMakeLists.txt:115 (message):
gtest library not found, some tests will not be run
-- Found OpenMP_C: -fopenmp
-- Found OpenMP_CXX: -fopenmp
-- Found OpenMP: TRUE
CMake Warning at src/matlab/CMakeLists.txt:79 (message):
Cannot find MATLAB or Octave instalation. Make sure that the 'bin'
directory from the MATLAB instalation or that mkoctfile is in PATH
hdf5 library not found, not compiling flann_example.cpp
-- Could NOT find LATEX (missing: LATEX_COMPILER)
-- Install prefix: /usr/local
-- Build type: RelWithDebInfo
-- Building C bindings: ON
-- Building python bindings: ON
-- Building matlab bindings: ON
-- Building CUDA library: OFF
-- Using OpenMP support: ON
-- Using MPI support: OFF
-- Configuring done
CMake Error at src/cpp/CMakeLists.txt:86 (add_library):
No SOURCES given to target: flann
CMake Error at src/cpp/CMakeLists.txt:32 (add_library):
No SOURCES given to target: flann_cpp
-- Build files have been written to: ~/flann-1.8.4-src/build
In your flann dir
run
touch src/cpp/empty.cpp
In src/cpp/CMakeLists.txt
replace
add_library(flann_cpp SHARED "") and add_library(flann SHARED "")
with
add_library(flann_cpp SHARED empty.cpp) and add_library(flann SHARED empty.cpp)
Hope this helps :)
link, thanks to the comment by Tsyvarev

CMake: satisfying dependencies when building shared object file (.so) from object file (.o)

I am able to do this without CMake using a handwritten Makefile, like so:
g++ $(CXSCINC) -c -fPIC cellComplex_extern.cpp -o cellComplex_extern.o
g++ $(CXSCINC) -shared -Wl -o cellComplex_lib.so cellComplex_extern.o $(CXSCLIB) -lcxsc
This gets me shared library cellComplex_lib.so, which then gets picked up by ctypes as a dynamically linked library (lib = ctypes.cdll.LoadLibrary('./cellComplex_lib.so') for later use.
My project has moved to CMake as a build system and I am looking to emulate the functionality of my Makefile above.
So far I have discovered the add_library() command for CMakeLists.txt, but the link to the CXSC library is never made (as evidenced by horrible complaining when I run make after cmake.
How can I tell CMake to build cellComplex_lib with the third-party library CXSC?
-- non-working CMakeLists.txt --
add_library(include/python/cellComplex_extern OBJECT
include/python/cellComplex_extern.cpp ${all_headers})
add_library(include/python/cellComplex_lib SHARED
include/python/cellComplex_extern)
target_link_libraries(include/python/cellComplex_lib ${CXSC_LIB_DIR}/libcxsc.a)
Result of running cmake followed by make:
.
.
.
[ 75%] Built target include/python/cellComplex_extern
Linking CXX shared library libinclude/python/cellComplex_lib.dylib
ld: can't open output file for writing: libinclude/python/cellComplex_lib.dylib, errno=2 for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [libinclude/python/cellComplex_lib.dylib] Error 1
make[1]: *** [CMakeFiles/include/python/cellComplex_lib.dir/all] Error 2
make: *** [all] Error 2
I think you need to use target_link_libraries
target_link_libraries(include/python/cellComplex_lib ${CXSLIB})
This is what I use during Win32 development:
link_directories(${LIB_ROOT_DIR}/lib ${LIB_ROOT_DIR2}/lib/morelibs)
add_library(MyDll1 SHARED File1.cpp File2.cpp)
add_library(MyDll2 SHARED File3.cpp File4.cpp)
add_dependencies(MyDll2 Dll1)
target_link_libraries(MyDll2 Dll1 some.lib another.lib)
Here you specify that Dll2 requires Dll1 and two other external lib's.