commit 46981239e8dc5982e0cd5f3db90058f40ac709c2
parent 03f37879ef167dba6f5944716c06da81902e436e
Author: Laurent Bercot <ska-skaware@skarnet.org>
Date: Fri, 20 Sep 2019 21:34:29 +0000
THAT'S IT WE HAVE EASY CROSS-COMPILATION FOLKS
Diffstat:
3 files changed, 132 insertions(+), 189 deletions(-)
diff --git a/configure b/configure
@@ -27,7 +27,6 @@ Fine tuning of the installation directories:
includedir will be /usr/include and sysdepdir will be /usr/lib/$package/sysdeps.
Dependencies:
- --with-sysdeps=DIR use provided sysdeps in DIR [autodetected]
--with-include=DIR add DIR to the list of searched directories for headers
--with-lib=DIR add DIR to the list of searched directories for static libraries
--with-dynlib=DIR add DIR to the list of searched directories for shared libraries
@@ -44,6 +43,10 @@ $package options:
--enable-tai-clock assume the system clock is TAI-10 instead of UTC [disabled]
--with-default-path=PATH default executable search path [/usr/bin:/bin]
+Sysdeps autodetection override:
+ --with-sysdep-X=yes|no|value override sysdep X with the given value [autodetected]
+List of mandatory X for cross-compiling: devurandom
+
EOF
exit 0
}
@@ -71,7 +74,7 @@ EOF
}
fail () {
- echo "$*"
+ echo "$*" 1>&2
exit 1
}
@@ -126,8 +129,8 @@ tryldflag () {
iscached ()
{
- if test -n "$sysdepspre" && grep -qF "${1}: " "$sysdepspre" ; then
- v=`grep -F "${1}: " "$sysdepspre" | tail -n 1 | awk '{print $2;}'`
+ if test -r "$tmps" && grep -qF "${1}: " "$tmps" ; then
+ v=`grep -F "${1}: " "$tmps" | tail -n 1 | awk '{print $2;}'`
echo "${1}: $v" >> "$sysdeps/sysdeps"
echo " ... user-provided: $v"
return 0 ;
@@ -139,8 +142,8 @@ iscached ()
choose () {
what="$1"
name="$2"
- if iscached "$name" ; then return ; fi
echo "Checking whether system has $3..."
+ if iscached "$name" ; then return ; fi
shift 3
libs="$*"
r=true
@@ -154,9 +157,13 @@ choose () {
fi
if $r ; then
case "$what" in
- *r*) ./try$name >/dev/null 2>&1 ; r=$?
+ *r*) if test -n "$cross" ; then
+ rm -f try$name.o try$name
+ fail "$0: sysdep $name cannot be autodetected when cross-compiling. Please manually provide a value with the --with-sysdep-${name}=yes|no|... option."
+ fi
+ ./try$name >/dev/null 2>&1 ; r=$?
case "$r" in
- 111) echo " ... test crashed, aborting." ; exit 111 ;;
+ 111) fail "$0: test crashed, aborting." ;;
0) r=true ;;
*) r=false ;;
esac
@@ -242,13 +249,11 @@ EOF
fi
done
rm -f "$tmpc"
- echo "$0: error: unable to determine endianness according to $i" 1>&2
- exit 1
+ fail "$0: error: unable to determine endianness according to $i"
fi
done
rm -f "$tmpc"
- echo "$0: error: unable to determine endianness: no endian.h found" 1>&2
- exit 1
+ fail "$0: error: unable to determine endianness: no endian.h found"
}
trysigned () {
@@ -276,8 +281,7 @@ EOF
fi
done
rm -f "$tmpc"
- echo "$0: error: unable to determine the size of $t on the target" 1>&2
- exit 1
+ fail "$0: error: unable to determine the size of $t on the target"
}
trystdtype () {
@@ -348,7 +352,7 @@ libdir='$prefix/lib/$package'
includedir='$prefix/include'
datadir='$prefix/etc'
sysdepdir='$prefix/lib/$package/sysdeps'
-sysdepspre=
+sysdeplist=
shared=true
static=true
allpic=true
@@ -378,7 +382,6 @@ for arg ; do
--includedir=*) includedir=${arg#*=} ;;
--datadir=*) datadir=${arg#*=} ;;
--sysdepdir=*) sysdepdir=${arg#*=} ;;
- --with-sysdeps=*) sysdepspre=${arg#*=} ;;
--with-include=*) var=${arg#*=} ; stripdir var ; addincpath="$addincpath -I$var" ;;
--with-lib=*) var=${arg#*=} ; stripdir var ; addlibspath="$addlibspath -L$var" ; vpaths="$vpaths $var" ;;
--with-dynlib=*) var=${arg#*=} ; stripdir var ; addlibdpath="$addlibdpath -L$var" ; vpathd="$vpathd $var" ;;
@@ -401,6 +404,8 @@ for arg ; do
--disable-monotonic|--enable-monotonic=no) ;;
--with-default-path=*) defaultpath=${arg#*=} ; dpathorig=false ;;
--without-default-path) defaultpath=$ddefaultpath ; dpathorig=true ;;
+ --with-sysdep-*=*) sysdeplist="$sysdeplist ${arg#--with-sysdep-}" ;;
+ --without-sysdep-*) sysdeplist="$sysdeplist ${arg#--with-sysdep-}=no" ;;
--enable-*|--disable-*|--with-*|--without-*|--*dir=*) ;;
--host=*|--target=*) target=${arg#*=} ;;
--build=*) build=${arg#*=} ;;
@@ -439,12 +444,13 @@ while : ; do
i=$(($i+1))
tmpc="./tmp-configure-$$-$PPID-$i.c"
tmpe="./tmp-configure-$$-$PPID-$i.tmp"
+ tmps="./tmp-configure-$$-$PPID-$i.sysdeps"
2>|/dev/null > "$tmpc" && break
2>|/dev/null > "$tmpe" && break
test "$i" -gt 50 && fail "$0: cannot create temporary files"
done
set +C
-trap 'rm -f "$tmpc" "$tmpe"' EXIT ABRT INT QUIT TERM HUP
+trap 'rm -f "$tmpc" "$tmpe" "$tmps"' EXIT ABRT INT QUIT TERM HUP
# Set slashpackage values
if $slashpackage ; then
@@ -489,7 +495,7 @@ fi
trycc ${cross}gcc
trycc ${cross}clang
trycc ${cross}cc
-test -n "$CC_AUTO" || { echo "$0: cannot find a C compiler" ; exit 1 ; }
+test -n "$CC_AUTO" || fail "$0: cannot find a C compiler"
echo " ... $CC_AUTO"
echo "Checking whether C compiler works... "
echo "typedef int x;" > "$tmpc"
@@ -536,97 +542,97 @@ if $shared ; then
tryldflag LDFLAGS -Wl,--hash-style=both
fi
-if test -n "$sysdepspre" ; then
- if test ! -d "$sysdepspre" || test ! -f $sysdepspre/target ; then
- echo "$0: error: $sysdepspre is not a valid sysdeps directory"
- exit 1
- fi
- if [ "x$target" != "x$(cat $sysdepspre/target)" ] ; then
- echo "$0: error: target $target does not match the contents of $sysdepspre/target"
- exit 1
- fi
- echo "Using pre-computed sysdeps in $sysdepspre."
- spawn_lib=$(cat $sysdepspre/spawn.lib)
- socket_lib=$(cat $sysdepspre/socket.lib)
- sysclock_lib=$(cat $sysdepspre/sysclock.lib)
- timer_lib=$(cat $sysdepspre/timer.lib)
- util_lib=$(cat $sysdepspre/util.lib)
-else
- if test -n "$cross" ; then
- echo "$0: warning: possible cross-build attempt with a native compiler" 1>&2
- fi
- sysdeps=sysdeps.cfg
- mkdir -p $sysdeps
- echo "$target" > $sysdeps/target
- :> "$sysdeps/sysdeps"
-
- exec 3>&1
- util_lib=
- echo > $sysdeps/util.lib
-
- socket_lib=`trylibs lsock 'accessible socket functions' -lsocket -lnsl` || fail "$0: unable to determine socket.lib sysdep"
- echo "$socket_lib" > $sysdeps/socket.lib
-
- hasclock=yes
- sysclock_lib=`trylibs clockrt 'clock_gettime()' -lrt` || hasclock=no
- echo "$sysclock_lib" > $sysdeps/sysclock.lib
- echo "clockrt: $hasclock" >> $sysdeps/sysdeps
-
- choose cl clockmon CLOCK_MONOTONIC $sysclock_lib
- choose cl clockboot CLOCK_BOOTTIME $sysclock_lib
-
- hasspawn=yes
- spawn_lib=`trylibs posixspawn 'posix_spawn()' -lrt` || hasspawn=no
- echo "$spawn_lib" > $sysdeps/spawn.lib
- echo "posixspawn: $hasspawn" >> $sysdeps/sysdeps
-
- hastimer=yes
- timer_lib=`trylibs timer 'timer_create()' -lrt` || hastimer=no
- echo "$timer_lib" > $sysdeps/timer.lib
- echo "timer: $hastimer" >> $sysdeps/sysdeps
- exec 3>&-
-
- tryendianness
- trytypes
- choose cl accept4 'accept4()'
- choose c cmsgcloexec 'MSG_CMSG_CLOEXEC'
- choose cl dirfd 'dirfd()'
- choose cl eventfd 'eventfd()'
- choose cl flock 'flock()'
- choose cl getrandom 'getrandom()'
- choose cl getpeereid 'getpeereid()'
- choose cl sopeercred 'SO_PEERCRED'
- choose cl getpeerucred 'getpeerucred()'
- choose cl ipv6 'IPv6 support' $socket_lib
- choose c msgdontwait 'MSG_DONTWAIT'
- choose c odirectory 'O_DIRECTORY'
- choose cl openat 'openat()'
- choose cl linkat 'linkat()'
- choose cl memmem 'memmem()'
- choose cl pipe2 'pipe2()'
- choose cl ppoll 'ppoll()'
- choose cl revoke 'revoke()'
- choose cl sendfile 'sendfile()'
- choose cl setgroups 'setgroups()'
- choose cl settimeofday 'settimeofday()'
- choose cl signalfd 'signalfd()'
- choose cl splice 'splice()'
- choose cl strcasestr 'strcasestr()'
- choose c strnlen 'strnlen()'
- choose c uint64t 'uint64_t'
- choose cl futimens 'futimens()'
- choose cl futimes 'futimes()'
- choose cl arc4random 'arc4random()'
- choose cl arc4random_addrandom 'arc4random_addrandom()'
- choose cl itimer 'setitimer()'
- choose cl namespaces 'namespaces'
- choose cl nsgetparent 'NS_GET_PARENT'
- choose cl explicit_bzero 'explicit_bzero()'
-
- choose clr devurandom '/dev/urandom'
-
+rm -f "$tmps"
+if test -n "$sysdeplist" ; then
+ :> "$tmps"
+ for i in $sysdeplist ; do
+ k=${i%%=*}
+ v=${i#*=}
+ if test "$v" = "true" ; then v=yes
+ elif test "$v" = "false" ; then v=no
+ fi
+ if grep -qF -e "${k}: " "$tmps" ; then
+ grep -vF -e "${k}: " "$tmps" > "$tmpe"
+ mv -f "$tmpe" "$tmps"
+ fi
+ echo "${k}: $v" >> "$tmps"
+ done
fi
+sysdeps=sysdeps.cfg
+mkdir -p $sysdeps
+echo "$target" > $sysdeps/target
+:> "$sysdeps/sysdeps"
+
+exec 3>&1
+util_lib=
+echo > $sysdeps/util.lib
+
+socket_lib=`trylibs lsock 'accessible socket functions' -lsocket -lnsl` || fail "$0: unable to determine socket.lib sysdep"
+echo "$socket_lib" > $sysdeps/socket.lib
+
+hasclock=yes
+sysclock_lib=`trylibs clockrt 'clock_gettime()' -lrt` || hasclock=no
+echo "$sysclock_lib" > $sysdeps/sysclock.lib
+echo "clockrt: $hasclock" >> $sysdeps/sysdeps
+
+choose cl clockmon CLOCK_MONOTONIC $sysclock_lib
+choose cl clockboot CLOCK_BOOTTIME $sysclock_lib
+
+hasspawn=yes
+spawn_lib=`trylibs posixspawn 'posix_spawn()' -lrt` || hasspawn=no
+echo "$spawn_lib" > $sysdeps/spawn.lib
+echo "posixspawn: $hasspawn" >> $sysdeps/sysdeps
+
+hastimer=yes
+timer_lib=`trylibs timer 'timer_create()' -lrt` || hastimer=no
+echo "$timer_lib" > $sysdeps/timer.lib
+echo "timer: $hastimer" >> $sysdeps/sysdeps
+exec 3>&-
+
+tryendianness
+trytypes
+choose cl accept4 'accept4()'
+choose c cmsgcloexec 'MSG_CMSG_CLOEXEC'
+choose cl dirfd 'dirfd()'
+choose cl eventfd 'eventfd()'
+choose cl flock 'flock()'
+choose cl getrandom 'getrandom()'
+choose cl getpeereid 'getpeereid()'
+choose cl sopeercred 'SO_PEERCRED'
+choose cl getpeerucred 'getpeerucred()'
+choose cl ipv6 'IPv6 support' $socket_lib
+choose c msgdontwait 'MSG_DONTWAIT'
+choose c odirectory 'O_DIRECTORY'
+choose cl openat 'openat()'
+choose cl linkat 'linkat()'
+choose cl memmem 'memmem()'
+choose cl pipe2 'pipe2()'
+choose cl ppoll 'ppoll()'
+choose cl revoke 'revoke()'
+choose cl sendfile 'sendfile()'
+choose cl setgroups 'setgroups()'
+choose cl settimeofday 'settimeofday()'
+choose cl signalfd 'signalfd()'
+choose cl splice 'splice()'
+choose cl strcasestr 'strcasestr()'
+choose c strnlen 'strnlen()'
+choose c uint64t 'uint64_t'
+choose cl futimens 'futimens()'
+choose cl futimes 'futimes()'
+choose cl arc4random 'arc4random()'
+choose cl arc4random_addrandom 'arc4random_addrandom()'
+choose cl itimer 'setitimer()'
+choose cl namespaces 'namespaces'
+choose cl nsgetparent 'NS_GET_PARENT'
+choose cl explicit_bzero 'explicit_bzero()'
+
+# And here are the evil irreducible sysdeps.
+
+choose clr devurandom '/dev/urandom'
+
+
+rm -f "$tmps"
echo "Creating config.mak..."
cmdline=$(quote "$0")
for i ; do cmdline="$cmdline $(quote "$i")" ; done
diff --git a/doc/crosscompile.html b/doc/crosscompile.html
@@ -57,56 +57,36 @@ options must be the valid paths for <strong>run-time</strong>. </li>
DESTDIR=<em>stage</em></tt>. </li>
</ul>
-<h2> Support for build-time options </h2>
+<h2> Support for build-time options and bypassing target execution tests </h2>
<p>
- skalibs now uses a standard <tt>./configure && make && make install</tt>
+ skalibs uses a standard <tt>./configure && make && make install</tt>
process, and cross-compiling build-time options can be given on the
<tt>./configure</tt> command line.
</p>
-<h2> Bypassing the build-time tests </h2>
-
-<p>
- This is the hardest part of cross-compilation, and very few build systems
-get it right. (GNU autotools does not, which is one of the reasons why
-skarnet.org packages do not use autotools.)
-</p>
-
<p>
- Native build procedures usually perform build-time tests: they compile
-executables and run them (on the build platform, which is the same as
-the target platform) to check for features and system quirks. skalibs
-does exactly that: the <tt>./configure</tt> step performs tests on the
-build platform and stores the system-dependent results in a directory
-that it calls the <em>sysdeps</em> for this platform.
+ skalibs performs a certain number of build-time tests, to collect
+behaviour information on the target architecture. Most of these tests
+work when cross-compiling, because they only involve characteristics
+of the target that the cross-toolchain knows at build time; but some
+actually require code execution on the target, and so they cannot be
+performed when cross-compiling. For those, you have to manually
+give a special option to configure, to tell the build system what the
+behaviour of the target architecture is. The option is of the form
+<tt>--with-sysdep-<em>key</em>=<em>value</em></tt>, where <em>key</em>
+is the name of the sysdep (i.e. the element of target behaviour that
+is being tested), and <em>value</em> the associated value, most of
+the time <tt>yes</tt> or <tt>no</tt>.
</p>
<p>
-But in a
-cross-compilation environment, build-time tests are invalid, since the build
-platform and the target platform differ.
- There is only one way to cross-compile portable code without resorting
-to build-time autodetection:
-<strong>you must provide by hand the sysdeps for your target
-architecture</strong>, via the --with-sysdeps option to configure.
-</p>
-
-<p>
- The easiest way to get the correct sysdeps for a target achitecture is
-to natively run skalibs' <tt>./configure</tt> script on that target,
-and steal the produced sysdeps files, which are normally written to the
-<tt>./sysdeps.cfg</tt> directory.
-Doing this is easy with a virtual machine, qemu for instance.
-You could also (politely) ask for precompiled sysdeps on the
-skaware mailing-list, if you cannot find them anywhere on the Internet.
-</p>
-
-<h2> Credits </h2>
-
-<p>
-<a href="http://www.kegel.com/">Dan Kegel</a> brought up the need for a
-clean cross-compilation system.
+ At all times, <tt>./configure --help</tt> provides the list of sysdeps
+you need to provide a <tt>--with-sysdep-*</tt> option for. As of
+skalibs-2.9.0.0, there is only one such sysdep, named <tt>devurandom</tt>,
+and the value should be <tt>yes</tt> if the target has a valid
+pseudorandom generation device in <tt>/dev/urandom</tt>, and <tt>no</tt>
+otherwise.
</p>
</body>
diff --git a/src/sysdeps/tryendianness.c b/src/sysdeps/tryendianness.c
@@ -1,43 +0,0 @@
-/* ISC license. */
-
-#include <stdio.h>
-
-int main (void)
-{
- unsigned long i = 0xdeadbeefUL ;
- if (sizeof(unsigned long) == 4)
- if ((((unsigned char *)(&i))[0] == 0xef)
- && (((unsigned char *)(&i))[1] == 0xbe)
- && (((unsigned char *)(&i))[2] == 0xad)
- && (((unsigned char *)(&i))[3] == 0xde))
- return (puts("little"), 0) ;
- else if ((((unsigned char *)(&i))[0] == 0xde)
- && (((unsigned char *)(&i))[1] == 0xad)
- && (((unsigned char *)(&i))[2] == 0xbe)
- && (((unsigned char *)(&i))[3] == 0xef))
- return (puts("big"), 0) ;
- else return (puts("unknown"), 1) ;
- else if (sizeof(unsigned long) == 8)
- if ((((unsigned char *)(&i))[0] == 0xef)
- && (((unsigned char *)(&i))[1] == 0xbe)
- && (((unsigned char *)(&i))[2] == 0xad)
- && (((unsigned char *)(&i))[3] == 0xde)
- && (((unsigned char *)(&i))[4] == 0x00)
- && (((unsigned char *)(&i))[5] == 0x00)
- && (((unsigned char *)(&i))[6] == 0x00)
- && (((unsigned char *)(&i))[7] == 0x00))
- return (puts("little"), 0) ;
- else if (sizeof(unsigned long) == 8)
- if ((((unsigned char *)(&i))[0] == 0x00)
- && (((unsigned char *)(&i))[1] == 0x00)
- && (((unsigned char *)(&i))[2] == 0x00)
- && (((unsigned char *)(&i))[3] == 0x00)
- && (((unsigned char *)(&i))[4] == 0xde)
- && (((unsigned char *)(&i))[5] == 0xad)
- && (((unsigned char *)(&i))[6] == 0xbe)
- && (((unsigned char *)(&i))[7] == 0xef))
- return (puts("big"), 0) ;
- else return (puts("unknown"), 1) ;
- else return 1 ;
- else return (puts("unknown unsigned long size"), 1) ;
-}