how to link a static library for iOS

2019-04-09 00:03发布

问题:

I have create a bunch of .o files (via gcc -c $file.c $someotherops -o $file.o). Now I want to link them into a static library.

I'm not exactly sure wether I am supposed to use ld or gcc for this. In the ld manual, it is said that I'm not supposed to use it directly. However, I cannot figure out the gcc parameters to create a static library.

I tried ld *.o -static -o libfoo.a but it complains about a lot of missing symbols (I think all from libc). I don't understand why it complains because it is supposed to be a static library. I thought it would check for the symbols once I link that static library to some other thing.

Another thing: I use /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/ld here (my target is iOS). It complains with the warning ld: warning: using ld_classic. What is this about?

Then I thought, maybe it needs to have the dynamic libraries specified. So I added -lc to link against libc. But it complains with can't locate file for: -lc. I added -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.0.sdk/usr/lib and there is a libc.dylib.

Any ideas?


About the -lc error: It got away after I specified -arch armv6. Then it complained about a wrong libcache.dylib (which must be linked from libc.dylib I guess because it didn't specified it). Adding -L.../usr/lib/system helped.

Now, for each single .o file, I get the warning ld: warning: CPU_SUBTYPE_ARM_ALL subtype is deprecated. What is this about?

And I still have a bunch of missing symbols, esp:

Undefined symbols for architecture armv6:
  "start", referenced from:
     -u command line option
     (maybe you meant: _PyThread_start_new_thread)
  "___udivsi3", referenced from:
      _get_len_of_range in bltinmodule.o
      _quorem in dtoa.o
      _array_resize in arraymodule.o
      _newarrayobject in arraymodule.o
      _array_fromfile in arraymodule.o
      _get_len_of_range in rangeobject.o
      _inplace_divrem1 in longobject.o
      ...
  "___unorddf2", referenced from:
      _builtin_round in bltinmodule.o
  ...

I checked some of those symbols, e.g. ___udivsi3 in get_len_of_range. This function uses C arithmetic only, no external call. So this seems to be translated to use some external functions like ___udivsi3. But what libraries is this in?


-lgcc_s.1 fixed most of the ___udivsi3 and related missing symbols. The start symbol is still missing. What does -u command line option mean?


From here, I got the feeling that maybe ld isn't the right tool after all. There, a simple call to aris used. And this seem to make more sense. I will check if that does work and transform this into an answer then.


While playing more around, ar throw some warnings at me when building a fat static library. It gave me the hint to use libtool instead. That is what I'm doing now, i.e. libtool -static -o libfoo.a *.o. Also I switched the compiler to /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clangbut not sure if that matters.

Now, at compiling some test application which links to this static library, I get these warnings:

ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in __PyBuiltin_Init from /Users/az/Programmierung/python-embedded/libpython.a(bltinmodule.o). To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000004 (0x001B70CC) to 0x1001B70C4
ld: warning: 32-bit absolute address out of range (0x1001B70C4 max is 4GB): from _usedpools + 0x00000000 (0x001B70CC) to 0x1001B70C4

What are they about? I don't use -mdynamic-no-pic. I also don't really see in _PyBuiltin_Init how I use absolute addressing there.

Also, what are these absolute addresses out of range about? Edit: These were some really huge allocations. I just removed this code for now (this was WITH_PYMALLOC, if anyone is interested in these specific Python internals).

When I start it on my iPhone, I get the abort:

dyld: vm_protect(0x00001000, 0x00173000, false, 0x07) failed, result=2 for segment __TEXT in /var/mobile/Applications/C15D9525-E7DC-4463-B05B-D39C9CA24319/...

When I use -no_pie for linking, it doesn't even link. It fails with:

Illegal text-relocation to ___stderrp in /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/usr/lib/libSystem.dylib from _read_object in /Users/az/Programmierung/python-embedded/libpython.a(marshal.o) for architecture armv7


I solved the PIE disabled, Absolute addressing error. I had a -static in my command line Clang. Once I removed that, the warning got away, as well as the dyld/vm_protect error. It was the first time it actually run some code.

Until I hit another strange error about integer comparison. Whereby this looks more like a bug in their Clang build.

回答1:

It all works now. Basically, the answer is:

  • Just compile every *.c file as usual to *.o files. The only real difference is the different GCC/Clang, the -arch armv7, the different SDK / include dirs.

  • Use libtool -static -o libfoo.a *.o to build the static library.

That's it. The other problems in my question were just wrongly headed tries.



回答2:

If anyone gets here by searching for the dyld: vm_protect(...) runtime error but you are using XCode, the -static flag mentioned in the OP is likely the issue.

Get rid of it by switching "Enable linking with shared libraries" to "Yes" (the default) in the LLVM compiler language settings. (This removes GCC_LINK_WITH_DYNAMIC_LIBRARIES = NO from the project file).