When trying to build a binary (see MWE below) that links a static library using clang I am getting the following error message:
⟩⟩⟩ clang -o test bar.a test.o
ld: warning: ignoring file bar.a, file was built for archive which is not the architecture being linked (x86_64): bar.a
> Undefined symbols for architecture x86_64:
> "_bar", referenced from:
> _main in test.o
> "_foo", referenced from:
> _main in test.o
> ld: symbol(s) not found for architecture x86_64
But the architecture is correct and consistent (x86_64) according to lipo
:
⟩⟩⟩ lipo -info test.o bar.a
input file bar.a is not a fat file
Non-fat file: test.o is architecture: x86_64
Non-fat file: bar.a is architecture: x86_64
otools -hv
shows similar output. All object files are built for x86_64. So what does this error message mean?
Here’s a complete, minimal, working example to reproduce the problem shown above:
foo.c
:
int foo(void) {
return 1;
}
bar.c
:
int bar(void) {
return 2;
}
test.c
:
#include <stdio.h>
int foo(void);
int bar(void);
int main(void) {
printf("foo = %d\n", foo());
printf("bar = %d\n", bar());
}
Compilation:
clang -c -o foo.o foo.c
ar rcs foo.a foo.o
clang -c -o bar.o bar.c
ar rcs bar.a foo.a bar.o
clang -c -o test.o test.c
clang -o test bar.a test.o
The error message is in fact misleading: The issue isn’t a mismatch in architecture, it’s the fact static libraries (.a
files) cannot be nested:
⟩⟩⟩ nm bar.a
bar.a(bar.o):
0000000000000000 T _bar
(Note that the entry _foo
from foo.a
is missing!)
But since ar
is originally a general-purpose archival utility, it has no qualms creating a nested archive via
ar rcs bar.a foo.a bar.o
As we can verify by listing its contents:
⟩⟩⟩ ar t bar.a
__.SYMDEF SORTED
foo.a
bar.o
To fix the problem, don’t nest archives but rather pack the object files directly:
rm bar.a
ar rcs bar.a foo.o bar.o
clang -o test bar.a test.o