mes/configure
Jan Nieuwenhuizen 5d3fa50384
build: Prepare for autoconfiscation.
Make build system more in alignment with how autotools work.  This
will make transition easier.

* mes/module/mes/boot-0.scm.in: Update from module/mes/boot-0.scm.
* scripts/mescc.in: Update from scripts/mescc.
* build-aux/pre-inst-env.in: New file.
* build-aux/cc-mes.sh: Use pre-inst-env.
* configure: Substitute new .in files.
* install.sh: Do not substitute mescc, boot-0.scm.
2018-07-21 18:28:47 +02:00

435 lines
17 KiB
Scheme
Executable file

#! /bin/sh
# -*- scheme -*-
unset LANG LC_ALL
echo -n "checking for guile..."
GUILE=$(command -v ${GUILE-guile})
GUIX=$(command -v ${GUIX-guix})
export GUILE GUIX
if [ -x "$GUILE" ]; then
echo " $GUILE"
elif [ -x "$GUIX" ]; then
cat <<EOF
not found
Missing dependencies, run
guix environment -l guix.scm
EOF
exit 1
else
cat <<EOF
not found
Missing dependencies, run
sudo apt-get install guile-2.2-dev
EOF
exit 1
fi
exec ${GUILE-guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
!#
;;; Mes --- Maxwell Equations of Software
;;; Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
;;;
;;; configure: This file is part of Mes.
;;;
;;; Mes is free software; you can redistribute it and/or modify it
;;; under the terms of the GNU General Public License as published by
;;; the Free Software Foundation; either version 3 of the License, or (at
;;; your option) any later version.
;;;
;;; Mes is distributed in the hope that it will be useful, but
;;; WITHOUT ANY WARRANTY; without even the implied warranty of
;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;;; GNU General Public License for more details.
;;;
;;; You should have received a copy of the GNU General Public License
;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
(define-module (configure)
#:use-module (srfi srfi-1)
#: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* (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")
(define GUILE (PATH-search-path (or (getenv "guile") "guile")))
(define GUILE_EFFECTIVE_VERSION (effective-version))
(define prefix "/usr/local")
(define infodir "${prefix}/share/info")
(define mandir "${prefix}/share/man")
(define sysconfdir "${prefix}/etc")
;;; Utility
(define (logf port string . rest)
(apply format (cons* port string rest))
(force-output port)
#t)
(define (stderr string . rest)
(apply logf (cons* (current-error-port) string rest)))
(define (stdout string . rest)
(apply logf (cons* (current-output-port) string rest)))
(define *verbose?* #f)
(define (verbose string . rest)
(if *verbose?* (apply stderr (cons string rest))))
(define (gulp-pipe command)
(let* ((port (open-pipe* OPEN_READ *shell* "-c" 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)))
(_ ""))))
(define (tuple< a b)
(cond
((and (null? a) (null? b)) #t)
((null? a) (not (null? b)))
((null? b) #f)
((and (not (< (car a) (car b)))
(not (< (car b) (car a))))
(tuple< (cdr a) (cdr b)))
(else (< (car a) (car b)))))
(define (tuple<= a b)
(or (equal? a b) (tuple< a b)))
;;; Configure
(define (version->string version)
((->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)))
(define optional '())
(define required '())
(define* (check-version name expected
#:key
optional?
(deb #f)
(version-option '--version)
(compare tuple<=)
(command name))
(stderr "checking for ~a~a..." (basename name)
(if (null? expected) ""
(format #f " [~a]" (version->string expected))))
(let* ((output (gulp-pipe (format #f "~a ~a 2>&1" command version-option)))
(actual (string->version output))
(pass? (and actual (compare expected actual)))
;(pass? (PATH-search-path command))
)
(stderr "~a ~a\n" (if pass? (if (pair? actual) "" " yes")
(if actual " no, found" "")) (version->string actual))
(or pass?
(if (not (pair? name)) (begin (if optional? (set! optional (cons (or deb name) optional))
(set! required (cons (or deb name) required)))
pass?)
(check-version (cdr name) expected deb version-option compare)))))
(define* (check-pkg-config package expected #:optional (deb #f))
(check-version (format #f "pkg-config --modversion ~a" package) expected deb))
(define (check-compile-header-c header)
(and (= 0 (system (format #f "echo '#include ~s' | gcc -E - > /dev/null 2>&1" header)))
'yes))
(define (check-compile-header-c++ header)
(and (= 0 (system (format #f "echo '#include ~s' | gcc --language=c++ --std=c++11 -E - > /dev/null 2>&1" header)))
'yes))
(define* (check-header-c header deb #:optional (check check-compile-header-c))
(stderr "checking for ~a..." header)
(let ((result (check header)))
(stderr " ~a\n" (if result result "no"))
(if (not result)
(set! required (cons deb required)))))
(define* (check-header-c++ header deb #:optional (check check-compile-header-c++))
(check-header-c header deb check))
(define guix?
(and (zero? (system "guix --version 1>/dev/null 2>/dev/null")) 1))
;;;
(define (parse-opts args)
(let* ((option-spec
'((build (value #t))
(host (value #t))
(help (single-char #\h))
(prefix (value #t))
(sysconfdir (value #t))
(verbose (single-char #\v))
(with-courage)
(infodir (value #t))
(mandir (value #t))
(disable-silent-rules)
(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
(disable-dependency-tracking) ; Ignored for Debian
)))
(getopt-long args option-spec)))
(define* (print-help #:optional (port (current-output-port)))
(format port "\
`configure' configures ~a ~a to adapt to many kinds of systems.
Usage: ./configure [OPTION]... [VAR=VALUE]
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.
Options:
-h, --help display this help
--build=BUILD configure for building on BUILD [guessed]
--disable-silent-rules
verbose build output [BUILD_DEBUG=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
Installation directories:
--prefix=DIR install in prefix DIR [~a]
--infodir=DIR info documentation [PREFIX/share/info]
--mandir=DIR man pages [PREFIX/share/man]
Ignored for Guix:
--enable-fast-install
Ignored for Debian:
--disable-dependency-tracking
--disable-maintainer-mode
--includedir=DIR
--libdir=DIR
--libexecdir=DIR
--localstatedir=DIR
--mandir=DIR
--runstatedir=DIR
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
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* (substitute file-name pairs
#:key (target (if (string-suffix? ".in" file-name)
(string-drop-right file-name 3) 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)))))
(define (main args)
(let* ((CC (or (getenv "CC") "gcc"))
(srcdir (dirname (car (command-line))))
(abs-top-srcdir (canonicalize-path srcdir))
(builddir (getcwd))
(abs-top-builddir (canonicalize-path builddir))
(BUILD_TRIPLET %host-type)
(ARCH (car (string-split BUILD_TRIPLET #\-)))
(options (parse-opts args))
(build-triplet (option-ref options 'build BUILD_TRIPLET))
(host-triplet (option-ref options 'host BUILD_TRIPLET))
(prefix (option-ref options 'prefix prefix))
(infodir (option-ref options 'infodir infodir))
(sysconfdir (option-ref options 'sysconfdir sysconfdir))
(datadir (string-append prefix "/share/mes"))
(moduledir (string-append datadir"module"))
(guile-effective-version (effective-version))
(guile-site-dir (if (equal? prefix ".") (canonicalize-path ".")
(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")))
(verbose? (option-ref options 'verbose #f))
(with-courage? (option-ref options 'with-courage #f))
(disable-silent-rules? (option-ref options 'disable-silent-rules #f))
(make? #f)
(vars (filter (cut string-index <> #\=) (option-ref options '() '())))
(help? (option-ref options 'help #f)))
(for-each (lambda (v) (apply setenv (string-split v #\=))) vars)
(let ((CC32 (or (getenv "CC32")
(if (member ARCH '("i686" "arm")) (string-append BUILD_TRIPLET "-" CC)
"i686-unknown-linux-gnu-gcc")))
(BASH (or (getenv "BASH") "bash"))
(HELP2MAN (or (getenv "HELP2MAN") "help2man"))
(TCC (or (getenv "TCC") "tcc"))
(MAKEINFO (or (getenv "MAKEINFO") "makeinfo"))
(GUILE_TOOLS (or (getenv "GUILE_TOOLS") "guile-tools"))
(BLOOD_ELF (or (getenv "BLOOD_ELF") "blood-elf"))
(HEX2 (or (getenv "HEX2") "hex2"))
(M1 (or (getenv "M1") "M1"))
(CFLAGS (getenv "CFLAGS"))
(CC32_CFLAGS (getenv "CC32_CFLAGS"))
(HEX2FLAGS (getenv "HEX2FLAGS"))
(M1FLAGS (getenv "M1FLAGS"))
(MES_CFLAGS (getenv "MES_CFLAGS"))
(MES_SEED (or (getenv "MES_SEED") "../mes-seed"))
(MESCC_TOOLS_SEED (or (getenv "MESCC_TOOLS_SEED") "../mescc-tools-seed"))
(TINYCC_SEED (or (getenv "TINYCC_SEED") "../tinycc-seed")))
(when help?
(print-help)
(exit 0))
(set! *verbose?* verbose?)
(check-version "guile" '(2 0))
(check-version "guile-tools" '(2 0))
(check-version "mes-seed" '(0 16 1) #:optional? #t #:command (string-append MES_SEED "/refresh.sh"))
(check-version "tinycc-seed" '(0 16) #:optional? #t #:command (string-append TINYCC_SEED "/refresh.sh"))
(check-version BLOOD_ELF '(0 1))
(check-version HEX2 '(0 3))
(check-version M1 '(0 3))
(check-version "nyacc" '(0 80 41) #:command (string-append GUILE " -c '(use-modules (nyacc lalr)) (display *nyacc-version*)'"))
(check-version "bash" '(4 0))
(when (and (check-version "git" '(2 0) #:optional? #t)
(not (file-exists? ".git")))
;; Debian wants to run `make clean' from a tarball
(and (zero? (system* "git" "init"))
(zero? (system* "git" "add" "."))
(zero? (system* "git" "commit" "-m" "Import mes"))))
(when (and (not (member ARCH '("i686" "x86_64"))) (not with-courage?))
(stderr "platform not supported: ~a, try --with-courage\n" ARCH)
(exit 1))
(if (check-version "bash" '(2))
(set! BASH (PATH-search-path BASH))
(set! BASH #f))
(if (not (check-version CC '(4 8) #:optional? #t))
(set! CC #f))
(when CC
(check-header-c "stdio.h" "libc-dev")
(check-header-c "limits.h" "linux-headers"))
(if (not (check-version CC32 '(4 8) #:optional? #t))
(set! CC32 #f))
(if (not (check-version TCC '(0 9 26) #:optional? #t #:version-option "-v"))
(set! TCC #f))
(set! make? (check-version "make" '(4 0) #:optional? #t))
(check-version "perl" '(5))
(if (not (check-version "makeinfo" '(6) #:optional? #t))
(set! MAKEINFO #f))
(if (not (check-version "help2man" '(1 47) #:optional? #t))
(set! HELP2MAN #f))
(when (pair? required)
(stderr "\nMissing dependencies [~a], run\n\n" ((->string ", ") required))
(if guix?
(stderr " guix environment -l guix.scm\n")
(stderr " sudo apt-get install ~a\n" ((->string " ") required)))
(exit 1))
(with-output-to-file ".config.make"
(lambda ()
(stdout "build:=~a\n" build-triplet)
(stdout "host:=~a\n" host-triplet)
(stdout "srcdir:=.\n")
(stdout "prefix:=~a\n" (gulp-pipe (string-append "echo " prefix)))
(stdout "infodir:=~a\n" infodir)
(stdout "mandir:=~a\n" mandir)
(stdout "datadir:=~a\n" datadir)
(stdout "moduledir:=~a\n" moduledir)
(stdout "sysconfdir:=~a\n" sysconfdir)
(stdout "ARCH:=~a\n" ARCH)
(stdout "CC:=~a\n" (or CC ""))
(stdout "CC32:=~a\n" (or CC32 ""))
(stdout "HELP2MAN:=~a\n" (or HELP2MAN ""))
(stdout "MAKEINFO:=~a\n" (or MAKEINFO ""))
(stdout "TCC:=~a\n" (or TCC ""))
(stdout "BLOOD_ELF:=~a\n" (or BLOOD_ELF ""))
(stdout "MES_SEED:=~a\n" (or MES_SEED ""))
(stdout "MESCC_TOOLS_SEED:=~a\n" (or MESCC_TOOLS_SEED ""))
(stdout "TINYCC_SEED:=~a\n" (or TINYCC_SEED ""))
(stdout "HEX2:=~a\n" (or HEX2 ""))
(stdout "M1:=~a\n" (or M1 ""))
(stdout "GUILE:=~a\n" GUILE)
(stdout "GUILE_TOOLS:=~a\n" GUILE_TOOLS)
(stdout "GUILE_FOR_BUILD:=~a\n" GUILE)
(stdout "GUILE_EFFECTIVE_VERSION:=~a\n" GUILE_EFFECTIVE_VERSION)
(stdout "GUIX_P:=~a\n" (if guix? guix? ""))
(stdout "HEX2:=~a\n" (or HEX2 ""))
(stdout "PACKAGE:=~a\n" PACKAGE)
(stdout "VERSION:=~a\n" VERSION)
(when disable-silent-rules?
(stdout "BUILD_DEBUG:=1\n"))
(when CFLAGS (stdout "CFLAGS:=~a\n" CFLAGS))
(when CC32_CFLAGS (stdout "CC32_CFLAGS:=~a\n" CC32_CFLAGS))
(when HEX2FLAGS (stdout "HEX2FLAGS:=~a\n" HEX2FLAGS))
(when M1FLAGS (stdout "M1FLAGS:=~a\n" M1FLAGS))
(when MES_CFLAGS (stdout "MES_CFLAGS:=~a\n" MES_CFLAGS))))
(let ((pairs `(("@abs_top_srcdir@" . ,abs-top-srcdir)
("@abs_top_builddir@" . ,abs-top-builddir)
("@BASH@" . ,BASH)
("@GUILE@" . ,GUILE)
("@guile_site_dir@" . ,guile-site-dir)
("@guile_site_ccache_dir@" . ,guile-site-ccache-dir)
("@VERSION@" . ,VERSION)
("mes/module/" . ,(string-append moduledir "/")))))
(for-each (lambda (o)
(substitute o pairs)
(chmod (string-drop-right o 3) #o755))
'(
"build-aux/pre-inst-env.in"
"mes/module/mes/boot-0.scm.in"
"scripts/mescc.in"
)))
(chmod "build-aux/pre-inst-env" #o755)
(rename-file "build-aux/pre-inst-env" "pre-inst-env")
(chmod "scripts/mescc" #o755)
(format (current-output-port)
"\nRun:
~a to build mes
~a help for help on other targets\n"
(if make? "make" "./build.sh")
(if make? "make" "./build.sh")))))