g++编译的静态库 gcc
Before statically linking you C and C++ programs, you should be aware of the drawbacks of the static linking especially with glibc. There are some good discussions already: with glibc you’re linking static programs which are not really static and some others here and here.
在静态链接C和C ++程序之前,您应该了解静态链接的缺点,尤其是glibc。 已经有一些很好的讨论: 使用glibc,您可以链接并非真正静态的静态程序,还可以 在此处和此处 链接其他程序 。
That said, you can choose to statically link C and C++ programs on Linux, only when you know what you are doing and why. And you have ways to avoid some problems like setting GCONV_PATH
, enabling --enable-static-nss
for glibc, using other DNS libraries rather than NSS and never use dlopen
. You can even use other libc implementation like uClibc or musl libc which are more friendly for static linking. A comparison of C/POSIX standard library implementations for Linux can be found here.
也就是说,只有在知道自己在做什么和为什么的情况下 ,才能选择在Linux上静态链接C和C ++程序。 而且,您可以避免一些问题,例如设置GCONV_PATH
, 为glibc启用--enable-static-nss
, 使用其他DNS库而不是NSS且从不使用dlopen
。 您甚至可以使用其他libc实现,例如uClibc或musl libc ,它们对于静态链接更友好。 可以在此处找到Linux的C / POSIX标准库实现的比较。
Linux binaries are not portable if they are built in normal way even with full static linking. However, there are many companies that supply portable Linux binaries that run on a wide range of Linux systems of various versions. Static linking is one of the techniques to build portable binaries. For a detailed explanation of common techniques for building portable binaries, I suggest Creating portable Linux binaries which discusses the “secret sauce”.
如果Linux二进制文件以完全静态链接的正常方式构建,则它们是不可移植的。 但是,有许多公司提供可移植的Linux二进制文件,这些二进制文件可在各种版本的Linux 系统上运行。 静态链接是构建可移植二进制文件的技术之一。 有关构建便携式二进制文件的常用技术的详细说明,我建议创建讨论“秘密秘诀”的便携式Linux二进制文件 。
One more note: this is not problems from the Linux kernel. Linux kernel keeps very good compatibility. Read Linus’ “WE DO NOT BREAK USERSPACE!” arguments here.
还有一点需要注意:这不是Linux内核的问题。 Linux内核保持了很好的兼容性。 阅读Linus的“我们不要破坏用户空间!” 这里的论点。
You may wonder why I am talking about static linking. My main motivation is to have memory mapping statically determined and controlled by the program. See the /proc/PID/maps
of one statically linked program as follows:
您可能想知道为什么我要谈论静态链接。 我的主要动机是由程序静态确定和控制内存映射。 请参阅一个静态链接程序的/proc/PID/maps
,如下所示:
00400000-0060c000 r-xp 00000000 fd:00 920962 /home/kvplus/think/tmp/runtime/vpc
0080b000-00814000 rwxp 0020b000 fd:00 920962 /home/kvplus/think/tmp/runtime/vpc
00814000-408a5000 rwxp 00000000 00:00 0
41652000-41675000 rwxp 00000000 00:00 0 [heap]
100000000-800000000 rwxp 00000000 00:00 0
240000000000-250000000000 rwxs 00000000 ca:11 36 /mnt/kvplus1-data/pmem-kvplus-0-0
250000000000-260000000000 rwxs 00000000 ca:11 37 /mnt/kvplus1-data/pmem-kvplus-0-1
260000000000-270000000000 rwxs 00000000 ca:11 38 /mnt/kvplus1-data/pmem-kvplus-0-2
270000000000-280000000000 rwxs 00000000 ca:11 39 /mnt/kvplus1-data/pmem-kvplus-0-3
280000000000-290000000000 rwxs 00000000 ca:11 40 /mnt/kvplus1-data/pmem-kvplus-0-4
290000000000-2a0000000000 rwxs 00000000 ca:11 41 /mnt/kvplus1-data/pmem-kvplus-0-5
2a0000000000-2b0000000000 rwxs 00000000 ca:11 42 /mnt/kvplus1-data/pmem-kvplus-0-6
2b0000000000-2c0000000000 rwxs 00000000 ca:11 43 /mnt/kvplus1-data/pmem-kvplus-0-7
2c0000000000-2d0000000000 rwxs 00000000 ca:11 44 /mnt/kvplus1-data/pmem-kvplus-0-8
2d0000000000-2e0000000000 rwxs 00000000 ca:11 45 /mnt/kvplus1-data/pmem-kvplus-0-9
2e0000000000-2f0000000000 rwxs 00000000 ca:11 46 /mnt/kvplus1-data/pmem-kvplus-0-10
2f0000000000-300000000000 rwxs 00000000 ca:11 47 /mnt/kvplus1-data/pmem-kvplus-0-11
340000000000-350000000000 rwxs 00000000 ca:11 48 /mnt/kvplus1-data/pmem-kvplus-0-12
350000000000-360000000000 rwxs 00000000 ca:11 49 /mnt/kvplus1-data/pmem-kvplus-0-13
360000000000-370000000000 rwxs 00000000 ca:11 50 /mnt/kvplus1-data/pmem-kvplus-0-14
370000000000-380000000000 rwxs 00000000 ca:11 51 /mnt/kvplus1-data/pmem-kvplus-0-15
380000000000-390000000000 rwxs 00000000 ca:11 52 /mnt/kvplus1-data/pmem-kvplus-0-16
390000000000-3a0000000000 rwxs 00000000 ca:11 53 /mnt/kvplus1-data/pmem-kvplus-0-17
3a0000000000-3b0000000000 rwxs 00000000 ca:11 54 /mnt/kvplus1-data/pmem-kvplus-0-18
3b0000000000-3c0000000000 rwxs 00000000 ca:11 55 /mnt/kvplus1-data/pmem-kvplus-0-19
3c0000000000-3d0000000000 rwxs 00000000 ca:11 56 /mnt/kvplus1-data/pmem-kvplus-0-20
3d0000000000-3e0000000000 rwxs 00000000 ca:11 57 /mnt/kvplus1-data/pmem-kvplus-0-21
3e0000000000-3f0000000000 rwxs 00000000 ca:11 58 /mnt/kvplus1-data/pmem-kvplus-0-22
3f0000000000-400000000000 rwxs 00000000 ca:11 59 /mnt/kvplus1-data/pmem-kvplus-0-23
7fd664000000-7fd664021000 rwxp 00000000 00:00 0
7fd664021000-7fd668000000 ---p 00000000 00:00 0
7fd66abb1000-7fd66abb2000 ---p 00000000 00:00 0
7fd66abb2000-7fd66b5b2000 rwxp 00000000 00:00 0
7fd66b5b2000-7fd66b5b3000 ---p 00000000 00:00 0
7fd66b5b3000-7fd66efb8000 rwxp 00000000 00:00 0
7fd66efb8000-7fd66efb9000 ---p 00000000 00:00 0
7fd66efb9000-7fd66f9b9000 rwxp 00000000 00:00 0
7fff054ba000-7fff054cf000 rwxp 00000000 00:00 0 [stack]
7fff055ff000-7fff05600000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
And a non-statically-linked programs /proc/PID/maps
is as follows:
和非静态链接的程序/proc/PID/maps
如下:
00400000-00406000 r-xp 00000000 fd:00 4115 /bin/sleep
00605000-00606000 rw-p 00005000 fd:00 4115 /bin/sleep
0173c000-0175d000 rw-p 00000000 00:00 0 [heap]
7f53a7dba000-7f53adbeb000 r--p 00000000 fd:00 133506 /usr/lib/locale/locale-archive
7f53adbeb000-7f53adc02000 r-xp 00000000 fd:00 1873 /lib64/libpthread-2.11.2.so
7f53adc02000-7f53ade01000 ---p 00017000 fd:00 1873 /lib64/libpthread-2.11.2.so
7f53ade01000-7f53ade02000 r--p 00016000 fd:00 1873 /lib64/libpthread-2.11.2.so
7f53ade02000-7f53ade03000 rw-p 00017000 fd:00 1873 /lib64/libpthread-2.11.2.so
7f53ade03000-7f53ade07000 rw-p 00000000 00:00 0
7f53ade07000-7f53adf7a000 r-xp 00000000 fd:00 1849 /lib64/libc-2.11.2.so
7f53adf7a000-7f53ae179000 ---p 00173000 fd:00 1849 /lib64/libc-2.11.2.so
7f53ae179000-7f53ae17d000 r--p 00172000 fd:00 1849 /lib64/libc-2.11.2.so
7f53ae17d000-7f53ae17e000 rw-p 00176000 fd:00 1849 /lib64/libc-2.11.2.so
7f53ae17e000-7f53ae183000 rw-p 00000000 00:00 0
7f53ae183000-7f53ae18a000 r-xp 00000000 fd:00 1877 /lib64/librt-2.11.2.so
7f53ae18a000-7f53ae389000 ---p 00007000 fd:00 1877 /lib64/librt-2.11.2.so
7f53ae389000-7f53ae38a000 r--p 00006000 fd:00 1877 /lib64/librt-2.11.2.so
7f53ae38a000-7f53ae38b000 rw-p 00007000 fd:00 1877 /lib64/librt-2.11.2.so
7f53ae38b000-7f53ae3a9000 r-xp 00000000 fd:00 1842 /lib64/ld-2.11.2.so
7f53ae5a0000-7f53ae5a3000 rw-p 00000000 00:00 0
7f53ae5a7000-7f53ae5a8000 rw-p 00000000 00:00 0
7f53ae5a8000-7f53ae5a9000 r--p 0001d000 fd:00 1842 /lib64/ld-2.11.2.so
7f53ae5a9000-7f53ae5aa000 rw-p 0001e000 fd:00 1842 /lib64/ld-2.11.2.so
7f53ae5aa000-7f53ae5ab000 rw-p 00000000 00:00 0
7fff7fede000-7fff7fef3000 rw-p 00000000 00:00 0 [stack]
7fff7fffd000-7fff7fffe000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
The mmap from the .so are problems for certain programs.
.so的mmap是某些程序的问题。
The following part of this post will introduce how to “statically” link C and C++ programs with gcc on Linux.
本文的以下部分将介绍如何在Linux上通过gcc“静态”链接C和C ++程序。
静态链接C程序∞ (Statically link C programs ∞)
You should first install the glibc-static
package. On Fedora/RHEL/CentOS, you can
您应该首先安装glibc-static
软件包。 在Fedora / RHEL / CentOS上,您可以
# yum install glibc-static
Add the -static
as a compilation option to gcc:
将-static
作为编译选项添加到gcc:
$ gcc -static src.c obj.o -o prog
Check whether the compiled binary is statically linked:
检查编译后的二进制文件是否静态链接:
$ ldd prog
It should print out:
它应该打印出:
not a dynamic executable
If you are using some libraries, such as pthread
, you should specify these libraries according to their reference order (referrer appears first):
如果您正在使用某些库,例如pthread
,则应根据它们的引用顺序指定这些库(引荐来源网址首先出现):
$ gcc -static prog.c -o prog -lpthread
More on the library order in the gcc manual
gcc手册中有关库顺序的更多信息
-l library
Search the library named library when linking. (The second alternative with the library as a separate argument is only for POSIX compliance and is not recommended.)
It makes a difference where in the command you write this option; the linker searches and processes libraries and object files in the order they are specified. Thus, foo.o -lz bar.o searches library z after file foo.o but before bar.o. If bar.o refers to functions in z, those functions may not be loaded.-l库
链接时搜索名为library的库。 (使用库作为单独参数的第二种替代方法仅是为了符合POSIX,不建议这样做。)
在命令中写入此选项的位置会有所不同。 链接器按照指定的顺序搜索和处理库和目标文件。 因此,foo.o -lz bar.o在文件foo.o之后但在bar.o之前搜索库z。 如果bar.o引用z中的函数,则可能不会加载这些函数。
静态链接C ++程序∞ (Statically link C++ programs ∞)
First, install the package needed:
首先,安装所需的软件包:
# yum install glibc-static libstdc++-static
Under GCC 4.4, you can use the -static
option as for C programs:
在GCC 4.4下,您可以像使用C程序一样使用-static
选项:
$ g++ -static
After GCC 4.5, gcc
supports the -static-libstdc++
option:
在GCC 4.5之后, gcc
支持-static-libstdc++
选项:
$ gcc -static -static-libstdc++ -static-libgcc
Also note the library order.
另请注意库顺序。
After building the program, check whether the program is statically linked as what we do for C programs:
生成程序后,请检查程序是否像我们对C程序所做的那样静态链接:
$ ldd cpp-program
not a dynamic executable
Note for CMake: to specify a static library (libssl as an example) in CMake (find more here):
CMake的注意事项:在CMake中指定一个静态库(以libssl为例)(在此处查找更多信息 ):
find_library(OPENSSL_LIBRARY libssl.a)
翻译自: https://www.systutorials.com/how-to-statically-link-c-and-c-programs-on-linux-with-gcc/
g++编译的静态库 gcc