* configure script for musl (?!) @ 2012-05-01 22:54 Rich Felker 2012-05-01 23:39 ` Rich Felker 0 siblings, 1 reply; 8+ messages in thread From: Rich Felker @ 2012-05-01 22:54 UTC (permalink / raw) To: musl OK before anybody flips out, no, there's no autoconf. :-) Partly as an exercise in learning the details of how users/systems integrators expect "./configure" to work, and partly in the interest of simplifying build/installation of musl, I've been playing around with writing a configure script. It's a flat shell script written in portable (POSIX) sh, and depending on no external programs except the compiler whose characteristics are being tested. What does this buy us? 1. Automatic selection of ARCH as long as the compiler supports the GCC -dumpmachine option. This works even if $CC is set to a cross-compiler. 2. Automatic selection of compiler options that can fix standards conformance issues, like -ffloat-store or -fexcess-precision=standard. I believe the latter is default with -std=c99 for all compilers that support it, but testing for it allows us to fallback to (better than nothing) -ffloat-store on ones that don't. We could also add things like -frounding-math if they're helpful without worrying about breaking build on compilers that don't support them. 3. Automatic enabling of preferred warning options without breaking build on older compilers that don't support them all, or becoming spamming on newer compilers that need -Wno-* options to disable some bogus ones. 4. Automatic enabling of debloating options when supported/possible (like omitting DWARF2 stuff when debugging is disabled). I'm going to start by committing some changes to Makefile with the minimum invasiveness to support configure-like semantics in config.mak. The key change needed is that we have to split up CFLAGS so that overriding CFLAGS from the make command line does not remove the essential options (like -std=c99, -ffreestanding, -D_XOPEN_SOURCE=700, etc.) and break things horribly. I'm also making some changes that make it easier to disable shared OR STATIC libs from the build process if desired, and some general cleanup. My intent is that these changes not break existing manually-written config.mak usage at all. After that, I'll post a draft configure script here, and if all goes well, it can be committed and can serve as an alternative to the manual configuration method (which will continue to work). Rich ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-01 22:54 configure script for musl (?!) Rich Felker @ 2012-05-01 23:39 ` Rich Felker 2012-05-02 14:00 ` Solar Designer 0 siblings, 1 reply; 8+ messages in thread From: Rich Felker @ 2012-05-01 23:39 UTC (permalink / raw) To: musl [-- Attachment #1: Type: text/plain, Size: 35 bytes --] Here's the configure draft.. Rich [-- Attachment #2: configure --] [-- Type: text/plain, Size: 5235 bytes --] #!/bin/sh usage () { cat <<EOF Usage: $0 [OPTION]... [VAR=VALUE]... [BUILDTYPE] To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. Installation directories: --prefix=PREFIX main installation prefix [/usr/local/musl] --exec-prefix=EPREFIX installation prefix for tools [/usr/local] Fine tuning of the installation directories: --bindir=DIR user executables [EPREFIX/bin] --libdir=DIR library files for the linker [PREFIX/lib] --includedir=DIR include files for the C compiler [PREFIX/include] --syslibdir=DIR location for the dynamic linker [/lib] System types: --target=TARGET configure to run on target TARGET [detected] --build=BUILD same as --target Optional features: --enable-debug build libraries with debugging information --disable-shared inhibit building shared library --disable-static inhibit building static library Some influential environment variables: CC C compiler command [guessed] CFLAGS C compiler flags [-O2 ...] Use these variables to override the choices made by configure. EOF exit 0 } # Helper functions fnmatch () { eval "case \"\$2\" in $1) return 0 ;; *) return 1 ;; esac" ; } cmdexists () { type "$1" >/dev/null 2>&1 ; } trycc () { test -z "$CC" && cmdexists "$1" && CC=$1 ; } setdir () { if eval "test -z \"\${$1}\"" ; then eval "$1=\$2" else eval "fnmatch '*/' \"\${$1}\"" && eval "$1=\${$1%/}" ; fi } tryflag () { printf "checking whether %s %s works... " "$CC" "$2" echo "typedef int x;" > "$tmpc" if "$CC" "$2" -c -o /dev/null "$tmpc" 2>/dev/null ; then printf "yes\n" eval "$1=\"\${$1} \$2\"" eval "$1=\${$1# }" else printf "no\n" fi } # Beginning of actual script prefix= exec_prefix= bindir= libdir= includedir= syslibdir= build= debug= shared= static= for arg ; do case "$arg" in --help) usage ;; --prefix=*) prefix=${arg#*=} ;; --exec-prefix=*) exec_prefix=${arg#*=} ;; --bindir=*) bindir=${arg#*=} ;; --libdir=*) libdir=${arg#*=} ;; --includedir=*) includedir=${arg#*=} ;; --syslibdir=*) syslibdir=${arg#*=} ;; --enable-shared|--enable-shared=yes) shared=yes ;; --disable-shared|--enable-shared=no) shared=no ;; --enable-static|--enable-static=yes) static=yes ;; --disable-static|--enable-static=no) static=no ;; --enable-debug|--enable-debug=yes) debug=yes ;; --disable-debug|--enable-debug=no) debug=no ;; --enable-*|--disable-*|--with-*|--without-*|--*dir=*|--host=*) ;; --build=*|--target=*) build=${arg#*=} ;; -* ) echo "$0: unknown option $arg" ;; CC=*) CC=${arg#*=} ;; CFLAGS=*) CFLAGS=${arg#*=} ;; CPPFLAGS=*) CPPFLAGS=${arg#*=} ;; LDFLAGS=*) LDFLAGS=${arg#*=} ;; *) build=$arg ;; esac done setdir prefix /usr/local/musl setdir exec_prefix '/usr/local' setdir bindir '$(exec_prefix)/bin' setdir libdir '$(prefix)/lib' setdir includedir '$(prefix)/include' setdir syslibdir '/lib' # Get a temp filename we can use test -n "$TMPDIR" && tmpc="$TMPDIR/conf$$.c" || tmpc="/tmp/conf$$.c" set -C > "$tmpc" || { echo "$0: cannot create temporary file $tmpc" exit 1 } set +C trap 'rm "$tmpc"' EXIT # Find a C compiler to use printf "checking for C compiler... " trycc gcc trycc c99 trycc cc printf "%s\n" "$CC" test -n "$CC" || { echo "$0: cannot find a C compiler" ; exit 1 ; } # Find the build architecture printf "checking build system type... " test -n "$build" || build=$("$CC" -dumpmachine 2>/dev/null) || build=unknown printf "%s\n" "$build" # Convert to just ARCH case "$build" in arm*) ARCH=arm ;; i?86*) ARCH=i386 ;; x86_64*) ARCH=x86_64 ;; unknown) echo "$0: unable to detect built target; try $0 --build=..." ; exit 1 ;; *) echo "$0: unknown or unsupported build target \"$build\"" ; exit 1 ;; esac # Try to get a conforming C99 freestanding environment tryflag CFLAGS_C99FSE -std=c99 tryflag CFLAGS_C99FSE -nostdinc tryflag CFLAGS_C99FSE -ffreestanding \ || tryflag CFLAGS_C99FSE -fno-builtin tryflag CFLAGS_C99FSE -fexcess-precision=standard \ || tryflag CFLAGS_C99FSE -ffloat-store # Default CFLAGS test -z "$CFLAGS" && CFLAGS=-O2 test "x$debug" = xyes && CFLAGS="$CFLAGS -g" tryflag CFLAGS -pipe # If debugging is disabled, omit bloated DWARF2 unwind tables & frame ptr if fnmatch '-g*|*\ -g*' "$CFLAGS" ; then : else tryflag CFLAGS -fno-asynchronous-unwind-tables tryflag CFLAGS -fomit-frame-pointer fi # Some optimization levels add bloated alignment that hurt performance tryflag CFLAGS -falign-functions=1 tryflag CFLAGS -falign-labels=1 tryflag CFLAGS -falign-loops=1 tryflag CFLAGS -falign-jumps=1 if test "$ARCH" = "i386" ; then fnmatch '-march=*|*\ -march=*' "$CFLAGS" || tryflag CFLAGS -march=i486 fnmatch '-mtune=*|*\ -mtune=*' "$CFLAGS" || tryflag CFLAGS -mtune=generic fi exec 1>config.mak cat << EOF ARCH = $ARCH prefix = $prefix exec_prefix = $exec_prefix bindir = $bindir libdir = $libdir includedir = $includedir syslibdir = $syslibdir CC = $CC CFLAGS = $CFLAGS CFLAGS_C99FSE = $CFLAGS_C99FSE CPPFLAGS = $CPPFLAGS LDFLAGS = $LDFLAGS EOF test "x$static" = xno && echo "STATIC_LIBS =" test "x$shared" = xno && echo "SHARED_LIBS =" ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-01 23:39 ` Rich Felker @ 2012-05-02 14:00 ` Solar Designer 2012-05-02 14:31 ` Rich Felker 0 siblings, 1 reply; 8+ messages in thread From: Solar Designer @ 2012-05-02 14:00 UTC (permalink / raw) To: musl Rich, This approach (including not using autoconf specifically) makes sense to me. One general problem with it, though, is that errors are not distinguished from actually and purposefully missing features. Sometimes it is preferable for the build to fail when an expected system feature is not present rather than for it to succeed with unexpectedly altered functionality. This is especially true if the non-detected feature had security relevance. On Owl, we have the configure-presets script for this reason - to pre-populate autoconf configure's cache. On Tue, May 01, 2012 at 07:39:26PM -0400, Rich Felker wrote: > # Get a temp filename we can use > test -n "$TMPDIR" && tmpc="$TMPDIR/conf$$.c" || tmpc="/tmp/conf$$.c" > set -C > > "$tmpc" || { > echo "$0: cannot create temporary file $tmpc" > exit 1 > } > set +C > trap 'rm "$tmpc"' EXIT Is "set -C" sufficiently portable? (I don't know. I guess that it is if you're using it here.) Assuming that "set -C" works, another user is able to prevent the above from working by pre-creating the file. I understand that you can't just use mktemp here, and implementing its full functionality right in your shell script is not pretty. Another issue is that if the script is running with a relaxed umask like 002, then another user (in the same group, if relevant) may not only notice that musl is being compiled, but also inject their own C code into the temporary file and maybe take over the musl-building user account (depending on whether you run the compiled code or not, as well as on the compiler's features and bugs available to be invoked from the source). Perhaps you need to set a safe umask like 077 in this script before it creates the temporary file (or chmod the file right after it's been created, before its first actual use - and exit if the chmod fails). Rather than use $TMPDIR or /tmp, I think it'd be safer to place the file in the same directory with the configure script or in the current directory. You're going to create config.mak in one of these directories anyway - so just create the temporary file in that same directory not to incur any extra risk (that you do by writing into a second directory). Alexander ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-02 14:00 ` Solar Designer @ 2012-05-02 14:31 ` Rich Felker 2012-05-02 15:05 ` Solar Designer 0 siblings, 1 reply; 8+ messages in thread From: Rich Felker @ 2012-05-02 14:31 UTC (permalink / raw) To: musl On Wed, May 02, 2012 at 06:00:04PM +0400, Solar Designer wrote: > Rich, > > This approach (including not using autoconf specifically) makes sense to > me. One general problem with it, though, is that errors are not > distinguished from actually and purposefully missing features. > Sometimes it is preferable for the build to fail when an expected system > feature is not present rather than for it to succeed with unexpectedly > altered functionality. This is especially true if the non-detected > feature had security relevance. On Owl, we have the configure-presets > script for this reason - to pre-populate autoconf configure's cache. I don't think we have any situations like that. The only options that are "essential" but might fail are GCC-specific options to turn the compiler into a conforming C99 freestanding implementation. The only reason I test them at all is to support hypothetical non-GCC-compatible compilers, and I assume (1) they're already sufficiently conforming, and (2) if the user is using a non-mainstream compiler, they know best what they're doing. As for the floating point ones, only gcc >= 4.5.x can really give correct behavior on x86, but -ffloat-store is sufficient to be mostly correct, and the difference is usually just very small rounding errors. For the really important functions that need to be correctly rounded, glibc doesn't even get them right anyway, and we have asm that DOES get them right even if the compiler is broken when it comes to compiling the portable (in theory; if compilers weren't broken) C version. > On Tue, May 01, 2012 at 07:39:26PM -0400, Rich Felker wrote: > > # Get a temp filename we can use > > test -n "$TMPDIR" && tmpc="$TMPDIR/conf$$.c" || tmpc="/tmp/conf$$.c" > > set -C > > > "$tmpc" || { > > echo "$0: cannot create temporary file $tmpc" > > exit 1 > > } > > set +C > > trap 'rm "$tmpc"' EXIT > > Is "set -C" sufficiently portable? (I don't know. I guess that it is > if you're using it here.) It's POSIX. My policy for this and future configure scripts I write is that you need a POSIX compatible shell to run configure. This is the same as MPlayer and FFmpeg/libav policy and I remember they took some heat for it back in the day from users of broken unices like Solaris, but telling those users to add /usr/xpg4/bin to their path and invoke configure with that version of the shell generally made them happy. I suspect it's a non-issue in 2012, and especially for musl where building on anything non-Linux-based (and thus anything without [bd]?ash as the shell) is going to be a special cross-compiling case. > Assuming that "set -C" works, another user is able to prevent the above > from working by pre-creating the file. I understand that you can't just > use mktemp here, and implementing its full functionality right in your > shell script is not pretty. Yes, mktemp does not work because it does not let you specify a suffix, and most compilers fail to recognize input files as C unless they have a .c suffix. It has a dry run option just to generate the filename (and let the caller handle creating it like we do now) but unfortunately busybox mktemp does not know that option so it doesn't seem at all safe/portable. I've actually been working on the issue and updated it to use $$, $PPID, and a retry counter, so random failures will be extremely rare. If anyone thinks it still matters, I'll add $(date|cksum) too. > Another issue is that if the script is running with a relaxed umask like > 002, then another user (in the same group, if relevant) may not only > notice that musl is being compiled, but also inject their own C code > into the temporary file and maybe take over the musl-building user > account (depending on whether you run the compiled code or not, as well > as on the compiler's features and bugs available to be invoked from the > source). Perhaps you need to set a safe umask like 077 in this script > before it creates the temporary file (or chmod the file right after it's > been created, before its first actual use - and exit if the chmod fails). Indeed, this seems like a good idea. > Rather than use $TMPDIR or /tmp, I think it'd be safer to place the file > in the same directory with the configure script or in the current > directory. You're going to create config.mak in one of these > directories anyway - so just create the temporary file in that same > directory not to incur any extra risk (that you do by writing into a > second directory). This seems reasonable. Rich ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-02 14:31 ` Rich Felker @ 2012-05-02 15:05 ` Solar Designer 2012-05-02 15:39 ` Rich Felker 0 siblings, 1 reply; 8+ messages in thread From: Solar Designer @ 2012-05-02 15:05 UTC (permalink / raw) To: musl On Wed, May 02, 2012 at 10:31:25AM -0400, Rich Felker wrote: > On Wed, May 02, 2012 at 06:00:04PM +0400, Solar Designer wrote: > > Is "set -C" sufficiently portable? (I don't know. I guess that it is > > if you're using it here.) > > It's POSIX. My policy for this and future configure scripts I write is > that you need a POSIX compatible shell to run configure. This is the > same as MPlayer and FFmpeg/libav policy and I remember they took some > heat for it back in the day from users of broken unices like Solaris, > but telling those users to add /usr/xpg4/bin to their path and invoke > configure with that version of the shell generally made them happy. I > suspect it's a non-issue in 2012, and especially for musl where > building on anything non-Linux-based (and thus anything without > [bd]?ash as the shell) is going to be a special cross-compiling case. I think the biggest problem here is in the failure mode. In the draft script you posted, if "set -C" fails the script will proceed to potentially clobber a file via a (sym)link provided by another user, or it may use a FIFO or a regular file pre-created by another user (and set to e.g. mode 666), in which case the input to the compiler would be under that other user's control (even if we're running with a safe umask). > > Assuming that "set -C" works, another user is able to prevent the above > > from working by pre-creating the file. I understand that you can't just > > use mktemp here, and implementing its full functionality right in your > > shell script is not pretty. > > Yes, mktemp does not work because it does not let you specify a > suffix, and most compilers fail to recognize input files as C unless > they have a .c suffix. It has a dry run option just to generate the > filename (and let the caller handle creating it like we do now) but > unfortunately busybox mktemp does not know that option so it doesn't > seem at all safe/portable. > > I've actually been working on the issue and updated it to use $$, > $PPID, and a retry counter, so random failures will be extremely rare. > If anyone thinks it still matters, I'll add $(date|cksum) too. Oh, I think it's better to simply use the approach I suggested last: > > Rather than use $TMPDIR or /tmp, I think it'd be safer to place the file > > in the same directory with the configure script or in the current > > directory. You're going to create config.mak in one of these > > directories anyway - so just create the temporary file in that same > > directory not to incur any extra risk (that you do by writing into a > > second directory). > > This seems reasonable. Alexander ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-02 15:05 ` Solar Designer @ 2012-05-02 15:39 ` Rich Felker 2012-05-02 15:41 ` Solar Designer 0 siblings, 1 reply; 8+ messages in thread From: Rich Felker @ 2012-05-02 15:39 UTC (permalink / raw) To: musl On Wed, May 02, 2012 at 07:05:43PM +0400, Solar Designer wrote: > I think the biggest problem here is in the failure mode. In the draft > script you posted, if "set -C" fails the script will proceed to > potentially clobber a file via a (sym)link provided by another user, or > it may use a FIFO or a regular file pre-created by another user (and set > to e.g. mode 666), in which case the input to the compiler would be > under that other user's control (even if we're running with a safe umask). Since set is a shell builtin, I was assuming it won't fail, but I can add "|| fail msg_here" to it. > > I've actually been working on the issue and updated it to use $$, > > $PPID, and a retry counter, so random failures will be extremely rare. > > If anyone thinks it still matters, I'll add $(date|cksum) too. > > Oh, I think it's better to simply use the approach I suggested last: > > > > Rather than use $TMPDIR or /tmp, I think it'd be safer to place the file > > > in the same directory with the configure script or in the current I agree. In that case, secure creation is mostly a non-issue. Rich ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-02 15:39 ` Rich Felker @ 2012-05-02 15:41 ` Solar Designer 2012-05-02 16:26 ` Rich Felker 0 siblings, 1 reply; 8+ messages in thread From: Solar Designer @ 2012-05-02 15:41 UTC (permalink / raw) To: musl On Wed, May 02, 2012 at 11:39:03AM -0400, Rich Felker wrote: > On Wed, May 02, 2012 at 07:05:43PM +0400, Solar Designer wrote: > > I think the biggest problem here is in the failure mode. In the draft > > script you posted, if "set -C" fails the script will proceed to > > potentially clobber a file via a (sym)link provided by another user, or > > it may use a FIFO or a regular file pre-created by another user (and set > > to e.g. mode 666), in which case the input to the compiler would be > > under that other user's control (even if we're running with a safe umask). > > Since set is a shell builtin, I was assuming it won't fail, but I can > add "|| fail msg_here" to it. FWIW, I was referring to possible script invocations with a non-POSIX shell. If these merely fail to configure musl, that's acceptable. If they expose the invoking user to unexpected security risks, that's another story. > > > > Rather than use $TMPDIR or /tmp, I think it'd be safer to place the file > > > > in the same directory with the configure script or in the current > > I agree. In that case, secure creation is mostly a non-issue. Right. Alexander ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: configure script for musl (?!) 2012-05-02 15:41 ` Solar Designer @ 2012-05-02 16:26 ` Rich Felker 0 siblings, 0 replies; 8+ messages in thread From: Rich Felker @ 2012-05-02 16:26 UTC (permalink / raw) To: musl On Wed, May 02, 2012 at 07:41:10PM +0400, Solar Designer wrote: > > Since set is a shell builtin, I was assuming it won't fail, but I can > > add "|| fail msg_here" to it. > > FWIW, I was referring to possible script invocations with a non-POSIX > shell. If these merely fail to configure musl, that's acceptable. > If they expose the invoking user to unexpected security risks, that's > another story. Yes, but I don't know any way to detect that a shell is non-conformant short of checking for failure after we perform some particular option (like set -C) that's possibly broken in non-POSIX shells. Rich ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2012-05-02 16:26 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-05-01 22:54 configure script for musl (?!) Rich Felker 2012-05-01 23:39 ` Rich Felker 2012-05-02 14:00 ` Solar Designer 2012-05-02 14:31 ` Rich Felker 2012-05-02 15:05 ` Solar Designer 2012-05-02 15:39 ` Rich Felker 2012-05-02 15:41 ` Solar Designer 2012-05-02 16:26 ` Rich Felker
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/musl/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).