Problem:
I am having difficulties linking glibcc/glibc++ into a shared library using CMake and GCC4.9 on my Ubuntu 16.04 installation.
Additional conditions:
Loading the shared library gives a problem om the Red Hat production environment(where I copy it to), I believe because it uses a different libstc++ version(error: GLIBCXX_3_4_20 not found). I do not have sudo rights and cannot upgrade the machine.
As I derived from this blog, this post, I tried linking static linking against libgcc and libgc++ using:
set(CMAKE_EXE_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
and againg using
set(CMAKE_SHARED_LINKER_FLAGS "-static-libgcc -static-libstdc++ -static")
But that doesn't work. What does work is this CMake script:
add_library(myLib SHARED ${SOURCE_FILES})
set(CMAKE_EXE_LINKER_FLAGS " -static")
target_link_libraries(myLib -static-libgcc -static-libstdc++)
This must be the wrong way of doing this, to my knowledge -static-libgcc and -static-libstdc++ are linker options and not libraries...
Question:
How do I link statically against -libgcc and -libstdc++ correctly?
Thanks in advance!
Yes, target_link_libraries is a correct way to set linker flags or linker options.
Documentation of target_link_libraries:
Specify libraries or flags to use when linking a given target.
Item names starting with -, but not -l or -framework, are treated as
linker flags.
https://cmake.org/cmake/help/latest/command/target_link_libraries.html (emphasis not in original)
As of cmake 3.13, there is a new cmake function for general linker options:
https://cmake.org/cmake/help/v3.13/command/target_link_options.html
target_link_options(<target> [BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [items1...]
[<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
The appropriate way to specify libraries to be linked is still:
https://cmake.org/cmake/help/v3.13/command/target_link_libraries.html
target_link_libraries(<target>
<PRIVATE|PUBLIC|INTERFACE> <item>...
[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)
There are a few different signatures depending on whether or not you want these libraries to be propagated to dependent targets, so be sure to check the docs.
Related
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.
I am trying to port some MSVC projects to Linux with help of CMAKE.
In one of the Library project there are some functions which are just declared and not being defined anywhere or used anywhere.
for ex:
int fun_a();
int fun_unsed() /*This function is never used in project*/
{
fun_a();
}
Now when I try to do make in Linux, I am observing undefined reference to the declared functions. But same code works on MSVC with same CMAKE files.
I tried to use below flags in my CMAKE files(from here), but it doesn't seems to help.
SET(GCC_COVERAGE_COMPILE_FLAGS "-unresolved-symbols=ignore-all")
SET(GCC_COVERAGE_LINK_FLAGS "-unresolved-symbols=ignore-all")
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )
am I missing something?
Below is cmake file for executable
#Add Library Projects to the test application
add_subdirectory ("${PROJECT_BINARY_DIR}/../../src/build/vc/" "${PROJECT_BINARY_DIR}/../../src/build/vc/")
#set additional search paths for libraries
#set(CMAKE_LIBRARY_PATH ${PROJECT_BINARY_DIR}/../../lib/Debug)
link_directories(${PROJECT_BINARY_DIR}/../../lib ${OPENCV_BUILD}/lib)
#set ignore undefined & unused functions errors. It seems GCC by defalt looks for them.
SET(GCC_COVERAGE_LINK_FLAGS "-unresolved-symbols=ignore-all")
SET(GCC_COVERAGE_COMPILE_FLAGS "-ffunction-sections")
SET(GCC_COVERAGE_LINK_FLAGS "-Wl,-gc-sections -flto")
SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
SET( CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}" )
#Get the exicutable for source files
add_executable (FaceAnalysis ${sources})
target_link_libraries (FaceAnalysis faceDetect.a libopencv_core.so libopencv_imgproc.so libopencv_imgcodecs.so libopencv_videoio.so libopencv_objdetect.so libopencv_highgui.so libopencv_video.so libopencv_ml.so SDL2)
add_dependencies(FaceAnalysis faceDetect)
If they were indeed unreferenced, you wouldn't get an "undefined reference" error.
The linker error should tell you where the symbol is used.
Edit: revised question
This can be worked around by asking the compiler to put each function into a separate section, so they are kept apart inside the object files until the final link, and then instructing the linker to discard sections that are unreferenced.
Add -ffunction-sections to CFLAGS and/or CXXFLAGS as appropriate, and -Wl,--gc-sections to LDFLAGS.
The link-time optimizer (-flto) can also do this, but AFAIK requires optimization to be enabled, so it would fail in Debug builds.
If you have no implementation for the function in your project, then it must be implemented in another library. In your visual studio project, right-click on the project, select "Properties", then under "Linker" take a look at the linked libraries and link directories. You'll see at least one library defined there. Then in CMAKE you just need to target_link_libraries to the same lib.
The flags which remove death code are, as Simon said in his answer:
-ffunction-sections and -Wl,--gc-sections1
But, GCC does not support them in some targets, like Windows and Linux on X86 and 64, with ELF file format.
My solution was to reduce the visibility of all functions, by also using the following flags:
-fvisibility=hidden and -fvisibility-inlines-hidden 2
All the flags together, removed the link time error.
1 -ffunction-sections puts each function in a different section
-Wl,--gc-sections should remove all the sections that are unused.
2 This flags change the visibility of all functions from default (public) to hidden. So the linker now know that the functions are not needed anymore if they are not used inside the executable or library, so it is free to remove them.
I am using CMake under Ubuntu 14.04 to configure my project.
I need to use a 3rd party library (say stuff.so).
In the CMakeLists.txt, I use TARGET_LINK_LIBRARIES to link the stuff library.
However, I got an error:
DIR_TO_LIB/stuff.so:-1: error: undefined reference to `shm_open'
I tried to put these flag in the CMakeLists.txt but it didn't work:
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -lrt")
A post (link) saying that -lrt should be put as the last argument of g++. In my case where CMake is used, how shall I do this?
UPDATE:
I added
SET (CMAKE_VERBOSE_MAKEFILE 1)
and I found that -lrt is not the last (even though I put it at the end of the target link). Please see this link for compile output.
As you can see from the compile output, there are some linking flags for the opencv.
I don't understand how could this happen as I link the OpenCV library first in the TARGET_LINK_LIBRARIES. How does CMake handle these linking order?
Please also see my CMakeLists.txt.
Thank you.
You need to add rt in TARGET_LINK_LIBRARIES as a last one, for example:
TARGET_LINK_LIBRARIES(my_app ${Boost_LIBRARIES} rt)
You can verify position of rt by enabling verbose build output:
SET (CMAKE_VERBOSE_MAKEFILE 1)
First, the answer is: Append -lrt to the end of your macro target_link_libraries for your target my_app, i.e.,
target_link_libraries(my_app ${Boost_LIBRARIES} -lrt)
That achieves the same effect in solving the missing library to be linked against by using e.g. gcc compiler:
gcc my_app.c -o my_app -lrt
The reason behind, as you may have already figured out, is the missing required ("realtime") library. For that, you can check by typing in the command
man shm_open
and then finding the key snippet explaining the reason of adding -lrt, i.e.,
"These functions are provided in glibc 2.2 and later. Programs using these functions must specify the -lrt flag to cc in order to link against the required ("realtime") library."
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.
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}.