I'm trying to build a 3rd party C++ library from source, and it depends on Boost. In the very last step when building, I got errors like this:
[ 90%] Linking CXX executable Shannon_RNASeq_Cpp
CMakeFiles/Shannon_RNASeq_Cpp.dir/src/main.cpp.o: In function `command_line_for_find_rep(int, char**, Shannon_C_setting&,
std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> >&)':
/home/lambda/Shannon_Cpp_RNA_seq/src/main.cpp:320: undefined reference to `boost::program_options::options_description::options_description(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, unsigned int, unsigned int)'
I searched other questions on StackOverflow (e.g. Boost Program Options link error), and initially thought that it was caused by the different compilers used to build the non-header part of Boost, so I downloaded the source of Boost 1.68.0 and built it in my personal directory using the same compiler I used to build the 3rd party library (the compiler is gcc 8.2.0), and from the error message, I can tell that C++11 standard was used (you can see cxx11
in the error message), so it can't be the case that compiler not supporting C++11 is causing the trouble, as supposed previously (e.g. undefined reference to boost::program_options in xubuntu). To build Boost with a custom compiler (the default compiler of the server is terribly outdated), I followed the instructions here.
Some further search reveals that this is a linking problem. The 3rd party library must be built by CMake, and I followed the instruction in an answer to a previous question (How to link C++ program with Boost using CMake), by adding this line to CMakeLists.txt
in the root directory of the 3rd party library:
target_link_libraries(Shannon_RNASeq_Cpp ${Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE})
However, the same problem persists. I checked the file CMakeCache.txt
, and confirmed that the desired compiler is used and Boost_PROGRAM_OPTIONS_LIBRARY_RELEASE
points to the libboost_program_options.so
in the directory where I put Boost 1.68.0 (the server has other older versions of Boost). I then used make VERBOSE=1
to check the bash commands invoked while building the library. The command doesn't sound wrong; the Boost program_options library has been linked; here's the command from make VERBOSE=1
:
/usr/bin/cmake3 -E cmake_link_script CMakeFiles/Shannon_RNASeq_Cpp.dir/link.txt --verbose=1
It's referring to something in link.txt
, and here's what I found there:
/home/lambda/mylibs/bin/c++ -g -rdynamic CMakeFiles/Shannon_RNASeq_Cpp.dir/src/main.cpp.o
CMakeFiles/Shannon_RNASeq_Cpp.dir/src/run_tasks.cpp.o -o
Shannon_RNASeq_Cpp lib_shannon/libmulti_graph_handler.a
lib_shannon/libcontig_graph_handler.a lib_shannon/libprimary_lib.a
-lboost_program_options lib_shannon/libsparse_flow_handler.a
-lglpk lib_shannon/libseq_graph_handler.a -lpthread
-lboost_system -Wl,-Bstatic -lmetis -Wl,-Bdynamic -lboost_filesystem
-lboost_program_options
So yes, Boost program_options has been linked (-lboost_program_options). I wonder if this is something wrong with program_options, since all errors that occurred at this stage are from program_options; I also linked to 2 other Boost compiled libraries, namely filesystem and system, and they do not appear in any error message I saw here.
I solved this problem myself (see my answer below), but new to CMake (and my only experiences with C++ is Rcpp
), I don't know why it worked. Can someone please explain why switching to a static library worked? Also, when CMake linked to the default version of Boost on the server, it also by default used the .so
s rather than the .a
s, even though the .a
s are available. Is there any way to tell CMake to use the .a
s rather than the .so
s? Are there other solutions?