Static link boost library with shared library in CMakeLists.txt - c++

I am trying to build an executable, and to change the link for boost library to static. The codes that I am trying to compile is here.
I am using Xubuntu 14.04, cmake 3.5.1, boost 1.54.
The error I got is:
Linking CXX shared library ../../lib/librexd.so
/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libboost_system.a(error_code.o): relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a shared object; recompile with -fPIC
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/libboost_system.a: error adding symbols: Bad value
Things I have done:
Set boost library to static link in CMakeLists.txt (an example):
set(Boost_USE_STATIC_LIBS ON)
FIND_PACKAGE(Boost 1.46.0 COMPONENTS system regex program_options thread filesystem REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(rexd ${Boost_LIBRARIES})
There are alot of CMakeLists.txt, so I did the above for 3 of them that uses Boost.
Next, I set the compiler flag to -fPIC for CMAKE_CXX_FLAGS and CMAKE_CXX_FLAGS_DEBUG, for example:
SET (CMAKE_CXX_FLAGS "-D_REENTRANT -fpic")
SET (CMAKE_CXX_FLAGS_DEBUG "-g -Wall -fpic")
Again, I did it for all CMakeLists that have CMAKE_CXX_FLAGS and CMAKE_CXX_FLAGS_DEBUG variables.
Lastly, I recompile boost with -fPIC option. I downloaded boost.tar.gz from sourceforge, extract it, and ran this:
bjam clean
bjam -d+2 link=static cxxflags="-fPIC" install
However, this does not seem to change anything. the date modification for libboost_system.a is dated a few years ago.
I have tried to tinker with add_library, making this static
ADD_LIBRARY(rexd STATIC ${sources_symbolic} ${sources_parsers} ${sources_lfit} ${sources_teacher} ${sources_rexd} ${sources_ippc_planner})
I got this error instead where it couldn't find a header .h:
No such file or directory
How should I proceed? I apologize if this question is too specific for my use case, but I can't find any other answers out there that I haven't tried.

Related

How do I link to a static library (libtiff) using CMake in my wxWidgets project?

For my wxWidgets project, I am trying to make the switch from my self-written Makefile to Cmake. I develop on macOS.
When I was writing that Makefile I ran into an issue with libtiff. I wanted to statically link my application so that I don't have to distribute any dylibs myself or rely on my users to install them. I built wxWidgets as a static library but when I compiled my code and checked my binary with otool I always found that my binary required a local dylib.
/usr/local/opt/libtiff/lib/libtiff.5.dylib
Finally I found a solution on here. In essence, in the linking line of my Makefile I replaced wx-config –-libs with LDFLAGS. LDFLAGS looks like this:
WXCONFIGLIBS := $(shell wx-config --libs)
WXCONFIGLIBS := $(WXCONFIGLIBS:-ltiff=/usr/local/opt/libtiff//lib/libtiff.a)
# I am not sure whether the double slash is a typo but it works so I don't change it
LDFLAGS := $(WXCONFIGLIBS)
Basically, I search-and-replaced -ltiff with the path to my static libtiff library.
Now I've managed to compile my project using Cmake. However, I'm getting the same warning message as I did when I battled my original issue.
ld: warning: dylib (/usr/local/lib/libtiff.dylib) was built for newer macOS version (11.0) than being linked (10.11)
How do I fix this? My CMakeLists contains these sections pertaining to wxWidgets:
find_package(wxWidgets REQUIRED gl core base OPTIONAL_COMPONENTS net)
include(${wxWidgets_USE_FILE})
...
add_executable(myapp ${SOURCES})
target_link_libraries(myapp ${wxWidgets_LIBRARIES})
set_property(TARGET myapp PROPERTY CXX_STANDARD 17)
I already tried running some search-and-replace shenanigans like
string(REPLACE "-ltiff" "/usr/local/opt/libtiff/lib/libtiff.a" wxWidgets_LIBRARIES ${wxWidgets_LIBRARIES})
But that doesn't work. It does replace -ltiff but also seems to remove the semicolons and whitespaces separating the different libraries.
I've been scouring the web for any clues as to what to do, but I don't seem to have a good enough grasp of libraries to fix this.
Any help would be greatly appreciated.
Set wxWidgets_USE_STATIC=ON before calling find_package(wxWidgets). See the documentation for wxWidgets here: https://cmake.org/cmake/help/latest/module/FindwxWidgets.html
option(wxWidgets_USE_STATIC "Link to wxWidgets statically" ON)
find_package(wxWidgets REQUIRED gl core base OPTIONAL_COMPONENTS net)
include(${wxWidgets_USE_FILE})
...
add_executable(myapp ${SOURCES})
target_link_libraries(myapp PRIVATE ${wxWidgets_LIBRARIES})
target_compile_features(myapp PRIVATE cxx_std_17)
My search-and-replace idea turned out to be not so bad. I was able to achieve the same outcome with Cmake as with my Makefile.
My problem was not using double quotes in the appropriate place. So instead of this:
string(REPLACE "-ltiff" "/usr/local/opt/libtiff/lib/libtiff.a" wxWidgets_LIBRARIES ${wxWidgets_LIBRARIES})
I simply needed to write:
string(REPLACE "-ltiff" "/usr/local/opt/libtiff/lib/libtiff.a" wxWidgets_LIBRARIES "${wxWidgets_LIBRARIES}")
So to solve my actual problem, I am calling this string() command just before the target_link_libraries() command.

Compiling Code with CMAKE written with C++ and DDS

I am new to using CMAKE and I am writing a Cmakelists.txt file to compile my project. I get the following error:
/usr/bin/ld: /home/tarun/rti_connext_dds-6.0.0/lib/x64Linux3gcc5.4.0/libnddsc.so: undefined reference to symbol 'PRESTypePlugin_interpretedSerialize'
/home/tarun/rti_connext_dds-6.0.0/lib/x64Linux3gcc5.4.0/libnddscore.so: error adding symbols: DSO missing from command line
I have tried other solutions already available like adding LFLAGS and CFLAGS but I still get the same error.
This is how I am linking my libraries in cmakelists
target_link_libraries(test_IMU_DDS PUBLIC
${CONNEXTDDS_CPP2_API_LIBRARIES_RELEASE_SHARED}
${CONNEXTDDS_EXTERNAL_LIBS}
${COMMANDTYPE_OBJS}
${PROJECT_SOURCE_DIR}/xspublic/xscommon
${PROJECT_SOURCE_DIR}/xspublic/xscontroller
${PROJECT_SOURCE_DIR}/xspublic/xstypes
${CMAKE_DL_LIBS}
)
Will anyone be able to help me out with this?
There is an example about how to build a ConnextDDS application in their community GitHub profile: Build a ConnextDDS application with CMake
That example is using the files from the "resources/cmake" folder (to call RTI Code Generator and a FindPackage CMake script). The FindPackage script is also provided with the ConnextDDS installation (6.0.0) but the one from the community is more updated. The FindPackage script will provide you with all the definitions, flags and libraries you need in order to integrate ConnextDDS in your project.
I added this nddscd, nddscored, nddscpp2 to target_link_libraries and these flags to CMakeLists.txt:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRTI_UNIX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRTI_LINUX")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DRTI_64BIT")

Cmake links multiple versions of boost/Cmake separate compilation of source files

I'm trying to build my project on a cluster, so I don't have any influence on the environment (ie no sudo). On my local machine I can get it to work.
Here the problem:
My project contains cuda files as well as c++ code. The latter one requires a library that needs gcc/g++ >6 (maybe >5 would work as well, afaik std=c++14). The cuda code on the other hand, as of cuda 7.5 needs gcc < 5.
I've already got this issue done by using the g++ 6.2.0 as standard compiler and pass the other gcc with -ccbin /path/to/gcc-4.x.
So my code compiles fine, but the problem is that it also uses the boost library, which needs to be a newer version on the cluster to work with the gcc 6.2.0 than the one I locally use. This is also not the problem itself, as linking the correct one does work, BUT when doing so, the nvcc still links an older version of boost (that is compatible with the gcc-4.x) and thus resulting in having multiple boost library version linked. This leads to segmentation faults during run time, whenever a function of the old boost library is used.
So a solution I was thinking about would be first compiling the c++ files and then only the cuda files, kinda like a simple makefile target would do:
foo: foo-class.o
nvcc foo-class.o foo.cu -o foo
I'm currently unsure if this would solve the problem and if this is possible to do with cmake, but if that is not the case, is there a possibility to take care of the double linkage?
Minimal cmake file example of how mine currently looks:
cmake_minimum_required(VERSION 3.2)
project(foo)
set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
set(LINKER_FLAGS "-lboost_program_options -lboost_regex -lSDL2 -lSDL2main -lboost_system -lboost_filesystem")
set(ADDITIONAL_FLAGS "-g -Wno-error=switch")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 ${LINKER_FLAGS} ${ADDITIONAL_FLAGS}")
set(SOURCE_FILES
runtime/main.cpp
foo.cpp)
set(CUDA_FILES cuda/food.cu)
set(CUDA_ADDITIONAL_FLAGS "-ccbin /usr/bin/gcc --Wno-deprecated-gpu-targets")
set(CUDA_SDK_ROOT_DIR "/afs/crc.nd.edu/x86_64_linux/c/cuda/8.0/")
find_package(CUDA QUIET REQUIRED)
set(CUDA_PROPAGATE_HOST_FLAGS OFF)
set(CUDA_NVCC_FLAGS -g ${CUDA_ADDITIONAL_FLAGS})
FIND_PACKAGE(Boost COMPONENTS program_options filesystem system regex REQUIRED)
cuda_add_executable(isosurfaces ${SOURCE_FILES} ${CUDA_FILES})
include_directories(~/lib/include)
include_directories(${BOOST_ROOT}/incldue)
target_link_libraries(foo ~/lib/lib/libThorSerialize17.so)
Thanks for any help, I really appreciate it.
To improve the CMake file I would suggest to use the variables provided by the Boost find script instead of manual setting (that will however most likely not help with the issue itself, but good in general):
find_package(Threads)
# set(Boost_USE_STATIC_LIBS ON) # uncomment to try with static libs
FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options filesystem system regex)
include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
target_link_libraries(isosurfaces
${Boost_LIBRARIES}
${CUDA_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
# remove -lboost_program_options -lboost_regex -lboost_system -lboost_filesystem
# from LINKER_FLAGS as provided better by ${Boost_LIBRARIES}
Regarding the issue itself with the different versions of Boost (if you really need to use Boost in the Cuda code for some reason), I'm afraid that will be quite difficult to get working in scope of a single executable. What you can do however, is to separate one of the modules (either the Cuda or the application code) to a separate shared library. That way it could work relatively straightforward, as the shared library can use a different Boost version than the rest of the application (you can experiment with using either static or shared Boost libraries, i.e. Boost_USE_STATIC_LIBS switched ON/OFF).
For example to create a shared library from the Cuda code you could do:
cuda_add_library(isosurfaces_cuda ${CUDA_FILES} SHARED)
add_executable(isosurfaces ${SOURCE_FILES})
target_link_libraries(isosurfaces
isosurfaces_cuda
${Boost_LIBRARIES}
${CUDA_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
Then it could probably work, provided that you do not use Boost in the interface between the Cuda code and the remaining C++ code.
It can also help to use the visibility attribute and hide all symbols by default, so that the Boost library symbols will not be exported from the Cuda shared library (or the other way around, if the library is created from the remaining C++ code). For that the "-fvisibility=hidden" compiler flag and "-Wl,--exclude-libs=ALL -Wl,--discard-all" linker flags can be used.

GLFW - linker errors on UBuntu 14.04 LTS

I want to compile an example code from this site (at the bottom). I downloaded GLFW 3.0.4 source code and I built it in a custom location. I used a default settings and GLFW was built as a static library. My CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 2.8)
project(glfw_test_project)
SET(CMAKE_CXX_FLAGS "-Wall -Werror -g -std=c++11")
find_package(OpenGL REQUIRED)
include_directories(/home/user/MyLibs/OpenGL/glfw-3.0.4/include)
link_directories(/home/user/MyLibs/OpenGL/glfw-3.0.4/build/src)
add_executable(glfw_test main.cpp)
target_link_libraries(glfw_test ${OPENGL_gl_LIBRARY})
target_link_libraries(glfw_test glfw3)
When I run make I get following info:
Linking CXX executable glfw_test
/usr/bin/ld: /home/user/MyLibs/OpenGL/glfw-3.0.4/build/src/libglfw3.a(x11_clipboard.c.o): undefined reference to symbol 'XConvertSelection'
//usr/lib/x86_64-linux-gnu/libX11.so.6: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
make[2]: *** [glfw_test] Error 1
make[1]: *** [CMakeFiles/glfw_test.dir/all] Error 2
make: *** [all] Error 2
What is wrong ?
Edit1
When I build GLFW as a dynamic library everything works fine. Then the last line in my CMakeLists.txt have to be replaced with:
target_link_libraries(glfw_test glfw)
What is wrong when using a static library ?
I experienced the same problems on Ubuntu 14.04 LTS.
First: error adding symbols: DSO missing from command line shows a wrong order of linker command line parameters. This post made me realise that. You need to call $ make VERBOSE=1 to see the linker call and check it with your own eyes. Remember: TARGET_LINK_LIBRARIES() should be the last command in your CMakeLists.txt And have a look at this order explanation.
Second: if you build against static GLFW3 libraries all the X11 libraries are not automatically added to your linker call, as atsui already showed above. In the GLFW-Documentation you can find a cmake variable which should fit your needs: ${GLFW_STATIC_LIBRARIES}. To make use of it and enable a more automatic build process, let pkg-config find all dependencies for X11 libs:
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
PROJECT(myProject)
FIND_PACKAGE( PkgConfig REQUIRED )
pkg_search_module( GLFW3 REQUIRED glfw3 ) # sets GLFW3 as prefix for glfw vars
# now ${GLFW3_INCLUDE_DIR}, ${GLFW3_LIBRARIES} and ${GLFW3_STATIC_LIBRARIES}
# are set
INCLUDE_DIRECTORIES( ${GLFW3_INCLUDE_DIR} )
ADD_EXECUTABLE( myProject mySource.cpp )
TARGET_LINK_LIBRARIES( myProject ${GLFW_STATIC_LIBRARIES} )
# they include X11 libs
Now check the linker lib parameters again with $ make VERBOSE=1 and you should find many more X11 libs like:
-lXrandr -lXi -lXrender -ldrm -lXdamage -lXxf86vm -lXext -lX11 and -lpthread.
Third: when linking against the shared library, the dependencies to X11 etc. are resolved dynamically. That is why you don't need to explicitly add X11 lib flags to the linker. In that case you only need:
TARGET_LINK_LIBRARIES( myProject ${GLFW_LIBRARIES} )
Fourth: it happened to me, that some glfwCommands had undefined reference to - linker errors. I found out, that I installed GLFW3 in /usr/local/lib but the linker was given only the LD_LIBRARY_PATH environment variable which was only set to /usr/lib32. Adding the parameter -L/usr/local/lib solved the reference problem. To avoid it in future I've set LD_LIBRARY_PATH=/usr/lib32;/usr/local/lib;.
Hint: to check what values are in your GLFW cmake variables, print them during build:
FOREACH(item ${GLFW3_STATIC_LIBRARIES})
MESSAGE(STATUS " using lib: " ${item})
ENDFOREACH()
It seems that you resolved your own issue by rebuilding GLFW as a shared library and linking the example code with that. Instead, I'll try to answer your followup question about why it doesn't work when you try to link the static library.
Basically, if you want to link against the static library libglfw3.a, you need to link all of the dependent X11 libraries. You get an error linking the static library because you didn't specify any additional libraries to link, and CMake doesn't know what these dependencies are. You don't get an error when you link the shared library libglfw.so because the X11 libraries are linked to the shared library, and CMake knows to pull those in for you automatically.
If you want to use the static library, you can determine the necessary libraries to link as follows. According to the .pc file in GLFW, you can type this in the command-line to find out what these are:
pkg-config --static --libs x11 xrandr xi xxf86vm gl
If you translate this into a CMake command, it would look like this:
target_link_libraries( glfw_test glfw3 Xrandr Xrender Xi GL m dl drm Xdamage X11-xcb xcb-glx xcb-dri2 xcb-dri3 xcb-present xcb-sync xshmfence Xxf86vm Xfixes Xext X11 pthread xcb Xau Xdmcp)
So if you add this to the CMakeLists.txt, the example code should build without an issue.
By the way, you can automatically find the X11 libraries using CMake in the following way:
find_package(X11 REQUIRED)
target_link_libraries( my_program ${X11_LIBRARIES} )
However, the set of libraries stored in the X11_LIBRARIES variable will only contain a subset of the libraries needed for statically linking GLFW.
I'm not really sure how to properly handle static/dynamic linking in CMake, but I hope this helps.

how to include NTL using CMake

I use this line to compile a simple program:
g++ main.cc -lntl -lm -lgmp
How do you include this into CMake?
find_package(NTL REQUIRED)
find_package(GMP REQUIRED)
Doesn't work. And gives the following error:
CMake Error at CMakeLists.txt:30 (find_package):
Could not find module FindNTL.cmake or a configuration file for package
NTL.
...
.
and
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++0x -lntl -lm -lgmp)
Doesn't work either (but I think it's just wrong in general).
Thank you!
If ntl, m, and gmp libraries are usually installed to somewhere in the default path (e.g. /usr/ or /usr/local/), you could simply do something like:
cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
add_executable(test main.cc)
target_link_libraries(test ntl m gmp)
This is probably closest to your original g++ command, but it isn't very robust however; if any of the libraries aren't found, you won't know about it until you try linking. If you want to fail at configure time (i.e. while running CMake), you could add find_library calls for each of the required libs, e.g.
find_library(NTL_LIB ntl)
if(NOT NTL_LIB)
message(FATAL_ERROR "ntl library not found. Rerun cmake with -DCMAKE_PREFIX_PATH=\"<path to lib1>;<path to lib2>\"")
endif()
You'd then have to change your target_link_libraries command to
target_link_libraries(test ${NTL_LIB} ${M_LIB} ${GMP_LIB})
You'd probably also then have to do a find_file for one of each lib's header files to find out the appropriate path to add via the include_directories command (which translates to -I for g++).
Note, it's important to put quotes around the extra CXX_FLAGS arguments, or CMake treats them like separate values in a list and inserts a semi-colon between the flags.
For further information about find_library, find_file, etc. run:
cmake --help-command find_library
cmake --help-command find_file
Regarding your error:
It doesn't look like there's a FindNTL.cmake module included with CMake. That means you'll have to either:
Write your own FindNTL.cmake,
Find another that somebody else has written,
Hack together a solution that:
Checks if NTL is installed
Provides link targets, relevant flags, etc.
From a (rather quick) Google search, it appears somebody has an NTL module for CMake. Since NTL use GMP, you will probably need the associated GMP module for CMake. It doesn't look like a fully-featured CMake module, but it also appears to be the best thing out there (again, it was a quick Google search, and I don't use NTL).
To use, you'll want to add some things to your CMakeLists.txt:
# Let CMake know where you've put the FindNTL.cmake module.
set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/build/CMake/Modules")
# Call the FindNTL module:
find_package(NTL REQUIRED)
SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=c++0x -lntl -lm -lgmp)
Yes, this is wrong. You don't want to be setting your CXX_FLAGS with linking directives. I would use:
SET ( CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} -std=cxx0x )
to set the Cxx standard you want to use. To actually link to libraries, you'll want to:
Ensure that you've found the libraries (with the relevant find_package ( FOO ) lines)
Link those against your target, like this:
# Build the Foo executable. (Or library, or whatever)
add_executable (FooEXE ${Foo_SOURCES} )
target_link_libraries (FooEXE
${bar_LIBRARIES}
${baz_LIBRARY}
)
Please note! ${bar_LIBRARIES} and ${baz_LIBRARY} is not a typo; there's no standard way of setting the relevant libraries in the FindFOO.cmake modules, which is, in my opinion, an annoyance. If one doesn't work, try the other, or, worst case, have a look in the relevant FindFOO.cmake file (there's a bunch installed with CMake by default) to see what each one uses. With the link i provided, you can use ${NTL_LIB} and ${GMP_LIB}.