3
votes

I am working on a server without root privileges. I have a simple command line application that links to OpenCV and Boost and I am using cmake 2.8.12. There are old boost libraries in /usr/lib64 but I want to use newer boost libraries which I can load using an environment module. The CMakeLists.txt file is the following:

cmake_minimum_required(VERSION 2.8.12)

find_package(Boost 1.55.0 REQUIRED COMPONENTS program_options system thread)
find_package(OpenCV REQUIRED)

message("Boost dirs: ${Boost_LIBRARY_DIRS} ${Boost_INCLUDE_DIRS}")
message("Boost libraries ${Boost_LIBRARIES}")

include_directories(${OpenCV_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS})

# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${Boost_LIBRARY_DIRS}")

add_executable(tile_images src/tile_images.cpp)
target_link_libraries(tile_images ${OpenCV_LIBRARIES} ${Boost_LIBRARIES} )

The messages print the full paths to the correct libraries:

Boost dirs: /cm/shared/apps/boost/1.56/lib /cm/shared/apps/boost/1.56/include

Boost libraries /cm/shared/apps/boost/1.56/lib/libboost_program_options.so;/cm/shared/apps/boost/1.56/lib/libboost_system.so;/cm/shared/apps/boost/1.56/lib/libboost_thread.so

The problem occurs when linking, cmake generates the following call to c++:

/usr/bin/c++ CMakeFiles/tile_images.dir/src/tile_images.cpp.o -o tile_images -rdynamic /cm/shared/apps/opencv/2.4.9/lib/libopencv_videostab.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_video.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_ts.a /cm/shared/apps/opencv/2.4.9/lib/libopencv_superres.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_stitching.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_photo.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_ocl.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_objdetect.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_nonfree.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_ml.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_legacy.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_imgproc.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_highgui.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_gpu.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_flann.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_features2d.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_core.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_contrib.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_calib3d.so.2.4.9 -lboost_program_options -lboost_system -lboost_thread -ldl -lm -lpthread -lrt /cm/shared/apps/opencv/2.4.9/lib/libopencv_nonfree.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_ocl.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_gpu.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_photo.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_objdetect.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_legacy.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_video.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_ml.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_calib3d.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_features2d.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_highgui.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_imgproc.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_flann.so.2.4.9 /cm/shared/apps/opencv/2.4.9/lib/libopencv_core.so.2.4.9

Note how the absolute path to the boost libraries has been stripped and it is not included using a -L flag. I then get the following warning, hinting at the fact that the linker is picking up the other, older boost installation in /usr/lib64

/usr/bin/ld: warning: libboost_system.so.1.56.0, needed by /cm/shared/apps/boost/1.56/lib/libboost_thread.so, may conflict with libboost_system.so.5

Linking then fails with a long list of errors, probably because the old Boost libraries are used but the code is built with the newer Boost headers.

If I add the following to the CMakeLists.txt:

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${Boost_LIBRARY_DIRS}")

then the code links without problems. I've spent some time researching, but so far I have drawn a blank for how to get CMake to include the -L flag or how to stop it stripping the absolute paths from the boost libraries. Any help would be much appreciated!

1
Did you check Boost_REALPATH and Boost_DEBUG in the documentation?Andreas Haferburg
Thanks, setting Boost_REALPATH to ON seems to fix it. I'm not sure I fully understand why this is not the default behaviour. Could you add an answer, then I'll accept it.Patrick
Actually I added it as an answer, then I saw the sentence "This does not affect linking and should not be enabled unless the user needs this information" and deleted it. I'm confused now.Andreas Haferburg
Yes, I'm also confused. When I print the ${Boost_LIBRARIES} after running find_package (without setting Boost_REALPATH to ON), the correct full paths to the libraries are printed. However when running make, in the call to c++ only the library names appear. This behaviour seems quite unexpected and I still don't see why it is the default...Patrick
I would say it's expected behavior that you need to manually add "Boost_LIBRARY_DIRS". You can do it more portably with LINK_DIRECTORIES(${Boost_LIBRARY_DIRS}). The reason that Boost_REALPATH helps is related to search order. By adjusting the library name to the one with the version in it, gcc now finds the new library even though it is lower in the search order, since it only exists there.Peter

1 Answers

0
votes

I believe this is explained in the documentation: set(Boost_REALPATH ON).

Boost_REALPATH - Set to ON to resolve symlinks for discovered libraries to assist with packaging. For example, the "system" component library may be resolved to "/usr/lib/libboost_system.so.1.42.0" instead of "/usr/lib/libboost_system.so". This does not affect linking and should not be enabled unless the user needs this information.