How to static link on OS X
Asked Answered
T

5

62

I'm trying to link to a static library on OS X. I used the -static flag in the gcc command but I get the following error message:

ld_classic: can't locate file for: -lcrt0.o
collect2: ld returned 1 exit status

I looked in the man pages and it reads something like:

This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.

Is there another way to link to this static library?

Taub answered 10/5, 2009 at 6:22 Comment(1)
The stupid Apple docs recommend dynamic linking, but they don't show any ld command that actually does this.Maihem
J
55

In order to link to an archive library (sometimes also called static library), just add it to the link line:

gcc main.o ... -lfoo ...

The linker will search for libfoo.dylib, and then libfoo.a, which is all you need.

If you have both versions of the library, and want to link with an archive version in preference of the dynamic one, just specify the full path to the archive on the link line:

gcc main.o ... /path/to/libfoo.a ...
Jimjimdandy answered 10/5, 2009 at 21:54 Comment(4)
There's no crt0.o or crt0.a or anything like that on OS X and XCode.Bonneau
@Bonneau You can get crt0.o through Csu (short for "C start up"), but unfortunately that crt0.o is unable to link with libc since there is no static version of libSystem.dylib. There are more details about this issue on a Github ticket for Csu.Decolonize
For someone just starting with C++, could you please explain why one would use the -static flag?Dripdry
Gregor, compiling static means there are no dynamic library dependencies that need to be present on a system for the program to run. All the code is compiled into the binary. This makes it more portable. It also means dead code elimination can happen on the library code, whereas a dynamic library must have all code present, not just the parts used by the calling code.Alceste
E
22

A common case is to static link against a third user library while dynamically linking against the system frameworks and libraries, so your users don't need to install third party libs before using your program. If the library is dynamically linked against frameworks (as is often the case), it may still ship with a static .a, but it is not sufficient just to replace -l<libname> with /path/to/libname.a because the .a will not have the dependencies in it. You will also have to dynamically link against those frameworks that your library was using.

For example, say you want to write a program that uses the open source libusb without requiring your user to download and install libusb. Say you have a dynamically linked binary you built with this:

clang -lusb-1.0 main.c -o myprogram

To statically link on OS X, the command looks like this (note the -framework arguments):

clang -framework CoreFoundation -framework IOKit main.c /path/to/libusb-1.0.a -o myprogram

To find what system frameworks and libraries you need to add, look at the third party dylib using otool:

otool -L /usr/local/opt/libusb/lib/libusb-1.0.0.dylib

which shows:

/usr/local/opt/libusb/lib/libusb-1.0.0.dylib:
    /usr/local/opt/libusb/lib/libusb-1.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1348.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)  

You can start by adding the frameworks, followed by the libraries one at a time and you will see the list of undefined reference errors shrink. Note you probably won't need to add every library, because some may be loaded as dependencies for the ones you explicitly added.

If you aren't sure where the dylib exists, build your program the original dynamic way (with -lusb-1.0), and run otool on it:

clang -lusb-1.0 main.c -o myprogram
otool -L myprogram

which gives:

myprogram:
    /usr/local/opt/libusb/lib/libusb-1.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1238.0.0)

Also, read the license of the library you are linking to.

Everson answered 6/1, 2017 at 21:39 Comment(0)
B
20

Regretfully, it's not supported. Some people reported it's possible to manually compile crt0 but nobody confirms it.

Bonneau answered 4/12, 2009 at 16:33 Comment(1)
You can compile crt0.o via Csu (short for "C start up"), but unfortunately that crt0.o is unable to link with libc since there is no static version of libSystem.dylib. So yeah, it's not supported until Apple provides us a static version of libSystem.dylib. Either that or don't use libc. There are more details on this Github ticket for Csu.Decolonize
S
9

-Bstatic seems to be a no-op on OS-X Lion - used gcc -v to confirm this.

Stylobate answered 7/8, 2012 at 19:39 Comment(0)
D
2

I've been run into the same issue. Here is an example to work around:

STEP1: create files

myfunc1.c:

#include <stdio.h>

void myfunc1() {
    printf( "This is my func1!\n" );
}

myfunc2.c:

#include <stdio.h>

void myfunc2() {
    printf( "This is my func2!\n" );
}

and myfunc.c:

#include <stdio.h>

void myfunc1( void );
void myfunc2( void );

int main() {
    myfunc1();
    myfunc2();
    return 0;
}

STEP2: create the lib

gcc -c myfunc1.c myfunc2.c

ar -r libmyfuncs.a myfunc1.o myfunc2.o

STEP3: link

gcc -o myfunc -L. myfunc.c -lmyfuncs 

Do not forget to type "-L."; dot indicates the current path.

Hope that helps.

Dmz answered 11/6, 2017 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.