Reputation: 131385
I've dynamically-linked an executable, my_app
, which has some dependencies it would fill at load time, e.g. libm.so.6
, libpthread.so.0
etc. And - the dependencies are satisfied on the system I'm on.
Now, I want to get a statically-linked version of my_app
, but - I don't want to do that by rebuilding it from source; I want to bake in the libraries that are currently found on my system, which allow me to run my_app
.
Is this possible? Can this be done easily?
Notes:
my_app
was written in C or C++.Upvotes: 1
Views: 3540
Reputation: 1677
Can I statically-link a dynamically-linked executable?
No not really, but here are some alternatives that might suite your needs.
Creating a wrapper over a dynamically linked library to behave as if it were statically linked is rather challenging and only something I'd ever consider if I didn't have access to the source code. But going the other way i.e. static->dynamically linked library is a lot easier.
What you are describing would be better achieved by crafting your build pipeline to start with statically linkable archives/objects and then optionally transforming them into a dynamic/statically linked executables. The predicate for this is that you have access to a statically linked version of your third-party deps.
Consider the example where you have the following files;
You could build this project using the following steps;
# Compile everything as it's own object file, including your main.
clang -c -o foo.o foo.c -fPIC
clang -c -o bar.o bar.c -fPIC
clang -c -o main.o main.o -fPIC
# Create the main archive with all your internal symbols resolved.
llvm-ar r main.a foo.o bar.o main.o
# Create your dynamically linked executable (clangs default). i.e.
# Resolve your external library symbols.
clang -o main_dynamic main.a -lm -lpthread
# Create a statically linked version. Note that we aren't recompiling from
# source rather we are changing the final stage in our build to choose a
# different linking mode.
clang -o main_static main.a -lm -lpthread -static
# Confirm we don't have any dynamic symbols.
ldd main_static
Something to keep in mind is that statically linking is not as well supported with linux libs as they are with dynamic so expect to run into weird errors like 'DYNAMIC_RELOC' when statically linking etc. A general thing to note as well is that when it comes to libc, it tends to be backwards compatible, but not forwards compatible. So when building your project in statically linked mode, do so on the oldest system that you expect to support, otherwise, you'll run into some really strange bugs, in areas where libc is interacting with the kernel i.e. syscalls.
In this case I'd highly recommend using something along the lines of ubuntu's 'snap' packager or fedoras 'flatpack' which allows you to bundle all your dynamic libs and other assets into an executable format. Think docker, but for regular executables.
I'm going to give a brief summary here as a complete response to this would be too long form for StackOverflow. Though there is a more complete guide here "Position-Independent Code with GCC for ARM Cortex-M" by Erich Styger, where he describes how to psuedo-statically link a dynamically linked executable for a microcontroller. In summary, this was the process to do so;
Upvotes: 2