6

I'm trying to build a C library (GMP 6.0.0) for arm64 for use on iOS. I'm running the configure script with the invocation below (compiler is as found using xcrun --find).

./configure \
CC="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" \
CPP="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -E" \
CPPFLAGS="-target arm64-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/ -miphoneos-version-min=7.0" \
--host=aarch64-apple-darwin

However this fails at the following line ("long long reliability test 1"):

checking compiler /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang -O2 -pedantic  -target arm64-apple-darwin -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.1.sdk/ -miphoneos-version-min=7.0... no, long long reliability test 1
configure: error: could not find a working compiler, see config.log for details

Full config.log available here. It shows multiple warning and errors for the long long reliability test compile, including the following:

conftest.c:9:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
f(){static const struct{t1 n;t1 src[9];t1 want[9];}d[]={{1,{0},{1}},};t1 got[9];int i;
^
conftest.c:10:44: error: implicit declaration of function 'h' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
                                           ^
conftest.c:10:48: error: implicit declaration of function 'g' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
                                               ^
conftest.c:10:100: warning: control reaches end of non-void function [-Wreturn-type]
for(i=0;i<1;i++){if(e(got,got,9,d[i].n)==0)h();g(i,d[i].src,d[i].n,got,d[i].want,9);if(d[i].n)h();}}
                                                                                                   ^

Using --host=none it works fine, but I'd really like to figure out how to build it with assembly optimized for arm64.

My system is x86_64-apple-darwin13.1.0 (or coreisbr-apple-darwin13.1.0 according to config.guess), an early '11 Core i7 MBP running OS X v10.9.2. I'm using Xcode 5.1 (5B130a).

Any help appreciated.

EDIT 1

Compiling for ARMv7 passes configure, but fails on make (full configure/make output here), apparently while compiling some assembly:

tmp-dive_1.s:165:18: error: unexpected token in '.section' directive
 .section .rodata
                 ^

EDIT 2

@MarcGlisse: By forcing clang to ignore the errors as suggested (-Wno-...) arm64 passes configure, but then fails on make (full output here):

tmp-mul_1.s:59:2: error: unrecognized instruction mnemonic
 bcc Lfi1
 ^
tmp-mul_1.s:60:2: error: unrecognized instruction mnemonic
 beq Lfi2
 ^

As a side note: these commits, I assume intended to remove the need for suppressing the error, don't seem to work i.e. I get the same error when removing the supression.

For armv7, using these commits as suggested fixes the .section error, but make fails later on with the following (full output here):

tmp-mode1o.s:64:2: error: unknown directive
 .protected ___gmp_binvert_limb_table
 ^

EDIT 3

Using the suggested edits, armv7, armv7s, i386 and x86_64 now all compile with assembly!

For arm64 the edits get it past the previous error, but now gives several errors about an invalid input constraint 'rZ', all in the same file (full output here):

divrem_1.c:237:5: error: invalid input constraint 'rZ' in asm
                  udiv_qrnnd_preinv (*qp, r, r, nshift, d, dinv);
                  ^
../gmp-impl.h:3062:2: note: expanded from macro 'udiv_qrnnd_preinv'
        add_ssaaaa (_qh, _ql, _qh, _ql, (nh) + 1, (nl));                \
        ^
../longlong.h:551:7: note: expanded from macro 'add_ssaaaa'
           : "rZ" (ah), "rZ" (bh), "%r" (al), "rI" (bl) __CLOBBER_CC)

EDIT 4

After commenting out add_ssaaaa and sub_ddmmss in longlong.h and editing some more assembly instructions in gcd_1.asm (blo to b.lo etc.), it now fails with several of the following errors (full output here):

tmp-invert_limb.s:75:22: error: immediate value expected for shifter operand
 add x1, x1, x2, lsr 1
                     ^
tmp-invert_limb.s:75:22: error: invalid operand for instruction
 add x1, x1, x2, lsr 1
                     ^

I'll post a total diff later.

EDIT 5

Ok, that gets us another step further, but it now hits into (full output here):

tmp-invert_limb.s:52:2: error: ADR/ADRP relocations must be GOT relative
 adrp x1, approx_tab
 ^

If this keeps going it might be better to continue this via email.

Patrick Pijnappel
  • 7,317
  • 3
  • 39
  • 39
  • Are you _sure_ you want to use a general purpose library that exits your code when it runs out of memory? It may be that's not a problem to you but you should at least be aware of it: https://gmplib.org/manual/Custom-Allocation.html. – paxdiablo Mar 31 '14 at 05:24
  • @paxdiablo as opposed to iOS, which kills your application when it runs out of memory? – pmdj Mar 31 '14 at 05:32
  • 1
    @Patrick I suspect GMP probably doesn't have ARM64 support yet? Also, note that GMP is distributed under the LGPL license, which is incompatible with Apple's App Store agreement. So while you can use it in an iOS app for educational purposes, or using Enterprise distribution, you must not publish the app on the App store. This would also explain why there might be no ARM64 support yet - the only major currently available ARM64 distribution platform is incompatible with the license. – pmdj Mar 31 '14 at 05:39
  • @pmjordan The release notes for 6.0.0 explicitly mention "Support for ARM64 alias Aarch64 alias ARMv8" (https://gmplib.org/gmp6.0.html) – Patrick Pijnappel Mar 31 '14 at 05:42
  • @Patrick The code in question doesn't look like it's platform-specific. Does the same build process work for ARMv7? If not: one difference between gcc and clang is that the former defaults to C89, while the latter picks C99 by default. Have you tried building with the -std=gnu89 flag to force C89 mode? – pmdj Mar 31 '14 at 06:03
  • ARMv7 passes configure but fails on make (see new details in original post). I tried `-std=gnu89`, with no success unfortunately. – Patrick Pijnappel Mar 31 '14 at 06:35
  • That is a horrible way to specify `$CC` etc. I would recommend `CC=xcrun clang` as being more reliable and less to type. Also you don't need to specify SYSROOT; simply use `xcrun --sdk`. – trojanfoe Mar 31 '14 at 06:44
  • 1
    Try https://gmplib.org/repo/gmp/rev/38068aa8e307 for the second error. For the first one, I'd try CC='clang -Wno-error -Wno-implicit-function-declaration' or something like that to convince clang to ignore this. – Marc Glisse Mar 31 '14 at 17:22
  • This bears repeating. It is criminal copyright infringement to embed GMP in an app deployed on the iOS App Store. It's licensed under LGPL, which means it cannot be submitted to the store unless you have contacted every contributor and asked for permission. – Abhi Beckert Apr 01 '14 at 01:31
  • @AbhiBeckert Yes, unfortunately - you'd have to use LibTomMath or something similar. I would like to test GMP's performance nevertheless to compare, it seems like a lot more developed. It's a pity, maybe I'll try contacting the developers later to see if something can be done... – Patrick Pijnappel Apr 01 '14 at 03:50
  • 1
    The acinclude.m4 edits only take effect if you rerun .bootstrap (downloading a later snapshot ( https://gmplib.org/download/snapshot/ ) may be easier). `--disable-assembly` could also help, though you will lose a lot of performance. – Marc Glisse Apr 01 '14 at 11:21
  • If you have legal issues with using GNU software on Apple products, don't bother contacting GNU, talk to Apple. – Marc Glisse Apr 01 '14 at 11:25
  • 1
    What happens if you simply delete the line with `.protected ___gmp_binvert_limb_table`? (delete it in a file called mode1o.asm, there are 2 in the mpn/arm/ subtree) – Marc Glisse Apr 01 '14 at 13:18
  • 1
    For the mul_1 errors, try and find the relevant mul_1.asm file, and replace bcc with b.cc, beq with b.eq etc until it stops complaining about this. – Marc Glisse Apr 01 '14 at 13:59
  • 1
    Strange, recent clang accepts rZ just fine for me. You could just remove the problematic macro from longlong.h, there is code in place for the case where it isn't defined. Could you please post a diff with all your edits so I don't forget one that should go to the repository? – Marc Glisse Apr 02 '14 at 12:17
  • @MarcGlisse what does Apple have to do with GPL? They don't know anything about it. All they know is that one or more of the copyright holders for your source code did not agree to their work being redistributed by Apple, and therefore it must be pulled. – Abhi Beckert Apr 03 '14 at 06:35
  • @AbhiBeckert Well, Apple could have set it up such that apps in the App Store can be compatible with the LPGL/GPL, i.e. give user the possibility to manually install apps without extra hurdles or costs (the lack of which is the main incompatibility with the license). – Patrick Pijnappel Apr 03 '14 at 06:40
  • @Patrick the biggest incompatibility with GPL is Apple's security model requiring all code be signed before it can be executed by the kernel. You can't execute an app without signing it with a private key, and Apple doesn't want malware authors to get their hands on those private keys. This means a typical home user cannot have their own private key (but developers can). So they can't let typical users install apps, even if they might want to allow it, without opening up the platform to malware like you see on windows / mac. – Abhi Beckert Apr 03 '14 at 06:45
  • And GPL clearly states you can't have any DRM on the binary. Also, GPL clearly states you can't distribute under any other license, and Apple forces all app developers to distribute under a single EULA which was written by Apple — ensuring malicious developers cannot put anything bad in the EULA. It's stupid, but Apple isn't going to budge. They have a good reason to do it the way they did. – Abhi Beckert Apr 03 '14 at 06:51
  • 1
    `add x1, x1, x2, lsr #1` (add the `#` in front of the constant). LLVM is just being silly on this one, what else could `1` mean? – Marc Glisse Apr 03 '14 at 11:17
  • Does `--disable-shared` help? (or `--disable-static` instead?) – Marc Glisse Apr 03 '14 at 13:26
  • 1
    Well, I'm giving up for now (until the debian arm64 port becomes official, it is too inconvenient for me). I'll still push what I can to the repository, so the diff would still be useful (or you can check after my (future) commits if I forgot something). For the "rZ" thing I expect that the next version of Apple's toolchain will handle it so I won't touch that. – Marc Glisse Apr 03 '14 at 13:56
  • Neither --disable-shared or --disable-static makes a difference. I'll make sure to check your commits for any omissions. – Patrick Pijnappel Apr 04 '14 at 06:40
  • If you still interested https://gist.github.com/sakrist/0ceaa98fb16535998020 – Volodymyr B. Sep 14 '15 at 15:36

2 Answers2

1

"Support for ARM64 alias Aarch64 alias ARMv8"

https://gmplib.org/gmp6.0

Polluks
  • 525
  • 2
  • 8
  • 19
-1

Copyright issues aside...

GMP may not be compatible with Apple's proprietary CPU, and may not be compatible with Clang/LLVM. Being a GNU project it is probably more thoroughly tested with GCC on non-proprietary chipsets.

A quick search shows historically at least there have been issues compiling GMP with clang.

You really should email the GMP community and ask for help on this one.

Abhi Beckert
  • 32,787
  • 12
  • 83
  • 110