gcc 的 -static 选项?
Posted
技术标签:
【中文标题】gcc 的 -static 选项?【英文标题】:-static option for gcc? 【发布时间】:2012-01-31 07:17:41 【问题描述】:我想知道 gcc 上的 -static 选项有什么作用。我在编译某个应用程序时需要此选项,但是当我这样做时,我收到以下错误:
gcc -static -O3 -o prog prog.c
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
需要安装什么?
GCC 版本:
[user@localhost dir]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.6.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.6.1 20110908 (Red Hat 4.6.1-9) (GCC)
【问题讨论】:
【参考方案1】:-static
选项静态链接程序,换句话说,它在运行时不需要依赖动态库即可运行。
要实现静态链接,需要系统上存在库的存档 (.a) 版本。所以 /usr/lib/libc.a /usr/lib/crt1.o 等等...
在现代 linux 系统上(如您使用 red hat):当二进制链接在一起时 1) 通过 .o 和 .a 文件将代码放入可执行文件,或 2) 放入对动态库 (. so) 由 /lib/ld-linux.so(或 /lib64/ld-linux=x86-64.so)解析的文件,该文件始终位于众所周知的位置。
对于您的特定系统,如果某个程序特别希望创建自己的静态版本,那么您需要安装开发工具的静态版本。您至少需要 glibc-static 包。您可能还需要 libstdc++-static 包。
【讨论】:
【参考方案2】:-static
标志强制链接器只接受静态库而不接受任何共享库。
如果您想使用-static
,您必须确保安装了静态版本的 C 库,这可能很难找到(大多数系统不再有静态 C 库)。或者你必须取消-static
的效果。但是,在示例中,这将违背 -static
的目的,因为唯一链接的库是(隐式)C 库。
【讨论】:
有什么特别的原因不能简单地让链接器静态附加来自链接器可用的任何库的代码吗?即使代码中的引用以必须在运行时解析的方式格式化,我认为应该可以将适当的例程附加到可执行文件,并修补引用以便它们指向可执行文件中的代码. @supercat:在普通的归档库中,各个目标文件是可单独识别的,可以很容易地从库中提取并链接到可执行文件中。我的印象(半知情)是共享库不以相同的方式包含单独的目标文件,所以你得到了全部或者你什么都得不到。我敢说,可以简单地将整个共享库链接到可执行文件中,但这也可能导致大量未使用的代码被内置。我知道一些大公司更喜欢对所有事情都使用静态链接——减少意外变化的风险。 即使代码最终必须动态加载,我建议安装的应用程序默认情况下应该接收自己的大多数库的副本。如果需要升级库,可以通过让操作系统为每个程序保留一个设置的“升级设置”[例如如果使用 FooLib 1.7 的程序注意到安装了“FooLib 1.8”,它可以允许用户使用 1.7 或 1.8 运行它并将选择保存为默认值]。这样,如果一个程序有 FooLib 相关的问题,用户可以升级它,但事情不会自发改变。 我想知道为什么系统没有在他们的程序执行基础设施中管理这样的功能?正如有人在另一条评论中指出的那样,链接器在 1980 年代很烦人,30 多年后仍然很烦人。他们应该有什么理由吗? 如果你实现它,也许它会被使用。共享库的优势在于您更改了共享库,并且所有使用的应用程序都会自动受益于新版本中的错误修复。静态链接的优点是您不必担心共享库管理,并且应用程序不会更改,除非您重新构建它。如果你走静态链接路线,那么你最终会使用更多的内存(每个不同的可执行文件都有自己的共享代码副本),但你知道程序不会意外更改。以上是关于gcc 的 -static 选项?的主要内容,如果未能解决你的问题,请参考以下文章