I'm linking against boost statically. When I do so, I get some undefined reference errors (below).
[100%] Linking CXX executable infiniteTests
/home/wdog/src/protos/infinite/libinfinite.a(ServiceDiscovery.cpp.o): In function `boost::date_time::month_formatter<boost::gregorian::greg_month, boost::date_time::simple_format<char>, char>::format_month(boost::gregorian::greg_month const&, std::ostream&)':
/home/wdog/src/3rdp/boost_1_63_0/boost/date_time/date_formatting.hpp:44: undefined reference to `boost::gregorian::greg_month::as_short_string() const'
/home/wdog/src/3rdp/boost_1_63_0/boost/date_time/date_formatting.hpp:49: undefined reference to `boost::gregorian::greg_month::as_long_string() const'
collect2: error: ld returned 1 exit status
When I link dynamically, the references are presumably present, and the build links successfully.
I need to be able to build this statically; requirement of the project.
I'm building with cmake. My link directories are ordered thus:
link_directories(
$ENV{PROJECT_LIB_DIR}
$ENV{BOOST_LIBRARY_DIR}
$ENV{HIREDIS_LIB_DIR}
$ENV{LIBEVENT_LIB_DIR}
$ENV{PROJECT_ROOT}
/usr/lib
/usr/local/lib
)
My target link libaries are defined as:
target_link_libraries(
${sThisProject}
${Boost_LIBRARIES}
libhiredis.a
libevent.a
libevent_core.a
libevent_pthreads.a
libssl.so
libcrypto.so
libpthread.so.0
)
Here's the CMakeLists.txt entry where I find boost:
find_package( Boost 1.63 EXACT REQUIRED COMPONENTS system chrono date_time filesystem program_options regex thread REQUIRED )
I also set the following:
SET (Boost_NO_SYSTEM_PATHS ON)
SET (Boost_USE_STATIC_LIBS ON)
SET (Boost_USE_MULTITHREADED ON)
SET (Boost_USE_STATIC_RUNTIME ON)
I've checked that my build of 1.63 has successfully built the appropriate static lib - libboost_date_time.a - and it's present in ${BOOST}/stage/lib/
It's my understanding that this can happen if the linker finds a boost static lib on the system install before the correct path.
Cmake appears to find the correct path for boost 1_63:
(output during build:)
-- Boost version: 1.63.0
-- Found the following Boost libraries:
-- system
-- chrono
-- date_time
-- filesystem
-- program_options
-- regex
-- thread
I run fedora 25, so my system installed version of boost was 1_60, so to avoid the above problem, I uninstalled it completely:
sudo dnf remove boost boost-atomic boost-chrono boost-container boost-context boost-coroutine boost-date-time boost-devel boost-filesystem boost-graph boost-iostreams boost-locale boost-log boost-math boost-program-options boost-python boost-random boost-regex boost-serialization boost-signals boost-system boost-test boost-thread boost-timer boost-type_erasure boost-wave
I built but do not install 1.63 in a 3rd party directory in my source tree. It's built with the following commands:
./bootstrap.sh
./b2 -j8
I set linker output with:
SET (CMAKE_EXE_LINKER_FLAGS -v)
And determined via the following output that I'm linking against the correct static libary:
-o
...
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_system.a
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_chrono.a
**/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_date_time.a**
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_filesystem.a
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_program_options.a
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_regex.a
/home/wdog/src/3rdp/boost_1_63_0/stage/lib/libboost_thread.a
...
I've run out of ideas; is there something else I should check?
That libinfinite.a needs to precede the boost libraries in the command line.
Related
I'm trying to install boost in a custom dir. I did:
cd boost_dir
./bootstrap.sh --prefix=/custom_dir
./b2
Now what I want to do is tell CMake to point to that library. To that end, I added:
set(BOOST_ROOT "/custom_dir")
FIND_PACKAGE(Boost COMPONENTS program_options REQUIRED)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(myProject ${Boost_LIBRARIES})
And CMake apparently found boost in that dir:
cmake .
-- Found Boost: /custom_dir (found suitable version "1.66.0", minimum required is "1.66") found components: program_options -- Configuring done
-- Generating done
-- Build files have been written to: /my_project
However, when compiling, I still get:
undefined reference to `boost::program_options::options_description::options_description(std::string const&, unsigned int, unsigned int)'
A few answers have noted that boost must have been compiled with the same compiler as the program I'm using. However, I'm not sure if the steps I did above actually compiled boost or simply copies the uncompressed libs?
Also, does it use the path-resolved g++ or something in the system default /usr/bin? Reason is that I do not have root access and installed an updated GCC in a custom dir as well. I've pointed my PATH to the updated g++.
So as it turns out, the GCC version was correct but it would only work if I compiled Boost with static linking and told CMake to link statically. I experimented with dynamic linking (both compiling Boost and setting CMake for my target app) and it doesn't work for some reason.
Just make sure to compile with the same ABI options.
This is driving me nuts. In my CMakeLists.txt I have:
find_package(Boost 1.63.0 REQUIRED SYSTEM)
Result:
[0/1] Re-running CMake...
Build type: Release
CMake Error at /usr/share/cmake-3.10/Modules/FindBoost.cmake:1947 (message):
Unable to find the requested Boost libraries.
Boost version: 1.65.1
Boost include path: /usr/include
Could not find the following Boost libraries:
boost_system
But:
$ locate libboost_system
/usr/lib/x86_64-linux-gnu/libboost_system.a
/usr/lib/x86_64-linux-gnu/libboost_system.so
/usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1
And:
$ sudo apt install libboost-all-dev
Reading package lists... Done
Building dependency tree
Reading state information... Done
libboost-all-dev is already the newest version (1.65.1.0ubuntu1).
I have previously used a self-compiled 1.63.0, but I have removed all the files from /usr/local/lib and /usr/local/include. Maybe it still somehow haunts here..?
If I find Boost like this (without system):
find_package(Boost 1.63.0 REQUIRED)
..then configuring succeeds, but won't link to ${Boost_SYSTEM_LIBRARY}:
/usr/bin/ld: src/app/CMakeFiles/app.dir/application.cpp.o: undefined reference to symbol '_ZN5boost6system15system_categoryEv'
//usr/lib/x86_64-linux-gnu/libboost_system.so.1.65.1: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
The problem was that you should require system instead of SYSTEM even though it complains about missing boost_system also when SYSTEM was used. I find that a bit confusing:
find_package(Boost 1.63.0 REQUIRED system)
I tried to import Boost 1.61.0 (downloaded from SourceForge - Boost 1.61.0 as .7z), but failed.
Console:
"D:\Program Files (x86)\JetBrains\CLion 2016.2\bin\cmake\bin\cmake.exe" --build C:\Users\Marczak\.CLion2016.2\system\cmake\generated\WsServer-e351c9f9\e351c9f9\Debug --target WsServer -- -j 4
[ 50%] Linking CXX executable WsServer.exe
CMakeFiles\WsServer.dir\build.make:96: recipe for target 'WsServer.exe' failed
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/WsServer.dir/all' failed
CMakeFiles\WsServer.dir/objects.a(main.cpp.obj): In function `_static_initialization_and_destruction_0':
C:/Users/Marczak/boost_1_61_0/boost/system/error_code.hpp:221: undefined reference to `boost::system::generic_category()'
C:/Users/Marczak/boost_1_61_0/boost/system/error_code.hpp:222: undefined reference to `boost::system::generic_category()'
C:/Users/Marczak/boost_1_61_0/boost/system/error_code.hpp:223: undefined reference to `boost::system::system_category()'
collect2.exe: error: ld returned 1 exit status
mingw32-make.exe[3]: *** [WsServer.exe] Error 1
mingw32-make.exe[2]: *** [CMakeFiles/WsServer.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFiles/WsServer.dir/rule] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/WsServer.dir/rule' failed
mingw32-make.exe: *** [WsServer] Error 2
Makefile:117: recipe for target 'WsServer' failed
CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(WsServer)
set(BOOST_ROOT "C:/Users/Marczak/boost_1_61_0")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
set(SOURCE_FILES src/main.cpp)
find_package(Boost)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(WsServer ${SOURCE_FILES})
If I do find_package(Boost 1.61.0 COMPONENTS system filesystem REQUIRED) I get:
Error: Unable to find the requested Boost libraries.
Boost version: 1.61.0
Boost include path: C:/Users/Marczak/boost_1_61_0
Could not find the following static Boost libraries:
boost_system boost_filesystem
No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.
I tried to set Boost_USE_STATIC_LIBRARIES on, but it failed too. I use CLion 2016.2.
UPDATE: I tried older versions too. Same error. What's inside the .7z:
In other topics I see lib folder. But here I don't see it. What I should put in BOOST_LIBRARYDIR?
UPDATE 2: Installed binary from https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/ . I noticed there's new folder: lib64-msvc-14.0. It contains many .dll and .lib files, e.g. boost_atomic-vc140-mt-1_61.dll.
Boost.org says:
If you plan to use your tools from the Windows command prompt, you're in the right place. If you plan to build from the Cygwin bash shell, you're actually running on a POSIX platform and should follow the instructions for getting started on Unix variants. Other command shells, such as MinGW's MSYS, are not supported—they may or may not work.
I'll try using Cygwin.
If you're new to C++, I suggest you to download MinGW distribution maintained by Stephan T. Lavavej (Microsoft C++ developer): https://nuwen.net/mingw.html. It, among other tools and libraries, contains pre-built boost binaries. Unpack it and specify the path to it via Settings | Build, Execution, Deployment | Toolchains.
After that you should be able to compile the program with the following CMakeLists.txt:
cmake_minimum_required(VERSION 3.5)
project(WsServer)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
set(SOURCE_FILES src/main.cpp)
find_package(Boost REQUIRED COMPONENTS filesystem)
include_directories(${Boost_INCLUDE_DIRS})
add_executable(WsServer ${SOURCE_FILES})
target_link_libraries(WsServer ${Boost_LIBRARIES})
Don't forget to drop CMake cache as find_packages doesn't update successful results due to performance reasons (in CLion it can be done via Cmake toolbar | Cache | red arrows icon).
Some additional remarks:
Boost_USE_STATIC_LIBRARIES is not meant to be set manually, it is set by running find_package(Boost), which uses BOOST_ROOT or BOOST_INCLUDEDIR + BOOST_LIBRARYDIR, you should set those if required. You don't have to do it with the MinGW distro I've linked because it already has boost includes and libraries in accessible locations.
You can check that the paths to libraries are correct by looking at Boost_* variables in CMake cache.
libs directory inside boost sources is unrelated to the problem, it doesn't conitain any binaries
You've downloaded boost binaries built with Visual Studio toolchain, not MinGW, so they are incompatible with your setup. If you don't want to use MinGW package I've linked, you have to either find boost binaries built with correct MinGW version or build it yourself.
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'm using cmake for project with boost, I've set boost-signals as required and cmake states it finds it, but when I compile the project I get a linking error.
I can resolve it with a linker directive set(CMAKE_EXE_LINKER_FLAGS -lboost_signals) but
this seems contrary to what it should be doing. Can someone suggest a better way? Thanks
in CMakeLists.txt
IF(UNIX)
find_package(Boost COMPONENTS system filesystem random regex signals thread program_options date_time REQUIRED)
INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
ENDIF()
Running cmake:
$ cmake ../
-- Boost version: 1.49.0
-- Found the following Boost libraries:
-- system
-- filesystem
-- random
-- regex
-- signals
-- thread
-- program_options
-- date_time
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/myproject/build
Linker error:
/usr/bin/ld: /usr/local/lib/libwt.so: undefined reference to symbol '_ZN5boost7signals9trackableD2Ev'
/usr/bin/ld: note: '_ZN5boost7signals9trackableD2Ev' is defined in DSO /usr/lib/libboost_signals.so.1.49.0 so try adding it to the linker command line
/usr/lib/libboost_signals.so.1.49.0: could not read symbols: Invalid operation
collect2: error: ld returned 1 exit status
Boost Signals is not a header-only library. In addition to giving the include directory, you need to tell CMake to link against it too.
add_executable(MyProgram [...] )
target_link_libraries(MyProgram ${Boost_LIBRARIES})
In case you plan to build on Windows as well, you might also want to disable auto-linking:
add_definitions(-DBOOST_ALL_NO_LIB)
Note that Boost Signals has been deprecated and replaced by Signals2, which is in fact a header-only library. If it is up to you to make the choice, consider using Signals2 instead.