Linking error in boost program_options - c++

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 .sos rather than the .as, even though the .as are available. Is there any way to tell CMake to use the .as rather than the .sos? Are there other solutions?

What I did was to change all the .sos in CMakeCache.txt into .as, like I changed libboost_program_options.so into libboost_program_options.a, and this error went away. Then the command from make VERBOSE=1 became:
/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
-Wl,-Bstatic -lboost_program_options lib_shannon/libsparse_flow_handler.a
-Wl,-Bdynamic -lglpk lib_shannon/libseq_graph_handler.a -lpthread
-Wl,-Bstatic -lboost_system -lmetis -lboost_filesystem -lboost_program_options -Wl,-Bdynamic

Related

udata.cpp: undefined reference to `icudt71_dat'

I am getting an odd ICU related linking error in the now project when building on Ubuntu 22.04.
/usr/bin/ld: /usr/bin/ld: DWARF error: invalid or unhandled FORM value: 0x23
/home/bkey1/vcpkg/installed/x64-linux/debug/lib/libicuuc.a(udata.ao): in function `openCommonData(char const*, int, UErrorCode*)':
udata.cpp:(.text+0x23f7): undefined reference to `icudt71_dat'
/usr/bin/ld: udata.cpp:(.text+0x2458): undefined reference to `icudt71_dat'
The link command is as follows.
usr/bin/cmake -E cmake_link_script CMakeFiles/now.dir/link.txt --verbose=1
/usr/bin/c++ -std=c++2a -Wall -Wextra -Wfloat-equal -Wno-long-long -Wpedantic -funsigned-char -D_GNU_SOURCE=1 -rdynamic CMakeFiles/now.dir/GetStardate.cpp.o CMakeFiles/now.dir/GetTime.cpp.o CMakeFiles/now.dir/GetTimePlatformPOSIX.cpp.o CMakeFiles/now.dir/GetTimePlatformWin32.cpp.o CMakeFiles/now.dir/ISO8601_time.cpp.o CMakeFiles/now.dir/InitLocale.cpp.o CMakeFiles/now.dir/executable_path.cpp.o CMakeFiles/now.dir/now.cpp.o CMakeFiles/now.dir/nowStrings.cpp.o -o now /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_chrono.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_filesystem.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_locale.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_log.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_program_options.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_regex.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_system.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_thread.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_date_time.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_log_setup.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libboost_atomic.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libicudata.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libicui18n.a /home/bkey1/vcpkg/installed/x64-linux/debug/lib/libicuuc.a
First I would like to stress, that there is very little information provided, so the answers such as my own will most likely need to guess what is happening. On the other hand I understand your situation: you cannot include info, that you don't know is relevant to the topic.
Answer:
I would like to draw your attention to the fact, that the symbol icudt71_dat does not appear anywhere in the code directly, but is generated using a macro. (Check .../source/common/unicode/utypes.h) So if the linker complains about not having found such a symbol it most probably means you are linking against a different version of the library than you have a header for. Now I don't know how specifically this could have happened, I would have to see your system, include path, link path etc. However I strongly suggest to revisit both include and link paths. You could perhaps recompile the library, verify, there is no other version recompile and start again. If the header corresponds to the source, it should work.
Aparently you missing icu-devtools package. Install that with command
sudo apt get install icu-devtools

Compiling boost flags with explicit location on boost binaries

I am compiling a project that needs boost::filesystem. I have included the following flags in my compilation step:
g++ -Wall -ggdb -Werror -std=c++11 -lboost_system
-lboost_filesystem -I /custom/path/to/boost_1_67_0
-o build/main build/cp.o build/walk.o build/diff.o build/main.o
and I get an error:
build/cp.o: In function `boost::filesystem::relative(boost::filesystem::path const&, boost::filesystem::path const&)':
/custom/path/boost_1_67_0/boost/filesystem/operations.hpp:690: undefined reference to `boost::filesystem::detail::relative(boost::filesystem::path const&, boost::filesystem::path const&, boost::system::error_code*)'
build/cp.o: In function `boost::filesystem::weakly_canonical(boost::filesystem::path const&)':
/custom/path/boost_1_67_0/boost/filesystem/operations.hpp:728: undefined reference to `boost::filesystem::detail::weakly_canonical(boost::filesystem::path const&, boost::system::error_code*)'
collect2: error: ld returned 1 exit status
make: *** [build] Error 1
I suspect that this is due to the fact that I have various other boost::filesystem binaries, some of which don't have relative and weakly_canonical in their versions. I don't really know where to supply the argument to specify the location of the binaries either. I suspect it's something to do with the flags lboost_system and lboost_filesystem where I can supply the location.
I am currently in process of building the .so's but I can see that the filesystem .so is already successfully built at /custom/path/boost_1_67_0/bin.v2/libs/filesystem/build/gcc-4.8.5/release/threading-multi/libboost_filesystem.so.1.67.0, so I want to point to that in the mean time. Building the library is taking a really long time.
So is it the -lboost_{libname} flags that I can extend upon? Is it the -I flag?
EDIT: Now that the binary location specified by --prefix during build is done, I tried the same thing, even with -L and it didn't work. Refer to my answer below for the LD_LIBRARY_PATH solution.
I have a solution, but it's not pretty:
I suspect it's because the other boost library binary is specified in $LD_LIBRARY_PATH, I could not load my own library in precedence using -L /custom/path/....
Thus, I did:
export LD_LIBRARY_PATH=/custom/path/...:$LD_LIBRARY_PATH
And it works.
This is by no means a good answer because it doesn't really make this build process portable to users without the LD_LIBRARY_PATH flag. Better answers will be approved instead of this.
Looks like you still need to provide the -L GCC option.
Use -L to tell the compiler where to look for the boost libraries.
Also, make sure you used bjam/b2 to install boost in a proper place. That bin.v2 directory is used to build boost libraries and not install.

g++ undefined reference error when linking to third party shared libraries

I'm trying to link a c++ program that uses several shared libraries from 3rd parties. Mainly, these libraries come from a github project called MBSim and I downloaded the latest daily build with all its binaries, libraries and headers, which I installed on /usr/local/mbsim-env.
The most important libraries called are libmbsim, libopenmbvcppinterface, libfmatvec and libboost_filesystem (the last one comes with the MBSim distro).
I set up a simple code to test it and it compiles like a charm using
g++ main.cpp -m64 -g3 -std=c++11 -Wall
-Wfatal-errors -Werror -Wno-unknown-pragmas -fopenmp
`pkg-config --cflags mbsim` -I. -c -o main.o
The pkg-config part calls, as you can wonder, the include directories and flags:
-DHAVE_ANSICSIGNAL -DHAVE_OPENMBVCPPINTERFACE -DHAVE_BOOST_FILE_LOCK
-I/usr/local/mbsim-env/include
-I/usr/include/x86_64-linux-gnu
-I/usr/include/x86_64-linux-gnu/c++/5
-I/usr/local/include
My problems appear when I try to link the objects with the pre-compiled libraries with:
g++ system.o main.o -o teste -L/usr/local/mbsim-env/lib
-lmbsim -lopenmbvcppinterface -lboost_system
-lfmatvec -lm
-Wl,-rpath,/usr/local/mbsim-env/lib
Edit: On the above command, I've tried to use pkg-config --libs as well. The results remain the same.
First of all, the linker issues a warning that I'm linking against an older boost library:
/usr/bin/ld: warning: libboost_system.so.1.53.0,
needed by /usr/local/mbsim-env/lib/libmbsim.so,
may conflict with libboost_system.so.1.61.0
I'm aware of that, but I intentionally want to link against the old one because that's the one that was used to compile the MBSim libraries.
After that, I got several undefined reference warnings for almost every method that I call from MBSim:
system.cpp:59: undefined reference to
MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
It seems to me that this error means that the target libraries don't have the RigidBody method implemented. Well, I know they do.
My first guess was that maybe the linker was looking at the wrong library path, so I set LD_LIBRARY_PATH=/usr/local/mbsim-env/lib and added the -rpath to the same folder. That didn't help at all.
Some googling showed me that the problem could be compiling in 64bits and linking it against 32bits libs. I believe that's not the case: I've done everything in Ubuntu 16.04 64bits and the MBSim libraries are also 64bits.
Could somebody point me out of this dead end?
Could it be that your 3rd party shared libraries are compiled using an older version of GCC? There was a new ABI introduced in GCC 5. It's probably enabled by default on your platform. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html.
You could try switching to the older ABI, but that might require your other libraries to have been compiled with the old ABI also. You might also be able to switch ABIs for the 3rd party libraries explicitly.
undefined reference to MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<std::char_traits<char>, std::allocator<char> > const&)
This is a reference to MBSim::RigidBody::RigidBody(const string&), compiled with g++ -std=c++11 and g++ version 5 or later.
As any1 probably correctly guessed, the binary for libmbsim.so that you downloaded was built with g++ 4.x, and defines the same function with this signature:
MBSim::RigidBody::RigidBody(std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&)
Note lack of __cxx11 namespace. You can easily confirm or disprove this:
nm -C libmbsim.so | grep 'MBSim::RigidBody::RigidBody'
If this mismatch is indeed the cause, simply rebuild this project from source with your compiler. That's what open source is for.

Linking errors on Linux gcc 4.3.4: "undefined reference" related to "jpeg" library (e.g., undefined reference to `jpeg_std_error(jpeg_error_mgr*)')

I am working with a large C++ code that has been developed over a few years. I have added to the code and have been successfully running it on Mac OX 10.7.5. However, it is very slow and I now want to run it on a cluster (g++ (SUSE Linux) 4.3.4 [gcc-4_3-branch revision 152973]). I am not very experienced as far as C++ and I'm a complete newbie as far as dealing with compilation / linking.
I am unable to get past a linking error related to a "jpeg" library and would be very grateful for any help. I have the library code installed in a directory where my code resides, but my understanding is that it is also available from the compiler.
There is a lot of error output, so I won't post it all. Here is the first part:
/data/place/number/account/program/libraries/libfile_intel.a(Grid.o):
In function program::Grid<double>::SaveToJPG(char const*,
int, bool, bool) const':
Grid.cpp:(.text._ZNK3program20GridIdE9SaveToJPGEPKcibb[program::Grid<double>::SaveToJPG(char
const*, int, bool, bool) const]+0x499): undefined reference to
jpeg_std_error(jpeg_error_mgr*)'
Grid.cpp:(.text._ZNK3program20GridIdE9SaveToJPGEPKcibb[program::Grid::SaveToJPG(char
const*, int, bool, bool) const]+0x4b5): undefined reference to
`jpeg_CreateCompress(jpeg_compress_struct*, int, unsigned long)'
What I have tried:
When I did a search in Google on this problem, I discovered from an old forum post that the jpeg library compiles in C. This apparently causes the C++ compiler to mess up names. I'm not clear on what this means, but I followed advice to add:
extern "C" {
#include "jpeglib.h"
}
in all of the files in my jpeg directory that contain "#include "jpeglib.h." I wrote, "jpeglib.h" because, as I mentioned, I have a directory containing the jpeg code. However, I did also try to use the jpeg code provided by default and I got a message saying it is not available on the cluster compiler.
In my makefile, I have checked all of my includes and paths. These do not seem to be the problem. Also, I have similar paths and includes for other libraries in other directories, and they're fine.
I also added: -lstdc++ to my list of compiler options (from advice on another old forum post). It had zero effect.
One weird observation I have made is that when I do "make" of the entire code (several libraries within various directories), the jpeg library does not make unless I specifically go into its directory and do "make" there. As I said, the code is way too big to post this to demonstrate that I have no path errors. I am pretty sure I don't, but this behavior seems very odd.
If anyone is still with me after this long post, I would be very grateful for any tips. Thanks.
Edit:
In my makefile, here is what i have for compiling/linking:
CC = g++
OPTIONS = -O3 -fpermissive -w -DSAMG_UNIX_LINUX -DSAMG_LCASE_USCORE
-DNDEBUG -DCSP_WITH_SAMG_SOLVER
Edit 2: result of Svens's advice
I did:
find /usr /opt -iname libjpeg*so*
And got:
/usr/lib/libjpeg.so.62
/usr/lib/libjpeg.so.62.0.0
/usr/lib64/libjpeg.so.62
/usr/lib64/libjpeg.so.62.0.0
/usr/lib64/libjpeg.so find:
/usr/lib64/mozilla': Permission denied find:
/usr/lpp/mmfs/gui/runtime': Permission denied
me#login1:/data/place/number/account/program/support_libraries/jpeg>
cd ../../libraries/
me#login1:/data/place/number/account/program/libraries> find $HOME
-iname libjpeg*so*
If my understanding is correct, the library exists and has been found in the "libraries" directory, which is where I expect. My main makefile that links all the libraries has an include path to the directory where the jpeg library resides. The other libraries in that directory are found. What is the "permission denied" doing?
Edit 3: result of Sven's advice to change the makefile options:
Here's what I changed:
First added "-lgems3k -L/usr/lib -ljpeg" to my LIBS (the libraries). This leads to the errors below.
Then added (leads to same error as original):
OPTIONS = -O3 -fpermissive -w -DSAMG_UNIX_LINUX -DSAMG_LCASE_USCORE -DNDEBUG -DCSP_WITH_SAMG_SOLVER -/usr/lib/libjpeg.so.62
-L/usr/lib -ljpeg /usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld:
skipping incompatible /usr/lib/libm.so when searching for -lm
/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld:
skipping incompatible /usr/lib/libm.a when searching for -lm
/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld:
skipping incompatible /usr/lib/libc.so when searching for -lc
/usr/lib64/gcc/x86_64-suse-linux/4.3/../../../../x86_64-suse-linux/bin/ld:
skipping incompatible /usr/lib/libc.a when searching for -lc
/data/place/number/account/program/libraries/lib1_intel.a(Grid.o): In
function `program::Grid::SaveToJPG(char const*, int, bool,
bool) const':
Grid.cpp:(.text._ZNK3program20GridIdE9SaveToJPGEPKcibb[program::Grid::SaveToJPG(char
const*, int, bool, bool) const]+0x499): undefined reference to
`jpeg_std_error(jpeg_error_mgr*)'
and so on...
Following up on the comments: are you sure you installed libjpeg? Run
find $HOME -iname libjpeg\*so\*
to find the libjpeg you need to link to. This command will most likely yield several results.
You can simply take the first line of this output and append it to your compilation command, but leave out the "-ljpeg" suggested above.
If it does not give any output at all, you don't have libjpeg installed in your home. So either
install libjpeg
disable the part of the code that needs it if you don't need it either
extend your search,
like
find /usr /opt -iname libjpeg\*so\*
... and try with one of the libjpeg installations on the system.
EDIT (after libjpeg was found on the system):
Try appending
/usr/lib/libjpeg.so.62
to the compile command (the OPTIONS variable in your Makefile). If that doesn't work, try
-L/usr/lib -ljpeg
(Edit by Mats:)
Also make sure EVERY place where #include "jpeglib.h" is covered by extern "C" { ... }. It may make sense to replace these with a c++ wrapper include, which does the addition of extern "C" { ... } in one place, and then just include "wrapped_jpeglib.h" in the relevant places.
(End Edit by Mats)

Error when static linking g++

I have a problem, i want to compile my application with static linking of mysql connector.
My command line:
g++ -o newserver stdafx.cpp ... -lboost_system -lboost_thread
-lpthread -lmysqlcppconn -static /usr/lib/libmysqlcppconn-static.a -std=c++0x
But i have error:
/usr/bin/ld: cannot find -lmysqlcppconn
/tmp/ccxpOfdZ.o: In function `IsEqualsDns(unsigned long, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)':
Server.cpp:(.text+0x356e): warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
collect2: ld returned 1 exit status
How can i fix this?
Thanks!
Where is the library libsqlcppconn.a or libsqucppconn.so
(static or dynamic)? The compiler is looking for it, and
doesn't find it.
Presumably, this is the same library as
/usr/lib/mysqlcppconn-static.a. If so, just drop the
-lmysqlcppconn. Or just use -lmysqlcppconn-static (no
spaces), and forget about the /usr/lib/libmysqlconn-static.a.
With a name like that, there shouldn't be a corresponding .so,
which means that g++ will link it statically, even without the
-static. You only need the -static if there is both
a libmysqlconn-static.so and a libmysqlconn-static.a in the
same directory.
With regards to the second error (which is just a warning, but
will cause problems if you try to run the linked program on
other machines, or even after an upgrade of your machine): if
you use -static anywhere in your command line (as you
currently do), then it applies to all files linked afterwards.
Including the system libraries, which you don't want to link
statically. My guess is that the -static isn't necessary (see
above); if it is, place it immediately before the library you
want to link statically, and place a -dynamic immediately
after (so that any following libraries, including the system
libraries, will be dynamically linked).
You could try g++ -static YOUR ARGUMENTS.
If you are coming from a Windows platform, linking against Boost can give a few surprises. The typicall Boost installation (e.g. after ./b2 install) will make both dynamic and static libraries and put them in the same directory. Typically, the two library forms only differ in their extension (.so or .a).
Windows supports auto-linking, which basically means that library files contain some flags in their first few bytes indicating whether they are for dynamic or for static linking. On Linux platforms, this is not the case and the linker gets confused which file to load (since you don't provide the extension of the library name). Therefore, you need to tell your linker which form of linking you want.