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-26)
50 #:use-module (ice-9 and-let-star)
51 #:use-module (ice-9 curried-definitions)
52 #:use-module (ice-9 getopt-long)
53 #:use-module (ice-9 match)
54 #:use-module (ice-9 optargs)
55 #:use-module (ice-9 popen)
56 #:use-module (ice-9 rdelim)
60 (define PACKAGE "mes")
61 (define VERSION "0.16")
62 (define GUILE (or (getenv "guile") "guile"))
63 (define GUILE_EFFECTIVE_VERSION (effective-version))
65 (define prefix "/usr/local")
66 (define infodir "${prefix}/share/info")
67 (define mandir "${prefix}/share/man")
68 (define sysconfdir "${prefix}/etc")
71 (define (logf port string . rest)
72 (apply format (cons* port string rest))
76 (define (stderr string . rest)
77 (apply logf (cons* (current-error-port) string rest)))
79 (define (stdout string . rest)
80 (apply logf (cons* (current-output-port) string rest)))
82 (define *verbose?* #f)
84 (define (verbose string . rest)
85 (if *verbose?* (apply stderr (cons string rest))))
87 (define (gulp-pipe command)
88 (let* ((port (open-pipe* OPEN_READ *shell* "-c" command))
89 (output (read-string port))
90 (status (close-pipe port)))
91 (verbose "command[~a]: ~s => ~a\n" status command output)
92 (if (not (zero? status)) "" (string-trim-right output #\newline))))
94 (define* ((->string #:optional (infix "")) h . t)
95 (let ((o (if (pair? t) (cons h t) h)))
97 ((? char?) (make-string 1 o))
98 ((? number?) (number->string o))
100 ((? symbol?) (symbol->string o))
101 ((h ... t) (string-join (map (->string) o) ((->string) infix)))
106 ((and (null? a) (null? b)) #t)
107 ((null? a) (not (null? b)))
109 ((and (not (< (car a) (car b)))
110 (not (< (car b) (car a))))
111 (tuple< (cdr a) (cdr b)))
112 (else (< (car a) (car b)))))
114 (define (tuple<= a b)
115 (or (equal? a b) (tuple< a b)))
118 (define (version->string version)
119 ((->string '.) version))
121 (define (string->version string)
122 (and-let* ((version (string-tokenize string
123 (char-set-adjoin char-set:digit #\.)))
125 (version (sort version (lambda (a b) (> (string-length a) (string-length b)))))
126 (version (car version))
127 (version (string-tokenize version
128 (char-set-complement (char-set #\.)))))
129 (map string->number version)))
131 (define* (PATH-search-path name #:key (default name) warn?)
132 (or (search-path (string-split (getenv "PATH") #\:) name)
133 (and (and warn? (format (current-error-port) "warning: not found: ~a\n" name))
136 (define optional '())
137 (define required '())
138 (define* (check-version name expected
142 (version-option '--version)
145 (stderr "checking for ~a~a..." (basename name)
146 (if (null? expected) ""
147 (format #f " [~a]" (version->string expected))))
148 (let* ((output (gulp-pipe (format #f "~a ~a 2>&1" command version-option)))
149 (actual (string->version output))
150 (pass? (and actual (compare expected actual)))
151 ;(pass? (PATH-search-path command))
153 (stderr "~a ~a\n" (if pass? (if (pair? actual) "" " yes")
154 (if actual " no, found" "")) (version->string actual))
156 (if (not (pair? name)) (begin (if optional? (set! optional (cons (or deb name) optional))
157 (set! required (cons (or deb name) required)))
159 (check-version (cdr name) expected deb version-option compare)))))
161 (define* (check-pkg-config package expected #:optional (deb #f))
162 (check-version (format #f "pkg-config --modversion ~a" package) expected deb))
164 (define (check-compile-header-c header)
165 (and (= 0 (system (format #f "echo '#include ~s' | gcc -E - > /dev/null 2>&1" header)))
168 (define (check-compile-header-c++ header)
169 (and (= 0 (system (format #f "echo '#include ~s' | gcc --language=c++ --std=c++11 -E - > /dev/null 2>&1" header)))
172 (define* (check-header-c header deb #:optional (check check-compile-header-c))
173 (stderr "checking for ~a..." header)
174 (let ((result (check header)))
175 (stderr " ~a\n" (if result result "no"))
177 (set! required (cons deb required)))))
179 (define* (check-header-c++ header deb #:optional (check check-compile-header-c++))
180 (check-header-c header deb check))
183 (and (zero? (system "guix --version 1>/dev/null 2>/dev/null")) 1))
186 (define (parse-opts args)
190 (help (single-char #\h))
192 (sysconfdir (value #t))
193 (verbose (single-char #\v))
197 (disable-silent-rules)
199 (enable-fast-install) ; Ignored for Guix
200 (includedir (value #t)) ; Ignored for Debian
201 (mandir (value #t)) ; Ignored for Debian
202 (localstatedir (value #t)) ; Ignored for Debian
203 (libdir (value #t)) ; Ignored for Debian
204 (libexecdir (value #t)) ; Ignored for Debian
205 (runstatedir (value #t)) ; Ignored for Debian
206 (disable-maintainer-mode) ; Ignored for Debian
207 (disable-dependency-tracking) ; Ignored for Debian
210 (getopt-long args option-spec)))
212 (define* (print-help #:optional (port (current-output-port)))
214 `configure' configures ~a ~a to adapt to many kinds of systems.
216 Usage: ./configure [OPTION]... [VAR=VALUE]
218 To assign environment variables (e.g., CC, CFLAGS...), specify them as
219 VAR=VALUE. See below for descriptions of some of the useful variables.
221 Defaults for the options are specified in brackets.
224 -h, --help display this help
225 --build=BUILD configure for building on BUILD [guessed]
226 --disable-silent-rules
227 verbose build output [BUILD_DEBUG=1]
228 --host=HOST cross-compile to build programs to run on HOST [BUILD]
229 -v, --verbose be verbose
230 --with-courage assert being courageous to configure for unsupported platform
232 Installation directories:
233 --prefix=DIR install in prefix DIR [~a]
234 --infodir=DIR info documentation [PREFIX/share/info]
235 --mandir=DIR man pages [PREFIX/share/man]
238 --enable-fast-install
241 --disable-dependency-tracking
242 --disable-maintainer-mode
250 Some influential environment variables:
251 CC C compiler command
252 CFLAGS C compiler flags
253 CC32 x86 C compiler command
254 CC32_CFLAGS x86 C compiler flags
256 GUILE_TOOLS guile-tools command
257 MES_CFLAGS MesCC flags
258 MES_SEED location of mes-seed
259 MESCC_TOOLS_SEED location of mescc-tools-seed
260 TCC tcc C compiler command
261 TINYCC_SEED location of tinycc-seed
262 " PACKAGE VERSION (getenv "prefix")))
265 (let* ((CC (or (getenv "CC") "gcc"))
266 (BUILD_TRIPLET %host-type)
267 (ARCH (car (string-split BUILD_TRIPLET #\-)))
268 (options (parse-opts args))
269 (build-triplet (option-ref options 'build BUILD_TRIPLET))
270 (host-triplet (option-ref options 'host BUILD_TRIPLET))
271 (prefix (option-ref options 'prefix prefix))
272 (infodir (option-ref options 'infodir infodir))
273 (sysconfdir (option-ref options 'sysconfdir sysconfdir))
274 (verbose? (option-ref options 'verbose #f))
275 (with-courage? (option-ref options 'with-courage #f))
276 (disable-silent-rules? (option-ref options 'disable-silent-rules #f))
278 (vars (filter (cut string-index <> #\=) (option-ref options '() '())))
279 (help? (option-ref options 'help #f)))
280 (for-each (lambda (v) (apply setenv (string-split v #\=))) vars)
281 (let ((CC32 (or (getenv "CC32")
282 (if (member ARCH '("i686" "arm")) (string-append BUILD_TRIPLET "-" CC)
283 "i686-unknown-linux-gnu-gcc")))
284 (HELP2MAN (or (getenv "HELP2MAN") "help2man"))
285 (TCC (or (getenv "TCC") "tcc"))
286 (MAKEINFO (or (getenv "MAKEINFO") "makeinfo"))
287 (GUILE_TOOLS (or (getenv "GUILE_TOOLS") "guile-tools"))
288 (BLOOD_ELF (or (getenv "BLOOD_ELF") "blood-elf"))
289 (HEX2 (or (getenv "HEX2") "hex2"))
290 (M1 (or (getenv "M1") "M1"))
291 (CFLAGS (getenv "CFLAGS"))
292 (CC32_CFLAGS (getenv "CC32_CFLAGS"))
293 (HEX2FLAGS (getenv "HEX2FLAGS"))
294 (M1FLAGS (getenv "M1FLAGS"))
295 (MES_CFLAGS (getenv "MES_CFLAGS"))
296 (MES_SEED (or (getenv "MES_SEED") "../mes-seed"))
297 (MESCC_TOOLS_SEED (or (getenv "MESCC_TOOLS_SEED") "../mescc-tools-seed"))
298 (TINYCC_SEED (or (getenv "TINYCC_SEED") "../tinycc-seed")))
302 (set! *verbose?* verbose?)
303 (check-version "guile" '(2 0))
304 (check-version "guile-tools" '(2 0))
305 (check-version "mes-seed" '(0 16) #:optional? #t #:command (string-append MES_SEED "/refresh.sh"))
306 (check-version "tinycc-seed" '(0 16) #:optional? #t #:command (string-append TINYCC_SEED "/refresh.sh"))
307 (check-version BLOOD_ELF '(0 1))
308 (check-version HEX2 '(0 3))
309 (check-version M1 '(0 3))
310 (check-version "nyacc" '(0 80 41) #:command (string-append GUILE " -c '(use-modules (nyacc lalr)) (display *nyacc-version*)'"))
312 (check-version "bash" '(4 0))
313 (when (and (check-version "git" '(2 0) #:optional? #t)
314 (not (file-exists? ".git")))
315 ;; Debian wants to run `make clean' from a tarball
316 (and (zero? (system* "git" "init"))
317 (zero? (system* "git" "add" "."))
318 (zero? (system* "git" "commit" "-m" "Import mes"))))
319 (when (and (not (member ARCH '("i686" "x86_64"))) (not with-courage?))
320 (stderr "platform not supported: ~a, try --with-courage\n" ARCH)
322 (if (not (check-version CC '(4 8) #:optional? #t))
325 (check-header-c "stdio.h" "libc-dev")
326 (check-header-c "limits.h" "linux-headers"))
327 (if (not (check-version CC32 '(4 8) #:optional? #t))
329 (if (not (check-version TCC '(0 9 26) #:optional? #t #:version-option "-v"))
331 (set! make? (check-version "make" '(4 0) #:optional? #t))
332 (check-version "perl" '(5))
333 (if (not (check-version "makeinfo" '(6) #:optional? #t))
335 (if (not (check-version "help2man" '(1 47) #:optional? #t))
338 (when (pair? required)
339 (stderr "\nMissing dependencies [~a], run\n\n" ((->string ", ") required))
341 (stderr " guix environment -l guix.scm\n")
342 (stderr " sudo apt-get install ~a\n" ((->string " ") required)))
344 (with-output-to-file ".config.make"
346 (stdout "build:=~a\n" build-triplet)
347 (stdout "host:=~a\n" host-triplet)
348 (stdout "srcdir:=.\n")
349 (stdout "prefix:=~a\n" (gulp-pipe (string-append "echo " prefix)))
350 (stdout "infodir:=~a\n" infodir)
351 (stdout "mandir:=~a\n" mandir)
352 (stdout "sysconfdir:=~a\n" sysconfdir)
354 (stdout "ARCH:=~a\n" ARCH)
355 (stdout "CC:=~a\n" (or CC ""))
356 (stdout "CC32:=~a\n" (or CC32 ""))
357 (stdout "HELP2MAN:=~a\n" (or HELP2MAN ""))
358 (stdout "TCC:=~a\n" (or TCC ""))
359 (stdout "BLOOD_ELF:=~a\n" (or BLOOD_ELF ""))
360 (stdout "MES_SEED:=~a\n" (or MES_SEED ""))
361 (stdout "MESCC_TOOLS_SEED:=~a\n" (or MESCC_TOOLS_SEED ""))
362 (stdout "TINYCC_SEED:=~a\n" (or TINYCC_SEED ""))
363 (stdout "HEX2:=~a\n" (or HEX2 ""))
364 (stdout "M1:=~a\n" (or M1 ""))
365 (stdout "GUILE:=~a\n" GUILE)
366 (stdout "GUILE_TOOLS:=~a\n" GUILE_TOOLS)
367 (stdout "GUILE_FOR_BUILD:=~a\n" GUILE)
368 (stdout "GUILE_EFFECTIVE_VERSION:=~a\n" GUILE_EFFECTIVE_VERSION)
369 (stdout "GUIX_P:=~a\n" (if guix? guix? ""))
370 (stdout "HEX2:=~a\n" (or HEX2 ""))
371 (stdout "PACKAGE:=~a\n" PACKAGE)
372 (stdout "VERSION:=~a\n" VERSION)
373 (when disable-silent-rules?
374 (stdout "BUILD_DEBUG:=1\n"))
375 (when CFLAGS (stdout "CFLAGS:=~a\n" CFLAGS))
376 (when CC32_CFLAGS (stdout "CC32_CFLAGS:=~a\n" CC32_CFLAGS))
377 (when HEX2FLAGS (stdout "HEX2FLAGS:=~a\n" HEX2FLAGS))
378 (when M1FLAGS (stdout "M1FLAGS:=~a\n" M1FLAGS))
379 (when MES_CFLAGS (stdout "MES_CFLAGS:=~a\n" MES_CFLAGS))))
380 (format (current-output-port)
383 ~a help for help on other targets\n"
384 (if make? "make" "./build.sh")
385 (if make? "make" "./build.sh")))))