views:

392

answers:

4

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.

A: 

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.

William Pursell
+3  A: 

You might give this technique a try.

genpfault
This looks like a very good option. Basically, you dynamically link, but use a special -rpath option to force the run-time linker to look for the libs in the same directory as the executable. Then you distributed the dynamic libraries with the executable.
swillden
This is a good technique but I ended up acquiring a copy of [Ermine](http://www.magicermine.com/). So worth it :-)
kolrie
A: 

If you use the platforms package manger (.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

Martin Beckett
A: 

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.

Nadir SOUALEM