5

I'd like to build a portable static C library that can be linked into macOS binaries regardless of macOS version. The C library does not have any dependencies (i.e. no stdlib, no OS specific calls). The only dependency is the CPU which has to be x86_64.

When extracting the relevant compiler triplet, I get x86_64-apple-darwin16.7.0 for Sierra, and x86_64-apple-darwin17.2.0 for High Sierra. Also, when I build on High Sierra, there is a warning if I use the static library from Sierra (even when I specify --target x86_64-apple-darwin16.7.0 for clang).

  • How can I build a truly portable static library for macOS? If it is not possible, what is the way to go? One different version per major macOS release that is built from the same release? Some hackery by copying SDKs from outdated Xcode versions? Keep in mind, my library is completely portable and does not depend on macOS or the stdlib in any way.

  • Does the version part at the end of the compiler triplet matter?

Etan
  • 17,014
  • 17
  • 89
  • 148
  • 1
    I'm not sure what the issue is. Build the library; use it. If, as you say, your code makes no system calls whatsoever (unusual, even quite remarkable, but not actually impossible), then what you compile on Mavericks will work on High Sierra. It isn't quite so clear working the other way around; if you compile on High Sierra, with the no system calls constraint respected, you should be OK using it on Mavericks. There is a compile-time environment variable you can set (but I've mislaid its name, and I've found evidence of an option ` -mmacosx-version-min=10.11` that may be settable with GCC). – Jonathan Leffler Dec 05 '17 at 15:27
  • Possible duplicate of [Creating static Mac OS X C build](https://stackoverflow.com/questions/5259249/creating-static-mac-os-x-c-build) – Ahmed Masud Dec 05 '17 at 15:34
  • I found a version of Perl (5.10.0 — antique) configured to use `ld='env MACOSX_DEPLOYMENT_TARGET=10.3 cc'` — that is, I think, the environment variable I was thinking of. – Jonathan Leffler Dec 05 '17 at 15:36
  • @AhmedMasud: That is about statically linked _executables_. My question is about statically linked libraries that are purely portable code. – Etan Dec 05 '17 at 17:34

1 Answers1

4

You can just create a static library directly by using macosx libtool

Here's what I just tested out on 3 different versions of Mac OS X (Sierra, High Sierra and Mavrick):

$ ls -al

total 64
drwxr-xr-x  8 masud  staff   272 Dec  5 11:12 .
drwxr-xr-x  7 masud  staff   238 Dec  5 10:35 ..
-rw-r--r--  1 masud  staff   386 Dec  5 11:11 Makefile
-rwxr-xr-x  1 masud  staff  8464 Dec  5 10:38 bar
-rw-r--r--  1 masud  staff    69 Dec  5 11:11 bar.c
-rw-r--r--  1 masud  staff    53 Dec  5 11:10 foo.c
-rw-r--r--  1 masud  staff    84 Dec  5 11:11 foo.h
-rw-r--r--  1 masud  staff    83 Dec  5 11:11 test.c

$ cat Makefile

LIBTOOL=libtool
STATIC=-static
LIBFOO_A=libfoo.a
SRC=foo.c bar.c

OBJ=$(SRC:.c=.o)
LIBFOOCFLAGS=-mmacosx-version-min=10.1

TESTSRC=test.c
TESTCFLAGS=-mmacosx-version-min=10.7

$(LIBFOO_A): $(OBJ)
    $(LIBTOOL) $(STATIC) -o $@ $(OBJ)

%.o: %.c
    $(CC) $(LIBFOOCFLAGS) -c -o $@ $<

test: $(LIBFOO_A) test.c
    $(CC) $(TESTCFLAGS) -o $@ test.c -L. -lfoo


clean:
    $(RM) test $(LIBFOO_A) $(OBJ)

$ cat foo.c

int foo(void) {
    volatile int a = 0;
    return a;
}

$ cat foo.h

#ifndef __FOO_H
#define __FOO_H


extern int foo(void);

#endif

$ cat bar.c

#include "foo.h"

int bar(int k) {
    return k-1;
}

In my tests, libfoo.a could be generated on any (of the three) platform(s) and copied to any (of the three) platform(s) and be used to generate test locally.

nm test on all three shows library statically linked into the binary.

Hope this helps.

on macosx libtool

P.S.: macosx libtool is NOT the same as the gnu libtool except in name. Completely different usage and functionality. the macosx libtool is essentially AR + ranlib + some darwinisms.

Ahmed Masud
  • 21,655
  • 3
  • 33
  • 58
  • Wow, thanks for the detailed response. Any idea what the `--target` switch is used for by Clang in that case? It seems like only `-mmacosx-version-min` is relevant from your example. – Etan Dec 05 '17 at 17:32
  • 1
    target selection in OSX bundled clang is controlled by four params `-arch` for architecture, `-mmacosx-min-version` for darwin min version `-miphone-os-minversion` for ios min version and `-march` which is for the type of cpu you want to generate code form – Ahmed Masud Dec 05 '17 at 17:42