0

I have a C++ project and I want to compile it into a single binary file which contains all the shared libraries, third-parties, and so on. I want to move the compiled file into different servers without installing any dependencies. That's why I need an all-in-one/bundled binary file.

For example, I've tried to compile this:

g++ sample.cpp -o sample -Wl,-Bstatic -l:libyaml-cpp.so

But I got this error, while I really have libyaml-cpp.so file in the /usr/lib directory:

/usr/bin/ld: attempted static link of dynamic object `/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/../../../../lib/libyaml-cpp.so'
collect2: error: ld returned 1 exit status

What's the best way to fix the issue and generally have a compiled file with all dependencies in GNU/Linux platform?

mortymacs
  • 3,456
  • 3
  • 27
  • 53
  • 1
    Perhaps `g++ sample.cpp -o sample -static -lyaml-cpp`? – HolyBlackCat Sep 05 '21 at 21:26
  • @HolyBlackCat it shows error: `/usr/bin/ld: cannot find -lyaml-cpp` – mortymacs Sep 05 '21 at 21:28
  • Did you install yaml-cpp from a package manager or built it yourself? – HolyBlackCat Sep 05 '21 at 21:32
  • @HolyBlackCat yes, I already did it. – mortymacs Sep 05 '21 at 21:38
  • What "yes"? Did you buid it yourself? Or did you install it from a package manager? If latter, how is the package called and what linux distribution are you using? – HolyBlackCat Sep 05 '21 at 21:44
  • @HolyBlackCat I've installed it by Arch package manager. I'm using ArchLinux. – mortymacs Sep 05 '21 at 21:46
  • *...which contains all the shared libraries...* You can't use **shared** libraries to do this. You'll need the equivalent static library or object files, and link those in. – Eljay Sep 05 '21 at 22:36
  • Not an answer, but this is why packaging exists. You can create a debian package of the application and list the dependencies, then you can simply install them via e.g. `apt-get`. Another nice option is to create a docker container with the application and its dependencies, then distribute that. Of course docker must be installed on the target machines. – Quimby Sep 05 '21 at 22:44

3 Answers3

1

You're explicitly demanding linkage against a shared object (.so)!

-l:libyaml-cpp.so

You say your linker can't find -lyaml-cpp, so you seem to be missing the necessary files; that should usually not be the case; the installation of the development files for libyaml-cpp should have included the necessary files.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
1

Normally you would use g++ sample.cpp -o sample -static -lyaml-cpp.

But it seems Arch tends to not include static libraries in their packages. Your options are:

  • Build yaml-cpp yourself to get a static library.

  • Distribute the dynamic library along with your executable.

    To avoid having to install it in system directories, you'll can do one of:

    • Set LD_LIBRARY_PATH env variable when running your program, to the location of the .so.

    • Add -Wl,-rpath='$ORIGIN' to the linker flags, then the resulting binary will automatically try to load libraries from its directory, before checking system directories.

      You can also modify rpath in existing executables and shared libraries using patchelf. This is useful when you want to include shared libraries that other shared libraries depend on, and the latter weren't compiled with -Wl,-rpath='$ORIGIN'.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
0

Generally speaking, there are two routes to go to ensure your program only consists of a single (executable) file:

Static Linking

You can compile a single binary, provided you have access to static libraries for all your dependencies (typically named something like lib*.a). Static libraries behave very similar to ordinary object files when linking the program. Note that your question explicitly refers to a dynamic library (lib*.so), which is the other kind of library that is compiled to be loaded from a file.

Be aware that the glibc does not like to be statically linked, and may not support it at all.

Embed Shared Object as Resource

Alternatively, you can embed shared objects (and other resources) into your executable and unpack it for execution. This can be done in a variety of ways (think self-extracting zip archives, files stored in global variables as byte arrays, this question may get you started).

You will then have to dump the shared libraries into files (e.g., in tempfs) and dlopen them.

danielschemmel
  • 10,885
  • 1
  • 36
  • 58