mescc: Remove dead code. Thanks Mark Weaver.
[mes.git] / configure
index 510a0d61ede4bad3654466aa7f9bbc33c47da381..81f602b4d943596eaf0b511c9b094fe2693f42a0 100755 (executable)
--- a/configure
+++ b/configure
@@ -1,28 +1,10 @@
 #! /bin/sh
-# -*- scheme -*-
-unset LANG LC_ALL
-guile=$(command -v ${GUILE-guile})
-guix=$(command -v ${GUIX-guix})
-if [ -n "$guix" ] ; then
-    install="guix environment -l .guix.scm"
-else
-    install="sudo apt-get install guile-2.2-dev"
-fi
-if [ -z "$guile" ]; then
-    cat <<EOF
-
-Missing dependencies: ${GUILE-guile}, please install Guile 2.2 or later; run
-    $install
-EOF
-exit 1
-fi
-GUILE=$guile
-export GUILE
-exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
+# -*-scheme-*-
+MES_ARENA=100000000 exec ${SCHEME-guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
 !#
 
 ;;; GNU Mes --- Maxwell Equations of Software
-;;; Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
+;;; Copyright © 2016,2017,2018,2019 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
 ;;;
 ;;; configure: This file is part of GNU Mes.
 ;;;
@@ -44,25 +26,49 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
   #:use-module (srfi srfi-9)
   #:use-module (srfi srfi-9 gnu)
   #:use-module (srfi srfi-26)
-  #:use-module (ice-9 and-let-star)
-  #:use-module (ice-9 curried-definitions)
   #:use-module (ice-9 getopt-long)
-  #:use-module (ice-9 match)
   #:use-module (ice-9 optargs)
   #:use-module (ice-9 popen)
   #:use-module (ice-9 rdelim)
-  #:use-module (ice-9 regex)
   #:export (main))
 
+(define *shell* "sh")
+(define PACKAGE "mes")
+(define PACKAGE-NAME "GNU Mes")
+(define PACKAGE-BUGREPORT "bug-mes@gnu.org")
+(define VERSION "0.19")
+
+(cond-expand
+ (guile)
+ (mes (mes-use-module (srfi srfi-1))
+      (mes-use-module (srfi srfi-9))
+      (mes-use-module (srfi srfi-9 gnu))
+      (mes-use-module (srfi srfi-26))
+      (mes-use-module (mes getopt-long))
+      (mes-use-module (mes guile))
+      (mes-use-module (mes misc))
+      (mes-use-module (mes optargs))
+      (define %host-type "x86_64-unknown-linux-gnu")
+      (define OPEN_READ "r")
+      (define (canonicalize-path o)
+        (if (string-prefix? "/" o) o
+            (string-append (getcwd) "/" o)))
+      (define (sort lst less)
+        lst)
+      (define (close-pipe o) 0)
+      (define (open-pipe* OPEN_READ . commands)
+        (let ((fake-pipe ".pipe"))
+          (with-output-to-file fake-pipe
+            (lambda _
+              (let ((status (apply system* (append commands))))
+                (set! close-pipe (lambda _ status)))))
+          (open-input-file fake-pipe)))))
+
 (define* (PATH-search-path name #:key (default name) warn?)
   (or (search-path (string-split (getenv "PATH") #\:) name)
       (and (and warn? (format (current-error-port) "warning: not found: ~a\n" name))
            default)))
 
-(define *shell* "sh")
-(define PACKAGE "mes")
-(define VERSION "0.16.1")
-
 ;;; Utility
 (define (logf port string . rest)
   (apply format (cons* port string rest))
@@ -80,22 +86,19 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
 (define (verbose string . rest)
   (if %verbose? (apply stderr (cons string rest))))
 
-(define (gulp-pipe command)
-  (let* ((port (open-pipe* OPEN_READ *shell* "-c" command))
+(define (gulp-pipe* . command)
+  (let* ((err (current-error-port))
+         (foo (set-current-error-port (open-output-file ".error")))
+         (port (apply open-pipe* OPEN_READ command))
          (output (read-string port))
-         (status (close-pipe port)))
-    (verbose "command[~a]: ~s => ~a\n" status command output)
-    (if (not (zero? status)) "" (string-trim-right output #\newline))))
-
-(define* ((->string #:optional (infix "")) h . t)
-  (let ((o (if (pair? t) (cons h t) h)))
-    (match o
-      ((? char?) (make-string 1 o))
-      ((? number?) (number->string o))
-      ((? string?) o)
-      ((? symbol?) (symbol->string o))
-      ((h ... t) (string-join (map (->string) o) ((->string) infix)))
-      (_ ""))))
+         (status (close-pipe port))
+         (error (with-input-from-file ".error" read-string)))
+    (when (file-exists? ".error")
+      (delete-file ".error"))
+    (set-current-error-port err)
+    (verbose "command[~a]: ~s => ~a [~a]\n" status command output error)
+    (if (not (zero? status)) ""
+        (string-trim-right (string-append output error)))))
 
 (define (tuple< a b)
   (cond
@@ -120,24 +123,39 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
 (define (string-replace-char string from to)
   (string-map (cut char->char from to <>) string))
 
+(define (string-replace-string string from to)
+  (cond ((string-contains string from)
+         => (lambda (i) (string-replace string to i (+ i (string-length from)))))
+        (else string)))
+
+(define (string-replace-string/all string from to)
+  (or (and=> (string-contains string from)
+             (lambda (i)
+               (string-append
+                (substring string 0 i)
+                to
+                (string-replace-string/all
+                 (substring string (+ i (string-length from))) from to))))
+      string))
+
 ;;; Configure
 
 (define-immutable-record-type <dependency>
-  (make-depedency name version-expected optional? version-option commands file-name)
+  (make-dependency name version-expected optional? version-option commands file-name data version-found)
   dependency?
   (name dependency-name)
   (version-expected dependency-version-expected)
-  (version-option dependency-version-option)
   (optional? dependency-optional?)
+  (version-option dependency-version-option)
   (commands dependency-commands)
   (file-name dependency-file-name)
+  (data dependency-data)
   (version-found dependency-version-found))
 
-(define* (make-dep name #:optional (version '(0))
-                   #:key optional? (version-option "--version") (commands (list name)) file-name)
+(define* (make-dep name #:key (version '(0)) optional? (version-option "--version") (commands (list name)) file-name data)
   (let* ((env-var (getenv (name->shell-name name)))
          (commands (if env-var (cons env-var commands) commands)))
-   (make-depedency name version optional? version-option commands file-name)))
+    (make-dependency name version optional? version-option commands file-name data #f)))
 
 (define (find-dep name deps)
   (find (compose (cut equal? <> name) dependency-name) deps))
@@ -153,18 +171,23 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
 (define (name->shell-name name)
   (string-upcase (string-replace-char name #\- #\_)))
 
+(define (->string o)
+  (cond ((number? o) (number->string o))
+        ((string? o) o)
+        (else (format #f "~a" o))))
+
 (define (version->string version)
-  ((->string '.) version))
+  (and version (string-join (map ->string version) ".")))
 
 (define (string->version string)
-  (and-let* ((version (string-tokenize string
-                                       (char-set-adjoin char-set:digit #\.)))
-             ((pair? version))
-             (version (sort version (lambda (a b) (> (string-length a) (string-length b)))))
-             (version (car version))
-             (version (string-tokenize version
-                                       (char-set-complement (char-set #\.)))))
-            (map string->number version)))
+  (let ((split (string-tokenize string
+                                (char-set-adjoin char-set:digit #\.))))
+    (and (pair? split)
+         (let* ((version (sort split (lambda (a b) (> (string-length a) (string-length b)))))
+                (version (car version))
+                (version (string-tokenize version
+                                          (char-set-complement (char-set #\.)))))
+           (map string->number version)))))
 
 (define (check-program-version dependency)
   (let ((name (dependency-name dependency))
@@ -174,15 +197,20 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
     (let loop ((commands commands))
       (if (null? commands) dependency
           (let ((command (car commands)))
-            (stdout "checking for ~a~a... " command
+            (stdout "checking for ~a~a... " name
                     (if (null? expected) ""
                         (format #f " [~a]" (version->string expected))))
-            (let* ((output (gulp-pipe (format #f "~a ~a 2>&1" command version-option)))
+            (let* ((output (gulp-pipe* command version-option))
+                   ;;(foo (stderr "output=~s\n" output))
                    (actual (string->version output))
+                   ;;(foo (stderr "actual=~s\n" actual))
+                   ;;(foo (stderr "expected=~s\n" expected))
                    (pass? (and actual (tuple< expected actual)))
+                   ;;(foo (stderr "PASS?~s\n" pass?))
                    (dependency (set-field dependency (dependency-version-found) actual)))
               (stdout "~a ~a\n" (if pass? (if (pair? actual) "" " yes")
-                                    (if actual " no, found" "no")) (version->string actual))
+                                    (if actual " no, found" "no"))
+                      (or (version->string actual) ""))
               (if pass? (let ((file-name (or (PATH-search-path command)
                                              (dependency-file-name dependency))))
                           (set-field dependency (dependency-file-name) file-name))
@@ -195,40 +223,85 @@ exec ${guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
     (stdout "~a\n" (or file-name ""))
     (set-field dependency (dependency-file-name) file-name)))
 
-(define* (check-header-c dependency  #:optional (check check-compile-header-c))
+(define* (check-header-c cc dependency #:optional (check check-preprocess-header-c))
   (let ((name (dependency-name dependency)))
     (stderr "checking for ~a..." name)
-    (let ((result (check name)))
+    (let ((result (check cc name)))
+      (when (file-exists? ".config.c")
+        (delete-file ".config.c"))
       (stderr " ~a\n" (if result "yes" "no"))
       (if result (set-field dependency (dependency-file-name) name)
-          dependency-file-name))))
+          dependency))))
 
-(define (check-compile-header-c header)
-  (zero? (system (format #f "echo '#include ~s' | gcc -E - > /dev/null 2>&1" header))))
+(define* (check-compile-c cc dependency #:optional (check check-compile-string-c))
+  (let ((name (dependency-name dependency)))
+    (stderr "checking for ~a..." name)
+    (let ((result (check cc (dependency-data dependency))))
+      (when (file-exists? ".config.c")
+        (delete-file ".config.c"))
+      (stderr " ~a\n" (if result "yes" "no"))
+      (if result (set-field dependency (dependency-file-name) name)
+          dependency))))
+
+(define* (check-link-c cc dependency #:optional (check check-link-string-c))
+  (let ((name (dependency-name dependency)))
+    (stderr "checking for ~a..." name)
+    (let ((result (check cc (dependency-data dependency))))
+      (when (file-exists? ".config.c")
+        (delete-file ".config.c"))
+      (stderr " ~a\n" (if result "yes" "no"))
+      (if result (set-field dependency (dependency-file-name) name)
+          dependency))))
+
+(define (check-preprocess-header-c cc header)
+  (with-output-to-file ".config.c"
+    (cut format #t "#include \"~a\"" header))
+  (with-error-to-file "/dev/null"
+    (cut zero? (system* cc "-E" "-o" ".config.E" ".config.c"))))
+
+(define (check-compile-string-c cc string)
+  (with-output-to-file ".config.c"
+    (cut display string))
+  (with-error-to-file "/dev/null"
+    (cut zero? (system* cc "--std=gnu99" "-c" "-o" ".config.o" ".config.c"))))
+
+(define (check-link-string-c cc string)
+  (with-output-to-file ".config.c"
+    (cut display string))
+  (with-error-to-file "/dev/null"
+    (cut zero? (system* cc "--std=gnu99" "-o" ".config" ".config.c"))))
 
 (define (parse-opts args)
   (let* ((option-spec
          '((build (value #t))
             (host (value #t))
-            (help (single-char #\h))
+
             (prefix (value #t))
+            (program-prefix (value #t))
             (bindir (value #t))
             (datadir (value #t))
             (docdir (value #t))
+            (includedir (value #t))
             (libdir (value #t))
             (srcdir (value #t))
             (sysconfdir (value #t))
+
+            (mes)
+            (help (single-char #\h))
             (verbose (single-char #\v))
+            (with-cheating)
             (with-courage)
             (infodir (value #t))
             (mandir (value #t))
+            (disable-colors)
+            (enable-colors)
             (disable-silent-rules)
+            (enable-silent-rules)
+            (with-system-libc)
 
             (enable-fast-install)       ; Ignored for Guix
-            (includedir (value #t))     ; Ignored for Debian
             (mandir (value #t))         ; Ignored for Debian
             (localstatedir (value #t))  ; Ignored for Debian
-            (libdir (value #t))         ; Ignored for Debian
             (libexecdir (value #t))     ; Ignored for Debian
             (runstatedir (value #t))    ; Ignored for Debian
             (disable-maintainer-mode)   ; Ignored for Debian
@@ -251,25 +324,36 @@ Defaults for the options are specified in brackets.
 Options:
   -h, --help           display this help
       --build=BUILD    configure for building on BUILD [guessed]
+      --colors         no colorized output
       --disable-silent-rules
-                       verbose build output [BUILD_DEBUG=1]
+                       verbose build output [V=1]
       --host=HOST      cross-compile to build programs to run on HOST [BUILD]
   -v, --verbose        be verbose
-  --with-courage       assert being courageous to configure for unsupported platform
+  --with-courage       Assert that even if this platform is unsupported,
+                       you will be courageous and port GNU Mes to it
+                       (see \"Porting GNU Mes\" in the manual.)
+  --with-cheating      cheat using Guile instead of Mes
+  --with-system-libc   use system libc
 
 Installation directories:
   --prefix=DIR         install in prefix DIR [~a]
+
+  --bindir=DIR         user executables [PREFIX/bin]
+  --includedir=DIR     C header files [PREFIX/include]
   --infodir=DIR        info documentation [PREFIX/share/info]
+  --libdir=DIR         object code libraries [EPREFIX/lib]
   --mandir=DIR         man pages [PREFIX/share/man]
 
+Program names:
+  --program-prefix=PREFIX            prepend PREFIX to installed program names
+  --program-suffix=SUFFIX            append SUFFIX to installed program names
+
 Ignored for Guix:
   --enable-fast-install
 
 Ignored for Debian:
   --disable-dependency-tracking
   --disable-maintainer-mode
-  --includedir=DIR
-  --libdir=DIR
   --libexecdir=DIR
   --localstatedir=DIR
   --runstatedir=DIR
@@ -277,57 +361,55 @@ Ignored for Debian:
 Some influential environment variables:
   CC                C compiler command
   CFLAGS            C compiler flags
-  CC32              x86 C compiler command
-  CC32_CFLAGS       x86 C compiler flags
   GUILE             guile command
-  GUILE_TOOLS       guile-tools command
-  MES_CFLAGS        MesCC flags
+  GUILD             guild command
+  MES_FOR_BUILD     build system MES [can be mes or guile]
   MES_SEED          location of mes-seed
-  MESCC_TOOLS_SEED  location of mescc-tools-seed
-  TCC               tcc C compiler command
-  TINYCC_SEED       location of tinycc-seed
 " PACKAGE VERSION (getenv "prefix")))
 
 (define (main args)
   (let* ((options (parse-opts args))
          (build-type (option-ref options 'build %host-type))
-
-         (arch (car (string-split build-type #\-)))
-         (host-type (option-ref options 'host %host-type))(prefix "/usr/local")
+         (host-type (option-ref options 'host build-type))
 
          (prefix "/usr/local")
          (prefix (option-ref options 'prefix prefix))
+         (program-prefix (option-ref options 'program-prefix ""))
+         (program-suffix (option-ref options 'program-suffix ""))
          (infodir (option-ref options 'infodir "${prefix}/share/info"))
-         (mandir (option-ref options 'infodir "${prefix}/share/man"))
+         (mandir (option-ref options 'mandir "${prefix}/share/man"))
          (sysconfdir (option-ref options 'sysconfdir "${prefix}/etc"))
 
-         (bindir (option-ref options 'bindir "${prefix}/etc"))
+         (bindir (option-ref options 'bindir "${prefix}/bin"))
          (datadir (option-ref options 'datadir "${prefix}/share"))
          (docdir (option-ref options 'docdir "${datadir}/doc/mes-${VERSION}"))
+         (includedir (option-ref options 'libdir "${prefix}/include"))
          (libdir (option-ref options 'libdir "${prefix}/lib"))
-         (moduledir "${datadir}/mes/module")
+         (pkgdatadir (string-append datadir "/mes"))
          (guile-effective-version (effective-version))
          (guile-site-dir (if (equal? prefix ".") (canonicalize-path ".")
-                             (string-append "${prefix}/share/guile/site/" guile-effective-version)))
+                             (string-append prefix "/share/guile/site/" guile-effective-version)))
          (guile-site-ccache-dir (if (equal? prefix ".") (canonicalize-path ".")
-                                    (string-append "${prefix}/lib/guile/" guile-effective-version "/site-ccache")))
+                                    (string-append prefix "/lib/guile/" guile-effective-version "/site-ccache")))
 
          (srcdir (dirname (car (command-line))))
+         (srcdest (if (equal? srcdir ".") ""
+                      (string-append srcdir "/")))
          (abs-top-srcdir (canonicalize-path srcdir))
          (abs-top-builddir (canonicalize-path (getcwd)))
          (top-builddir (if (equal? srcdir ".") "."
                            abs-top-builddir))
-         (top-builddest (if (equal? srcdir ".") ""
-                        (string-append abs-top-builddir "/")))
-
 
+         (with-cheating? (option-ref options 'with-cheating #f))
          (with-courage? (option-ref options 'with-courage #f))
+         (disable-colors? (option-ref options 'disable-colors #f))
+         (enable-colors? (option-ref options 'enable-colors #f))
          (disable-silent-rules? (option-ref options 'disable-silent-rules #f))
+         (enable-silent-rules? (option-ref options 'enable-silent-rules #f))
+         (with-system-libc? (option-ref options 'with-system-libc #f))
          (vars (filter (cut string-index <> #\=) (option-ref options '() '())))
-         (help? (option-ref options 'help #f)))
-    (define (srcdir-relative file-name)
-      (if (equal? srcdir ".") file-name
-          (string-append srcdir "/" file-name)))
+         (help? (option-ref options 'help #f))
+         (mes? (option-ref options 'mes #f)))
     (when help?
       (print-help)
       (exit 0))
@@ -336,50 +418,98 @@ Some influential environment variables:
       (stderr "configure args=~s\n" args))
     (for-each (lambda (v) (apply setenv (string-split v #\=))) vars)
     (let* ((mes-seed (or (getenv "MES_SEED")
-                         (srcdir-relative "../mes-seed")))
-           (tinycc-seed (or (getenv "TINYCC_SEED")
-                            (srcdir-relative "../tinycc-seed")))
-           (mescc-tools-seed (or (getenv "MESCC_TOOLS_SEED")
-                                 (srcdir-relative "../mescc-tools-seed")))
+                         (string-append srcdest "../mes-seed")))
+           (mes-seed (and mes-seed
+                          (file-exists? (string-append mes-seed "/x86-mes/mes.S"))
+                          mes-seed))
+           (tinycc-prefix (or (getenv "TINYCC_PREFIX")
+                              (string-append srcdest "../tinycc-prefix")))
+           (gcc (or (getenv "CC") "gcc"))
+           (tcc (or (getenv "TCC") "tcc"))
+           (mescc (or (getenv "MESCC") "mescc"))
            (deps (fold (lambda (program results)
                          (cons (check-program-version program) results))
                        '()
-                       (list (make-dep "guile" '(2 0) #:commands '("guile-2.2" "guile-2.0" "guile-2" "guile"))
-                             (make-dep "guix" '(0 13) #:optional? #t)
-                             (make-dep "bash" '(2 0) #:optional? #t)
-                             (make-dep "guile-tools" '(2 0))
-                             (make-dep "mes-seed" '(0 16 1) #:optional? #t
-                                       #:commands (list (string-append mes-seed "/refresh.sh"))
-                                       #:file-name mes-seed)
-                             (make-dep "tinycc-seed" '(0 16) #:optional? #t
-                                       #:commands (list (string-append tinycc-seed "/refresh.sh"))
-                                       #:file-name tinycc-seed)
-                             (make-dep "cc" '(2 95) #:commands '("gcc"))
-                             (make-dep "make" '(4))
-                             (make-dep "cc32" '(2 95)
-                                       #:optional? #t
-                                       #:commands '("i686-unknown-linux-gnu-gcc"))
-                             (make-dep "M1" '(0 3))
-                             (make-dep "blood-elf" '(0 1))
-                             (make-dep "hex2" '(0 3))
-                             (make-dep "tcc" '(0 9 26) #:optional? #t #:version-option "-v")
-                             (make-dep "makeinfo" '(5) #:optional? #t)
-                             (make-dep "dot" '(2) #:version-option "-V")
-                             (make-dep "help2man" '(1 47) #:optional? #t)
-                             (make-dep "perl" '(5) #:optional? #t)
-                             (make-dep "git" '(2) #:optional? #t))))
-           (deps (cons (check-program-version (make-dep "nyacc" '(0 80 41) #:commands (list (string-append (file-name "guile" deps) " -c '(use-modules (nyacc lalr)) (display *nyacc-version*)'")) #:file-name #t))
-                       deps))
-           (deps (if (file-name "cc" deps)
-                     (cons* (check-header-c (make-dep "stdio.h"))
-                            (check-header-c (make-dep "limits.h"))
+                       (list (make-dep "hex2" #:version '(0 3))
+                             (make-dep "M1" #:version '(0 3))
+                             (make-dep "blood-elf" #:version '(0 1))
+                             (make-dep "diff" #:optional? #t)
+                             (make-dep "guile" #:version '(2 0) #:commands '("guile-2.2" "guile-2.0" "guile-2" "guile") #:optional? #t)
+                             (make-dep "mes" #:version '(0 18) #:optional? #t)
+                             (make-dep "guix" #:version '(0 13) #:optional? #t)
+                             (make-dep "ar" #:version '(2 10) #:optional? #t)
+                             (make-dep "sh" #:version '(0) #:optional? #t)
+                             (make-dep "bash" #:version '(2 0) #:optional? #t)
+                             (make-dep "guild" #:version '(2 0) #:commands '("guild" "guile-tools"))
+                             (make-dep "cc" #:commands (list gcc tcc mescc) #:optional? #t)
+                             (make-dep "make" #:optional? #t)
+                             (make-dep "makeinfo" #:optional? #t)
+                             (make-dep "dot" #:version-option "-V" #:optional? #t)
+                             (make-dep "help2man" #:version '(1 47) #:optional? #t)
+                             (make-dep "perl" #:version '(5) #:optional? #t)
+                             (make-dep "git" #:version '(2) #:optional? #t))))
+           (guile (file-name "guile" deps))
+           (deps (if guile (cons (check-program-version (make-dep "nyacc" #:version '(0 86 0) #:commands (list (string-append guile " -c '(use-modules (nyacc lalr)) (display *nyacc-version*)'")) #:file-name #t))
+                                 deps)
+                     deps))
+           (guile (or guile "guile"))
+           (cc (file-name "cc" deps))
+           (deps (if cc
+                     (cons* (check-header-c cc (make-dep "limits.h"))
+                            (check-header-c cc (make-dep "stdio.h" #:optional? #t))
                             deps)
                      deps))
-           (deps (cons (check-file (make-dep "mescc-tools-seed" '(0) #:optional? #t
-                                             #:file-name mescc-tools-seed))
+           (deps (cons (check-file (make-dep "tinycc-prefix" #:optional? #t
+                                             #:file-name tinycc-prefix))
                        deps))
            (missing (filter (conjoin (negate dependency-file-name)
-                                     (negate dependency-optional?)) deps)))
+                                     (negate dependency-optional?)) deps))
+           (deps (if cc
+                     (cons (check-compile-c cc (make-dep "cc is GNU C" #:data "#if !defined (__GNUC__)
+#error no gnuc
+#endif
+"))
+                           deps)
+                     deps))
+           (gcc? (file-name "cc is GNU C" deps))
+           (deps (if cc
+                     (cons (check-compile-c cc (make-dep "cc is Mes C" #:data "#if !defined (__MESC__)
+#error no mesc
+#endif
+"))
+                           deps)
+                     deps))
+           (mesc? (file-name "cc is Mes C" deps))
+           (deps (if cc
+                     (cons (check-compile-c cc (make-dep "cc is Tiny CC" #:data "#if !defined (__TINYCC__)
+#error no tinycc
+#endif
+"))
+                           deps)
+                     deps))
+           (tcc? (file-name "cc is Tiny CC" deps))
+           (deps (if cc
+                     (cons (check-link-c cc (make-dep "if cc can create executables" #:data "int main () {return 0;}"))
+                           deps)
+                     deps))
+           (system-libc? (and with-system-libc? (file-name "if cc can create executables" deps)))
+           (build-type (or (and cc (gulp-pipe* cc "-dumpmachine")) build-type))
+           (build-type-list (string-split build-type #\-))
+           (mes-cpu (car build-type-list))
+           (mes-cpu (cond ((member mes-cpu '("i386" "i486" "i586" "i686")) "x86")
+                          ((member mes-cpu '("arm" "armv4" "armv7l")) "arm")
+                          (else mes-cpu)))
+           (mes-bits (if (member mes-cpu '("x86_64")) "64"
+                         "32"))
+           (mes-libc (if system-libc? "system" "mes"))
+
+           (kernel-list (filter (compose not (cut equal? <> "unknown")) (cdr build-type-list)))
+           (mes-kernel (cond ((or (equal? '("linux" "gnu") kernel-list)
+                                  (equal? "linux" (car kernel-list))) "linux")
+                             ((equal? '( "gnu") kernel-list) "gnu")
+                             (else "unknown")))
+           (compiler (if gcc? "gcc" "mescc"))
+           (mes-system (string-join (list mes-cpu mes-kernel "mes") "-")))
 
       (define* (substitute file-name pairs
                            #:key (target (if (string-suffix? ".in" file-name)
@@ -387,13 +517,20 @@ Some influential environment variables:
         (system* "mkdir" "-p" (dirname target))
         (with-output-to-file target
           (lambda _
-            (display
-             (fold (lambda (o result)
-                     (regexp-substitute/global #f (car o) result 'pre (cdr o) 'post))
-                   (with-input-from-file file-name read-string) pairs)))))
-
-      (when (and (not (member arch '("i686" "x86_64"))) (not with-courage?))
-        (stderr "platform not supported: ~a, try --with-courage\n" arch)
+            (let ((in (open-input-file file-name)))
+              (let loop ((line (read-line in 'concat)))
+                (when (not (eof-object? line))
+                  (display (fold (lambda (o result)
+                                   (string-replace-string/all result (car o) (cdr o)))
+                                 line pairs))
+                  (loop (read-line in 'concat))))))))
+
+      (when (and (not (member mes-system '("arm-linux-mes"
+                                           "x86-linux-mes"
+                                           "x86_64-linux-mes")))
+                 (not with-courage?))
+        (stderr "platform not supported: ~a
+See \"Porting GNU Mes\" in the manual, or try --with-courage\n" mes-system)
         (exit 1))
       (when (pair? missing)
         (stderr "\nMissing dependencies: ~a\n" (string-join (map dependency-name missing)))
@@ -404,88 +541,137 @@ Some influential environment variables:
           ;; Debian wants to run `make clean' from a tarball
           (and (zero? (system* "git" "init"))
                (zero? (system* "git" "add" "."))
+               (zero? (system* "touch" ".git-for-build"))
                (zero? (system* "git" "commit" "--allow-empty" "-m" "Import mes")))))
-      (with-output-to-file ".config.make"
-        (lambda _
-          (stdout "PACKAGE:=~a\n" PACKAGE)
-          (stdout "VERSION:=~a\n" VERSION)
-
-          (stdout "ARCH:=~a\n" arch)
-          (stdout "build:=~a\n" build-type)
-          (stdout "host:=~a\n" host-type)
-
-          (stdout "top_builddest:=~a\n" top-builddest)
-          (stdout "top_builddir:=~a\n" top-builddir)
-          (stdout "abs_top_builddir:=~a\n" abs-top-builddir)
-          (stdout "abs_top_srcdir:=~a\n" abs-top-srcdir)
-
-          (stdout "srcdir:=~a\n" srcdir)
-
-          (stdout "prefix:=~a\n" (gulp-pipe (string-append "echo " prefix)))
-          (stdout "datadir:=~a\n" datadir)
-          (stdout "docdir:=~a\n" docdir)
-
-          (stdout "bindir:=~a\n" bindir)
-          (stdout "guile_site_ccache_dir:=~a\n" guile-site-ccache-dir)
-          (stdout "guile_site_dir:=~a\n" guile-site-dir)
-          (stdout "infodir:=~a\n" infodir)
-          (stdout "libdir:=~a\n" libdir)
-          (stdout "mandir:=~a\n" mandir)
-          (stdout "moduledir:=~a\n" moduledir)
-          (stdout "sysconfdir:=~a\n" sysconfdir)
-
-          (for-each (lambda (o)
-                      (stdout "~a:=~a\n" (variable-name o) (or (dependency-file-name o) "")))
-                    deps)
-          (stdout "GUILE_EFFECTIVE_VERSION:=~a\n" (effective-version))
-
-          (when disable-silent-rules?
-            (stdout "BUILD_DEBUG:=1\n"))
-
-          (for-each (lambda (o)
-                      (stdout "~a:=~a\n" o (or (getenv o) "")))
-                    '(
-                      "CFLAGS"
-                      "CC32_CFLAGS"
-                      "HEX2FLAGS"
-                      "M1FLAGS"
-                      "CC32_CFLAGS"
-                      "MES_CFLAGS"
-                      ))))
-
-      (let ((pairs `(("@srcdir@" . ,abs-top-srcdir)
+
+      (let ((pairs `(("@PACKAGE@" . ,PACKAGE)
+                     ("@PACKAGE_NAME@" . ,PACKAGE-NAME)
+                     ("@PACKAGE_BUGREPORT@" . ,PACKAGE-BUGREPORT)
+                     ("@VERSION@" . ,VERSION)
+
+                     ("@build@" . ,build-type)
+                     ("@host@" . ,host-type)
+
+                     ("@courageous@" . ,(if with-courage? "true" "false"))
+                     ("@compiler@" . ,compiler)
+                     ("@mes_bits@" . ,mes-bits)
+                     ("@mes_kernel@" . ,mes-kernel)
+                     ("@mes_cpu@" . ,mes-cpu)
+                     ("@mes_libc@" . ,mes-libc)
+                     ("@mes_system@" . ,mes-system)
+
                      ("@abs_top_srcdir@" . ,abs-top-srcdir)
                      ("@abs_top_builddir@" . ,abs-top-builddir)
                      ("@top_builddir@" . ,top-builddir)
-                     ("@top_builddest@" . ,top-builddest)
-                     ("@BASH@" . ,(file-name "bash" deps))
-                     ("@GUILE@" . ,(file-name "guile" deps))
-                     ("@guile_site_dir@" . ,guile-site-dir)
+
+                     ("@srcdest@" . ,srcdest)
+                     ("@srcdir@" . ,srcdir)
+
+                     ("@prefix@" . ,prefix)
+                     ("@program_prefix@" . ,program-prefix)
+                     ("@bindir@" . ,bindir)
+                     ("@datadir@" . ,datadir)
+                     ("@pkgdatadir@" . ,pkgdatadir)
+                     ("@docdir@" . ,docdir)
                      ("@guile_site_ccache_dir@" . ,guile-site-ccache-dir)
-                     ("@VERSION@" . ,VERSION)
-                     ("mes/module/" . ,(string-append moduledir "/")))))
+                     ("@guile_site_dir@" . ,guile-site-dir)
+                     ("@infodir@" . ,infodir)
+                     ("@includedir@" . ,includedir)
+                     ("@libdir@" . ,libdir)
+                     ("@mandir@" . ,mandir)
+                     ("@sysconfdir@" . ,sysconfdir)
+
+                     ("@GUILE_EFFECTIVE_VERSION@" . ,(effective-version))
+                     ("@colors@" . ,(if disable-colors? "no" "yes"))
+                     ("@V@" . ,(if disable-silent-rules? "1" "0"))
+
+                     ("@AR@" . ,(or (file-name "ar" deps) ""))
+                     ("@BASH@" . ,(or (file-name "bash" deps) ""))
+                     ("@CC@" . ,(or (file-name "cc" deps) ""))
+                     ("@DIFF@" . ,(or (file-name "diff" deps) (string-append abs-top-builddir "/pre-inst-env diff.scm")))
+                     ("@DOT@" . ,(or (file-name "dot" deps) ""))
+                     ("@GIT@" . ,(or (file-name "git" deps) ""))
+                     ("@GUILE@" . ,guile)
+                     ("@GUIX@" . ,(or (file-name "guix" deps) ""))
+                     ("@HELP2MAN@" . ,(or (file-name "help2man" deps) ""))
+                     ("@MAKEINFO@" . ,(or (file-name "makeinfo" deps) ""))
+                     ("@MES_FOR_BUILD@" . ,(or (file-name "mes" deps)
+                                               guile))
+                     ("@MES_SEED@" . ,(or mes-seed ""))
+                     ("@PERL@" . ,(or (file-name "perl" deps) ""))
+                     ("#SCHEME=\"@SCHEME@\"" . ,(if with-cheating? (string-append "\nSCHEME=\"" guile "\"") ""))
+                     ("@SCHEME@" . ,(if with-cheating? guile ""))
+                     ("@SHELL@" . ,(or (file-name "bash" deps)
+                                       (file-name "sh" deps)
+                                       "sh"))
+
+                     ("@CFLAGS@" . ,(or (getenv "CFLAGS") ""))
+                     ("@HEX2FLAGS@" . ,(or (getenv "HEX2FLAGS") ""))
+                     ("@M1FLAGS@" . ,(or (getenv "M1FLAGS") ""))
+
+                     ,@(map
+                        (lambda (o)
+                          (cons (string-append "@" (variable-name o) "@") (or (format #f "~a" (dependency-file-name o)) "")))
+                        deps))))
+
+        (when (and (not cc)
+                   (not mes-seed))
+          (format (current-error-port) "must supply C compiler or MES_SEED/x86-mes/mes.S\n")
+          (exit 2))
         (for-each (lambda (o)
-                    (let* ((src (srcdir-relative o))
+                    (let* ((src (string-append srcdest o))
                            (target (string-drop-right o 3))
                            (target (if (not (string-prefix? "build-aux/" target)) target
                                        (string-drop target (string-length "build-aux/")))))
                       (substitute src pairs #:target target)))
                   '(
+                    "build-aux/GNUmakefile.in"
+                    "build-aux/config.sh.in"
+                    "build-aux/build.sh.in"
+                    "build-aux/check.sh.in"
+                    "build-aux/install.sh.in"
                     "build-aux/pre-inst-env.in"
-                    "mes/module/mes/boot-0.scm.in"
+                    "build-aux/uninstall.sh.in"
+                    "scripts/mesar.in"
+                    "scripts/mescc.scm.in"
                     "scripts/mescc.in"
                     ))
-        (when (not (equal? srcdir "."))
-          (substitute (string-append srcdir "/build-aux/GNUmakefile.in")
-                      pairs
-                      #:target "GNUmakefile")
-          (system (string-append "cd mes/module/mes && ln -sf " abs-top-srcdir "/mes/module/mes/*.mes ."))))
-      (chmod "pre-inst-env" #o755)
-      (chmod "scripts/mescc" #o755)
+        (chmod "pre-inst-env" #o755)
+        (chmod "scripts/mesar" #o755)
+        (chmod "scripts/mescc" #o755)
+        (chmod "scripts/mescc.scm" #o755)
+        (chmod "build.sh" #o755)
+        (chmod "check.sh" #o755)
+        (chmod "install.sh" #o755)
+        (chmod "uninstall.sh" #o755)
+
+        (system* "mkdir" "-p" "include/mes")
+        (let ((pkgdatadir (gulp-pipe* "sh" "-c" (string-append "prefix=" prefix
+                                                               ";datadir=" datadir
+                                                               ";echo ${datadir}/mes"))))
+          (with-output-to-file "include/mes/config.h"
+            (lambda _
+              (if system-libc?
+                  (display "#define SYSTEM_LIBC 1
+")
+                  (display "#undef SYSTEM_LIBC
+"))
+              (display (string-append "
+#define MES_VERSION \"" VERSION "\"
+#define MES_PKGDATADIR \"" pkgdatadir "\"
+")))))
+        (substitute (string-append srcdest "build-aux/config.make.in") pairs #:target ".config.make"))
+
       (let ((make (and=> (file-name "make" deps) basename)))
-        (format (current-output-port)
-                "\nRun:
-  ~a            to build mes
-  ~a help       for help on other targets\n"
-                (or make "./build.sh")
-                (or make "./build.sh"))))))
+        (display (string-append "
+GNU Mes is configured for
+   compiler: " compiler "
+   cpu:      " mes-cpu "
+   bits:     " mes-bits "
+   libc:     " mes-libc "
+   kernel:   " mes-kernel "
+   system:   " mes-system "
+
+Run:
+  " (or make "./build.sh") "           to build mes
+  " (or make "./build.sh") " help      for help on other targets\n"))))))