Created attachment 36399 [details] Don't disable assembly when building GMP in-tree GMP has an issue when it is being cross-compiled for certain machine architectures without assembly loops: x86_64 to MIPS works fine, but x86_64 to ARM and x86_64 to Sparc32 both fail to build correctly. I've verified that the issue is triggered with GMP 5.1.3 and 6.0.0a; it may or may not apply with older versions of GMP. When GMP is being built as part of the GCC build with in-tree sources, GCC disables assembly by configuring GMP with: --host=none-${host_vendor}-${host_os} and --target=none-${host_vendor}-${host_os} This evokes the GMP issue, leading to the GCC build failing when it's being cross-compiled (for the problematic architectures) and GMP is built in-tree. The precise error I encountered was when linking ISL; the command: /bin/bash ./libtool --tag=CC --mode=link arm-cbl-linux-gnueabihf-gcc -g -O2 -static-libstdc++ -static-libgcc -o isl_test isl_test.o libisl.la /tmp/build/build-gcc-4/./gmp/libgmp.la fails with undefined references to __gmpn_invert_limb. In Makefile.def, I see a comment saying that the reason that asm optimizations are disabled for the GMP build is that it makes the bootstrap test of the compiler more rigorous, which makes sense. On the other hand, breaking the build for some machine architectures seems problematic! I don't know enough about the build machinery in GCC to try to figure out how to detect the particular problematic situation I've found and re-enable assembly only for that case. All I did was verify that removing the configure flags that disable assembly entirely from Makefile.def and then regenerating Makefile.in corrects the problem -- which it does! I don't know whether re-enabling assembly is the best solution, but it is the best one I could come up with.
Sounds like the bug is an issue with ISL rather than GMP itself. I don't normally building with ISL so I have never noticed the issue. Also I think your patch is incorrect since there is a reason why we disable the assembly version is because GMP nativelly tries to detect the current processor and then use the assembler version for that.
Thanks for your swift comment! I disagree that the bug is in ISL. The problem is that gmp, although the build appears successful, is *not* correctly built. Six object files that should be compiled and linked into gmplib.a are not built because they are only built correctly when assembly is enabled. One of those is invert_limb.o, which contains the symbol __gmpn_invert_limb, which is needed by ISL. So the *bug* is in the GMP build, but the *consequence* of the bug is that ISL cannot be linked. I agree that my patch is not adequate, though -- I just tested and found that I couldn't build an x86_64-to-arm cross-gcc when my patch is installed. The configure for GMP crashes with: configure: error: --target is not appropriate for GMP Use --build=CPU-VENDOR-OS if you need to specify your CPU and/or system explicitly. Use --host if cross-compiling (see "Installing GMP" in the manual for more on this). Obviously the best way to address this situation is by getting GMP to build properly for all architectures regardless of whether assembly is enabled. Until or unless that's done, though, it seems like it would be worthwhile to do *something* to address the issue on the GCC side, since that's where I (and others, according to google) have tripped over it. Maybe a documentation change, to say that GMP shouldn't be built in-tree when cross-compiling GCC? Or something of that sort?
Is __gmpn_invert_limb supposed to be exported? Or is ISL using private APIs here?
at least this configuration works when doing cross-builds from X86_64 => ARM: gmp -> ../gmp-4.3.2 mpc -> ../mpc-0.8.1 mpfr -> ../mpfr-2.4.2 isl -> ../isl-0.12.2
GMP does, or did, select an ABI at configuration time that may not be the same as that used by default by the compiler used to build it. For example, if building on an x86_64 processor it might select a 64-bit ABI even if you have configured GCC for a 32-bit host. If your goal is to make multiple-precision computations as fast as possible, choosing the ABI for that purpose makes sense - but for GCC's uses the requirement is to choose the same ABI as for the selected host, even if that's slower than some other ABI available on the processor.
Created attachment 36441 [details] document symptoms of problem and workaround Since the issue is a corner-case (it's only triggered when cross-compiling for certain architectures, using recent versions of GMP, and with in-tree GMP and ISL sources), and since there's an easy and obvious workaround, it seems pointless to spend a lot of time trying to adjust the build machinery. On the other hand, a something search reveals I'm not the only person to run into this situation, so it seems worthwhile to at least document the workaround. Here's a suggested paragraph -- it would have saved *me* a headache and a few hours of frustration when I tripped across the problem, so perhaps it will be helpful to someone else in the future?
*** Bug 70211 has been marked as a duplicate of this bug. ***
The initial bug report was for cross compiling. Bug 70211 is for native builds on ARM. Given the huge growth in ARM development boards, this needs at least documenting. As with the original reporter I spent ages trying to figure this out before stumbling across a solution (and the solution isn't to build GMP out of tree either). Building GMP out of tree creates another can of worms (esp on multiarch machines). Any documentation fix should mention the targets that need the change (ARM), and that both cross and native builds are affected. Also reference the undefined symbol __gmpn_invert_limb so people know they have run across it. Once you do the above it sort of becomes obvious that actually building GMP intree with the correct CPU instead of none is proper solution. Or does that not work for cross compilies? The easier it is for people to build gcc themselves the more testing prelease versions will get.
(In reply to Andrew Roberts from comment #8) > The initial bug report was for cross compiling. Bug 70211 is for native > builds on ARM. Given the huge growth in ARM development boards, this needs > at least documenting. As with the original reporter I spent ages trying to > figure this out before stumbling across a solution (and the solution isn't > to build GMP out of tree either). Building GMP out of tree creates another > can of worms (esp on multiarch machines). > > Any documentation fix should mention the targets that need the change (ARM), > and that both cross and native builds are affected. Also reference the > undefined symbol __gmpn_invert_limb so people know they have run across it. > > Once you do the above it sort of becomes obvious that actually building GMP > intree with the correct CPU instead of none is proper solution. Or does that > not work for cross compilies? > > The easier it is for people to build gcc themselves the more testing > prelease versions will get. what happens if you use the versions from download_prerequisites? gmp -> ../gmp-4.3.2 mpc -> ../mpc-0.8.1 mpfr -> ../mpfr-2.4.2
Bernd, I don't think there is any argument that those specific versions of the library dependencies work. My sense is that it is a bug to assert "GNU Multiple Precision Library (GMP) version 4.3.2 (or later)" as a prerequisite to GCC on https://gcc.gnu.org/install/prerequisites.html if versions of GMP later than 4.3.2 do not work in some circumstances. If it is OK that GCC builds will fail on one or more supported architectures when using stable released versions of GMP later than 4.3.2, then the documentation should assert "GMP version 4.3.2" as the prerequisite. If it is not OK that GCC builds will fail in those circumstances, then the build machinery for GCC should be fixed.
On Native ARM platform the bootstrap does work with the old in tree GMP 4.3.2, regardless of wether you use none-linux-gnu or armv7l-linux-gnu when configuring GMP. Bulding by patching toplevel Makefile to remove none- and replace with armv7l- ../gcc-6.0.0/configure ... uname_m=`uname -m` sed -i "s/none-/${uname_m}-/" Makefile make make install Using: gmp -> ../gmp-4.3.2 mpc -> ../mpc-0.8.1 mpfr -> ../mpfr-2.4.2 (plus latest patches to mpfr to 2.4.2) isl -> ../isl-0.16.1 ^ Builds Ok and compiles simple program (not bootstrapped due to time taken) Using: gmp -> ../gmp-4.3.2 mpc -> ../mpc-0.8.1 mpfr -> ../mpfr-2.4.2 (plus latest patches to mpfr 2.4.2) isl -> ../isl-0.15 (download_prerequisites version) ^ Builds Ok and compiles simple program (not bootstrapped due to time taken) Bulding by WITHOUT patching toplevel Makefile but with bootstrapping ../gcc-6.0.0/configure ... --enable-bootstrap make bootstrap-lean make install Using: gmp -> ../gmp-4.3.2 mpc -> ../mpc-0.8.1 mpfr -> ../mpfr-2.4.2 (plus latest patches to mpfr 2.4.2) isl -> ../isl-0.15 (download_prerequisites version) ^ Builds and bootstraps Ok and compiles simple program This is all as expected. But as noted the docs suggest later versions of GMP are ok as well. If the build was fixed to use correct CPU for configuring GMP it would build with both old and new versions of GMP. If there are some specific tests which would exercise the GMP/ISL parts of gcc I could give them a go as well, but running the entire test suite would take forever due to the slow storage.
It is on purpose that the in-tree gmp is configured to use no assembly, but the in-tree configuration does not really work with gmp-6.1.0, and apparently disables the assembly only half-way. It is not possible to fix that without breaking compatibility to gmp-4.3.2 at the same time. I fully agree that it is time to move to a new gmp version for gcc-7, but if we do so we will also require a specific mpfr and mpc version too. And from the experience in the past, I would bet that you will not be able to simply use any future gmp version, without very careful testing, and updating mpfr and mpc to compatible versions at the same time. As a matter of fact, even when not building in-tree, there are often incompatibilities: For instance mpfr-2.4.2/INSTALL says: 0. You first need to install GMP. See <http://www.gnu.org/software/gmp/>. MPFR requires GMP version 4.1 or later. And gmp-6.1.0/INSTALL does not mention MPFR at all. But building mpfr-2.4.2 with gmp-6.1.0 fails. For instance mpc-0.8.1/INSTALL says: 0. You first need to install GMP and MPFR. See <http://gmplib.org/> and <http://www.mpfr.org>. MPC requires GMP version 4.2 or later and MPFR version 2.3.1 or later. And again mpfr-3.1.3/INSTALL does not mention MPC at all. But building mpc-0.8.1 with gmp-6.1.0 and mpfr-3.1.3 fails. So it is simply impossible to give any guarantees of that kind. All we can do is update to a specific gmp/mpfr/mpc version, and guarantee that exactly that combination will actually work.
OK, then it would make sense to have a documentation fix for GCC that specifies those exact versions for GMP, MPC, and MPFR as the versions that must be used, rather than claiming -- inaccurately! -- "x.y.z or later".
Note that I don't think we ever got a proper bug report for GMP. Verified instructions on how to reproduce the issue with just the latest version of GMP (without having to download the sources of mpfr, mpc, isl, gcc, etc) would be nice...
Marc, not entirely clear what you mean by reproducing the issue without downloading mpfr, mpc, isl etc. Do you mean the missing symbol in GMP or the issues with GMP when using assembly code? If you could please clarify. I've built GMP 6.1.0 on its own on ARM armv7l, using the following conifgurations: ../gmp-6.1.0/configure --prefix=/home/alarm/gcc/gmp/gmp-default # This picks armv7lneon as cpu make make check # No Failures make install nm ../gmp-default/lib/libgmp.so | grep gmpn_invert_limb # 0004cca8 T __gmpn_invert_limb ../gmp-6.1.0/configure --prefix=/home/alarm/gcc/gmp/gmp-armv7l \ --target=armv7l-linux-gnu \ --build=armv7l-linux-gnu \ --host=armv7l-linux-gnu make make check # No Failures make install nm ../gmp-armv7l/lib/libgmp.so | grep gmpn_invert_limb # 0004cca8 T __gmpn_invert_limb ../gmp-6.1.0/configure --prefix=/home/alarm/gcc/gmp/gmp-none \ --target=none-linux-gnu \ --build=none-linux-gnu \ --host=none-linux-gnu make make check # No Failures make install nm ../gmp-none/lib/libgmp.a | grep gmpn_invert_limb # no .so built, gmpn_invert_limb not in .a file I note that GMP 6.1.0 at least as a configure option --enable-assembly=no which seems to disable the assembly. But as with the none-linux-gnu configuration this results in no gmpn_invert_limb symbol ../gmp-6.1.0/configure --prefix=/home/alarm/gcc/gmp/gmp-armv7l-noasm \ --target=armv7l-linux-gnu \ --build=armv7l-linux-gnu \ --host=armv7l-linux-gnu \ --enable-assembly=no make make check # No Failures make install nm ../gmp-armv7l-noasm/lib/libgmp.so | grep gmpn_invert_limb # gmpn_invert_limb not in .so or .a file So I think the problem is that ISL is using a symbol which isn't always available on all targets when no assembler is selected. But there might be merrit investigating the --enable-assembly=no configure flag and which GMP versions support it. All of this does raise several isues: 1) If we are trying to disable assembler in GMP for some reason, shouldn't we tell people building GMP outside of the tree to configure it that way. It seems strange to have spent time and effort adding all those configuration switches to find GMP, MPFR, ISL, MPC etc but then saying you really need to build it in a special way, but we're not documenting it... 2) I've also found that different gcc versions require different versions of ISL to build. For example ISL 0.14 does not work with gcc < 5.0.0, you need ISL 0.12.2. If there are dependencies on on which versions gcc needs for a given release, shouldn't they also be documented (and the download_prerequisites script updated accordingly).
you should use whatever gmp,mpfr,mpc version you like. with or without assembly should not make any difference. That should work, but dont expect it to work in-tree. Instead use the --with-gmp --with-mpfr and --with-mpc configure options. Or use the versions that download_prerequisites downloads by default in-tree, that will work also. Right?
(In reply to Andrew Roberts from comment #15) > not entirely clear what you mean by reproducing the issue without > downloading mpfr, mpc, isl etc. Do you mean the missing symbol in GMP or the > issues with GMP when using assembly code? If you could please clarify. The missing symbol (not sure what "issues with GMP when using assembly code" you are talking about). > I've built GMP 6.1.0 on its own on ARM armv7l, using the following > conifgurations: The whole point is that those external builds don't seem to reproduce the issue, probably because they don't use exactly the same options... > So I think the problem is that ISL is using a symbol which isn't always > available on all targets when no assembler is selected. In PR 70211, I see: /home/alarm/gcc/gcc-build/./gmp/.libs/libgmp.a(divrem_1.o): In function `__gmpn_divrem_1': divrem_1.c:(.text+0xb0): undefined reference to `__gmpn_invert_limb' meaning that the reference to __gmpn_invert_limb comes from GMP itself, not ISL. If you called nm on this libgmp.a, you would see uses of __gmpn_invert_limb but no definition. > 2) I've also found that different gcc versions require different versions of > ISL to build. For example ISL 0.14 does not work with gcc < 5.0.0, you need > ISL 0.12.2. If there are dependencies on on which versions gcc needs for a > given release, shouldn't they also be documented (and the > download_prerequisites script updated accordingly). I think download_prerequisites is updated. And the requirements were documented, although I am not sure how to get them except looking at the archives for https://gcc.gnu.org/install/prerequisites.html around the date of the release of 4.9.0 or 5.0.1.
Ah, I managed to reproduce. GMP has a nice "CFLAGS= -g -DNO_ASM" in its Makefile, but gcc overrides it by calling make CFLAGS=-g. Not much we can do from the GMP side (and ISL is innocent). Well, maybe the definition of NO_ASM could move to config.h, but I don't think gcc should be doing what it is doing. I think this issue was already described in another PR.
(In reply to Marc Glisse from comment #18) > I think this issue was already described in another PR. Ah, that was PR 69134 for MPFR. https://gcc.gnu.org/ml/gcc-patches/2016-01/msg00127.html
Does the latest GMP snapshot from https://gmplib.org/download/snapshot/ work for you? I moved NO_ASM to config.h, so GCC's approach of overriding CFLAGS should not break it anymore.
Tested with: gcc-6-20160313 and in-tree: gmp-6.1.99-20160321 mpc-1.0.3 mpfr-3.1.4 isl-0.16.1 On: x86_64 Centos 7 (Full bootstrap) This is Ok. /usr/local/gcc-6.0.0/bin/gcc -v Using built-in specs. COLLECT_GCC=/usr/local/gcc-6.0.0/bin/gcc COLLECT_LTO_WRAPPER=/usr/local/gcc-6.0.0/libexec/gcc/x86_64-unknown-linux-gnu/6.0.0/lto-wrapper Target: x86_64-unknown-linux-gnu Configured with: ../gcc-6.0.0/configure --prefix=/usr/local/gcc-6.0.0 --program-suffix= --disable-werror --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --enable-gnu-indirect-function --enable-lto --with-isl --enable-languages=c,c++,fortran --disable-libgcj --with-tune=generic --enable-multilib --with-arch_32=i686 --host=x86_64-unknown-linux-gnu --build=x86_64-unknown-linux-gnu --with-ld=/usr/local/bin/ld --with-gnu-ld --with-as=/usr/local/bin/as --with-gnu-as --enable-bootstrap Thread model: posix gcc version 6.0.0 20160313 (experimental) (GCC) /usr/local/bin/ld -v GNU ld (GNU Binutils) 2.26.20160125 aarch64 Arch Linux Arm (ODroid-C2) (not stable enough to bootstrap) This is Ok. /usr/local/gcc-6.0.0/bin/gcc -v Using built-in specs. COLLECT_GCC=/usr/local/gcc-6.0.0/bin/gcc COLLECT_LTO_WRAPPER=/usr/local/gcc-6.0.0/libexec/gcc/aarch64-unknown-linux-gnu/6.0.0/lto-wrapper Target: aarch64-unknown-linux-gnu Configured with: ../gcc-6.0.0/configure --prefix=/usr/local/gcc-6.0.0 --program-suffix= --disable-werror --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --enable-gnu-indirect-function --enable-lto --with-isl --enable-languages=c,c++,fortran --disable-libgcj --enable-clocale=gnu --disable-libstdcxx-pch --enable-install-libiberty --disable-multilib --enable-shared --enable-clocale=gnu --with-arch-directory=aarch64 --enable-multiarch --host=aarch64-unknown-linux-gnu --build=aarch64-unknown-linux-gnu --with-arch=armv8-a --disable-bootstrap Thread model: posix gcc version 6.0.0 20160313 (experimental) (GCC) armv7l Arch Linux Arm (Raspberry Pi 3) (not bootstrapped yet due to build time) I've not got this working yet, not sure if the new GMP is the issue or changes in my build scripts. I'll go back to released GMP 6.1 and my working script and then post the results later today or early tomorrow.
Tested with: gcc-6-20160313 and in-tree: gmp-6.1.99-20160321 mpc-1.0.3 mpfr-3.1.4 isl-0.16.1 On: armv7l Arch Linux Arm (Raspberry Pi 3) (not bootstrapped yet due to build time) This also builds ok with new GMP snapshot. /usr/local/gcc-6.0.0/bin/gcc -v Using built-in specs. COLLECT_GCC=/usr/local/gcc-6.0.0/bin/gcc COLLECT_LTO_WRAPPER=/usr/local/gcc-6.0.0/libexec/gcc/armv7l-unknown-linux-gnueab ihf/6.0.0/lto-wrapper Target: armv7l-unknown-linux-gnueabihf Configured with: ../gcc-6.0.0/configure --prefix=/usr/local/gcc-6.0.0 --program- suffix= --enable-languages=c,c++,fortran --enable-shared --enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit --disable-libunwind-exceptio ns --enable-clocale=gnu --disable-libstdcxx-pch --disable-libssp --enable-gnu-un ique-object --enable-linker-build-id --enable-lto --enable-plugin --enable-insta ll-libiberty --with-linker-hash-style=gnu --enable-gnu-indirect-function --disab le-multilib --disable-werror --enable-checking=release --host=armv7l-unknown-lin ux-gnueabihf --build=armv7l-unknown-linux-gnueabihf --target=armv7l-unknown-linu x-gnueabihf --with-arch=armv7-a --with-float=hard --with-fpu=vfpv3-d16 --disable -bootstrap Thread model: posix gcc version 6.0.0 20160313 (experimental) (GCC) ld -v GNU ld (GNU Binutils) 2.26.0.20160302
Hi, I tried this combination in-tree: gmp -> gmp-6.1.0 mpfr -> mpfr-3.1.3 mpc -> mpc-1.0.3 isl -> isl-1.15 While I can now reproduce the original problem, I noticed another anomaly: make check-mpc fails because it does not resolve -lmpfr make check-mpc [...] libtool: link: ( cd ".libs" && rm -f "libmpc-tests.la" && ln -s "../libmpc-tests.la" "libmpc-tests.la" ) gcc -DHAVE_CONFIG_H -I. -I../../../gcc-trunk/mpc/tests -I.. -I../../../gcc-trunk/mpc/src -I/home/ed/gnu/gcc-build/./gmp -I/home/ed/gnu/gcc-trunk/mpfr/src -g -O2 -MT tabs.o -MD -MP -MF .deps/tabs.Tpo -c -o tabs.o ../../../gcc-trunk/mpc/tests/tabs.c mv -f .deps/tabs.Tpo .deps/tabs.Po /bin/bash ../libtool --tag=CC --mode=link gcc -g -O2 -no-install -static-libstdc++ -static-libgcc -o tabs tabs.o libmpc-tests.la ../src/libmpc.la -lmpfr -lgmp -lm libtool: link: gcc -g -O2 -static-libstdc++ -static-libgcc -o tabs tabs.o ./.libs/libmpc-tests.a ../src/.libs/libmpc.a -lmpfr /home/ed/gnu/gcc-build/./gmp/.libs/libgmp.a -lm /usr/bin/ld: cannot find -lmpfr collect2: error: ld returned 1 exit status make[3]: *** [tabs] Error 1 make[3]: Leaving directory `/home/ed/gnu/gcc-build/mpc/tests' make[2]: *** [check-am] Error 2 make[2]: Leaving directory `/home/ed/gnu/gcc-build/mpc/tests' make[1]: *** [check-recursive] Error 1 make[1]: Leaving directory `/home/ed/gnu/gcc-build/mpc' make: *** [check-mpc] Error 2
Created attachment 38101 [details] possible patch Hi, this is a patch that fixes the check-mpc issue and fixes gmp-6.1.0 in-tree The reason for the mpc check problem is that mpfr changed the place where the libmpfr.la is around. It was moved from mpfr/.lib to mpfr/src/.lib and of course, we override LDFLAGS with "-static-libstdc++ -static-libgcc" while mpc would normally use LDFLAGS="-L.../gcc-build/./gmp/.libs -L.../gcc-build/./mpfr/.libs -static-libstdc++ -static-libgcc" That used to work because we also add mpfr/.libs to the LD_LIBRARY_PATH but we have foggot to ad mpfr/src/.lib which my patch does, to fix the check-mpc make target. Bernd.
The patch works on native armv7l-unknown-linux-gnuabihf with: gcc-6-20160320 and in tree gmp 6.1.0 mpc 1.0.3 mpfr 3.1.4 isl 0.16.1 although I wasn't seeing a problem with check-mpc. At least the build completes without needing the GMP snapshot or seding none- to `uname -m`- in the makefile.
with unpatched trunk and mpfr-3.1.4 and mpc-1.0.3 in-tree I've got this in mpc/src/libmpc.la: dependency_libs=' -lmpfr /home/ed/gnu/gcc-build1/./gmp/.libs/libgmp.la -lm' and check-mpc fails to build this: libtool: link: /home/ed/gnu/gcc-build1/./prev-gcc/xgcc -B/home/ed/gnu/gcc-build1/./prev-gcc/ -B/home/ed/gnu/install1/x86_64-pc-linux-gnu/bin/ -B/home/ed/gnu/install1/x86_64-pc-linux-gnu/bin/ -B/home/ed/gnu/install1/x86_64-pc-linux-gnu/lib/ -isystem /home/ed/gnu/install1/x86_64-pc-linux-gnu/include -isystem /home/ed/gnu/install1/x86_64-pc-linux-gnu/sys-include -g -O2 -static-libstdc++ -static-libgcc -o tabs tabs.o ./.libs/libmpc-tests.a ../src/.libs/libmpc.a -lmpfr /home/ed/gnu/gcc-build1/./gmp/.libs/libgmp.a -lm /usr/bin/ld: cannot find -lmpfr and with the patch this line in mpc/src/libmpc.la changed to: dependency_libs=' /home/ed/gnu/gcc-build/./mpfr/.libs/libmpfr.la /home/ed/gnu/gcc-build/./gmp/.libs/libgmp.la' and the check-mpc succeeds on a plain x86_64-ubuntu14.04 with definitely no gmp or mpfr libs installed
Unfortunately this patch was dismissed, see: https://gcc.gnu.org/ml/gcc-patches/2016-03/msg01502.html We will update the download_prerequisite for gcc-7 to use the "latest" available versions, that is generally agreed upon. Therefore I have to set this bug to wont-fix.