views:

637

answers:

2

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.

A: 

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.
Troubadour
Thanks for the links. The first one was quite informative. The "-t" option for "ld" enables "ld" to log each library it links against.
Michael Aaron Safyan
The file referenced only contains "#dummy". Using "-t" shows nothing unusual (all libraries referenced come from the SDK).
Michael Aaron Safyan
The libgpg-error configure scripts do not accept "-isysroot" and "-arch"; invoking the script with those options gives "configure: error: unrecognized option: -isysroot".
Michael Aaron Safyan
The reason I thought they were accepted is that I grep'ed for them and they came up in ltmain.sh which I thought was invoked by configure but it's obviously not that simple. As for the file showing #dummy it shows that for me too after the configure stage. It gets populated at some point during the make stage for me.
Troubadour
Using the -t option on ld isn't going to help here since we know that it's the symbols that are wrong, not the fact it can't find them. In fact we kind of know that ld is looking in the right paths since it can't find these symbols. :)
Troubadour
Even after running "make", the file still contains "#dummy".
Michael Aaron Safyan
Since we are simply doing a proof-of-concept, I think we will remove the GNUTLS dependency and not use SSL/TLS for this iteration. We will have to look into alternative libraries and evaluate how easy they are to cross-compile for the various target devices. Anyway, for your efforts, you deserve the bounty. Congratulations.
Michael Aaron Safyan
A: 

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.

iksaif