tpoechtrager / osxcross

Mac OS X cross toolchain for Linux, FreeBSD, OpenBSD and Android (Termux)
GNU General Public License v2.0
2.87k stars 326 forks source link

unable to use LTO with static library #366

Open jboekesteijn opened 1 year ago

jboekesteijn commented 1 year ago

I have built osxcross on an Ubuntu 20.04 system with the llvm-dev and lld packages installed using:

env UNATTENDED=true OSX_VERSION_MIN=10.13 TARGET_DIR=/usr/x86_64-apple-darwin17 ./build.sh

For my test, I created three files lib.h, lib.c and main.c:

lib.h:

int sum(int a, int b);
int mul(int a, int b);

lib.c:

int sum(int a, int b) {
  return a + b;
}

int mul(int a, int b) {
  return a * b;
}

main.c:

#include <stdio.h>
#include "lib.h"

int main() {
  printf("sum = %d\n", sum(40, 2));
  return 0;
}

This works and results in a binary without the mul function, as expected:

x86_64-apple-darwin17-clang -flto=thin -o lib.o -c lib.c
x86_64-apple-darwin17-clang -flto=thin -o main.o -c main.c
x86_64-apple-darwin17-clang -flto=thin -o main main.o lib.o

This also works and results in a binary with the (unused) mul function:

x86_64-apple-darwin17-clang -o lib.o -c lib.c
x86_64-apple-darwin17-ar cr lib.a lib.o
x86_64-apple-darwin17-ranlib lib.a
x86_64-apple-darwin17-clang -o main.o -c main.c
x86_64-apple-darwin17-clang -o main main.o lib.a

Trying to combine a static library and LTO fails:

x86_64-apple-darwin17-clang -flto=thin -o lib.o -c lib.c
x86_64-apple-darwin17-ar cr lib.a lib.o
x86_64-apple-darwin17-ranlib lib.a
x86_64-apple-darwin17-clang -flto=thin -o main.o -c main.c
x86_64-apple-darwin17-clang -flto=thin -o main main.o lib.a

Here ranlib produces this warning:

warning: x86_64-apple-darwin17-ranlib: archive library: lib.a the table of contents is empty (no object file members in the library define global symbols)

The final linking step fails with:

undef: _sum
Undefined symbols for architecture x86_64:
  "_sum", referenced from:
      _main in lto.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

...which is to be expected after the earlier ranlib warning about the static library. The same steps using the native toolchain clang, ar and ranlib tools on macOS result in a working binary with LTO correctly applied (so without a mul symbol).

Then I tried directly using llvm-ar and llvm-ranlib (because the .o files contain LLVM bitcode) from my Ubuntu host system:

x86_64-apple-darwin17-clang -flto=thin -o lib.o -c lib.c
llvm-ar cr lib.a lib.o
llvm-ranlib lib.a
x86_64-apple-darwin17-clang -flto=thin -o main.o -c main.c
x86_64-apple-darwin17-clang -flto=thin -o main main.o lib.a

This way I do not get a warning from llvm-ranlib but the final linking step still fails:

ld: warning: ignoring file lib.a, building for macOS-x86_64 but attempting to link with file built for unknown-unsupported file format ( 0x21 0x3C 0x61 0x72 0x63 0x68 0x3E 0x0A 0x2F 0x20 0x20 0x20 0x20 0x20 0x20 0x20 )
undef: _sum
Undefined symbols for architecture x86_64:
  "_sum", referenced from:
      _main in lto.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Probably because ld64 from osxcross does not recognize the archive produced by llvm-ar. At this point I'm not sure which combination of tools/linkers should be used to achieve the desired result.

jboekesteijn commented 1 year ago

@tpoechtrager Do you think this is something that can be solved within the osxcross tools/wrappers?