How can I statically link standard library to my C++ program?

48,319

Solution 1

Since nobody else has come up with an answer yet, I will give it a try. Unfortunately, I don't know that Code::Blocks IDE so my answer will only be partial.

1 How to Create a Statically Linked Executable with GCC

This is not IDE specific but holds for GCC (and many other compilers) in general. Assume you have a simplistic “hello, world” program in main.cpp (no external dependencies except for the standard library and runtime library). You'd compile and statically link it via:

  1. Compile main.cpp to main.o (the output file name is implicit):

    $ g++ -c -Wall main.cpp
    

    The -c tells GCC to stop after the compilation step (not run the linker). The -Wall turns on most diagnostic messages. If novice programmers would use it more often and pay more attention to it, many questions on this site would not have been asked. ;-)

  2. Link main.o (could list more than one object file) statically pulling in the standard and runtime library and put the executable in the file main:

    $ g++ -o main main.o -static
    

    Without using the -o main switch, GCC would have put the final executable in the not so well-named file a.out (which once eventually stood for “assembly output”).

Especially at the beginning, I strongly recommend doing such things “by hand” as it will help get a better understanding of the build tool-chain.

As a matter of fact, the above two commands could have been combined into just one:

$ g++ -Wall -o main main.cpp -static

Any reasonable IDE should have options for specifying such compiler / linker flags.

2 Pros and Cons of Static Linking

Reasons for static linking:

  • You have a single file that can be copied to any machine with a compatible architecture and operating system and it will just work, no matter what version of what library is installed.

  • You can execute the program in an environment where the shared libraries are not available. For example, putting a statically linked CGI executable into a chroot() jail might help reduce the attack surface on a web server.

  • Since no dynamic linking is needed, program startup might be faster. (I'm sure there are situations where the opposite is true, especially if the shared library was already loaded for another process.)

  • Since the linker can hard-code function addresses, function calls might be faster.

  • On systems that have more than one version of a common library (LAPACK, for example) installed, static linking can help make sure that a specific version is always used without worrying about setting the LD_LIBRARY_PATH correctly. Obviously, this is also a disadvantage since now you cannot select the library any more without recompiling. If you always wanted the same version, why would you have installed more than one in the first place?

Reasons against static linking:

  • As you have already mentioned, the size of the executable might grow dramatically. This depends of course heavily on what libraries you link in.

  • The operating system might be smart enough to load the text section of a shared library into the RAM only once if several processes need the library at the same time. By linking statically, you void this advantage and the system might run short of memory more quickly.

  • Your program no longer profits from library upgrades. Instead of simply replacing one shared library with a (hopefully ABI compatible) newer release, a system administrator will have to recompile and reinstall every program that uses it. This is the most severe drawback in my opinion.

    Consider for example the OpenSSL library. When the Heartbleed bug was discovered and fixed earlier this year, system administrators could install a patched version of OpenSSL and restart all services to fix the vulnerability within a day as soon as the patch was out. That is, if their services were linking dynamically against OpenSSL. For those that have been linked statically, it would have taken weeks until the last one was fixed and I'm pretty sure that there is still proprietary “all in one” software out in the wild that did not see a fix up to the present day.

  • Your users cannot replace a shared library on the fly. For example, the torsocks script (and associated library) allows users to replace (via setting LD_PRELOAD appropriately) the networking system library by one that routes their traffic through the Tor network. And this even works for programs whose developers never even thought of that possibility. (Whether this is secure and a good idea is subject of an unrelated debate.) An other common use-case is debugging or “hardening” applications by replacing malloc and the like with specialized versions.

In my opinion, the disadvantages of static linking outweigh the advantages in all but very special cases. As a rule of thumb: link dynamically if you can and statically if you have to.

A Addendum

As Alf has pointed out (see comments), there is a special GCC option to selectively link in the C++ standard library statically but not link the whole program statically. From the GCC manual:

-static-libstdc++

When the g++ program is used to link a C++ program, it normally automatically links against libstdc++. If libstdc++ is available as a shared library, and the -static option is not used, then this links against the shared version of libstdc++. That is normally fine. However, it is sometimes useful to freeze the version of libstdc++ used by the program without going all the way to a fully static link. The -static-libstdc++ option directs the g++ driver to link libstdc++ statically, without necessarily linking other libraries statically.

Solution 2

In Visual C++, the /MT option does a static link and the /MD option does a dynamic link. (see http://msdn.microsoft.com/en-us/library/2kzt1wy3.aspx)

I'd recommend using /MD and redistributing the C++ runtime, which is freely available from Microsoft. Once the C++ runtime is installed, than any program requiring the run time will continue to work. You would need to pass the proper option to tell the compiler which runtime to use. There is a good explanation here, Should I compile with /MD or /MT?

On Linux, I'd recommend redistributing libstdc++ instead of a static link. If their system libstdc++ works, I'd let the user just use that. System libraries, such as libpthread and libgcc should just use the system default. This requires compiling the program on a system with symbols compatible with all linux versions you are distributing for.

On Mac OS X, just redistribute the app with dynamic linking to libstdc++. Anyone using the same OS version should be able to use your program.

Share:
48,319

Related videos on Youtube

AmRCPP
Author by

AmRCPP

Updated on July 05, 2022

Comments

  • AmRCPP
    AmRCPP almost 2 years

    I'm using Code::Blocks IDE(v13.12) with GNU GCC Compiler.

    1. I want to the linker to link static versions of required runtime libraries for my programs, how may I do this?
    2. I already know that my executable size will increase. Would you please tell me other the downsides?
    3. What about doing this in Visual C++ Express?
    • 5gon12eder
      5gon12eder over 9 years
      Can't you just pass the -static flag to GCC?
    • AmRCPP
      AmRCPP over 9 years
      @5gon12eder I'm so sorry but i'm a newbie programmer,i don't know how to pass this flag to GCC?
    • SwiftMango
      SwiftMango over 9 years
      And why do you want to static linking?
    • 5gon12eder
      5gon12eder over 9 years
      Look for “compiler / linker invocation” or “linker flags” in the “project configuration” of your IDE. Maybe someone else who is using the same IDE can give more precise instruction.
    • AmRCPP
      AmRCPP over 9 years
      @texasbruce I don't want external dependencies.(even for standard libraries)
    • AmRCPP
      AmRCPP over 9 years
      @5gon12eder I'm sorry i didn't find it!!!
    • SwiftMango
      SwiftMango over 9 years
      And why you don't want dependency? It is a bad practice to include all libraries in your program.
    • Cheers and hth. - Alf
      Cheers and hth. - Alf over 9 years
      @texasbruce: having a single executable file is a common reason.
    • SwiftMango
      SwiftMango over 9 years
      @Cheersandhth.-Alf That doesn't affect the fact that it can be a single executable.
    • Mark Ransom
      Mark Ransom over 9 years
      @texasbruce why do you consider it a bad practice? There are reasons for and against of course, but not to the point where you should exclude a valid approach.
    • SwiftMango
      SwiftMango over 9 years
      @MarkRansom Of course it is valid approach, and I did not exclude it. Performance wise it is bad, but there are scenarios it is used for sure.
    • Cheers and hth. - Alf
      Cheers and hth. - Alf over 9 years
      @texasbruce: you're not making sense, sorry. techno-babble.
    • SwiftMango
      SwiftMango over 9 years
      @Cheersandhth.-Alf Which part it doesn't make sense?
    • Cheers and hth. - Alf
      Cheers and hth. - Alf over 9 years
      @AmRCPP: using the popular approach of killing flies with intercontinental atomic weapon missile, you can use the Nuwen distribution of MinGW (on a 64-bit computer that is). it's built to use static linking by default. but note that this is about the c++ standard library etc. the runtime library may be linked dynamically anyway, but if so then it's not a dependency that requires any redistributable so you're fine. with visual studio you have such choice in the project properties' "C/C++" -> "Code Generation".
    • Mooing Duck
      Mooing Duck over 9 years
      @texasbruce: Performance wise it is bad? Performance-wise, static linkage should be faster!
    • SwiftMango
      SwiftMango over 9 years
      @MooingDuck If a dynamic library was previously loaded into memory by another program, then the loading time would be almost zero for the new program
    • Mooing Duck
      Mooing Duck over 9 years
      @texasbruce: Ah yes, I hadn't considered that aspect. I was merely thinking of runtime.
  • Cheers and hth. - Alf
    Cheers and hth. - Alf over 9 years
    +1 great answer in general. i just wonder if -static is enough for c++ program? or is there some other option for the c++ standard library implementation?
  • 5gon12eder
    5gon12eder over 9 years
    @Cheersandhth.-Alf Not quite sure what you mean. echo 'int main() {}' > main.cpp && gcc main.cpp -static && ldd a.out shows that there are no dynamic links. (Compare without using -static.) Alternatively, try su --command="chroot $PWD ./a.out" with a simple “hello, world” program (in an otherwise empty directory) linked with and without -static. Is this what you mean?
  • Cheers and hth. - Alf
    Cheers and hth. - Alf over 9 years
    just asking. i remembered vaguely some separate option(s) for the c++ standard library implementation. turns out it was -static-libstdc++, which allows you to link that statically without linking the basic runtime library statically. docs at (gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/…).
  • 5gon12eder
    5gon12eder over 9 years
    @Cheersandhth.-Alf That's good to know; I had no idea. On the other hand, I have not encountered a use-case yet where I would have wanted to statically link in the standard but not the runtime and other libraries. But who knows what the future will call for.
  • Juan
    Juan over 9 years
    The blogger in this post states a few things in line with what I was saying about not linking against system libraries. micro.nicholaswilson.me.uk/post/31855915892/…
  • galinette
    galinette over 8 years
    I would add another advantage : statically linking might (often) reduce the total size of the executable and the library, as unused library functions will not be included. If you want to reduce the size of an installer and need to ship the library with it, this is something you might want.