创建静态的Mac OS X C编译

40

我如何在Mac OS X上创建一个.c文件的静态构建版本? 当我尝试时:

gcc -o test Main.c -static

我得到:

ld: library not found for -lcrt0.o
collect2: ld returned 1 exit status

3个回答

34

在Mac OS X的gcc中不支持此功能:

http://discussions.apple.com/message.jspa?messageID=11053384

也许在MacOS X上,"-static"标志根本无法工作。并非所有gcc的功能都在MacOS X上实现。在未来的操作系统版本中,苹果甚至不会再使用gcc。

我不知道如何使用“-static”进行链接。我无法想到在MacOS X上使用它的任何理由。如果我知道您为什么要使用“-static”,我可能会更加关注这个问题。目前,我就是搞不懂。通过寻求帮助,您本质上是在寻求项目的合作者——即使只有10分钟。您需要让我感兴趣。

而且http://developer.apple.com/library/mac/#qa/qa2001/qa1118.html

在Mac OS X上不支持用户二进制文件的静态链接。将用户二进制文件与Mac OS X库和接口的内部实现绑定将限制我们更新和增强Mac OS X的能力。相反,支持动态链接(例如自动链接crt1.o而不是查找crt0.o)。

我们强烈建议您仔细考虑静态链接的限制,并考虑您的客户及其需求以及您需要提供的长期支持。

更新:被禁止的是静态二进制文件。但是,您仍然可以编译一些静态库并将其与另一个程序一起使用。程序将与您的库静态链接,但像libc这样的其他库将是动态的,因此程序将是动态可执行文件。


使用-static编译的一个原因是创建内核。我最近也遇到了这个问题。这是否意味着不能在OS X机器上开发内核? - Igbanam
2
内核链接(操作系统内核)在任何情况下都是一个特殊的阶段。内核通常没有外部库(所谓的C语言自由模式,gcc的-nostdlib-nodefaultlibs选项;不会使用crt*文件),并且不链接到典型的对象格式(ELF/Mach-O;或者至少不使用动态链接器ld.so)。使用特殊的链接器脚本和一些后处理来将对象转换为原始二进制引导映像。因此,我相信可以在Mac OS X上编译Darwin内核。 - osgx
3
我对C语言还很陌生,但我至少能看出使用静态变量的三个原因:教学(遵循C语言书籍),可移植性和稳定性(如果您意外删除了一个链接文件,可执行文件将无法正常工作)。 - ling

16

在OSX下无法构建没有动态加载库的二进制文件。我尝试了苹果的llvm-gcc和macports的gcc。然而,到目前为止没有回答提到的是这不是必需的。您可以将c/c++库静态链接(并使用一些动态部分)。

文件hello.cpp:

#include <iostream>
using namespace std; 
int main()
{
    cout << "Hello World!";
}

按照惯例编译:

g++ hello.cpp -o hello

检查链接:

otool -L hello
hello:
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

我们无法摆脱对libSystem.B.dylib的依赖,但是通过使用MacPorts GCC,我们可以做到这一点:

g++-mp-4.6 -static-libgcc -static-libstdc++ hello.cpp -o hello

otool -L hello
hello:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

显然,只有苹果不支持静态链接:

llvm-g++ -static-libgcc -static-libstdc++ hello.cpp -o hello

otool -L hello
hello:
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)

-static-libgcc -static-libstdc++ 对于 gcc(而不是 g++)有效吗? - Hanxue
“-static-libstdc++” 对于 C 程序不是必需的,只有对于 C++ 程序才需要。所以,是的,这两个选项在 gcc 中也可以使用。 - osgx

7

想象一下你想把某些函数转换成一个库。

文件:example.c

#include <stdio.h>

void aFunction( int a )
{
    printf( "%d\n", a );
}

文件:example.h

void aFunction( int a );

文件: main.c

#include "example.h"

int main( ) 
{
    aFunction( 3 );

    return 0;
}

创建库的步骤如下:
gcc -c example.c
ar -r libmylibrary.a  example.o

连接库的方法如下:
gcc main.c -lmylibrary -L. -I.

然后,文件example.c是整个程序的静态构建。


我如何确认它是一个静态构建? - Daniel
3
换句话说,你可以将库编译为静态的,但不能将程序编译为静态的? - Daniel
预处理器将库的代码包含在最终可执行文件中。当需要“aFunction”函数时,操作系统不必与库绑定,因为代码已经在可执行文件内部。 - momboco
我不理解:编译一个静态程序。操作系统会加载您的程序并执行它。在中途,进程可以加载带有代码的动态库。另一方面,代码在被执行之前嵌入到您的二进制文件中。 - momboco
在Linux上使用ar cr;在Mac上使用ar -r(仅供Google参考)。+1,这正是我要找的。 - Qix - MONICA WAS MISTREATED
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接