Cross-compile libgcrypt for the iPhone? Linker err

2019-05-06 21:43发布

问题:

I have successfully cross-compiled the Apache Portable Runtime (APR) for the iPhone, using a set of configure scripts that invoke the GNU Autotools "./configure" with the necessary cross-compilation options.

I am now attempting to cross-compile GNUTLS which depends on libtasn1 and on libgcrypt, which in turn, depends on libgpg-error. This is where I am running into trouble and could use your help...

I am currently trying to cross-compile libgpg-error. The configure scripts that I used before are working beautifully; the "./configure" process completes cleanly. The problems occur when I run "make". When I run make, everything seems to compile, but then I get the following nasty linker error at the end:

/bin/sh ../libtool --tag=CC   --mode=link /Users/michaelsafyan/Downloads/libgpg-error-1.7/compile /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2  -std=c99 -arch armv6 -pipe -no-cpp-precomp --sysroot='/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk' -isystem /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/lib/gcc/arm-apple-darwin9/4.2.1/include/ -isystem /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include -isystem /Developer/Platforms/iPhoneOS.platform/Developer/usr/include -isystem /opt/iphone-3.0/include -isystem /usr/local/iphone-3.0/include  -arch armv6 --sysroot='/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk' -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/lib -L/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib -L/opt/iphone-3.0/lib -L/usr/local/iphone-3.0/lib -o gpg-error gpg_error-strsource-sym.o gpg_error-strerror-sym.o gpg_error-gpg-error.o  ./libgpg-error.la  
/Users/michaelsafyan/Downloads/libgpg-error-1.7/compile /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 -std=c99 -arch armv6 -pipe -no-cpp-precomp --sysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk -isystem /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/lib/gcc/arm-apple-darwin9/4.2.1/include/ -isystem /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/include -isystem /Developer/Platforms/iPhoneOS.platform/Developer/usr/include -isystem /opt/iphone-3.0/include -isystem /usr/local/iphone-3.0/include -arch armv6 --sysroot=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk -o gpg-error gpg_error-strsource-sym.o gpg_error-strerror-sym.o gpg_error-gpg-error.o  -L/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/lib -L/Developer/Platforms/iPhoneOS.platform/Developer/usr/lib -L/opt/iphone-3.0/lib -L/usr/local/iphone-3.0/lib ./.libs/libgpg-error.a
Undefined symbols:
  "_fwrite$UNIX2003", referenced from:
      _main in gpg_error-gpg-error.o
  "_strerror$UNIX2003", referenced from:
      _gpg_strerror in libgpg-error.a(libgpg_error_la-strerror.o)
ld: symbol(s) not found
collect2: ld returned 1 exit status
make[3]: *** [gpg-error] Error 1
make[2]: *** [all] Error 2
make[1]: *** [all-recursive] Error 1
make: *** [all] Error 2

Any ideas on how to get this to work? The versions of the software that I am compiling are:

  • libgpg-error: 1.7
  • libgcrypt: 1.4.4
  • libtasn1: 2.2
  • gnutls: 2.8.4

Please help. Thank you.

Update

As per initial feedback, each SDK has a copy of "libSystem.dylib" in "$SDKROOT/usr/lib". There is no copy of libSystem in "$DEVROOT/usr/lib", where:

  • $DEVROOT = "/Developer/Platforms/iPhoneOS.platform/Developer"
  • $SDKROOT = "$DEVROOT/SDKs/iPhoneOS$VER.sdk"

The "libSystem" libraries contain the ordinary, undecorated versions, of each symbol, but do not contain the "$UNIX2003" variants of the symbols. I suspect that GPG-ERROR is defining "_POSIX_C_SOURCE", "_UNIX", or another UNIX feature test macro, and that a rogue header that is appending "$UNIX2003" to the functions when these feature test macros are present is being included. Removing "$DEVROOT/usr/include" from the list of include directories has no effect with regard to removing this error message.

As a last resort, I see that "ld" accepts an "-alias_list" option that allows one to specify a file with entries like "_fwrite _fwrite$UNIX2003" to forcibly resolve these undefined symbols to their undecorated variants. If possible, I would like to avoid this option, since it seems hackish and potentially dangerous.

回答1:

Usually an unresolved symbol$UNIX2003 means that you're linking against an older SDK than the one the existing object files were built against.

One strange looking include path to me, and please note that I'm only vaguely familiar with Mac developement and not at all with iPhone developement, is the path

/Developer/Platforms/iPhoneOS.platform/Developer/usr/include

which is not actually in the SDK folder. Is it possible that you've picked up the rogue symbols, if they are that, from there? Seems unlikely since it occurs later in the command line than the SDK include paths.

Perhaps instead the symbols are the expected versions of _fwrite and _strerror and so gpg_error-gpg-error.o and libgpg-error.a are okay and it's really a linking issue although again unlikely as you have

/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk/usr/lib

as a -L option. I'm assuming there's a libSystem dylib in there somewhere?

I guess the first thing to do is ascertain whether the UNIX2003 version of the symbol is what you expect or not. My guess is it is, but as I say I could be completely wrong. :)

Secondly you could try getting verbose output from ld to see where it is finding symbols. I'm sure there is an environment variable you can set to make this happen but I can't see any listed in the on-line man page for ld. (Update: The two env variables are LD_TRACE_ARCHIVES and LD_TRACE_DYLIBS but perhaps they give the same as -t?).

Edit:

OK, so I was completely wrong about the UNIX2003 symbols being the ones that were required. lol.

When you built libgpg-error I think it will have created a file

src/.deps/gpg_error-gpg-error.Po

which contains header dependencies (at least it did on my Linux system). This might give a clue as to where it picked up the wrong header when building gpg_error-gpg-error.o.

BTW, it looks as if the libgpg-error configure script accepts both an -isysroot and -archoptions. Can you not use those instead of your own version of the configure script?

Edit2:

Okay, let's have another go :) Here are some things to try, starting from a clean source folder:

  • use -isysroot instead of --sysroot
  • use -isysroot as well as --sysroot
  • temporarily make your normal system headers unavailable by, for example, renaming the folder. Hopefully the build will fall over failing to find a header and it'll tell you exactly where.


回答2:

Try to preprocess gpg_error-gpg-error.c with -E then search the missing symbols. You should find from where there are inclued (something like asm ("_" "nice" "@UNIX2003"). Then, modify this header (unistd.h for example to add a #warning "HERE"). Now, recompile, and you should find the include stack.



回答3:

The $2003 suffix is generated by the compiler under some circumstances which you can find fully documented in the manual entry for compat

man compat

I wrestled with this for some time before finally fixing it by setting

-mmacosx-version-min=10.3

Any version prior to 10.4 will do the job. I suspect that given Troubadour's answer I may be better off searching for erroneously linked libraries using the -t option of ld

Hope this helps.