[Firmware] Building cross-compiler.sh natively on arm.
Rob Landley
rob at landley.net
Fri Oct 10 02:15:35 CDT 2008
So I'm testing the uClibc snapshot, and the most recent version builds for all
the targets. The next step is to run a smoke test script that fires up
system-image for a target, does a "wget
http://landley.net/hg/firmware/archive/tip.tar.gz", extracts it,
runs ./download.sh, and then does "BUILD_STATIC=1 ./cross-compiler.sh" for
the arch.
So I'm trying to do a native build of the cross compiler for the target, if
that makes sense. (Hey, easy smoke test of the build infrastructure.)
This works fine on i686, and goes "boing" on armv4l. Sigh. Ok, dig in.
Building binutils 2.17 on armv4l is breaking in libiberty/regex.c, saying that
memcmp() and such are implicitly defined and then dying on improper use of
them. This is because "strings.h" and such are not being #included. At
first I was blaming the uClibc headers, but the problem is actually that
those headers are only included if STDC_HEADERS is #defined, and it isn't.
# grep STDC_HEADERS libiberty/config.h
/* #undef STDC_HEADERS */
Yes, ./configure is checking whether or not it has standard header files, and
is getting conflicting answers in different directories. Sigh.
Now the _top_ level ./configure seems to be producing reasonable values. It's
the subdirectories that "make configure-host" populates that are screwing up.
At first I thought it might be a parallelism issue. I'm doing "make -j $CPUS
configure-host", and I tried taking that out. No change. However, the
single processor logs are much easier to read, and they're saying:
checking for ANSI C header files... yes
Meaning this test is _succeeding_, and config.h is winding up with the wrong
value anyway. Hmmm... Looking at config.h with vi, it hasn't got _anything_
set. Something's up.
The way configure works in the subdirectories is the main configure script
runs 8 gazillion tests, then generates a second script called "config.status"
which generates the half-dozen output files used by the actual build,
including config.h. If you cd libiberty and run ./config.status it
rebuilds 'em all, and you can also "rm config.h; ./config.status config.h" to
beat slightly more granular behavior out of the thing. (Don't ask me why
running it without arguments rebuilds them all, but running it on just one
does dependency checking and won't rebuild the file if it exists. Isn't that
backwards? Oh well, it's autoconf. It is NOT SANE.)
After drilling through layers of horrible, horrible shell script, it turns out
the core of what config.status _does_ is run a huge sed invocation
against "binutils/libiberty/config.in" to produce config.h (and similar for
the other files, but this is the one that I'm trying to debug). The source
file's in the binutils source directory. (This package is one of those
FSF "you must build out of tree" things so you have to look
at ../../binutils/libiberty to see the files it's working on. However, you
must _be_ in build/libiberty to run the script. If you just run
libiberty/config.status from the top level build directory it'll complain it
can't find its source files. Sigh.)
The config.in file contains #undef lines for every possible config entry, and
the sed invocation searches for each enabled one and changes it to a #define,
and comments out the rest. Hideously roundabout way to do it? But of
course! This is <strike>sparta</strike> autoconf.
The easy way to figure out what it's feeding to sed is to replace sed with
something that captures it. So, I create the subdirectory "squish" and put a
file "sed" in there:
#!/bin/bash
echo "sed $@" >> /home/walrus
exec /tools/bin/sed "$@"
#chmod +x squish/sed
#rm config.h
#PATH=`pwd`/squish:$PATH ./config.status config.h
And then /home/walrus contains:
sed h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x
sed 1q
sed s,[^:]*:,,
sed s,:.*,,
sed
s/[ ]*$// /home/firmware-763712cce21f/build/temp-armv4l/binutils/libiberty/
sed -f ./confstatAK4AMo/undefs.sed ./confstatAK4AMo/in
That last line looks interesting, so let's tell the script to copy those files
by adding this to squish/sed:
if [ $# -eq 3 ]
then
cp $2 /home/two
cp $3 /home/three
fi
And now:
#cd /home
#sed -f two three | grep STDC
/* #undef STDC_HEADERS */
So we know it's reproducing the problem. (Incidentally, "three" is identical
to binutils/libiberty/config.in. Why it had to copy it into a temp directory
when it's used read only, I have no clue.)
So the next question is, will running that on x86 _not_ reproduce the problem?
Or was the creation of "two" screwed up by an earlier step? Looking
at "two", it contains:
/^[ ]*#[ ]*undef/!b
t clr
: clr
s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)PACKAGE_NAME$,
\1#\2define\3PACKAGE_NAME "",;t
s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */,
And if you'll notice, there are no interersting symbol names in there.
Nothing to recognize STDC_HEADERS and switch it on instead of off.
At this point, I need to compare what's happening on a working system with
what's happening on the broken system. It's probably a busybox sed thing
that's only happening on arm for some reason (Endianness? Alignment?
Dunno.) But that's just a guess. More debugging to come...
Rob
P.S. The above took something like 4 hours to work out, and I am now _tired_.
Wheee...
More information about the Firmware
mailing list