C++ Executable distribution strategy - c++

Recently I have asked a question about what I should use to create self-contained executables that would be deployed under a number of Linux distribution. I got very scared at first, but after reading about C++ a little, I managed to get the first version of my executable going.
After a day full of joy, I just hit the wall again with another dilemma. The resulting executable must be installed in a number of Linux distributions (Slackware, Arch, Ubuntu, Debian, CentOS and a few more), and I am completely clueless on how to achieve it. All I know CentOS and Debian-based OSes has package managers, like apt or yum, but I am not sure those apply to my case.
The code I wrote depends on a couple of libraries (more specifically RudeSocket and yaml-cpp. I have been told that I would be able to compile the executable and link it dynamically, so I just needed to distribute the executable.
It happens that I could not find the .a file for the yaml-cpp library (just for RudeSocket). And here's my problem so far:
At first, I went with dynamic linking but (obviously) when I copied the executable to another box:
$ ./main
./main: error while loading shared libraries: libyaml-cpp.so.0.2: cannot open shared object file: No such file or directory
When trying to compile it statically, I get an error too (because I don't have the yaml-cpp .a file as I mentioned):
$ g++ main.cpp parse.cpp parse.h rudesocket-1.3.0/.libs/librudesocket.a -o main -static -L/usr/local/librudesocket-1.3.0/.libs/librudesocket.a(socket_connect_normal.o): In function `rude::sckt::Socket_Connect_Normal::simpleConnect(int&, char const*, int)':
/root/webbyget/sockets/rudesocket-1.3.0/src/socket_connect_normal.cpp:250: warning: Using 'gethostbyname' in statically linked applications requires at runtime the shared libraries from the glibc version used for linking
/tmp/cc3cEVK1.o: In function `operator>>(YAML::Node const&, Job&)':
parse.cpp:(.text+0x1a83): undefined reference to `YAML::Node::size() const'
/tmp/cc3cEVK1.o: In function `handle_job(rude::Socket, char const*)':
parse.cpp:(.text+0x1b79): undefined reference to `YAML::Parser::Parser(std::basic_istream<char, std::char_traits<char> >&)'
parse.cpp:(.text+0x1bfd): undefined reference to `YAML::Node::Node()'
parse.cpp:(.text+0x1c10): undefined reference to `YAML::Parser::GetNextDocument(YAML::Node&)'
parse.cpp:(.text+0x1dc6): undefined reference to `YAML::Node::size() const'
parse.cpp:(.text+0x1dee): undefined reference to `YAML::Node::~Node()'
parse.cpp:(.text+0x1e18): undefined reference to `YAML::Node::~Node()'
parse.cpp:(.text+0x1e37): undefined reference to `YAML::Parser::~Parser()'
parse.cpp:(.text+0x1e61): undefined reference to `YAML::Parser::~Parser()'
(...)
It's pretty obvious to me that g++ cannot compile it statically without telling it where to find the classes for yaml-cpp.
It is very important that the installation should happen without human interaction, in an automated fashion.
So my question is really twofold:
how can I distribute this compiled program in the least complex way targeting all those distributions?
is there any de facto standard solution for this kind of problem?
Thank you in advance,
Felipe.

You might give this technique a try.

There are many de-facto standards, but none of them are standardized. :( If you want to distribute a compiled binary, you will probably want to make a package for each platform you want to target. Generating an rpm and a deb will probably get you 90% of the way. If you want to automate the build process, autoconf/automake is still (probably) the best way to go.

Maybe The best solution for you is to use CMake.
CMake is cross-platform, open-source build system. It is a family of tools designed to build, test and package software. For Packaging, Mgb is right, CMake can easily be coupled with CPack.
KDE is using this solution and its a very good alternative to automake/autoconf.

If you use the platforms package manager (.rpm or .deb) the system will check for the correct version of the shared library for you and download it if it is needed.
CPack is probably the easiest package generator

Related

Boost linking error - single undefined reference

I'm having an odd linking problem with Boost (version 1.58). I'm building with g++ 4.8 on Ubuntu 15.10.
I get the following error:
undefined reference to
'boost::program_options::options_description::options_description(std::string
const&, unsigned int, unsigned int)' collect2: error: ld returned 1
exit status
What's strange is that all other symbols from lboost_program_options are found; options_description is the only undefined reference. If I comment out uses of options_description but keep uses of positional_options_description (which I'm also using) then the whole program compiles and links flawlessly. I am linking with -lboost_program_options, and if I remove this then as expected there are 8 missing boost::options_description symbols.
For a long time linking has worked correctly. Without any build system changes that I'm aware of it suddenly broke. The only systems level change was an upgrade to Ubuntu 15.10, which I don't think should have affected anything.
Any thoughts or suggestions appreciated.
Update: After lots of fiddling I got this working again, although I'm not sure what did it. I'm still interested in any answers to what could cause this type of behavior though.
Check that the ABI is compatible (you're using the same compiler version and flags used when compiling the boost libraries).
On Ubuntu, this means using stock GCC with libstdc++.
If you can't, compile your own Boost System and Boost Program Options binaries using your preferred flags.
Similar things prevent code samples from linking on http://coliru.stacked-crooked.com if your compiler is not the same as used when compiling boost there.
I had a similar problem after upgrading to Ubuntu 15.10 with a different symbol missing in a lib belonging to boost::program_options.
It helped to simply clean up the whole project by throwing away all object files etc. and recompiling it from scratch.

dynamic library using boost has undefined references when built on ARM architecture

I have a C++ based dynamic library that I have built for the big 3 OSs that relies heavily on boost. Currently, I am compiling it for the raspberry pi. It took me a while to find the magic words to get the library to even build (-frepo as a compiler flag was the key, but I confess that I am not certain why this is the case).
Now, when I try to link to the library, I get an 'undefined reference' error to every boost call that my library makes, i.e.:
//`libmylib.so`: undeifined reference to `boost::shared_ptr<boost::detail::thread_data_base>::shared_ptr()'
When I build libmylib.so, I also build a custom version of boost as libboost.a. This all compiles and links fine on other OSs and non-ARM architectures so I tried putting -lboost as one of the flags, but I still get the same plethora of undefined reference errors form libmylib.so.
Needless to say, all my paths are correct.
It seems like linking behaves a bit differently on the raspberry pi than it does on other linux systems. For example, I built a static library (libmythread.a) that uses libpthread. When I link to that libmythread.a, I also get undefined reference errors unless I also use -lpthread in the build recipe. On my Thinkpad running Fedora, I would never have to do this since I included -lpthread in the compilation of the static library libmythread.a.
I would love to find a tutorial or guide that explains these discrepancies. I would also love to overcome them!
I also tried the same build on a conventional linux machine and everything linked fine, no problem. At least I know that my build process is OK. This does open up the possibility, though, that the -frepo flag is doing something funny that I don't understand and that this could be the root of the problem.
Solved. In the end, the trouble stemmed from the -frepo flag. This was necessary to compile a file called legacy_abi.cpp that is part of my library to allow third party developers using older and more exotic OSs/compilers. This isn't needed on the Pi, so I just removed it from the offending file from the build, dropped the -frepo flag and happy happy.
One final note, aptitude (for Pi, anyway) only supplies boost up to 1.49 (as far as I can tell). My project requires boost >= 1.50. This is an inherited project, so I'm still discovering all its little idiosyncracies.

MPI undefined object references

I'm trying to install a program (the Parallel Ice Sheet Model, or PISM) which uses MPI. I keep running into the errors
libpismutil.so: undefined reference to `ompi_mpi_cxx_op_intercept'
libpismutil.so: undefined reference to `MPI::Datatype::Free()'
libpismutil.so: undefined reference to `MPI::Comm::Comm()'
libpismutil.so: undefined reference to `MPI::Win::Free()'
when linking a CXX executable. I'm sort of stumped as to why this is occurring; the configuration for the program found where all of the MPI executables and libraries are located.
In another thread, someone suggested that this is due to different naming conventions when MPI is built with Fortran or C, but seeing as I have both mpicc.mpich2 and mpif90.mpich2 in my /usr/bin I would think this wouldn't be a problem.
After much consternation, I've found the culprit. The program I'm trying to install uses a library for scientific computation called PETSc; the standard install of PETSc doesn't generate the shared object files needed by PISM, you have to explicitly tell it to make them. Once this was done, PISM installed correctly.
Of course, I was unable to run it because of some other obscure error with openmpi, but that's a story for another thread.

Port from gcc 3.3.3 to 4.1.0, C++ templates, undefined reference to

Our application makes use of C++ templates in a number of places. I am currently attempting to port from gcc 3.3.3 to 4.1.0 and am encountering issues. I have recreated the problem in a small shared library and executable. I am building the share library Ok, but the executable fails to link with the following:
undefined reference to `MyNumber<int>::~MyNumber()'
undefined reference to `MyNumber<int>::MyNumber(int)'
undefined reference to `MyNumber<int>::number()'
I am not using the template classes directly within the executable and would have expected this all to be encapsulated within the implementation within the shared library (probably naively so).
The problem only appears to show when working with a shared library. When I build our application on SLES 11 (gcc 4.3.2) most of my issues appear to be resolved but I still receive a number of the following:
undefined reference to `vtable for MYCLASS<T1, T2>'
This all when linking the executable to the shared libs.
It's a painfully obscure message, but it means you didn't define a virtual function, See here
I had a similar problem, and resolved it by implementating functions in the header file, not in a cpp file.
Salu2.
Without knowing more about your source code this is very hard to answer. However asking this particular question on the gcc mailing list may yield better results, as the people who work on gcc know all the intricacies better than everyone else.
Thanks for the comments. I removed the -frepo and -fno-impicit-templates from my compile/link options and was good to go.

Problems linking static Intel IPP libraries on Linux with g++

I've been trying to move a project over from Xcode to Linux (Ubuntu x86 for now, but hopefully the statically-linked executable will run on an x86 CentOS machine? I hope I hope?). I have the whole project compiling but it fails at the linking stage-- it's giving me undefined references for all functions defined by IPP. This is probably something really small and silly but I've been beating my head over this for a couple days now and I can't get it to work.
Here's the compile statement (I also have a makefile that's generating the same errors):
g++ -static
/opt/intel/ipp/6.0.1.071/ia32/lib/libippiemerged.a
/opt/intel/ipp/6.0.1.071/ia32/lib/libippimerged.a
/opt/intel/ipp/6.0.1.071/ia32/lib/libippsemerged.a
/opt/intel/ipp/6.0.1.071/ia32/lib/libippsmerged.a
/opt/intel/ipp/6.0.1.071/ia32/lib/libippcore.a
-pthread -I /opt/intel/ipp/6.0.1.071/ia32/include
-I tools/include -o main main.cpp pick_peak.cpp
get_starting_segments.cpp
get_segment_timing_differences.cpp
recast_and_normalize_wave_file.cpp
rhythm_score.cpp pitch_score.cpp
pitch_curve.cpp
tools/source/LocalBuffer.cpp
tools/source/wave.cpp distance.cpp
...and here is the beginning of the long list of linker errors:
./main.o: In function `main':
main.cpp:(.text+0x13f): undefined reference to `ippsMalloc_16s'
main.cpp:(.text+0x166): undefined reference to `ippsMalloc_32f'
main.cpp:(.text+0x213): undefined reference to `ippsMalloc_16s'
Any ideas? FWIW, these are the IPP dependencies in my Xcode project that builds, links, and runs without a problem: "-lippiemerged",
"-lippimerged",
"-lippsemerged",
"-lippsmerged",
"-lippcore",
Thanks!
Your linking problem is likely due to the fact that your link line is completely backwards: archive libraries should follow source and object files on command line, not precede them. To understand why the order matters, read this.
Also note that on Linux statically linked executables are significantly less portable than dynamically linked ones. In general, if you link system libraries dynamically on an older Linux system, it will work on all newer systems (I use ancient RedHat 6.2, and I haven't seen a system on which my executable will not run). This is not true for completely static executables; they may crash in all kinds of "interesting" ways when moved to a system with a different libc from the one against which they were linked.
I had problems with linking code with the v 6 of the ipp; using the v11 version of the compiler (with the included updates to the ipp) mysteriously fixed them. Granted, that was with a windows platform, but I was getting 8u versions of functions to compile and no 32f versions, despite both being listed as valid in the documentation.