Static library link issue with Mac OS X: symbol(s) not found for architecture x86_64
Asked Answered
D

3

8

I'm trying to generate a static library and link it with an execution binary.

This is a library function:

#include <stdio.h>

int hello() {
    return 10;
}

With these commands, I could get a static library.

gcc -c io.c 
ar -crv libio.a io.o

With lip -info, I checked it is x86_64 architecture.

ar> lipo -info libio.a 
input file libio.a is not a fat file
Non-fat file: libio.a is architecture: x86_64

This is the main function that uses the library.

#include <stdio.h>
extern int hello();

int main(int argc, char *argv[]) {
    printf("%d", hello());
}

However, when I link the object with the static library, I have errors.

gcc main.c -lio -o main -L.

Error messages are:

ld: warning: ignoring file ./libio.a, file was built for archive which is not the architecture being linked (x86_64): ./libio.a
Undefined symbols for architecture x86_64:
  "_hello", referenced from:
      _main in main-2c41a0.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I use the ar as in /bin/ar, and Mac OS X is 10.10.2 with clang-602.0.53.

ar> clang -v
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.3.0
Thread model: posix

What might be wrong?

Denature answered 19/6, 2015 at 23:44 Comment(2)
what is really wrong is that apple unethically put a wrapper around clang/llvm and called it gcc, when on most systems gcc refers to gnu gcc not apple's clang/llvm. since liblto_plugin.so is a gnu extension apple's compiler haven't a clue about where to find it since it not in a system path or framework. i've used ar rcs lib*.a *.o and you do not have to use libtool at all just link to to gnu gcc, install with macports or brew.Selfexplanatory
These two questions are not the exact duplicates but are very similar: Object files not properly added to archive on mac and Symbol not found when static linking on MacOSX.Slowpoke
D
13

The library should have generated with libtool -static.

gcc -c io.c 
libtool -static -o libio.a io.o
gcc main.c -lio -o main -L.
main

Returns

10

ar> lipo -info libio.a 
input file libio.a is not a fat file
Non-fat file: libio.a is architecture: x86_64

ar> file libio.a 
libio.a: current ar archive

ar> nm libio.a 

io.o:
0000000000000000 T _hello

Hints from this page.

Denature answered 20/6, 2015 at 0:23 Comment(0)
D
4

From hacking CMake generate make file (CMakeFiles/test.dir/link.txt), the ar in /usr/local/ar which is used in default does not seem to be working correctly.

This is the content of the link.txt.

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar qc libtest.a  CMakeFiles/test.dir/test.c.o   
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib libtest.a

From the script, /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar is the one that I had to use.

smcho@macho ar> ls -alF /usr/bin/ar
-rwxr-xr-x  1 root  wheel  18160 Oct 17 18:49 /usr/bin/ar*
smcho@macho ar> ls -alF /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar 
-rwxr-xr-x  1 root  wheel  33472 Oct 29 16:36 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar*

Likewise, the ranlib that should be used is /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib not the default one.

smcho@macho ar> ls -alF `which ar`
-rwxr-xr-x  1 root  wheel  18160 Oct 17 18:49 /usr/bin/ar*
smcho@macho ar> ls -alF /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib
lrwxr-xr-x  1 root  wheel  7 Nov 10 21:10 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib@ -> libtool

Other than that -qc option needed to be used (from the cmake generated script)

 -c      Whenever an archive is created, an informational message to that
         effect is written to standard error.  If the -c option is speci-
         fied, ar creates the archive silently. 
 -q      (Quickly) append the specified files to the archive.  If the ar-
         chive does not exist a new archive file is created.  Much faster
         than the -r option, when creating a large archive piece-by-piece,
         as no checking is done to see if the files already exist in the
         archive.

These are commands for getting correct library file:

clang -c hellolib.cpp -o hellolib.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar -qc libhello.a hellolib.o
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib libhello.a

The usage is:

clang usehello.cpp -lhello -L.

nm and lipo show the correct library file information:

smcho@macho ar> nm libhello.a 
libhello.a(hellolib.o):
0000000000000000 T __Z3addii
smcho@macho ar> lipo -info libhello.a 
input file libhello.a is not a fat file
Non-fat file: libhello.a is architecture: x86_64
Denature answered 30/11, 2015 at 2:37 Comment(2)
you, sir, are my hero! The xcode.app paths fixed the issue!Cutout
Looks pretty convincing to me but it didn't work in my case. Anyway it cleared out the previous answer which has worked.Eusebioeusebius
C
0

I started getting the linker error symbol(s) not found for architecture x86_64 due to an improperly built static .lib file after I upgraded my macOS system to Catalina (this also upgraded the version of Xcode and Apple Clang). These failures would only occur trying to link to one particular static library (my application builds and links to several dozen C++ static libs -- all with nearly identical CMake settings).

After each build I could verify whether the static library was built properly or not by running ar -t /path/to/mystatic.lib. I'd either get a list of functions in the archive, or an error. Funny enough, sometimes the library built fine and other times it was corrupt -- using the same build configuration. This same library always built fine when my macOS system ran Mojave. But I was not about to downgrade.

The following addition to the CMakeLists.txt file resolved the issue:

if(APPLE)
    set(CMAKE_CXX_ARCHIVE_CREATE "<CMAKE_AR> -r -LS <TARGET> <LINK_FLAGS> <OBJECTS>")
endif()

The -r -LS parameters run ar without creating an archive symbol table. After running ar CMake automatically runs ranlib (actually libtool on macOS) in a manner that creates the symbol table. Somehow this ensures the static library is always built reliably.

My other static libraries do not require the above CMake setting. I have no idea why only one library was affected.

Chiasma answered 20/10, 2023 at 6:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.