BOOST_ROOT not respected at link stage after cmake config - c++

Apologies for a lengthy title.
I am struggling linking boost with cmake due to existence of boost libraries in /usr/lib64 directory. My boost is compiled in a different place and I am pointing cmake with BOOST_ROOT. Aware of potential problems I am setting a minimal version and Boost_NO_SYSTEM_PATH. Configure stage works fine, but when linking I get an error:
test.cpp:(.text._ZN5boost15program_options25basic_command_line_parserIcEC2EiPKPKc[_ZN5boost15program_options25basic_command_line_parserIcEC5EiPKPKc]+0xa8): undefined reference to `boost::program_options::detail::cmdline::cmdline(std::vector<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>
>, std::allocator<std::__cxx11::basic_string<char,std::char_traits<char>, std::allocator<char> > > > const&)'
This is clearly a problem of picking up the wrong library and I can see with make VERBOSE=2 that the g++ line doesn't respect my previously found boost setting in BOOST_ROOT
g++ CMakeFiles/test.dir/test.cpp.o -o test -rdynamic -lboost_program_options-mt
But I would expect something along these lines:
g++ ... -L/path/to/my/own/boost/lib -lboost_program_options-mt
As a "debug" step I print out a message in cmake with Boost_LIBRARY_DIRS and I can see /path/to/my/own/boost/lib. When I "manually" add the -L flag the linking works, which is how I know that the system libs are still interfering. Also, my *LIBRARY_PATH are pointing only at /path/to/my/own/boost/lib.
Perhaps, it's not unlikely that this is a bug of FindBoost module, but I am finding it hard to believe. It seems to me that there's still something major in cmake I do not understand? Why is the -L flag not generated in this instance or a link to a specific file? Please advise.
Here is my CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
set(Boost_NO_SYSTEM_PATHS ON)
find_package(Boost 1.67.0 REQUIRED COMPONENTS program_options)
include_directories(${Boost_INCLUDE_DIR})
add_executable(test test.cpp)
target_link_libraries(test LINK_PUBLIC ${Boost_PROGRAM_OPTIONS_LIBRARY})
And my program:
#include <iostream>
#include <string>
#include <boost/program_options.hpp>
namespace po=boost::program_options;
int main( int argc, char* argv[])
{
po::options_description options_description;
po::positional_options_description positional_options_description;
po::variables_map variables_map;
options_description.add_options()
("help,h", "print usage message");
po::store(po::command_line_parser(argc, argv).options(
options_description).positional(positional_options_description).run(),
variables_map);
return 0;
}
Other relevant output
I am using message to pull out varables from cmake config step after find_package:
${Boost_INCLUDE_DIR} /path/to/my/own/boost/include
${Boost_LIBRARY_DIRS} /path/to/my/own/boost/lib
${Boost_LIBRARIES} /path/to/my/own/boost/lib/libboost_program_options-mt.so
${Boost_PROGRAM_OPTIONS_LIBRARY} /path/to/my/own/boost/lib/libboost_program_options-mt.so

I don't know which CMake version you are using but did you try using Boost imported target instead of the old-fashioned CMake variable:
i.e.
replace:
target_link_libraries(test LINK_PUBLIC ${Boost_PROGRAM_OPTIONS_LIBRARY})
by
target_link_libraries(test LINK_PUBLIC Boost::program_options)

After calling in on cmake-developer mailing list and finally leaving a post on cmake gitlab issues I realised that the problem was not so much my cmake version, but rather my cmake_minimum_required which I inherited from an older project.
I was setting:
cmake_minium_required(VERSION 2.8)
After updating it to 3.12 that I got the correct behaviour:
/path/to/g++ -rdynamic CMakeFiles/test.dir/test.cpp.o -o test -lboost_program_options-mt
Reading cmake_minimum_required docs I understood that "command implicitly invokes" cmake_policy. I believe the latter wasn't playing well with FindBoost from my 3.12 `cmake.
I am not sure if this post is useful to SO, but I have certainly learnt my cmake lesson here.

Related

Getting tbb linker errors when including the <execution> header

I have been writing a visualisation tool using OpenGL. It has been compiling and linking just fine (using gcc 11.2.0) until I recently installed the Linux dependencies for OpenVDB (listed under Using UNIX apt-get). I am now getting linker errors that I have narrowed down to the inclusion of the <execution> header file:
/usr/bin/ld: CMakeFiles/test.dir/main.cpp.o: in function `tbb::detail::d1::execution_slot(tbb::detail::d1::execution_data const&)':
main.cpp:(.text._ZN3tbb6detail2d114execution_slotERKNS1_14execution_dataE[_ZN3tbb6detail2d114execution_slotERKNS1_14execution_dataE]+0x18): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
/usr/bin/ld: CMakeFiles/test.dir/main.cpp.o: in function `tbb::detail::d1::current_thread_index()':
main.cpp:(.text._ZN3tbb6detail2d120current_thread_indexEv[_ZN3tbb6detail2d120current_thread_indexEv]+0x12): undefined reference to `tbb::detail::r1::execution_slot(tbb::detail::d1::execution_data const*)'
The above is from the following minimal example.
main.cpp:
#include <execution>
#include <iostream>
int main()
{
std::cout << "Hello, World!" << std::endl;
return 0;
}
CMakeLists.txt:
cmake_minimum_required(VERSION 3.22)
project(test)
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD 20)
add_executable(test main.cpp)
I have tried linking TBB with my project like so:
# Find and link TBB.
find_package(TBB REQUIRED)
include_directories(${TBB_INCLUDE_DIRS})
link_directories(${TBB_LIBRARY_DIRS})
add_definitions(${TBB_DEFINITIONS})
if(NOT TBB_FOUND)
message("Error: TBB not found")
endif(NOT TBB_FOUND)
add_executable(test main.cpp)
target_link_libraries(test ${TBB_LIBRARIES})
...and also adding the -ltbb linker flag (as per the answer to this post) using
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -ltbb")
However, this does not solve the issue.
What I find particularly strange is that I didn't use to have to link against tbb despite having included the <excution> header all along. Only after installing the OpenVDB dependencies has this become an issue.
Can anyone advise me on how to solve this (either by appropriately linking tbb, or not having to link it at all, as was the case before)? Any form of insight would be much appreciated.
I have managed to successfully link tbb as follows:
find_package(TBB REQUIRED COMPONENTS tbb)
add_executable(test main.cpp)
target_link_libraries(test tbb)
Although I am still clueless as to why I suddenly needed to link with tbb, considering I previously didn't need to.
Uninstalling libtbb-dev also works and dont require editing the CMakeFiles.txt.

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.

Cmake: How to link multiple libraries?

I am using CMake to define the compilation of a C++ executable. The goal is to use 2 third-party libraries, Open3D and OpenCV. I am able to include one of the two with target_link_libraries, but including both results in OpenCV functions not being found.
This is my current CMakeLists.txt
minimum_required(VERSION 3.20)
project(ORB_SLAM)
find_package(Open3D REQUIRED)
find_package(OpenCV REQUIRED)
set(CMAKE_CXX_STANDARD 20)
add_executable(ORB_SLAM src/main.cpp)
#target_link_libraries(ORB_SLAM ${Open3D_LIBRARIES})
target_link_libraries(ORB_SLAM ${OpenCV_LIBS})
# When printed, ${Open3D_LIBRARIES} = Open3D::Open3D
# ${OpenCV_LIBS} = opencv_calib3d;opencv_core;...many more..;opencv_xphoto
With this CMakeList.txt, I can successfully use OpenCV functions. By using the commented out Open3D target_link_libraries, I can successfully use Open3D. When uncommenting both target_link_libraries, it fails to find OpenCV functionality, regardless of the order of the find_package and target_link_libraries. The same error even occurs if I include both in a single target_link_libraries(ORB_SLAM ${OpenCV_LIBS} ${Open3D_LIBRARIES}). The same error occurs for CMake 3.16.3 and 3.21.3.
The error is as follows:
/usr/bin/ld: CMakeFiles/ORB_SLAM.dir/src/main.cpp.o: in function `main':
/home/m/CLionProjects/ORB_SLAM/src/main.cpp:20: undefined reference to `cv::VideoCapture::VideoCapture(std::string const&, int)'
For the code
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
//#include <open3d/Open3D.h>
int main() {
cv::VideoCapture cap("/home/.../scene.mp4");
//auto sphere = open3d::geometry::TriangleMesh::CreateSphere(1.0);
}
It seems as though Open3D::Open3D takes precedence over opencv_calib3d;opencv_core;.... What is causing this and how can I fix it? Is this perhaps due to the discrepancy in Open3D's "::" vs OpenCV's lowercase notation?
Edit: Here is a dump of all CMake variables if it is of any use https://textuploader.com/t5dvl/raw
Excuse my inexperience. I have searched through CMake documentation and Stackoverflow questions for a lead, but so far I have found nothing.
The problem was solved by finding this Github issue: https://github.com/isl-org/Open3D/issues/2286
By using specific build flags when building Open3D, the libraries could both be linked correctly and simultaneously with the target_link_libraries(ORB_SLAM ${OpenCV_LIBS} ${Open3D_LIBRARIES}) command.
The build commands were as follows;
git clone --recursive https://github.com/intel-isl/Open3D
cd Open3D && source util/scripts/install-deps-ubuntu.sh
mkdir build && cd build
cmake -DBUILD_EIGEN3=ON -DBUILD_GLEW=ON -DBUILD_GLFW=ON -DBUILD_JSONCPP=ON -DBUILD_PNG=ON -DGLIBCXX_USE_CXX11_ABI=ON -DPYTHON_EXECUTABLE=/usr/bin/python -DBUILD_UNIT_TESTS=ON ..
make -j4
sudo make install

Undefined reference errors in simple boost serialization

I have a minimal example of Boost serialization where I try to save an integer in a binary archive file
Here is main.cpp:
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
int main() {
int t = 0;
std::ofstream file("Test.bin");
boost::archive::binary_oarchive archive(file);
archive << t;
file.close();
return 0;
}
and here is the CMake file:
cmake_minimum_required(VERSION 3.15)
project(Test)
set(CMAKE_CXX_STANDARD 17)
find_package(Boost REQUIRED serialization)
add_executable(Test main.cpp)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(Test ${Boost_LIBRARIES})
endif()
When I try to run this program in CLion, I get a large list of undefined reference errors as shown here:
https://pastebin.com/8uX9MZFf
I have setup Boost using vcpkg package manager. I'm compiling using Mingw-w64. The CMake file loads without errors (only a warning that says "New Boost version may have incorrect or missing dependencies and imported targets," though I've heard this warning isn't of concern, as it just means the current version of CMake isn't aware of the newest version of Boost).
I've tried to look for solutions to this everywhere, but I can't seem to find anything that works here. Any help would be appreciated.
I'm using cmake 3.15.3, boost 1.73.0 and mingw-w64 6.0.
EDIT
I uninstalled and reinstalled Boost without using the package manager, and tried getting the serialization library again. In this context, CMake runs into errors saying it can't find Boost with serialization (Though it can find Boost alone). I set Boost_DEBUG to ON and looked at the output, and noticed the following things:
_boost_COMPILER = "-mgw81" (guessed)
CMake seems to guess that the compiler I used to compile boost was mgw81. I'm guessing it got the 8.1 from my gcc version, which is correct.
Searching for SERIALIZATION_LIBRARY_RELEASE: boost_serialization-mgw81-mt-x64-1_73;boost_serialization-mgw81-mt-x64;...
As a result of that compiler selection, it searches for a file with "-mgw81" in the name. The problem is that the library files generated when I built boost are named like so:
libboost_serialization-mgw8-mt-x64-1_73.a
This says "-mgw8" instead of "-mgw81". I don't know how to correct CMake or build boost in such a way that this conflict doesn't happen. I've tried rebuilding boost with toolset=gcc-8.1 instead of toolset=gcc, but I still get "-mgw8" in the library file names.
EDIT 2
I found the solution to the above issue. I've posted it below.
After realizing that the issue was what I mentioned in EDIT, I looked further into how that issue could be resolved, and I found out you can manually set the compiler that is used to search through the variable Boost_COMPILER.
I changed my CMake file to the following:
cmake_minimum_required(VERSION 3.15)
project(Test)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "C:/boost_1_73_0")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "C:/boost_1_73_0/libs")
set(Boost_DEBUG ON)
set(Boost_COMPILER -mgw8)
set(Boost_ARCHITECTURE -x64)
set(BOOST_ROOT C:/boost)
set(BOOST_INCLUDEDIR C:/boost/include/boost-1_73/boost)
set(BOOST_LIBRARYDIR C:/boost/lib)
set(BOOST_NO_SYSTEM_PATHS ON)
find_package(Boost REQUIRED serialization)
add_executable(Test main.cpp)
if(Boost_FOUND)
include_directories(${Boost_INCLUDE_DIRS})
target_link_libraries(Test ${Boost_LIBRARIES})
endif()
I believe the critical changes here were setting Boost_COMPILER and Boost_ARCHITECTURE. I realized Boost_ARCHITECTURE needed to be set from this question: Linking boost in CLion project.
With this CMake file, my main.cpp file from above ran properly.

linking glbinding with cmake

I'm trying to use glbinding in my own project. I'm using cmake to build everything. The problem is linker cannot find this library. Probably I don't build library thus it cannot be linked, but I don't know how to achive that.
I've written linking code according to https://github.com/hpicgs/glbinding#linking-binaries.
Cmake:
set(SOURCE_FILES main.cpp)
add_executable(AKOpenGLEngine ${SOURCE_FILES})
set(CMAKE_PREFIX_PATH ${CMAKE_MODULE_PATH} glbinding )
find_package(glbinding REQUIRED)
include_directories(${GLBINDING_INCLUDES})
target_link_libraries(AKOpenGLEngine glbinding ${GLBINDING_LIBRARIES})
Error:
Linking CXX executable AKOpenGLEngine
ld: library not found for -lglbinding
main.cpp:
#include <glbinding/gl/gl.h>
int main(void) {
glbinding::Binding::initialize();
exit(EXIT_SUCCESS);
}
My current project structure:
Have you tried to remove the glbinding from target_link_libraries? ${GLBINDING_LIBRARIES} should be sufficient; it passes <your_specific_file_path_to_glbinding_library> to the linker. With -lglbinding the linker searches for a library within some default directories, your glbinding or build directory not included, thus throwing a library not found. To verify the content of ${GLBINDING_LIBRARIES} you can print it to cmake output, e.g., via message(STATUS ${GLBINDING_LIBRARIES}). However, i also suggest to integrate glbinding as external project as suggested by #janisz.
EDIT: sorry, didn't see the valid, but collapsed answer of #jet47