pybind11 and another libs in one project [duplicate] - c++

I want to be able to call my C++ code as a python package. To do this I am using pybind11 with CMakelists (following this example https://github.com/pybind/cmake_example). My problem is that I have to include GSL libraries in the compilation of the code, and these need an explicit linker -lgsl .
If I were just to compile and run the C++ without wrapping it with python, the following Cmakelists.txt file does the job
cmake_minimum_required(VERSION 3.0)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14")
project(myProject)
add_executable(
myexecutable
main.cpp
function1.cpp
)
find_package(GSL REQUIRED)
target_link_libraries(myexecutable GSL::gsl GSL::gslcblas)
but when using pybind11 the template I found doesn't allow the add_executable therefore target_link_libraries doesn't work.
I have trie this
project(myProject)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED YES) # See below (1)
# Set source directory
set(SOURCE_DIR "project")
# Tell CMake that headers are also in SOURCE_DIR
include_directories(${SOURCE_DIR})
set(SOURCES "${SOURCE_DIR}/functions.cpp")
# Generate Python module
add_subdirectory(lib/pybind11)
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
FIND_PACKAGE(GSL REQUIRED)
target_link_libraries(GSL::gsl GSL::gslcblas)
but this produces errors in the building.
Any idea ?

Function pybind11_add_module creates a library target, which can be used for link added module with other libraries:
pybind11_add_module(namr ${SOURCES} "${SOURCE_DIR}/bindings.cpp")
target_link_libraries(namr PUBLIC GSL::gsl GSL::gslcblas)
This is explicitely stated in documentation:
This function behaves very much like CMake’s builtin add_library (in fact, it’s a wrapper function around that command). It will add a library target called <name> to be built from the listed source files. In addition, it will take care of all the Python-specific compiler and linker flags as well as the OS- and Python-version-specific file extension. The produced target <name> can be further manipulated with regular CMake commands.

Related

Linking with cmake, icc and pthreads (linux)

I am trying to compile a simple test project with the Intel C++ Compiler, CMake, and std::threads support.
If I do :
icpc -std=c++11 -lpthread source/main.cpp
Then the build and the program work fine.
But with CMake I get an error:
CMake Error at CMakeLists.txt:21 (TARGET_LINK_LIBRARIES):
Cannot specify link libraries for target "test" which is not built by
this project.
CMakeLists.txt is:
project(test)
set (CMAKE_CXX_FLAGS "-std=c++11")
set(SOURCE_LIST "source/main.cpp")
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
I am building in an environment set by the script supplied by icc (compilervars.sh) and CMake is called with the -DCMAKE_C_COMPILER=icc -DCMAKE_CXX_COMPILER=icpc options. It works if I'm not using threads.
What is wrong with my use of CMake?
Thanks!
Looking back the documentation for target_link_libraries, a target must be declared before being used:
The named <target> must have been created in the current directory by a command such as add_executable() or add_library().
BTW as stated in this answer, you should not set CMAKE_CXX_FLAGS explicitly, and prefer setting CMAKE_CXX_STANDARD and related variables:
project(test)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(SOURCE_LIST "source/main.cpp")
add_executable(${PROJECT_NAME} ${SOURCE_LIST})
target_link_libraries(${PROJECT_NAME} pthread)
The order is wrong: first declare your executable and let CMake know that it exists
add_executable (${PROJECT_NAME} ${SOURCE_LIST})
and afterwards add the link libraries
TARGET_LINK_LIBRARIES(${PROJECT_NAME} pthread)
From target_link_libraries's documentation:
The named must have been created in the current directory by a command such as add_executable() or add_library()

gtest setup cmake to get it run

I want to include gtest to my C++ project. I am using Clion as IDE, which should work. Some tests are already working, but I cannot use any functions from B_RocChoice.h. It says that the function is not declared in this scope.
Can somebody tell me what I am doing wrong? How I must change my CMakeLists.txt files that it recogizes my methods?
This is my basic_tests.cpp, where my testcases will be written.
This is my Directory.
Here, the most outer CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project(cli)
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread")
set(SOURCE_FILES
include/A_WowbaggerChoice.h
include/AbstractChoice.h
include/B_RocChoice.h
include/C_CnnChoice.h
include/D_DetectorChoice.h
include/E_LearningChoice.h
include/Help.h
include/MyException.h
include/StartScreen.h
include/tinyxml.h
include/types.h
src/A_WowbaggerChoice.cpp
src/AbstractChoice.cpp
src/B_RocChoice.cpp
src/C_CnnChoice.cpp
src/D_DetectorChoice.cpp
src/E_LearningChoice.cpp
src/Help.cpp
src/main.cpp
src/MyException.cpp
src/StartScreen.cpp
tinyxml/tinystr.cpp
tinyxml/tinystr.h
tinyxml/tinyxml.cpp
tinyxml/tinyxml.h)
add_subdirectory(googletest)
add_executable(cli ${SOURCE_FILES})
target_link_libraries( cli ${OpenCV_LIBS} )
CMakeLists.txt for gtest.
cmake_minimum_required(VERSION 2.6.2)
project( googletest-distribution )
enable_testing()
option(BUILD_GTEST "Builds the googletest subproject" ON)
#Note that googlemock target already builds googletest
option(BUILD_GMOCK "Builds the googlemock subproject" OFF)
if(BUILD_GMOCK)
add_subdirectory( googlemock )
elseif(BUILD_GTEST)
add_subdirectory( googletest )
endif()
add_subdirectory(basic_tests)
CMakeLists.txt for basic_tests
include_directories($(gtest_SOURCE_DIR}/include
${getest_SOURCE_DIR}))
#include_directories(../../src/)
include_directories(../../include/)
add_executable(runBasicCli
basic_check.cpp)
target_link_libraries(runBasicCli gtest gtest_main)
#target_link_libraries(cli)
I'm assuming your compiler is complaining it can't find the B_RocChoices.h header? Your question seems to imply the compiler error is about not finding a function, but B_RocChoices is a header and not a function in your basic_tests.cpp file.
Assuming your problem is that the compiler isn't finding the B_RocChoices.h header, I expect that when you include_directories(../../include) you are wanting to make the directory where B_RocChoices.h resides part of the header search path. This is a relative path, so it depends where the compiler is being run from as to what path it means (it wouldn't work if you were doing out of source builds, for example). Try using either CMAKE_SOURCE_DIR or CMAKE_CURRENT_SOURCE_DIR to define the path unambiguously. For example:
include_directories(${CMAKE_SOURCE_DIR}/include)
If you are using CMake 2.8.11 or later, I'd recommend you consider using target_include_directories() instead and probably also read up on target_link_libraries(). Together, these allow you to make the header search paths and linked libraries specific to a target rather than global to all targets. Lastly, if you prefer to download GoogleTest as part of your build rather than embedding it directly in your project sources, you may find the following link useful:
https://crascit.com/2015/07/25/cmake-gtest/

CMake third party library undefined reference

I already read and searched a lot (e.g. 1 2 3, several docs for CMake, similar projects, etc. to find a solution but I have not been able to solve my problem. I am relatively new to Cmake and Linux (Ubuntu 14.04).
I want to use libsbp (https://github.com/swift-nav/libsbp) to write a program in C++ to communicate with a GPS module. I cloned the repository and installed the C-Library. So now in /usr/local/lib there are two files: libsbp.so and libsbp-static.a and the headers are in /usr/local/include/libsbp
In my own project I include the headers with #include "libsbp/sbp.h" which also works.
Now the Problem: if I want to use a method from libsbp e.g. sbp_state_init(&s); I get undefined reference to "sbp_state_init(sbp_state_t*)"
The relevant part of my Cmake for my own project:
link_directories(/usr/local/lib)
add_executable(main ${QT_SOURCES} ${QT_HEADER_HPP})
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)
As I said before, I tried some things:
find_library(SBP_LIB sbp /usr/local/lib) -> same error
same goes for using libsbp in target_link_libraries or searching for it
link_directory(/usr/local/lib)
trying different paths, even moveing libsbp.so into the project directory and "finding" it with ${CMAKE_CURRENT_SOURCE_DIR}
Maybe you can help me!
edit:
this is the CMakeList.txt from the libsbp/c/src directory
if (NOT DEFINED BUILD_SHARED_LIBS)
set(BUILD_SHARED_LIBS ON)
endif (NOT DEFINED BUILD_SHARED_LIBS)
file(GLOB libsbp_HEADERS "${PROJECT_SOURCE_DIR}/include/libsbp/*.h")
include_directories("${PROJECT_SOURCE_DIR}/CBLAS/include")
include_directories("${PROJECT_SOURCE_DIR}/clapack-3.2.1-CMAKE/INCLUDE")
include_directories("${PROJECT_SOURCE_DIR}/lapacke/include")
include_directories("${PROJECT_SOURCE_DIR}/include/libsbp")
set(libsbp_SRCS
edc.c
sbp.c
)
add_library(sbp-static STATIC ${libsbp_SRCS})
install(TARGETS sbp-static DESTINATION lib${LIB_SUFFIX})
if(BUILD_SHARED_LIBS)
add_library(sbp SHARED ${libsbp_SRCS})
install(TARGETS sbp DESTINATION lib${LIB_SUFFIX})
else(BUILD_SHARED_LIBS)
message(STATUS "Not building shared libraries")
endif(BUILD_SHARED_LIBS)
install(FILES ${libsbp_HEADERS} DESTINATION include/libsbp)
this is the CMakeList.txt from /libsbp/c/
cmake_minimum_required(VERSION 2.8.9)
project(libsbp)
# Setup flags for Code Coverage build mode
set(CMAKE_CXX_FLAGS_COVERAGE "${CMAKE_CXX_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C++ compiler for building with code coverage."
FORCE )
set(CMAKE_C_FLAGS_COVERAGE "${CMAKE_C_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the C compiler for building with code coverage."
FORCE )
SET(CMAKE_EXE_LINKER_FLAGS_COVERAGE
"${CMAKE_EXE_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used for linking binaries with code coverage."
FORCE )
set(CMAKE_SHARED_LINKER_FLAGS_COVERAGE
"${CMAKE_SHARED_LINKER_FLAGS_DEBUG} --coverage" CACHE STRING
"Flags used by the shared libraries linker during builds with code coverage."
FORCE )
mark_as_advanced(
CMAKE_CXX_FLAGS_COVERAGE
CMAKE_C_FLAGS_COVERAGE
CMAKE_EXE_LINKER_FLAGS_COVERAGE
CMAKE_SHARED_LINKER_FLAGS_COVERAGE )
# Update the documentation string of CMAKE_BUILD_TYPE for GUIs
set(CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage."
FORCE )
# Set project version using Git tag and hash.
execute_process(
COMMAND git describe --dirty --tags --always
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
RESULT_VARIABLE GIT_VERSION_FOUND
ERROR_QUIET
OUTPUT_VARIABLE GIT_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (GIT_VERSION_FOUND)
set(VERSION "unknown")
else (GIT_VERSION_FOUND)
set(VERSION ${GIT_VERSION})
endif (GIT_VERSION_FOUND)
# Set project version explicitly for release tarballs.
#set(VERSION foo)
message(STATUS "libsbp version: ${VERSION}")
cmake_minimum_required(VERSION 2.8)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
# Some compiler options used globally
set(CMAKE_C_FLAGS "-Wall -Wextra -Wno-strict-prototypes -Wno-unknown-warning-option -Werror -std=gnu99 ${CMAKE_C_FLAGS}")
add_subdirectory(src)
add_subdirectory(docs)
add_subdirectory(test)
It seems that your program uses C++ and the library is written in C.
Symbols in C and C++ are encoded differently (mangled). When including C headers from C++ you need to tell the compiler. This can be done by declaring the symbols extern "C".
extern "C" {
#include <libsbp/sbp.h>
}
Some libraries already include this in their headers, but not sbp.
You have (at least) two possibilities:
Installing the library (this is what you did)
Integrating the library in your CMake project
When installing the library, the target_link_libraries command needs to be modified slightly:
find_library(SBP_LIB sbp /usr/local/lib)
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} ${SBP_LIB})
When you integrate the library in your CMake project, you can directly use the following command without using find_library. This works, because the library is known to CMake since it is built within the current project.
target_link_libraries(main ${QT_LIBRARIES} ${catkin_LIBRARIES} sbp)

translate g++ code to clion environment

I am new in clion. on gcc i always use:
g++ bin/obj/main.o -o bin/main -lboost_filesystem -lboost_system -lcrypto
How to do it in clion?
It seems my CMakeList does not work:
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
link_libraries(lboost_filesystem)
link_libraries(lboost_system)
link_libraries(lcrypto)
Try including the keyword "CMake" into your search next time. This question is actually not CLion specific because CLion actually uses CMake as buildsystem.
CMake is very well documented, and you should be able to find a lot of answers regarding your problem.
You could first try to get rid of that "l":
link_libraries(boost_filesystem)
If that doesn't work you should take a look how the find_package() command works. http://www.cmake.org/Wiki/CMake:How_To_Find_Libraries
And here is a detailed explanation how to find Boost libs and include directory.
http://www.cmake.org/cmake/help/v3.0/module/FindBoost.html
As you are using CMake 3.1 you can use some more advanced features of CMake.
With CMAKE_CXX_STANDARD you can select which C++ version you want to use and CMake will select the corresponding compiler flags (see docs).
link_libraries is one possibility, but it has to be called before add_executable or add_library. The alternative is target_link_libraries which links only to a single target, but can also manage transitive dependencies (docs).
CMake comes with find_package modules for OpenSSL and Boost to find dependencies and with the option REQUIRED, you can ensure that they are found on the system. Boost also supports COMPONENTS to select which libraries you need.
In case you ever work on a system, where OpenSSL and Boost are not installed in /usr/, you can already use target_include_directories to specify where the headers for your executable is found. Like target_link_libraries, target_include_directories can work with transitive dependencies, in this case PRIVATE.
cmake_minimum_required(VERSION 3.1)
project(motion_simulation)
set(CMAKE_CXX_STANDARD 11)
find_package(Boost REQUIRED COMPONENTS filesystem system)
find_package(OpenSSL REQUIRED)
set(SOURCE_FILES main.cpp)
add_executable(motion_simulation ${SOURCE_FILES})
target_include_directories(motion_simulation PRIVATE ${Boost_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIR})
target_link_libraries( motion_simulation PRIVATE ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES})

Can I make a library from multiple targets?

I'm trying to learn cmake and have started converting an old make project over to cmake. Here is a simplified version of the directory structure I now have:
CMakeLists.txt
src/
CMakeLists.txt
main.cpp
core/
CMakeLists.txt
/sourcecode, other cmakes, etc.
test/
CMakeLists.txt
someTest.cpp
Currently, in my root CMakeLists.txt file I simply have this:
cmake_minimum_required(VERSION 2.8)
project(all)
add_subdirectory(src)
add_subdirectory(test)
What I wanted to do, was have a library created by core/CMakeLists.txt that can be used by both src/CMakeLists.txt to build the main executable, but also loaded by test/CMakeLists to build the unit tests.
So my src/core/CMakeLists.txt file currently looks sort of like this:
cmake_minimum_required(VERSION 2.8)
project(core)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wpedantic -Wreorder -DBOOST_TEST_DYN_LINK -DBOOST_LOG_DYN_LINK ")
#some other directories in my core code:
add_subdirectory(display)
add_subdirectory(training)
add_subdirectory(utility)
#some packages I use...
find_package(Boost 1.55.0
COMPONENTS
log
program_options
serialization
thread
system
filesystem
REQUIRED)
find_package(GLUT REQUIRED)
find_package(OpenGL REQUIRED)
find_package(Eigen3 REQUIRED)
include_directories(
${PROJECT_SOURCE_DIR}
${EIGEN3_INCLUDE_DIR})
target_link_libraries(core
display
training
utility
${Boost_LIBRARIES}
${OPENGL_LIBRARIES}
${GLUT_LIBRARY}
${OpenMP_LIBRARIES})
So the idea is that I now have a core target I can simply link against to run my tests, and everything should work. However, when I try to build main, for example, I get:
Cannot specify link libraries for target "core" which is not built by this
project.
I thought this might be because core doesn't have a add_library command, but if I add add_library(core) I get this error:
You have called ADD_LIBRARY for library core without any source files. This typically indicates a problem with your CMakeLists.txt file
But I don't want to add any source files; I just want this target to link the targets in the core directory and produce a target I can link against from test.
Clearly I'm missing some core knowledge here, either with cmake or the toolchain itself. Help is appreciated :)
If you only want to create a core target without source files, you need to declare it like an INTERFACE target. So, try to add the following code to your src/core/CMakeLists.txt:
cmake_minimum_required(VERSION 3.0) # REQUIRED 3.x.x version
project(core)
...
# Here declare your core_interface target
add_library(core_interface INTERFACE)
target_link_libraries(core_interface INTERFACE
display
training
utility
${Boost_LIBRARIES}
${OPENGL_LIBRARIES}
${GLUT_LIBRARY}
${OpenMP_LIBRARIES})
As you can see, if you make this, you'll need to upgrade your CMake installed version.
Then, you'll build your tests or any executable, linking with this interface target directly:
add_executable(main main.cpp)
target_link_libraries(main core_interface)