~ chicken-core (master) /egg-compile.scm
Trap1;;;; egg-info processing and compilation2;3; Copyright (c) 2017-2022, The CHICKEN Team4; All rights reserved.5;6; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following7; conditions are met:8;9; Redistributions of source code must retain the above copyright notice, this list of conditions and the following10; disclaimer.11; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following12; disclaimer in the documentation and/or other materials provided with the distribution.13; Neither the name of the author nor the names of its contributors may be used to endorse or promote14; products derived from this software without specific prior written permission.15;16; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS17; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY18; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR19; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR20; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR21; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY22; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR23; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE24; POSSIBILITY OF SUCH DAMAGE.252627(define default-extension-options '())28(define default-program-options '())29(define default-static-program-link-options '())30(define default-dynamic-program-link-options '())31(define default-static-extension-link-options '())32(define default-dynamic-extension-link-options '())33(define default-static-compilation-options '("-O2" "-d1"))34(define default-dynamic-compilation-options '("-O2" "-d1"))35(define default-import-library-compilation-options '("-O2" "-d0"))3637(define default-program-linkage38 (if staticbuild '(static) '(dynamic)))3940(define default-extension-linkage41 (if staticbuild '(static) '(static dynamic)))4243(define +unix-executable-extension+ "")44(define +windows-executable-extension+ ".exe")45(define +unix-object-extension+ ".o")46(define +unix-archive-extension+ ".a")47(define +windows-object-extension+ ".obj")48(define +windows-archive-extension+ ".a")49(define +link-file-extension+ ".link")5051(define keep-generated-files #f)52(define dependency-targets '())535455;;; some utilities5657(define override-prefix58 (let ((prefix (get-environment-variable "CHICKEN_INSTALL_PREFIX")))59 (lambda (dir default)60 (if prefix61 (string-append prefix dir)62 default))))6364(define (object-extension platform)65 (case platform66 ((unix) +unix-object-extension+)67 ((windows) +windows-object-extension+)))6869(define (archive-extension platform)70 (case platform71 ((unix) +unix-archive-extension+)72 ((windows) +windows-archive-extension+)))7374(define (executable-extension platform)75 (case platform76 ((unix) +unix-executable-extension+)77 ((windows) +windows-executable-extension+)))7879(define (copy-directory-command platform)80 "cp -r")8182(define (copy-file-command platform)83 "cp")8485(define (mkdir-command platform)86 "mkdir -p")8788(define (install-executable-command platform)89 (string-append default-install-program " "90 default-install-program-executable-flags))9192(define (install-file-command platform)93 (string-append default-install-program " "94 default-install-program-data-flags))9596(define (remove-file-command platform)97 "rm -f")9899(define (cd-command platform)100 "cd")101102(define (uses-compiled-import-library? mode)103 (not (and (eq? mode 'host) staticbuild)))104105;; this one overrides "destination-repository" in egg-environment to allow use of106;; CHICKEN_INSTALL_PREFIX (via "override-prefix")107(define (effective-destination-repository mode #!optional run)108 (if (eq? 'target mode)109 (if run target-run-repo target-repo)110 (or (get-environment-variable "CHICKEN_INSTALL_REPOSITORY")111 (override-prefix (string-append "/lib/chicken/" (number->string binary-version))112 host-repo))))113114;;; topological sort with cycle check115116(define (sort-dependencies dag eq)117 (condition-case (topological-sort dag eq)118 ((exn runtime cycle)119 (error "cyclic dependencies" dag))))120121122;;; collect import libraries for all modules123124(define (import-libraries mods dest rtarget mode)125 (define (implib name)126 (conc dest "/" name ".import."127 (if (uses-compiled-import-library? mode)128 "so"129 "scm")))130 (if mods131 (map implib mods)132 (list (implib rtarget))))133134135;;; normalize target path for "random files" (data, c-include, scheme-include)136137(define (normalize-destination dest mode)138 (let ((dest* (normalize-pathname dest)))139 (if (irregex-search '(: bos ".." ("\\/")) dest*)140 (error "destination must be relative to CHICKEN install prefix" dest)141 (normalize-pathname142 (make-pathname (if (eq? mode 'target)143 default-prefix144 (override-prefix "/" host-prefix))145 dest*)))))146147148;;; check condition in conditional clause149150(define (check-condition tst mode link)151 (define (fail x)152 (error "invalid conditional expression in `cond-expand' clause"153 x))154 (let walk ((x tst))155 (cond ((and (list? x) (pair? x))156 (cond ((and (eq? (car x) 'not) (= 2 (length x)))157 (not (walk (cadr x))))158 ((eq? 'and (car x)) (every walk (cdr x)))159 ((eq? 'or (car x)) (any walk (cdr x)))160 (else (fail x))))161 ((memq x '(dynamic static)) (memq x link))162 ((memq x '(target host)) (memq x mode))163 ((symbol? x) (feature? x))164 (else (fail x)))))165166167;;; parse custom configuration information from script168169(define (parse-custom-config arg)170 (define (read-all)171 (let loop ((lst '()))172 (let ((x (read)))173 (if (eof-object? x)174 (reverse lst)175 (loop (append (reverse (flatten x)) lst))))))176 (if (and (list? arg) (eq? 'custom-config (car arg)))177 (let* ((arg (cdr arg))178 (in (with-input-from-pipe179 (conc default-csi " -s "180 (if (list? arg)181 (string-intersperse (map ->string arg) " ")182 (->string arg)))183 read-all)))184 (map ->string in))185 (list arg)))186187188;;; compile an egg-information tree into abstract build/install operations189190(define (compile-egg-info eggfile info version platform mode)191 (let ((exts '())192 (prgs '())193 (objs '())194 (data '())195 (genfiles '())196 (cinc '())197 (scminc '())198 (target #f)199 (src #f)200 (files '())201 (ifiles '())202 (cbuild #f)203 (oname #f)204 (link '())205 (dest #f)206 (sdeps '())207 (cdeps '())208 (lopts '())209 (opts '())210 (mods #f)211 (lobjs '())212 (tfile #f)213 (ptfile #f)214 (ifile #f)215 (install #t)216 (eggfile (locate-egg-file eggfile))217 (objext (object-extension platform))218 (arcext (archive-extension platform))219 (exeext (executable-extension platform)))220 (define (check-target t lst)221 (when (member t lst)222 (error "target multiply defined" t))223 t)224 (define (addfiles . filess)225 (set! ifiles (concatenate (cons ifiles filess)))226 files)227 (define (checkfiles files target)228 (when (null? files)229 (warning "target has no files" target)))230 (define (compile-component info)231 (case (car info)232 ((extension)233 (fluid-let ((target (check-target (cadr info) exts))234 (cdeps '())235 (sdeps '())236 (src #f)237 (cbuild #f)238 (link (if (null? link) default-extension-linkage link))239 (tfile #f)240 (ptfile #f)241 (ifile #f)242 (lopts lopts)243 (lobjs '())244 (oname #f)245 (mods #f)246 (opts opts))247 (for-each compile-extension/program (cddr info))248 (let ((dest (effective-destination-repository mode #t))249 ;; Respect install-name if specified250 (rtarget (or oname target)))251 (when (eq? #t tfile) (set! tfile rtarget))252 (when (eq? #t ifile) (set! ifile rtarget))253 (addfiles254 (if (memq 'static link)255 (list (conc dest "/" rtarget256 (if (null? lobjs)257 objext258 arcext))259 (conc dest "/" rtarget +link-file-extension+))260 '())261 (if (memq 'dynamic link) (list (conc dest "/" rtarget ".so")) '())262 (if tfile263 (list (conc dest "/" tfile ".types"))264 '())265 (if ifile266 (list (conc dest "/" ifile ".inline"))267 '())268 (import-libraries mods dest rtarget mode))269 (set! exts270 (cons (list target271 dependencies: cdeps272 source: src options: opts273 link-options: lopts linkage: link custom: cbuild274 mode: mode types-file: tfile inline-file: ifile275 predefined-types: ptfile eggfile: eggfile276 modules: (or mods (list rtarget))277 source-dependencies: sdeps278 link-objects: lobjs279 output-file: rtarget)280 exts)))))281 ((installed-c-object c-object)282 (fluid-let ((target (check-target (cadr info) exts))283 (cdeps '())284 (sdeps '())285 (src #f)286 (cbuild #f)287 (link (if (null? link) default-extension-linkage link))288 (oname #f)289 (mods #f)290 (install (eq? 'installed-c-object (car info)))291 (opts opts))292 (for-each compile-extension/program (cddr info))293 (let ((dest (effective-destination-repository mode #t))294 ;; Respect install-name if specified295 (rtarget (or oname target)))296 (when install297 (addfiles (list (conc dest "/" rtarget objext))))298 (set! objs299 (cons (list target dependencies: cdeps source: src300 options: opts301 linkage: link custom: cbuild302 mode: mode303 eggfile: eggfile304 source-dependencies: sdeps305 output-file: rtarget)306 objs)))))307 ((data)308 (fluid-let ((target (check-target (cadr info) data))309 (dest #f)310 (files '()))311 (for-each compile-data/include (cddr info))312 (checkfiles files target)313 (let* ((dest (or (and dest (normalize-destination dest mode))314 (if (eq? mode 'target)315 default-sharedir316 (override-prefix "/share" host-sharedir))))317 (dest (normalize-pathname (conc dest "/"))))318 (addfiles (map (cut conc dest <>) files)))319 (set! data320 (cons (list target dependencies: '() files: files321 destination: dest mode: mode)322 data))))323 ((generated-source-file)324 (fluid-let ((target (check-target (cadr info) data))325 (src #f)326 (cbuild #f)327 (sdeps '())328 (cdeps '()))329 (for-each compile-extension/program (cddr info))330 (unless cbuild331 (error "generated source files need a custom build step" target))332 (set! genfiles333 (cons (list target dependencies: cdeps source: src334 custom: cbuild source-dependencies: sdeps335 eggfile: eggfile)336 genfiles))))337 ((c-include)338 (fluid-let ((target (check-target (cadr info) cinc))339 (dest #f)340 (files '()))341 (for-each compile-data/include (cddr info))342 (checkfiles files target)343 (let* ((dest (or (and dest (normalize-destination dest mode))344 (if (eq? mode 'target)345 default-incdir346 (override-prefix "/include" host-incdir))))347 (dest (normalize-pathname (conc dest "/"))))348 (addfiles (map (cut conc dest <>) files)))349 (set! cinc350 (cons (list target dependencies: '() files: files351 destination: dest mode: mode)352 cinc))))353 ((scheme-include)354 (fluid-let ((target (check-target (cadr info) scminc))355 (dest #f)356 (files '()))357 (checkfiles files target)358 (for-each compile-data/include (cddr info))359 (let* ((dest (or (and dest (normalize-destination dest mode))360 (if (eq? mode 'target)361 default-sharedir362 (override-prefix "/share" host-sharedir))))363 (dest (normalize-pathname (conc dest "/"))))364 (addfiles (map (cut conc dest <>) files)))365 (set! scminc366 (cons (list target dependencies: '() files: files367 destination: dest mode: mode)368 scminc))))369 ((program)370 (fluid-let ((target (check-target (cadr info) prgs))371 (cdeps '())372 (sdeps '())373 (cbuild #f)374 (src #f)375 (link (if (null? link) default-program-linkage link))376 (lobjs '())377 (lopts lopts)378 (oname #f)379 (opts opts))380 (for-each compile-extension/program (cddr info))381 (let ((dest (if (eq? mode 'target)382 default-bindir383 (override-prefix "/bin" host-bindir)))384 ;; Respect install-name if specified385 (rtarget (or oname target)))386 (addfiles (list (conc dest "/" rtarget exeext)))387 (set! prgs388 (cons (list target dependencies: cdeps389 source: src options: opts390 link-options: lopts linkage: link391 custom: cbuild392 mode: mode output-file: rtarget393 source-dependencies: sdeps394 link-objects: lobjs395 eggfile: eggfile)396 prgs)))))397 (else (compile-common info compile-component 'component))))398 (define (compile-extension/program info)399 (case (car info)400 ((linkage)401 (set! link (cdr info)))402 ((types-file)403 (set! tfile404 (cond ((null? (cdr info)) #t)405 ((not (pair? (cadr info)))406 (arg info 1 name?))407 (else408 (set! ptfile #t)409 (set! tfile410 (or (null? (cdadr info))411 (arg (cadr info) 1 name?)))))))412 ((objects)413 (let ((los (map ->string (cdr info))))414 (set! lobjs (append lobjs los))415 (set! cdeps (append cdeps (map ->dep los)))))416 ((inline-file)417 (set! ifile (or (null? (cdr info)) (arg info 1 name?))))418 ((custom-build)419 (set! cbuild (->string (arg info 1 name?))))420 ((csc-options)421 (set! opts422 (apply append423 opts424 (map parse-custom-config (cdr info)))))425 ((link-options)426 (set! lopts427 (apply append428 lopts429 (map parse-custom-config (cdr info)))))430 ((source)431 (set! src (->string (arg info 1 name?))))432 ((install-name)433 (set! oname (->string (arg info 1 name?))))434 ((modules)435 (set! mods (map library-id (cdr info))))436 ((component-dependencies)437 (set! cdeps (append cdeps (map ->dep (cdr info)))))438 ((source-dependencies)439 (set! sdeps (append sdeps (map ->dep (cdr info)))))440 (else (compile-common info compile-extension/program 'extension/program))))441 (define (compile-common info walk context)442 (case (car info)443 ((target)444 (when (eq? mode 'target)445 (for-each walk (cdr info))))446 ((host)447 (when (eq? mode 'host)448 (for-each walk (cdr info))))449 ((error)450 (apply error (cdr info)))451 ((cond-expand)452 (compile-cond-expand info walk))453 (else454 (fprintf (current-error-port) "\nWarning (~a): property `~a' invalid or in wrong context (~a)\n\n" eggfile (car info) context))))455 (define (compile-data/include info)456 (case (car info)457 ((destination)458 (set! dest (->string (arg info 1 name?))))459 ((files)460 (set! files (append files (map ->string (cdr info)))))461 (else (compile-common info compile-data/include 'data/include))))462 (define (compile-options info)463 (define (custom info)464 (map parse-custom-config info))465 (case (car info)466 ((csc-options) (set! opts (apply append opts (custom (cdr info)))))467 ((link-options) (set! lopts (apply append lopts (custom (cdr info)))))468 ((linkage) (set! link (apply append link (custom (cdr info)))))469 (else (error "invalid component-options specification" info))))470 (define (compile-cond-expand info walk)471 (let loop ((clauses (cdr info)))472 (cond ((null? clauses)473 (error "no matching clause in `cond-expand' form"474 info))475 ((or (eq? 'else (caar clauses))476 (check-condition (caar clauses) mode link))477 (for-each walk (cdar clauses)))478 (else (loop (cdr clauses))))))479 (define (->dep x)480 (if (name? x)481 (if (symbol? x) x (string->symbol x))482 (error "invalid dependency" x)))483 (define (compile info)484 (case (car info)485 ((synopsis dependencies test-dependencies category version author maintainer486 license build-dependencies foreign-dependencies platform487 distribution-files) #f)488 ((components) (for-each compile-component (cdr info)))489 ((component-options)490 (for-each compile-options (cdr info)))491 (else (compile-common info compile 'toplevel))))492 (define (arg info n #!optional (pred (constantly #t)))493 (when (< (length info) n)494 (error "missing argument" info n))495 (let ((x (list-ref info n)))496 (unless (pred x)497 (error "argument has invalid type" x))498 x))499 (define (name? x) (or (string? x) (symbol? x)))500 (define dep=? equal?)501 (define (filter pred lst)502 (cond ((null? lst) '())503 ((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))504 (else (filter pred (cdr lst)))))505 (define (filter-deps name deps)506 (filter (lambda (dep)507 (and (symbol? dep)508 (or (assq dep exts)509 (assq dep objs)510 (assq dep data)511 (assq dep cinc)512 (assq dep scminc)513 (assq dep genfiles)514 (assq dep prgs)515 (error "unknown component dependency" dep))))516 deps))517 ;; collect information518 (for-each compile info)519 ;; sort topologically, by dependencies520 (let* ((all (append prgs exts objs genfiles))521 (order (reverse (sort-dependencies522 (map (lambda (dep)523 (cons (car dep)524 (filter-deps (car dep)525 (get-keyword dependencies: (cdr dep)))))526 all)527 dep=?))))528 ;; generate + return build/install commands529 (values530 ;; build commands531 (append-map532 (lambda (id)533 (cond ((assq id exts) =>534 (lambda (data)535 (let ((link (get-keyword linkage: (cdr data)))536 (mods (get-keyword modules: (cdr data))))537 (append (if (memq 'dynamic link)538 (list (apply compile-dynamic-extension data))539 '())540 (if (memq 'static link)541 ;; if compiling both static + dynamic, override542 ;; modules/types-file/inline-file properties to543 ;; avoid generating things twice:544 (list (apply compile-static-extension545 (if (memq 'dynamic link)546 (cons (car data)547 (append '(modules: #f548 types-file: #f549 inline-file: #f)550 (cdr data)))551 data)))552 '())553 (if (uses-compiled-import-library? mode)554 (map (lambda (mod)555 (apply compile-import-library556 mod (cdr data))) ; override name557 mods)558 '())))))559 ((assq id prgs) =>560 (lambda (data)561 (let ((link (get-keyword linkage: (cdr data))))562 (append (if (memq 'dynamic link)563 (list (apply compile-dynamic-program data))564 '())565 (if (memq 'static link)566 (list (apply compile-static-program data))567 '())))))568 ((assq id objs) =>569 (lambda (data)570 (let ((link (get-keyword linkage: (cdr data))))571 (append (if (memq 'dynamic link)572 (list (apply compile-dynamic-object data))573 '())574 (if (memq 'static link)575 (list (apply compile-static-object data))576 '())))))577 ((assq id genfiles) =>578 (lambda (data)579 (list (apply compile-generated-file data))))580 ((or (assq id data)581 (assq id cinc)582 (assq id scminc))583 '()) ;; nothing to build for data components584 (else (error "Error in chicken-install, don't know how to build component" id))))585 order)586 ;; installation commands587 (append588 (append-map589 (lambda (ext)590 (let ((link (get-keyword linkage: (cdr ext)))591 (mods (get-keyword modules: (cdr ext))))592 (append593 (if (memq 'static link)594 (list (apply install-static-extension ext))595 '())596 (if (memq 'dynamic link)597 (list (apply install-dynamic-extension ext))598 '())599 (if (and (memq 'dynamic link)600 (uses-compiled-import-library? (get-keyword mode: ext)))601 (map (lambda (mod)602 (apply install-import-library603 mod (cdr ext))) ; override name604 mods)605 (map (lambda (mod)606 (apply install-import-library-source607 mod (cdr ext))) ; s.a.608 mods))609 (if (get-keyword types-file: (cdr ext))610 (list (apply install-types-file ext))611 '())612 (if (get-keyword inline-file: (cdr ext))613 (list (apply install-inline-file ext))614 '()))))615 exts)616 (map (lambda (obj) (apply install-object obj)) objs)617 (map (lambda (prg) (apply install-program prg)) prgs)618 (map (lambda (data) (apply install-data data)) data)619 (map (lambda (cinc) (apply install-c-include cinc)) cinc)620 (map (lambda (scminc) (apply install-data scminc)) scminc))621 ;; augmented egg-info622 (append `((installed-files ,@ifiles))623 (if version `((version ,version)) '())624 info)))))625626627;;; shell code generation - build operations628629(define ((compile-static-extension name #!key mode dependencies630 source-dependencies631 source (options '())632 predefined-types eggfile633 link-objects modules634 custom types-file inline-file)635 srcdir platform)636 (let* ((cmd (or (custom-cmd custom srcdir platform)637 default-csc))638 (sname (prefix srcdir name))639 (tfile (prefix srcdir (conc types-file ".types")))640 (ifile (prefix srcdir (conc inline-file ".inline")))641 (lfile (conc sname +link-file-extension+))642 (opts (append (if (null? options)643 default-static-compilation-options644 options)645 (if (and types-file646 (not predefined-types))647 (list "-emit-types-file" tfile)648 '())649 (if inline-file650 (list "-emit-inline-file" ifile)651 '())))652 (out1 (conc sname ".static"))653 (out2 (target-file (conc out1654 (object-extension platform))655 mode))656 (out3 (if (null? link-objects)657 out2658 (target-file (conc out1659 (archive-extension platform))660 mode)))661 (imps (map (lambda (m)662 (prefix srcdir (conc m ".import.scm")))663 (or modules '())))664 (targets (append (list out3 lfile)665 (maybe types-file tfile)666 (maybe inline-file ifile)667 imps))668 (src (or source (conc name ".scm"))))669 (when custom670 (prepare-custom-command cmd platform))671 (print-build-command targets672 `(,@(filelist srcdir source-dependencies) ,src ,eggfile673 ,@(if custom (list cmd) '())674 ,@(get-dependency-targets dependencies))675 `(,@(if custom '("sh") '())676 ,cmd ,@(if keep-generated-files '("-k") '())677 "-regenerate-import-libraries"678 ,@(if modules '("-J") '()) "-M"679 "-setup-mode" "-static" "-I" ,srcdir680 "-emit-link-file" ,lfile681 ,@(if (eq? mode 'host) '("-host") '())682 "-D" "compiling-extension"683 "-c" "-unit" ,name684 "-D" "compiling-static-extension"685 "-C" ,(conc "-I" srcdir)686 ,@opts ,src "-o" ,out2)687 platform)688 (when (pair? link-objects)689 (let ((lobjs (filelist srcdir690 (map (cut conc <> ".static" (object-extension platform))691 link-objects))))692 (print-build-command (list out3)693 `(,out2 ,@lobjs)694 `(,target-librarian ,target-librarian-options ,out3 ,out2 ,@lobjs)695 platform)))696 (print-end-command platform)))697698(define ((compile-dynamic-extension name #!key mode mode dependencies699 source (options '())700 (link-options '())701 predefined-types eggfile702 link-objects703 source-dependencies modules704 custom types-file inline-file)705 srcdir platform)706 (let* ((cmd (or (custom-cmd custom srcdir platform)707 default-csc))708 (sname (prefix srcdir name))709 (tfile (prefix srcdir (conc types-file ".types")))710 (ifile (prefix srcdir (conc inline-file ".inline")))711 (opts (append (if (null? options)712 default-dynamic-compilation-options713 options)714 (if (and types-file715 (not predefined-types))716 (list "-emit-types-file" tfile)717 '())718 (if inline-file719 (list "-emit-inline-file" ifile)720 '())))721 (out (target-file (conc sname ".so") mode))722 (src (or source (conc name ".scm")))723 (lobjs (map (lambda (lo)724 (target-file (conc lo725 (object-extension platform))726 mode))727 link-objects))728 (imps (map (lambda (m)729 (prefix srcdir (conc m ".import.scm")))730 modules))731 (targets (append (list out)732 (maybe inline-file ifile)733 (maybe (and types-file734 (not predefined-types)) tfile)735 imps)))736 (add-dependency-target name out)737 (when custom738 (prepare-custom-command cmd platform))739 (print-build-command targets740 `(,src ,eggfile ,@(if custom (list cmd) '())741 ,@(filelist srcdir lobjs)742 ,@(filelist srcdir source-dependencies)743 ,@(get-dependency-targets dependencies))744 `(,@(if custom '("sh") '())745 ,cmd ,@(if keep-generated-files '("-k") '())746 ,@(if (eq? mode 'host) '("-host") '())747 "-D" "compiling-extension"748 "-J" "-s" "-regenerate-import-libraries"749 "-setup-mode" "-I" ,srcdir750 "-C" ,(conc "-I" srcdir)751 ,@opts752 ,@link-options753 ,src754 ,@(filelist srcdir lobjs)755 "-o" ,out)756 platform)757 (print-end-command platform)))758759(define ((compile-import-library name #!key mode760 source-dependencies761 (options '()) (link-options '()))762 srcdir platform)763 (let* ((cmd default-csc)764 (sname (prefix srcdir name))765 (opts (if (null? options)766 default-import-library-compilation-options767 options))768 (out (target-file (conc sname ".import.so") mode))769 (src (conc name ".import.scm")))770 (print-build-command (list out)771 ;; TODO: eggfile not part of dependencies?772 `(,src #;,eggfile ,@(filelist srcdir source-dependencies))773 `(,cmd ,@(if keep-generated-files '("-k") '())774 "-setup-mode" "-s"775 ,@(if (eq? mode 'host) '("-host") '())776 "-I" ,srcdir "-C" ,(conc "-I" srcdir)777 ,@opts ,@link-options778 ,src779 "-o" ,out)780 platform)781 (print-end-command platform)))782783(define ((compile-static-object name #!key mode dependencies784 source-dependencies785 source (options '())786 eggfile custom)787 srcdir platform)788 (let* ((cmd (or (custom-cmd custom srcdir platform)789 default-csc))790 (sname (prefix srcdir name))791 (ssname (and source (prefix srcdir source)))792 (opts (if (null? options)793 default-static-compilation-options794 options))795 (out (target-file (conc sname796 ".static"797 (object-extension platform))798 mode))799 (src (or ssname (conc sname ".c"))))800 (when custom801 (prepare-custom-command cmd platform))802 (print-build-command (list out)803 `(,@(filelist srcdir source-dependencies) ,src ,eggfile804 ,@(if custom (list cmd) '())805 ,@(get-dependency-targets dependencies))806 `(,@(if custom '("sh") '())807 ,cmd "-setup-mode" "-static" "-I" ,srcdir808 ,@(if (eq? mode 'host) '("-host") '())809 "-c" "-C" ,(conc "-I" srcdir)810 ,@opts ,src "-o" ,out)811 platform)812 (print-end-command platform)))813814(define ((compile-dynamic-object name #!key mode mode dependencies815 source (options '())816 eggfile817 source-dependencies818 custom)819 srcdir platform)820 (let* ((cmd (or (custom-cmd custom srcdir platform)821 default-csc))822 (opts (if (null? options)823 default-dynamic-compilation-options824 options))825 (sname (prefix srcdir name))826 (ssname (and source (prefix srcdir source)))827 (out (target-file (conc sname828 (object-extension platform))829 mode))830 (src (or ssname (conc sname ".c"))))831 (add-dependency-target name out)832 (when custom833 (prepare-custom-command cmd platform))834 (print-build-command (list out)835 `(,src ,eggfile ,@(if custom (list cmd) '())836 ,@(filelist srcdir source-dependencies)837 ,@(get-dependency-targets dependencies))838 `(,@(if custom '("sh") '())839 ,cmd ,@(if (eq? mode 'host) '("-host") '())840 "-s" "-c" "-C" ,(conc "-I" srcdir)841 ,@opts ,src "-o" ,out)842 platform)843 (print-end-command platform)))844845(define ((compile-dynamic-program name #!key source mode dependencies846 (options '()) (link-options '())847 source-dependencies848 custom eggfile link-objects)849 srcdir platform)850 (let* ((cmd (or (custom-cmd custom srcdir platform)851 default-csc))852 (sname (prefix srcdir name))853 (opts (if (null? options)854 default-dynamic-compilation-options855 options))856 (out (target-file (conc sname857 (executable-extension platform))858 mode))859 (lobjs (map (lambda (lo)860 (target-file (conc lo861 (object-extension platform))862 mode))863 link-objects))864 (src (or source (conc name ".scm"))))865 (when custom866 (prepare-custom-command cmd platform))867 (print-build-command (list out)868 `(,src ,eggfile ,@(if custom (list cmd) '())869 ,@(filelist srcdir source-dependencies)870 ,@(filelist srcdir lobjs)871 ,@(get-dependency-targets dependencies))872 `(,@(if custom '("sh") '())873 ,cmd ,@(if keep-generated-files '("-k") '())874 "-setup-mode"875 ,@(if (eq? mode 'host) '("-host") '())876 "-I" ,srcdir877 "-C" ,(conc "-I" srcdir)878 ,@opts ,@link-options ,src879 ,@(filelist srcdir lobjs)880 "-o" ,out)881 platform)882 (print-end-command platform)))883884(define ((compile-static-program name #!key source dependencies885 (options '()) (link-options '())886 source-dependencies887 custom mode eggfile link-objects)888 srcdir platform)889 (let* ((cmd (or (custom-cmd custom srcdir platform)890 default-csc))891 (sname (prefix srcdir name))892 (opts (if (null? options)893 default-static-compilation-options894 options))895 (out (target-file (conc sname896 (executable-extension platform))897 mode))898 (lobjs (map (lambda (lo)899 (target-file (conc lo900 (object-extension platform))901 mode))902 link-objects))903 (src (or source (conc name ".scm"))))904 (when custom905 (prepare-custom-command cmd platform))906 (print-build-command (list out)907 `(,src ,eggfile ,@(if custom (list cmd) '())908 ,@(filelist srcdir lobjs)909 ,@(filelist srcdir source-dependencies)910 ,@(get-dependency-targets dependencies))911 `(,@(if custom '("sh") '())912 ,cmd ,@(if keep-generated-files '("-k") '())913 ,@(if (eq? mode 'host) '("-host") '())914 "-static" "-setup-mode" "-I" ,srcdir915 "-C" ,(conc "-I" srcdir)916 ,@opts ,@link-options ,src917 ,@(filelist srcdir lobjs)918 "-o" ,out)919 platform)920 (print-end-command platform)))921922(define ((compile-generated-file name #!key source custom dependencies923 source-dependencies eggfile)924 srcdir platform)925 (let ((cmd (custom-cmd custom srcdir platform))926 (out (or source name)))927 (add-dependency-target name out)928 (prepare-custom-command cmd platform)929 (print-build-command (list out)930 (append931 (filelist srcdir source-dependencies)932 (get-dependency-targets dependencies))933 `("sh" ,cmd ,eggfile)934 platform)935 (print-end-command platform)))936937938;; installation operations939940(define ((install-static-extension name #!key mode output-file941 link-objects)942 srcdir platform)943 (let* ((cmd (install-file-command platform))944 (mkdir (mkdir-command platform))945 (ext (if (null? link-objects)946 (object-extension platform)947 (archive-extension platform)))948 (sname (prefix srcdir name))949 (out (qs* (target-file (conc sname ".static" ext) mode)))950 (outlnk (qs* (conc sname +link-file-extension+)))951 (dest (effective-destination-repository mode))952 (dfile (qs* dest))953 (ddir (shell-variable "DESTDIR")))954 (print "\n" mkdir " " ddir dfile)955 (print cmd " " out " " ddir956 (qs* (conc dest "/" output-file ext)))957 (print cmd " " outlnk " " ddir958 (qs* (conc dest "/" output-file +link-file-extension+)))959 (print-end-command platform)))960961(define ((install-dynamic-extension name #!key mode (ext ".so")962 output-file)963 srcdir platform)964 (let* ((cmd (install-executable-command platform))965 (mkdir (mkdir-command platform))966 (sname (prefix srcdir name))967 (out (qs* (target-file (conc sname ext) mode)))968 (dest (effective-destination-repository mode))969 (dfile (qs* dest))970 (ddir (shell-variable "DESTDIR"))971 (destf (qs* (conc dest "/" output-file ext))))972 (print "\n" mkdir " " ddir dfile)973 (print cmd " " out " " ddir destf)974 (print-end-command platform)))975976(define ((install-import-library name #!key mode)977 srcdir platform)978 ((install-dynamic-extension name mode: mode ext: ".import.so"979 output-file: name)980 srcdir platform))981982(define ((install-import-library-source name #!key mode)983 srcdir platform)984 (let* ((cmd (install-file-command platform))985 (mkdir (mkdir-command platform))986 (sname (prefix srcdir name))987 (out (qs* (target-file (conc sname ".import.scm") mode)))988 (dest (effective-destination-repository mode))989 (dfile (qs* dest))990 (ddir (shell-variable "DESTDIR")))991 (print "\n" mkdir " " ddir dfile)992 (print cmd " " out " " ddir993 (qs* (conc dest "/" name ".import.scm")))994 (print-end-command platform)))995996(define ((install-types-file name #!key mode types-file)997 srcdir platform)998 (let* ((cmd (install-file-command platform))999 (mkdir (mkdir-command platform))1000 (out (qs* (prefix srcdir (conc types-file ".types"))))1001 (dest (effective-destination-repository mode))1002 (dfile (qs* dest))1003 (ddir (shell-variable "DESTDIR")))1004 (print "\n" mkdir " " ddir dfile)1005 (print cmd " " out " " ddir1006 (qs* (conc dest "/" types-file ".types")))1007 (print-end-command platform)))10081009(define ((install-inline-file name #!key mode inline-file)1010 srcdir platform)1011 (let* ((cmd (install-file-command platform))1012 (mkdir (mkdir-command platform))1013 (out (qs* (prefix srcdir (conc inline-file ".inline"))))1014 (dest (effective-destination-repository mode))1015 (dfile (qs* dest))1016 (ddir (shell-variable "DESTDIR")))1017 (print "\n" mkdir " " ddir dfile)1018 (print cmd " " out " " ddir1019 (qs* (conc dest "/" inline-file ".inline")))1020 (print-end-command platform)))10211022(define ((install-program name #!key mode output-file) srcdir platform)1023 (let* ((cmd (install-executable-command platform))1024 (mkdir (mkdir-command platform))1025 (ext (executable-extension platform))1026 (sname (prefix srcdir name))1027 (out (qs* (target-file (conc sname ext) mode)))1028 (dest (if (eq? mode 'target)1029 default-bindir1030 (override-prefix "/bin" host-bindir)))1031 (dfile (qs* dest))1032 (ddir (shell-variable "DESTDIR"))1033 (destf (qs* (conc dest "/" output-file ext))))1034 (print "\n" mkdir " " ddir dfile)1035 (print cmd " " out " " ddir destf)1036 (print-end-command platform)))10371038(define ((install-object name #!key mode output-file) srcdir platform)1039 (let* ((cmd (install-file-command platform))1040 (mkdir (mkdir-command platform))1041 (ext (object-extension platform))1042 (sname (prefix srcdir name))1043 (out (qs* (target-file (conc sname ext) mode)))1044 (dest (effective-destination-repository mode))1045 (dfile (qs* dest))1046 (ddir (shell-variable "DESTDIR")))1047 (print "\n" mkdir " " ddir dfile)1048 (print cmd " " out " " ddir1049 (qs* (conc dest "/" output-file ext)))1050 (print-end-command platform)))10511052(define (install-random-files dest files mode srcdir platform)1053 (let* ((fcmd (install-file-command platform))1054 (dcmd (copy-directory-command platform))1055 (root (string-append srcdir "/"))1056 (mkdir (mkdir-command platform))1057 (sfiles (map (cut prefix srcdir <>) files))1058 (dfile (qs* dest))1059 (ddir (shell-variable "DESTDIR")))1060 (print "\n" mkdir " " ddir dfile)1061 (let-values (((ds fs) (partition directory? sfiles)))1062 (for-each1063 (lambda (d)1064 (let* ((ds (strip-dir-prefix srcdir d))1065 (fdir (pathname-directory ds)))1066 (when fdir1067 (print mkdir " " ddir1068 (qs* (make-pathname dest fdir))))1069 (print dcmd " " (qs* d)1070 " " ddir1071 (if fdir1072 (qs* (make-pathname dest fdir))1073 dfile))1074 (print-end-command platform)))1075 ds)1076 (when (pair? fs)1077 (for-each1078 (lambda (f)1079 (let* ((fs (strip-dir-prefix srcdir f))1080 (fdir (pathname-directory fs)))1081 (when fdir1082 (print mkdir " " ddir1083 (qs* (make-pathname dest fdir))))1084 (print fcmd " " (qs* f)1085 " " ddir1086 (if fdir1087 (qs* (make-pathname dest fdir))1088 dfile)))1089 (print-end-command platform))1090 fs)))))10911092(define ((install-data name #!key files destination mode)1093 srcdir platform)1094 (install-random-files (or destination1095 (if (eq? mode 'target)1096 default-sharedir1097 (override-prefix "/share"1098 host-sharedir)))1099 files mode srcdir platform))11001101(define ((install-c-include name #!key deps files destination mode)1102 srcdir platform)1103 (install-random-files (or destination1104 (if (eq? mode 'target)1105 default-incdir1106 (override-prefix "/include"1107 host-incdir)))1108 files mode srcdir platform))11091110;; manage dependency-targets11111112(define (add-dependency-target target output)1113 (cond ((assq target dependency-targets) =>1114 (lambda (a)1115 (set-cdr! a output)))1116 (else (set! dependency-targets1117 (cons (cons target output) dependency-targets)))))11181119(define (get-dependency-targets targets)1120 (append-map1121 (lambda (t)1122 (cond ((assq t dependency-targets) => (lambda (a) (list (cdr a))))1123 (else '())))1124 targets))112511261127;;; Generate shell or batch commands from abstract build/install operations11281129(define (generate-shell-commands platform cmds dest srcdir prefix suffix keep)1130 (fluid-let ((keep-generated-files keep))1131 (with-output-to-file dest1132 (lambda ()1133 (prefix platform)1134 (print (cd-command platform) " " (qs* srcdir))1135 (for-each1136 (lambda (cmd) (cmd srcdir platform))1137 cmds)1138 (suffix platform)))))113911401141;;; affixes for build- and install-scripts11421143(define ((build-prefix mode name info) platform)1144 (printf #<<EOF1145#!/bin/sh~%1146set -e1147PATH=~a:$PATH1148export CHICKEN_CC=~a1149export CHICKEN_CXX=~a1150export CHICKEN_CSC=~a1151export CHICKEN_CSI=~a11521153EOF1154 (qs* default-bindir) (qs* default-cc)1155 (qs* default-cxx) (qs* default-csc)1156 (qs* default-csi)))11571158(define ((build-suffix mode name info) platform)1159 (printf #<<EOF1160EOF1161 ))11621163(define ((install-prefix mode name info) platform)1164 (printf #<<EOF1165#!/bin/sh~%1166set -e11671168EOF1169 ))11701171(define ((install-suffix mode name info) platform)1172 (let* ((infostr (with-output-to-string (cut pp info)))1173 (dcmd (remove-file-command platform))1174 (mkdir (mkdir-command platform))1175 (dir (destination-repository mode))1176 (qdir (qs* dir))1177 (dest (qs* (make-pathname dir name +egg-info-extension+)))1178 (ddir (shell-variable "DESTDIR")))1179 (printf #<<EOF11801181~a ~a~a1182~a ~a~a1183cat >~a~a <<'ENDINFO'1184~aENDINFO~%1185EOF1186 mkdir ddir qdir1187 dcmd ddir dest1188 ddir dest infostr)))11891190;;; some utilities for mangling + quoting11911192(define (qs* arg)1193 (qs (->string arg)))11941195(define (prefix dir name)1196 (make-pathname dir (->string name)))11971198(define (system+ str platform)1199 (system (if (eq? platform 'windows)1200 (string-append "sh -c \"" str "\"")1201 str)))12021203(define (target-file fname mode)1204 (if (eq? mode 'target) (string-append fname ".target") fname))12051206(define (joins strs platform)1207 (string-intersperse (map qs* strs) " "))12081209(define (filelist dir lst)1210 (map (cut prefix dir <>) lst))12111212(define (shell-variable var)1213 (string-append "\"${" var "}\""))12141215(define prepare-custom-command void)12161217(define (custom-cmd custom srcdir platform)1218 (and custom (prefix srcdir custom)))12191220(define (print-build-command targets sources command-and-args platform)1221 (print "\n" (qs* default-builder) " "1222 (joins targets platform)1223 " : " (joins sources platform) " "1224 " : " (joins command-and-args platform)))12251226(define print-end-command void)12271228(define (strip-dir-prefix prefix fname)1229 (let* ((plen (string-length prefix))1230 (p1 (substring fname 0 plen)))1231 (assert (string=? prefix p1) "wrong prefix" prefix p1)1232 (substring fname (add1 plen))))12331234(define (maybe f x) (if f (list x) '()))12351236(define (ensure-line-limit str lim)1237 (when (>= (string-length str) lim)1238 (error "line length exceeds platform limit: " str))1239 str)