4 echo -n "checking for guile..."
5 GUILE=$(command -v ${GUILE-guile})
6 GUIX=$(command -v ${GUIX-guix})
8 if [ -x "$GUILE" ]; then
10 elif [ -x "$GUIX" ]; then
13 Missing dependencies, run
15 guix environment -l guix.scm
21 Missing dependencies, run
23 sudo apt-get install guile-2.2-dev
27 exec ${GUILE-guile} -L . --no-auto-compile -e '(configure)' -s "$0" ${1+"$@"}
30 ;;; Mes --- Maxwell Equations of Software
31 ;;; Copyright © 2016,2017,2018 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
33 ;;; configure: This file is part of Mes.
35 ;;; Mes is free software; you can redistribute it and/or modify it
36 ;;; under the terms of the GNU General Public License as published by
37 ;;; the Free Software Foundation; either version 3 of the License, or (at
38 ;;; your option) any later version.
40 ;;; Mes is distributed in the hope that it will be useful, but
41 ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
42 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
43 ;;; GNU General Public License for more details.
45 ;;; You should have received a copy of the GNU General Public License
46 ;;; along with Mes. If not, see <http://www.gnu.org/licenses/>.
48 (define-module (configure)
49 #:use-module (srfi srfi-1)
50 #:use-module (srfi srfi-26)
51 #:use-module (ice-9 and-let-star)
52 #:use-module (ice-9 curried-definitions)
53 #:use-module (ice-9 getopt-long)
54 #:use-module (ice-9 match)
55 #:use-module (ice-9 optargs)
56 #:use-module (ice-9 popen)
57 #:use-module (ice-9 rdelim)
58 #:use-module (ice-9 regex)
61 (define* (PATH-search-path name #:key (default name) warn?)
62 (or (search-path (string-split (getenv "PATH") #\:) name)
63 (and (and warn? (format (current-error-port) "warning: not found: ~a\n" name))
67 (define PACKAGE "mes")
68 (define VERSION "0.16.1")
69 (define GUILE (PATH-search-path (or (getenv "guile") "guile")))
70 (define GUILE_EFFECTIVE_VERSION (effective-version))
72 (define prefix "/usr/local")
73 (define infodir "${prefix}/share/info")
74 (define mandir "${prefix}/share/man")
75 (define sysconfdir "${prefix}/etc")
78 (define (logf port string . rest)
79 (apply format (cons* port string rest))
83 (define (stderr string . rest)
84 (apply logf (cons* (current-error-port) string rest)))
86 (define (stdout string . rest)
87 (apply logf (cons* (current-output-port) string rest)))
89 (define *verbose?* #f)
91 (define (verbose string . rest)
92 (if *verbose?* (apply stderr (cons string rest))))
94 (define (gulp-pipe command)
95 (let* ((port (open-pipe* OPEN_READ *shell* "-c" command))
96 (output (read-string port))
97 (status (close-pipe port)))
98 (verbose "command[~a]: ~s => ~a\n" status command output)
99 (if (not (zero? status)) "" (string-trim-right output #\newline))))
101 (define* ((->string #:optional (infix "")) h . t)
102 (let ((o (if (pair? t) (cons h t) h)))
104 ((? char?) (make-string 1 o))
105 ((? number?) (number->string o))
107 ((? symbol?) (symbol->string o))
108 ((h ... t) (string-join (map (->string) o) ((->string) infix)))
113 ((and (null? a) (null? b)) #t)
114 ((null? a) (not (null? b)))
116 ((and (not (< (car a) (car b)))
117 (not (< (car b) (car a))))
118 (tuple< (cdr a) (cdr b)))
119 (else (< (car a) (car b)))))
121 (define (tuple<= a b)
122 (or (equal? a b) (tuple< a b)))
125 (define (version->string version)
126 ((->string '.) version))
128 (define (string->version string)
129 (and-let* ((version (string-tokenize string
130 (char-set-adjoin char-set:digit #\.)))
132 (version (sort version (lambda (a b) (> (string-length a) (string-length b)))))
133 (version (car version))
134 (version (string-tokenize version
135 (char-set-complement (char-set #\.)))))
136 (map string->number version)))
138 (define optional '())
139 (define required '())
140 (define* (check-version name expected
144 (version-option '--version)
147 (stderr "checking for ~a~a..." (basename name)
148 (if (null? expected) ""
149 (format #f " [~a]" (version->string expected))))
150 (let* ((output (gulp-pipe (format #f "~a ~a 2>&1" command version-option)))
151 (actual (string->version output))
152 (pass? (and actual (compare expected actual)))
153 ;(pass? (PATH-search-path command))
155 (stderr "~a ~a\n" (if pass? (if (pair? actual) "" " yes")
156 (if actual " no, found" "")) (version->string actual))
158 (if (not (pair? name)) (begin (if optional? (set! optional (cons (or deb name) optional))
159 (set! required (cons (or deb name) required)))
161 (check-version (cdr name) expected deb version-option compare)))))
163 (define* (check-pkg-config package expected #:optional (deb #f))
164 (check-version (format #f "pkg-config --modversion ~a" package) expected deb))
166 (define (check-compile-header-c header)
167 (and (= 0 (system (format #f "echo '#include ~s' | gcc -E - > /dev/null 2>&1" header)))
170 (define (check-compile-header-c++ header)
171 (and (= 0 (system (format #f "echo '#include ~s' | gcc --language=c++ --std=c++11 -E - > /dev/null 2>&1" header)))
174 (define* (check-header-c header deb #:optional (check check-compile-header-c))
175 (stderr "checking for ~a..." header)
176 (let ((result (check header)))
177 (stderr " ~a\n" (if result result "no"))
179 (set! required (cons deb required)))))
181 (define* (check-header-c++ header deb #:optional (check check-compile-header-c++))
182 (check-header-c header deb check))
185 (and (zero? (system "guix --version 1>/dev/null 2>/dev/null")) 1))
188 (define (parse-opts args)
192 (help (single-char #\h))
194 (sysconfdir (value #t))
195 (verbose (single-char #\v))
199 (disable-silent-rules)
201 (enable-fast-install) ; Ignored for Guix
202 (includedir (value #t)) ; Ignored for Debian
203 (mandir (value #t)) ; Ignored for Debian
204 (localstatedir (value #t)) ; Ignored for Debian
205 (libdir (value #t)) ; Ignored for Debian
206 (libexecdir (value #t)) ; Ignored for Debian
207 (runstatedir (value #t)) ; Ignored for Debian
208 (disable-maintainer-mode) ; Ignored for Debian
209 (disable-dependency-tracking) ; Ignored for Debian
212 (getopt-long args option-spec)))
214 (define* (print-help #:optional (port (current-output-port)))
216 `configure' configures ~a ~a to adapt to many kinds of systems.
218 Usage: ./configure [OPTION]... [VAR=VALUE]
220 To assign environment variables (e.g., CC, CFLAGS...), specify them as
221 VAR=VALUE. See below for descriptions of some of the useful variables.
223 Defaults for the options are specified in brackets.
226 -h, --help display this help
227 --build=BUILD configure for building on BUILD [guessed]
228 --disable-silent-rules
229 verbose build output [BUILD_DEBUG=1]
230 --host=HOST cross-compile to build programs to run on HOST [BUILD]
231 -v, --verbose be verbose
232 --with-courage assert being courageous to configure for unsupported platform
234 Installation directories:
235 --prefix=DIR install in prefix DIR [~a]
236 --infodir=DIR info documentation [PREFIX/share/info]
237 --mandir=DIR man pages [PREFIX/share/man]
240 --enable-fast-install
243 --disable-dependency-tracking
244 --disable-maintainer-mode
252 Some influential environment variables:
253 CC C compiler command
254 CFLAGS C compiler flags
255 CC32 x86 C compiler command
256 CC32_CFLAGS x86 C compiler flags
258 GUILE_TOOLS guile-tools command
259 MES_CFLAGS MesCC flags
260 MES_SEED location of mes-seed
261 MESCC_TOOLS_SEED location of mescc-tools-seed
262 TCC tcc C compiler command
263 TINYCC_SEED location of tinycc-seed
264 " PACKAGE VERSION (getenv "prefix")))
266 (define* (substitute file-name pairs
267 #:key (target (if (string-suffix? ".in" file-name)
268 (string-drop-right file-name 3) target)))
269 (with-output-to-file target
272 (fold (lambda (o result)
273 (regexp-substitute/global #f (car o) result 'pre (cdr o) 'post))
274 (with-input-from-file file-name read-string) pairs)))))
277 (let* ((CC (or (getenv "CC") "gcc"))
278 (srcdir (dirname (car (command-line))))
279 (abs-top-srcdir (canonicalize-path srcdir))
281 (abs-top-builddir (canonicalize-path builddir))
282 (BUILD_TRIPLET %host-type)
283 (ARCH (car (string-split BUILD_TRIPLET #\-)))
284 (options (parse-opts args))
285 (build-triplet (option-ref options 'build BUILD_TRIPLET))
286 (host-triplet (option-ref options 'host BUILD_TRIPLET))
287 (prefix (option-ref options 'prefix prefix))
288 (infodir (option-ref options 'infodir infodir))
289 (sysconfdir (option-ref options 'sysconfdir sysconfdir))
290 (datadir (string-append prefix "/share/mes"))
291 (moduledir (string-append datadir"module"))
292 (guile-effective-version (effective-version))
293 (guile-site-dir (if (equal? prefix ".") (canonicalize-path ".")
294 (string-append prefix "/share/guile/site/" guile-effective-version)))
295 (guile-site-ccache-dir (if (equal? prefix ".") (canonicalize-path ".")
296 (string-append prefix "/lib/guile/" guile-effective-version "/site-ccache")))
297 (verbose? (option-ref options 'verbose #f))
298 (with-courage? (option-ref options 'with-courage #f))
299 (disable-silent-rules? (option-ref options 'disable-silent-rules #f))
301 (vars (filter (cut string-index <> #\=) (option-ref options '() '())))
302 (help? (option-ref options 'help #f)))
303 (for-each (lambda (v) (apply setenv (string-split v #\=))) vars)
304 (let ((CC32 (or (getenv "CC32")
305 (if (member ARCH '("i686" "arm")) (string-append BUILD_TRIPLET "-" CC)
306 "i686-unknown-linux-gnu-gcc")))
307 (BASH (or (getenv "BASH") "bash"))
308 (HELP2MAN (or (getenv "HELP2MAN") "help2man"))
309 (TCC (or (getenv "TCC") "tcc"))
310 (MAKEINFO (or (getenv "MAKEINFO") "makeinfo"))
311 (GUILE_TOOLS (or (getenv "GUILE_TOOLS") "guile-tools"))
312 (BLOOD_ELF (or (getenv "BLOOD_ELF") "blood-elf"))
313 (HEX2 (or (getenv "HEX2") "hex2"))
314 (M1 (or (getenv "M1") "M1"))
315 (CFLAGS (getenv "CFLAGS"))
316 (CC32_CFLAGS (getenv "CC32_CFLAGS"))
317 (HEX2FLAGS (getenv "HEX2FLAGS"))
318 (M1FLAGS (getenv "M1FLAGS"))
319 (MES_CFLAGS (getenv "MES_CFLAGS"))
320 (MES_SEED (or (getenv "MES_SEED") "../mes-seed"))
321 (MESCC_TOOLS_SEED (or (getenv "MESCC_TOOLS_SEED") "../mescc-tools-seed"))
322 (TINYCC_SEED (or (getenv "TINYCC_SEED") "../tinycc-seed")))
326 (set! *verbose?* verbose?)
327 (check-version "guile" '(2 0))
328 (check-version "guile-tools" '(2 0))
329 (check-version "mes-seed" '(0 16 1) #:optional? #t #:command (string-append MES_SEED "/refresh.sh"))
330 (check-version "tinycc-seed" '(0 16) #:optional? #t #:command (string-append TINYCC_SEED "/refresh.sh"))
331 (check-version BLOOD_ELF '(0 1))
332 (check-version HEX2 '(0 3))
333 (check-version M1 '(0 3))
334 (check-version "nyacc" '(0 80 41) #:command (string-append GUILE " -c '(use-modules (nyacc lalr)) (display *nyacc-version*)'"))
336 (check-version "bash" '(4 0))
337 (when (and (check-version "git" '(2 0) #:optional? #t)
338 (not (file-exists? ".git")))
339 ;; Debian wants to run `make clean' from a tarball
340 (and (zero? (system* "git" "init"))
341 (zero? (system* "git" "add" "."))
342 (zero? (system* "git" "commit" "-m" "Import mes"))))
343 (when (and (not (member ARCH '("i686" "x86_64"))) (not with-courage?))
344 (stderr "platform not supported: ~a, try --with-courage\n" ARCH)
346 (if (check-version "bash" '(2))
347 (set! BASH (PATH-search-path BASH))
349 (if (not (check-version CC '(4 8) #:optional? #t))
352 (check-header-c "stdio.h" "libc-dev")
353 (check-header-c "limits.h" "linux-headers"))
354 (if (not (check-version CC32 '(4 8) #:optional? #t))
356 (if (not (check-version TCC '(0 9 26) #:optional? #t #:version-option "-v"))
358 (set! make? (check-version "make" '(4 0) #:optional? #t))
359 (check-version "perl" '(5))
360 (if (not (check-version "makeinfo" '(6) #:optional? #t))
362 (if (not (check-version "help2man" '(1 47) #:optional? #t))
365 (when (pair? required)
366 (stderr "\nMissing dependencies [~a], run\n\n" ((->string ", ") required))
368 (stderr " guix environment -l guix.scm\n")
369 (stderr " sudo apt-get install ~a\n" ((->string " ") required)))
371 (with-output-to-file ".config.make"
373 (stdout "build:=~a\n" build-triplet)
374 (stdout "host:=~a\n" host-triplet)
375 (stdout "srcdir:=.\n")
376 (stdout "prefix:=~a\n" (gulp-pipe (string-append "echo " prefix)))
377 (stdout "infodir:=~a\n" infodir)
378 (stdout "mandir:=~a\n" mandir)
379 (stdout "datadir:=~a\n" datadir)
380 (stdout "moduledir:=~a\n" moduledir)
381 (stdout "sysconfdir:=~a\n" sysconfdir)
383 (stdout "ARCH:=~a\n" ARCH)
384 (stdout "CC:=~a\n" (or CC ""))
385 (stdout "CC32:=~a\n" (or CC32 ""))
386 (stdout "HELP2MAN:=~a\n" (or HELP2MAN ""))
387 (stdout "MAKEINFO:=~a\n" (or MAKEINFO ""))
388 (stdout "TCC:=~a\n" (or TCC ""))
389 (stdout "BLOOD_ELF:=~a\n" (or BLOOD_ELF ""))
390 (stdout "MES_SEED:=~a\n" (or MES_SEED ""))
391 (stdout "MESCC_TOOLS_SEED:=~a\n" (or MESCC_TOOLS_SEED ""))
392 (stdout "TINYCC_SEED:=~a\n" (or TINYCC_SEED ""))
393 (stdout "HEX2:=~a\n" (or HEX2 ""))
394 (stdout "M1:=~a\n" (or M1 ""))
395 (stdout "GUILE:=~a\n" GUILE)
396 (stdout "GUILE_TOOLS:=~a\n" GUILE_TOOLS)
397 (stdout "GUILE_FOR_BUILD:=~a\n" GUILE)
398 (stdout "GUILE_EFFECTIVE_VERSION:=~a\n" GUILE_EFFECTIVE_VERSION)
399 (stdout "GUIX_P:=~a\n" (if guix? guix? ""))
400 (stdout "HEX2:=~a\n" (or HEX2 ""))
401 (stdout "PACKAGE:=~a\n" PACKAGE)
402 (stdout "VERSION:=~a\n" VERSION)
403 (when disable-silent-rules?
404 (stdout "BUILD_DEBUG:=1\n"))
405 (when CFLAGS (stdout "CFLAGS:=~a\n" CFLAGS))
406 (when CC32_CFLAGS (stdout "CC32_CFLAGS:=~a\n" CC32_CFLAGS))
407 (when HEX2FLAGS (stdout "HEX2FLAGS:=~a\n" HEX2FLAGS))
408 (when M1FLAGS (stdout "M1FLAGS:=~a\n" M1FLAGS))
409 (when MES_CFLAGS (stdout "MES_CFLAGS:=~a\n" MES_CFLAGS))))
410 (let ((pairs `(("@abs_top_srcdir@" . ,abs-top-srcdir)
411 ("@abs_top_builddir@" . ,abs-top-builddir)
414 ("@guile_site_dir@" . ,guile-site-dir)
415 ("@guile_site_ccache_dir@" . ,guile-site-ccache-dir)
416 ("@VERSION@" . ,VERSION)
417 ("mes/module/" . ,(string-append moduledir "/")))))
418 (for-each (lambda (o)
420 (chmod (string-drop-right o 3) #o755))
422 "build-aux/pre-inst-env.in"
423 "mes/module/mes/boot-0.scm.in"
426 (chmod "build-aux/pre-inst-env" #o755)
427 (rename-file "build-aux/pre-inst-env" "pre-inst-env")
428 (chmod "scripts/mescc" #o755)
429 (format (current-output-port)
432 ~a help for help on other targets\n"
433 (if make? "make" "./build.sh")
434 (if make? "make" "./build.sh")))))