Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Crossdev bug, How to build 2 toolchains for glib AND newlib
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
hackernotcracker
n00b
n00b


Joined: 13 Aug 2018
Posts: 13
Location: Oregon, USA

PostPosted: Tue Aug 14, 2018 2:00 am    Post subject: Crossdev bug, How to build 2 toolchains for glib AND newlib Reply with quote

I'm building a cross compiler ... but there is a problem with a bug (or three) in the crossdev script when accepting four part target <tuples> including a C library name.
If you don't need the gory details, but want an overview of my problem and crossdev bugs, scroll down to the second post of this thread.

------------------------------------------
My question, in very gory detail:

My cross compiler needs to link with newlib rather than glibc (sometimes) and glibc the rest of the time.
My build and host machine is an x86_64 platform, though I don't think that is the cause of the Gentoo scripts failing to compile the newlib library.
The processor I'm trying to build a toolchain for is the ultra low power arm family:
armv6m-softfloat-eabi-newlib and armv6m-softfloat-eabi-glib
This chipset is a microcontroller, typically used for bluetooth devices, but which can run a super tiny linux-like unix kernel.

Typing crossdev by itself on the command line will result in crossdev asking for a target tuple of ARCH-VENDOR-OS-LIBC , a four name target prefix convention.
But apparently the four name method is untested as it's very buggy.

for example, I tried:
crossdev armv6m-softfloat-eabi-newlib

But crossdev failed to even build the compiler, although it would build the compiler if I executed the command:

crossdev armv6m-softfloat-eabi

But the shorter name doesn't allow me to make two separate toolchains with different default C libraries.
(I'm a noob to Gentoo, so if I'm overlooking something, let me know.)

The reason for failure to compile the longer name appears to be that the gnu autoconfigure scripts don't recognize all versions of C libraries as vaild target names. (Even though C libraries aren't really part of gcc, itself; and should be separately validated. ) Gnu autoconfig chokes on an arbitrary library name is appended to a target, and returns error codes. So, the gnu configure scripts simply don't like gentoo's extended names. This problem, theoretically, can be worked around by changing the configuration switches passed to autoconfigure by ebuild/eclass scripts; Changing configuration switches does work for binutils, but there's a bug in gcc autotools that makes compiling with a four name prefix impossible. ( I suspect this is why the gentoo scripts were never fully tested before releasing, as the problem is very hard to work around. )

I debugged gcc autoconfigure, created a user patch for gcc in gentoo, and then modified ebuild gentoo scripts to pass two swtiches; eg: an abbreviated --target name, and a full length --program-prefix to properly name the binaries with the C library name and pass the --target test. Using two configure switches does fix the bug in gcc's autoconfig, and allows building both gcc and binutils binaries with a four name prefix. So I was quite ecstatic when I got a good compiler from this fix.

The bug in gcc autoconfigure is documented, here, by me;
https://stackoverflow.com/questions/50850313/autotools-gccs-makefile-in-has-a-bug-7-3-0-and-earlier-how-to-re-program-au
I intend to talk with the gcc developers about it later, and see if they will fix the autoconfigure bug permanently.

The patch I came up with is largely gcc version independent, because the autoconfigure scripts in question are hand written ones.
Only the line numbers occasionally change in the "configure" scripts. ( an updated patch for gcc-8.2.0 is here: https://forums.gentoo.org/viewtopic-p-8256364.html#8256364 see the Wednesday Aug29, 2018 post. )
However, the compiler is not usable (for some reason) to compile most of Gentoo's packages.

Part of the problem "seems" to be that several inconsistent (undocumented) and redundant places exist for the binaries of cross compilers and C libraries.
The rest of the problem is that the toolchain naming convention and assumptions change in a lot of places, making computing path names difficult to impossible.
I am unsure of the philosophy of the gentoo crossdev programmers when reading ebuild source code.
How can I get in touch with the programmers responsible for making crossdev?

What is the relationship of /usr/libexec/gcc/arm* vs. /usr/bin/arm-* vs. /usr/arm-* etc... there are so many places where cross compiler binaries and links show up!
Edit: ( I found out that /usr/arm-* is the target's root staging directory. So that directory, I understand now. I still don't understand the relationship of the other two.)

Secondly, based on my experience:
A C compiler is traditionally only linked with one default C library ; I assume GCC isn't optimized to compile for a "use case" of one gcc binary but multiple C libraries. eg: because gcc documentation suggests that gcc partially decides how to compile and optimize itself based on which C library is used. I'd rather just not take a chance on conflicts. For now, I'd like to make two completely binary independent compiler toolchains. Although, maybe Gentoo developers will want to go in another direction ... and I'd like to collaborate and not waste effort. I almost have everything working, BUT... today I discovered that there are two newlib libraries; one newlib library comes with gcc's source code, and another library is a standalone package under Gentoo.

Even though crossdev properly recognizes that I WANT to build a newlib library .. it ignores the one bundled with gcc, and is incapable of compiling the one which gentoo supplies.
This is true regardless of how I've tried to get crossdev to make a toolchain.

I am not sure what the intention of the authors of crossdev is... which library really needs to be built, and under what conditions?

With my patches, Gentoo does build armv6m-softfloat-eabi-newlib-gcc , armv6m-softfloat-eabi-newlib-as, and all other toools (Only stage -s0 and -s1, but -s3 fails. ) . eg: Crossdev can't make a crt0 library with Gentoo's standalone newlib ; but it does make a crt library with gcc's newlib,

I'd appreciate some advice on how to proceed.
In order to reproduce my situation, the rest of this post is dedicated to my patches which enabled me to compile gcc with newlib in the prefix.
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------



First; I pre-set the toolchain use flags before crossdev is even run, to minimize what is being built.
Once I get newlib to compile, I'll probably change the use flags to more reasonable settings, but this simplifies debugging Gentoo scripts.

FILE: /etc/portage/packages.use/cross-armv6m-softfloat-eabi-newlib
Code:
cross-armv6m-softfloat-eabi-newlib/binutils multilib
cross-armv6m-softfloat-eabi-newlib/gcc -cxx -openmp -sanitize -vtv -selinux -boundschecking -d -gcj -gtk -libffi -mudflap -objc -objc++ -objc-gc -fortran -go -openmp -sanitize -vtv multilib


Then I modify the toolchain ebuild scripts to pass a three name target name to autoconfigure, but a four name binary prefix for making executables.

The following three patches all do the same thing. Unfortunately, as gentoo evolves -- the version number of the scripts which need to be modified will change.
As of a sync done today AUG 2018, binutils version 2.31.1 was current. But the same patch will work if you locate the correct lines in other ebuilds for binutils.

Gentoo does not seem to support user patches to the ebuild scripts, themselves, and I'm a noob. So I patch the system ebuild scripts manually, and recompute the manifest.
The eclass scripts, on the other hand, will run with no recomputation. ( The security / corruption protection of Gentoo is weirdly inconsistent, DOH !!!)


To find out which version of binutils is current on your system, try the crossdev command and if it fails you can do:

equery which cross-armv6m-softfloat-eabi-newlib/binutils

This commmand will reveal which ebuild crossdev tried to use, and therefore the ebuild which needs a patch like the following:
Note: The first character of the patch shows which lines are added or deleted, and don't actually get edited into the file.
Only lines starting with a single "+" need to be added to the file, and lines with a single "-" are deleted. All other lines are left unchanged, and can be used to find where the patch needs to be applied.

FILE: /usr/portage/sys-devel/binutils/binutils-2.31.1.ebuild.patch
Code:
--- /root/binutils-2.31.1.ebuild.old   2018-08-13 21:11:51.700670025 -0700
+++ binutils-2.31.1.ebuild   2018-08-13 21:11:36.374003668 -0700
@@ -220,10 +220,21 @@
       myconf+=( --enable-default-hash-style=gnu )
    fi
 
+   # autoconfig lacks support for architechture quadtuplets with library name
+   # shorten gentoo quadtuplets into gnu triplets
+   # FIXME: I don't know if there are any quadtuplets that might work,
+   # and need not to be shortened. Those should be passed through.
+   CTARGET3=${CTARGET}
+   case ${CTARGET} in *-*-*-*lib*)
+      CTARGET3=${CTARGET%-*}
+      myconf+=( "--program-prefix=${CTARGET}-" )
+   ;;
+   esac
+
    myconf+=(
       --prefix="${EPREFIX}"/usr
       --host=${CHOST}
-      --target=${CTARGET}
+      --target=${CTARGET3}
       --datadir="${EPREFIX}"${DATAPATH}
       --datarootdir="${EPREFIX}"${DATAPATH}
       --infodir="${EPREFIX}"${DATAPATH}/info


Note: The ebuild patch will be "upgraded" back to the old buggy version the next time you do an emerge --sync ; but I'm a Gentoo newbie, and don't know a permanent way yet.
So, until I get Gentoo figured out better ... this is the only way I can show the fixes I know how to do on the ebuilds.
Once you have copied and pasted the patch into the appropriate editor and file, then you can use the patch command to automatically apply it.
The following example uses patch with a lowercase L option -l . That makes it forgiving if the copy and paste of the patch messes up the spacing a little.

Code:
cd /usr/portage/sys-devel/binutils
patch -l binutils-2.31.1.ebuild binutils-2.31.1.ebuild.patch
ebuild ${PWD}/binutils-2.31.1.ebuild manifest


These next two patches do the exact same thing, and are applied the same way, but don't need a manifest fixup.
You may not need to install the toolchain-binutils.eclass patch, as it is only run when a new binutils release first comes out.
When a version specific ebuild (like the previous patch) is released by Gentoo, this generic binutils script no longer appears to be used.
I present the patch, just for completeness.

File: /usr/portage/eclass/toolchain-binutils.eclass.patch
Code:
--- /root/toolchain-binutils.eclass.old   2018-08-13 17:13:26.790958491 -0700
+++ toolchain-binutils.eclass   2018-08-13 17:13:18.937625318 -0700
@@ -282,10 +282,22 @@
    has_version ">=${CATEGORY}/glibc-2.5" && myconf+=( --enable-secureplt )
    has_version ">=sys-libs/glibc-2.5" && myconf+=( --enable-secureplt )
 
+   # autoconfig lacks support for architechture quadtuplets with library name
+   # shorten gentoo quadtuplets into gnu triplets
+   # FIXME: I don't know if there are any quadtuplets that might work,
+   # and need not to be shortened. Those should be passed through.
+
+   CTARGET3=${CTARGET}
+   case "${CTARGET}" in *-*-*-*lib*)
+      CTARGET3="${CTARGET3%-*}"
+      myconf+=( "--program-prefix=${CTARGET}-" )
+      ;;
+   esac
+
    myconf+=(
       --prefix="${EPREFIX}"/usr
       --host=${CHOST}
-      --target=${CTARGET}
+      --target=${CTARGET3}
       --datadir="${EPREFIX}"${DATAPATH}
       --infodir="${EPREFIX}"${DATAPATH}/info
       --mandir="${EPREFIX}"${DATAPATH}/man


This next patch is for the eclass which builds gcc. It fixes the major problems.

FILE: /usr/portage/eclass/toolchain.eclass.patch
Code:
--- toolchain.eclass.old   2018-08-13 22:21:53.427251960 -0700
+++ toolchain.eclass   2018-08-14 12:53:55.662863516 -0700
@@ -874,7 +874,38 @@
       # "GCC has code to correctly determine the correct value for target
       # for nearly all native systems. Therefore, we highly recommend you
       # not provide a configure target when configuring a native compiler."
-      confgcc+=( --target=${CTARGET} )
+
+      # autoconfig lacks support for architechture quadtuplets with library name
+      # shorten gentoo quadtuplets into gnu triplets
+      # FIXME: I don't know if there are any quadtuplets that might work,
+      # and need not to be shortened. Those should be passed through.
+
+      CTARGET3=${CTARGET}
+      case "${CTARGET}" in *-*-*-*)
+         CTARGET3="${CTARGET3%-*}"
+         confgcc+=( "--program-prefix=${CTARGET}-" )
+         ;;
+      esac
+
+      # BINUTILS was installed to the system earlier in the emerge.
+      # Autoconfig looks only for binaries matching --target name.
+      # Autoconfig is not smart enough to use --program-prefix
+      # to locate the proper target binaries !!
+      # So, we manually set the binary names that would have
+      # been installed system wide.  /usr/bin must be
+      # hardcoded, because $BINPATH is different for binutils vs. gcc.
+      # I'm not sure if a variable exists to replace /usr/bin.
+
+      for i in \
+            ar as dlltool ld nm objcopy objdump ranlib readelf strip \
+            cc cxx windres windmc ; do
+         j="$i"
+         case ${i} in cc) j="gcc" ;; cxx) j="g++" ;; esac
+         if [ -x /usr/bin/${CTARGET}-${j} ]; then
+            confgcc+=( "${i^^}_FOR_TARGET=/usr/bin/${CTARGET}-${j}" )
+         fi
+      done
+      confgcc+=( "--target=${CTARGET3}" )
    fi
    [[ -n ${CBUILD} ]] && confgcc+=( --build=${CBUILD} )


Make sure there are no trailing spaces after the backslashes \ that end a line. Sometimes, copy paste from a web browser messes that up.
If you get a "syntax error near unexpected token" when running crossdev, a space is the likely culprit.

After creating the previous two patch files, you can just run this in a terminal:
Code:
cd /usr/portage/eclass
patch -l toolchain-binutils.eclass toolchain-binutils.eclass.patch
patch -l toolchain.eclass toolchain.eclass.patch


Finally, I created a user patch to fix the bugs in gcc's autoconfigure. There are no bugs in the binutils autoconfigure, so this is only needed for gcc .
For GCC 7.3.0, use the following:

FILE: /etc/portage/patches/cross-armv6m-softfloat-eabi-newlib/gcc/autoconfig.patch # This file and directory must be created, with the following contents.
Code:
--- gcc-old/libcpp/Makefile.in
+++ gcc-new/libcpp/Makefile.in
@@ -28,3 +28,3 @@
 INSTALL = @INSTALL@
-AR = ar
+AR ?= ar
 ARFLAGS = cru
--- gcc-old/gcc/configure
+++ gcc-new/gcc/configure
@@ -29531,3 +29531,5 @@
      ;;
    esac
 
+   if [ -n $OBJDUMP ]; then export_sym_check="$OBJDUMP -T"; fi
+
--- gcc-old/libcc1/configure
+++ gcc-new/libcc1/configure
@@ -14574,3 +14574,5 @@
      ;;
    esac
 
+   if [ -n $OBJDUMP ]; then export_sym_check="$OBJDUMP -T"; fi
+


For gcc 8.2.0, use the previous patch but change the @@ lines numbered 29531 in both places to 29856, and @@ line numbered 14574 to 14587 in both places.

With the above patches installed, crossdev -s1 armv6m-softfloat-eabi-newlib , will generate a working gcc toolchain.

At the end, I get the following warning:

gcc-config: Profile does not exist or invalid setting for /etc/env.d/gcc/armv6m-softfloat-eabi-newlib-7.3.0

When I look inside the profile / environment file armv6m-softfloat-eabi-newlib-7.3.0, everything is correct.
The target line reads, "CTARGET=armv6m-softfloat-eabi-newlib"
This target name is apparently what breaks the compile of the gentoo newlib package, because ... again, gcc autoconfigure scripts don't accept a four name target.
When I try to switch to my new arm compiler, I get the no-profile warning again ... and gcc-config refuses to enable the new arm compiler.

I did a little digging, and gcc stores target libraries under /usr/lib/gcc.
This location for the target binaries is from a bug already worked on by gentoo in toolchain.eclass; there is a whole function gcc_movelibs() dedicated to this inconsistency.
Unfortunately, it's use of XGCC is probably why the "newlib" suffix gets dropped in the directory name /usr/lib/gcc/armv6m-softfloat-eabi .
When I rename the directory to be /usr/lib/gcc/armv6m-softfloat-eabi-newlib , then gcc-config works perfectly.

But, this inconsistent naming problem keeps cropping up, ad nausium.

Without patching each package's configure script, or modifying every ebuild, this problem will show up again in every package I try to cross compile ...

I wonder what is the "RIGHT" way to use crossdev in order to handle more than one standard C library including newlib?
(I am still a noob, in 2018... ;) )
_________________
What's the difference between a liar and a joker? A liar always claims what they said was just a joke, but a real joker just laughs.


Last edited by hackernotcracker on Thu Aug 30, 2018 12:13 am; edited 28 times in total
Back to top
View user's profile Send private message
hackernotcracker
n00b
n00b


Joined: 13 Aug 2018
Posts: 13
Location: Oregon, USA

PostPosted: Tue Aug 14, 2018 8:29 pm    Post subject: Reply with quote

A shorter version of the opening question, asking it in a generic way:

Gentoo's crossdev script is supposed to create an overlay for various cross compiler toolchains, automatically.
There appear to be possible conflicts in the way the packages are installed, that can potentially corrupt the integrity of a cross-compiler toolchain.
These conflicts are what I'm trying to understand (I'm a gentoo noob in 2018, but a programming vetran on other linux systems. I learn really fast. )
I barely understand slots on Gentoo, but crossdev seems to be setting them up wrong .... ??

IF crossdev is run with no arguments, it prints a help message saying "Target (-t) takes a tuple ARCH-VENDOR-OS-LIBC"
This target <tuple> is the default argument when -t is not specified, so a naiive attempt is to do:

crossdev armv6b-softfloat-eabi-newlib # This doesn't work.
crossdev armv6b-softfloat-eabi # This does work, and defaults to newlib; but doesn't add the name for newlib to the toolchain...

Crossdev then creates an overlay in a local portage repository which uses the supplied name as a directory/container. ( on my system it's: /var/db/repos/crossdev/cross-armv6m-softfloat-eabi )

Inside the overlay directory, crossdev will create links to the original portage repository for C compiler source code:
For crossdev -s1 armv6m-softfloat-eabi , the following overlay directory was made (notice newlib is not appended to the tuple name, for this to work without my patches! )

Code:

rabbitport / # ls /var/db/repos/crossdev/cross-armv6m-softfloat-eabi -l
total 16
lrwxrwxrwx 1 root root 31 Aug 29 13:42 binutils -> /usr/portage/sys-devel/binutils
lrwxrwxrwx 1 root root 26 Aug 29 13:42 gcc -> /usr/portage/sys-devel/gcc
lrwxrwxrwx 1 root root 26 Aug 29 13:42 gdb -> /usr/portage/sys-devel/gdb
lrwxrwxrwx 1 root root 28 Aug 29 13:42 newlib -> /usr/portage/sys-libs/newlib


In general, then, crossdev is automatically emerging each of these packages; the hidden process would be vaguely like:

emerge cross-armv6b-softloat-eabi/binutils
emerge cross-armv6b-softfloat-eabi/gcc # with multiple stages not shown
emerge cross-armv6b-softfloat-eabi/newlib

The identical thing SHOULD happen if I do crossdev -s1 armv6m-softfloat-eabi-newlib ; but it doesn't because of bugs in crossdev and gcc configure scripts; (See previous post for gory details.)

The problem I have with crossdev is that, when there are multiple toolchains ( cross-armv6b-softfloat-eabi vs. cross-armv6b-softfloat-eabi-glib ), the hardware target architechture is the same.

Given that autoconfig -target DOESN'T accept all C library names; and crossdev is buggy; Is there any known way to solve the following issues/Q's:

Q1: How is Gentoo's crossdev supposed to allow a user to handle multiple C libraries? ( Can you show me an example of how to compile and use the both toolchains I want? )
eg: can crossdev be run twice to create cross-armv6b-softfloat-eabi with TWO libraries? eg: can the --libc switch specify both the library name and version, twice?
Or, does each run of crossdev require a unique name INCLUDING the C library, for it to generate a different gentoo "slot"? (How do I get that effect?)

Q2: If crossdev can be run twice, but at different times/years/ when GCC versions change, How does the Gentoo system protect toolchain C libraries from clobbering each other?

eg: the newlib version and toolchain might be GCC 7 the first time crossdev is run, while the next time crossdev is run with glib, the toolchain might be GCC 8.
How does each toolchain figure out NOT to use the binaries from the other toolchain if they are both named simply "cross-armv6m-softfloat-eabi" ?

After running crossdev armv6m-softfloat-eabi, I tried running crossdev armv6m-softfloat-eabi-glib , and sure enough it crashes out after saying "Detected file collision(s): /usr/libexec/gcc/armv6m-softfloat-eabi/7.3.0/lto-wrapper .... "
So, it doesn't even look like crossdev is able to even install multiple instances of a compiler target, with different C libraries.

Can anyone give me some guidance about how to get two toolchains with different C libraries to peacefully co-exist on the same host?
Who debugs crossdev / how do I report a serious Gentoo bug ?
_________________
What's the difference between a liar and a joker? A liar always claims what they said was just a joke, but a real joker just laughs.
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum