~ 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 eggfile 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* ((args (cdr arg))178 (in (with-input-from-pipe179 (string-intersperse180 (append181 (list default-csi "-s"182 (make-pathname (pathname-directory eggfile)183 (->string (car args))))184 (cdr args))185 " ")186 read-all)))187 (map ->string in))188 (list arg)))189190191;;; compile an egg-information tree into abstract build/install operations192193(define (compile-egg-info eggfile info version platform mode)194 (let ((exts '())195 (prgs '())196 (objs '())197 (data '())198 (genfiles '())199 (cinc '())200 (scminc '())201 (target #f)202 (src #f)203 (files '())204 (ifiles '())205 (cbuild #f)206 (oname #f)207 (link '())208 (dest #f)209 (sdeps '())210 (cdeps '())211 (lopts '())212 (opts '())213 (mods #f)214 (lobjs '())215 (tfile #f)216 (ptfile #f)217 (ifile #f)218 (install #t)219 (eggfile (locate-egg-file eggfile))220 (objext (object-extension platform))221 (arcext (archive-extension platform))222 (exeext (executable-extension platform)))223 (define (check-target t lst)224 (when (member t lst)225 (error "target multiply defined" t))226 t)227 (define (addfiles . filess)228 (set! ifiles (concatenate (cons ifiles filess)))229 files)230 (define (checkfiles files target)231 (when (null? files)232 (warning "target has no files" target)))233 (define (compile-component info)234 (case (car info)235 ((extension)236 (fluid-let ((target (check-target (cadr info) exts))237 (cdeps '())238 (sdeps '())239 (src #f)240 (cbuild #f)241 (link (if (null? link) default-extension-linkage link))242 (tfile #f)243 (ptfile #f)244 (ifile #f)245 (lopts lopts)246 (lobjs '())247 (oname #f)248 (mods #f)249 (opts opts))250 (for-each compile-extension/program (cddr info))251 (let ((dest (effective-destination-repository mode #t))252 ;; Respect install-name if specified253 (rtarget (or oname target)))254 (when (eq? #t tfile) (set! tfile rtarget))255 (when (eq? #t ifile) (set! ifile rtarget))256 (addfiles257 (if (memq 'static link)258 (list (conc dest "/" rtarget259 (if (null? lobjs)260 objext261 arcext))262 (conc dest "/" rtarget +link-file-extension+))263 '())264 (if (memq 'dynamic link) (list (conc dest "/" rtarget ".so")) '())265 (if tfile266 (list (conc dest "/" tfile ".types"))267 '())268 (if ifile269 (list (conc dest "/" ifile ".inline"))270 '())271 (import-libraries mods dest rtarget mode))272 (set! exts273 (cons (list target274 dependencies: cdeps275 source: src options: opts276 link-options: lopts linkage: link custom: cbuild277 mode: mode types-file: tfile inline-file: ifile278 predefined-types: ptfile eggfile: eggfile279 modules: (or mods (list rtarget))280 source-dependencies: sdeps281 link-objects: lobjs282 output-file: rtarget)283 exts)))))284 ((installed-c-object c-object)285 (fluid-let ((target (check-target (cadr info) exts))286 (cdeps '())287 (sdeps '())288 (src #f)289 (cbuild #f)290 (link (if (null? link) default-extension-linkage link))291 (oname #f)292 (mods #f)293 (install (eq? 'installed-c-object (car info)))294 (opts opts))295 (for-each compile-extension/program (cddr info))296 (let ((dest (effective-destination-repository mode #t))297 ;; Respect install-name if specified298 (rtarget (or oname target)))299 (when install300 (addfiles (list (conc dest "/" rtarget objext))))301 (set! objs302 (cons (list target dependencies: cdeps source: src303 options: opts304 linkage: link custom: cbuild305 mode: mode306 eggfile: eggfile307 source-dependencies: sdeps308 output-file: rtarget)309 objs)))))310 ((data)311 (fluid-let ((target (check-target (cadr info) data))312 (dest #f)313 (files '()))314 (for-each compile-data/include (cddr info))315 (checkfiles files target)316 (let* ((dest (or (and dest (normalize-destination dest mode))317 (if (eq? mode 'target)318 default-sharedir319 (override-prefix "/share" host-sharedir))))320 (dest (normalize-pathname (conc dest "/"))))321 (addfiles (map (cut conc dest <>) files)))322 (set! data323 (cons (list target dependencies: '() files: files324 destination: dest mode: mode)325 data))))326 ((generated-source-file)327 (fluid-let ((target (check-target (cadr info) data))328 (src #f)329 (cbuild #f)330 (sdeps '())331 (cdeps '()))332 (for-each compile-extension/program (cddr info))333 (unless cbuild334 (error "generated source files need a custom build step" target))335 (set! genfiles336 (cons (list target dependencies: cdeps source: src337 custom: cbuild source-dependencies: sdeps338 eggfile: eggfile)339 genfiles))))340 ((c-include)341 (fluid-let ((target (check-target (cadr info) cinc))342 (dest #f)343 (files '()))344 (for-each compile-data/include (cddr info))345 (checkfiles files target)346 (let* ((dest (or (and dest (normalize-destination dest mode))347 (if (eq? mode 'target)348 default-incdir349 (override-prefix "/include" host-incdir))))350 (dest (normalize-pathname (conc dest "/"))))351 (addfiles (map (cut conc dest <>) files)))352 (set! cinc353 (cons (list target dependencies: '() files: files354 destination: dest mode: mode)355 cinc))))356 ((scheme-include)357 (fluid-let ((target (check-target (cadr info) scminc))358 (dest #f)359 (files '()))360 (checkfiles files target)361 (for-each compile-data/include (cddr info))362 (let* ((dest (or (and dest (normalize-destination dest mode))363 (if (eq? mode 'target)364 default-sharedir365 (override-prefix "/share" host-sharedir))))366 (dest (normalize-pathname (conc dest "/"))))367 (addfiles (map (cut conc dest <>) files)))368 (set! scminc369 (cons (list target dependencies: '() files: files370 destination: dest mode: mode)371 scminc))))372 ((program)373 (fluid-let ((target (check-target (cadr info) prgs))374 (cdeps '())375 (sdeps '())376 (cbuild #f)377 (src #f)378 (link (if (null? link) default-program-linkage link))379 (lobjs '())380 (lopts lopts)381 (oname #f)382 (opts opts))383 (for-each compile-extension/program (cddr info))384 (let ((dest (if (eq? mode 'target)385 default-bindir386 (override-prefix "/bin" host-bindir)))387 ;; Respect install-name if specified388 (rtarget (or oname target)))389 (addfiles (list (conc dest "/" rtarget exeext)))390 (set! prgs391 (cons (list target dependencies: cdeps392 source: src options: opts393 link-options: lopts linkage: link394 custom: cbuild395 mode: mode output-file: rtarget396 source-dependencies: sdeps397 link-objects: lobjs398 eggfile: eggfile)399 prgs)))))400 (else (compile-common info compile-component 'component))))401 (define (compile-extension/program info)402 (case (car info)403 ((linkage)404 (set! link (cdr info)))405 ((types-file)406 (set! tfile407 (cond ((null? (cdr info)) #t)408 ((not (pair? (cadr info)))409 (arg info 1 name?))410 (else411 (set! ptfile #t)412 (set! tfile413 (or (null? (cdadr info))414 (arg (cadr info) 1 name?)))))))415 ((objects)416 (let ((los (map ->string (cdr info))))417 (set! lobjs (append lobjs los))418 (set! cdeps (append cdeps (map ->dep los)))))419 ((inline-file)420 (set! ifile (or (null? (cdr info)) (arg info 1 name?))))421 ((custom-build)422 (set! cbuild (->string (arg info 1 name?))))423 ((csc-options)424 (set! opts425 (apply append426 opts427 (map (cut parse-custom-config eggfile <>) (cdr info)))))428 ((link-options)429 (set! lopts430 (apply append431 lopts432 (map (cut parse-custom-config eggfile <>) (cdr info)))))433 ((source)434 (set! src (->string (arg info 1 name?))))435 ((install-name)436 (set! oname (->string (arg info 1 name?))))437 ((modules)438 (set! mods (map library-id (cdr info))))439 ((component-dependencies)440 (set! cdeps (append cdeps (map ->dep (cdr info)))))441 ((source-dependencies)442 (set! sdeps (append sdeps (map ->dep (cdr info)))))443 (else (compile-common info compile-extension/program 'extension/program))))444 (define (compile-common info walk context)445 (case (car info)446 ((target)447 (when (eq? mode 'target)448 (for-each walk (cdr info))))449 ((host)450 (when (eq? mode 'host)451 (for-each walk (cdr info))))452 ((error)453 (apply error (cdr info)))454 ((cond-expand)455 (compile-cond-expand info walk))456 (else457 (fprintf (current-error-port) "\nWarning (~a): property `~a' invalid or in wrong context (~a)\n\n" eggfile (car info) context))))458 (define (compile-data/include info)459 (case (car info)460 ((destination)461 (set! dest (->string (arg info 1 name?))))462 ((files)463 (set! files (append files (map ->string (cdr info)))))464 (else (compile-common info compile-data/include 'data/include))))465 (define (compile-options info)466 (define (custom info)467 (map (cut parse-custom-config eggfile <>) info))468 (case (car info)469 ((csc-options) (set! opts (apply append opts (custom (cdr info)))))470 ((link-options) (set! lopts (apply append lopts (custom (cdr info)))))471 ((linkage) (set! link (apply append link (custom (cdr info)))))472 (else (error "invalid component-options specification" info))))473 (define (compile-cond-expand info walk)474 (let loop ((clauses (cdr info)))475 (cond ((null? clauses)476 (error "no matching clause in `cond-expand' form"477 info))478 ((or (eq? 'else (caar clauses))479 (check-condition (caar clauses) mode link))480 (for-each walk (cdar clauses)))481 (else (loop (cdr clauses))))))482 (define (->dep x)483 (if (name? x)484 (if (symbol? x) x (string->symbol x))485 (error "invalid dependency" x)))486 (define (compile info)487 (case (car info)488 ((synopsis dependencies test-dependencies category version author maintainer489 license build-dependencies foreign-dependencies platform490 distribution-files) #f)491 ((components) (for-each compile-component (cdr info)))492 ((component-options)493 (for-each compile-options (cdr info)))494 (else (compile-common info compile 'toplevel))))495 (define (arg info n #!optional (pred (constantly #t)))496 (when (< (length info) n)497 (error "missing argument" info n))498 (let ((x (list-ref info n)))499 (unless (pred x)500 (error "argument has invalid type" x))501 x))502 (define (name? x) (or (string? x) (symbol? x)))503 (define dep=? equal?)504 (define (filter pred lst)505 (cond ((null? lst) '())506 ((pred (car lst)) (cons (car lst) (filter pred (cdr lst))))507 (else (filter pred (cdr lst)))))508 (define (filter-deps name deps)509 (filter (lambda (dep)510 (and (symbol? dep)511 (or (assq dep exts)512 (assq dep objs)513 (assq dep data)514 (assq dep cinc)515 (assq dep scminc)516 (assq dep genfiles)517 (assq dep prgs)518 (error "unknown component dependency" dep))))519 deps))520 ;; collect information521 (for-each compile info)522 ;; sort topologically, by dependencies523 (let* ((all (append prgs exts objs genfiles))524 (order (reverse (sort-dependencies525 (map (lambda (dep)526 (cons (car dep)527 (filter-deps (car dep)528 (get-keyword dependencies: (cdr dep)))))529 all)530 dep=?))))531 ;; generate + return build/install commands532 (values533 ;; build commands534 (append-map535 (lambda (id)536 (cond ((assq id exts) =>537 (lambda (data)538 (let ((link (get-keyword linkage: (cdr data)))539 (mods (get-keyword modules: (cdr data))))540 (append (if (memq 'dynamic link)541 (list (apply compile-dynamic-extension data))542 '())543 (if (memq 'static link)544 ;; if compiling both static + dynamic, override545 ;; modules/types-file/inline-file properties to546 ;; avoid generating things twice:547 (list (apply compile-static-extension548 (if (memq 'dynamic link)549 (cons (car data)550 (append '(modules: #f551 types-file: #f552 inline-file: #f)553 (cdr data)))554 data)))555 '())556 (if (uses-compiled-import-library? mode)557 (map (lambda (mod)558 (apply compile-import-library559 mod (cdr data))) ; override name560 mods)561 '())))))562 ((assq id prgs) =>563 (lambda (data)564 (let ((link (get-keyword linkage: (cdr data))))565 (append (if (memq 'dynamic link)566 (list (apply compile-dynamic-program data))567 '())568 (if (memq 'static link)569 (list (apply compile-static-program data))570 '())))))571 ((assq id objs) =>572 (lambda (data)573 (let ((link (get-keyword linkage: (cdr data))))574 (append (if (memq 'dynamic link)575 (list (apply compile-dynamic-object data))576 '())577 (if (memq 'static link)578 (list (apply compile-static-object data))579 '())))))580 ((assq id genfiles) =>581 (lambda (data)582 (list (apply compile-generated-file data))))583 ((or (assq id data)584 (assq id cinc)585 (assq id scminc))586 '()) ;; nothing to build for data components587 (else (error "Error in chicken-install, don't know how to build component" id))))588 order)589 ;; installation commands590 (append591 (append-map592 (lambda (ext)593 (let ((link (get-keyword linkage: (cdr ext)))594 (mods (get-keyword modules: (cdr ext))))595 (append596 (if (memq 'static link)597 (list (apply install-static-extension ext))598 '())599 (if (memq 'dynamic link)600 (list (apply install-dynamic-extension ext))601 '())602 (if (and (memq 'dynamic link)603 (uses-compiled-import-library? (get-keyword mode: ext)))604 (map (lambda (mod)605 (apply install-import-library606 mod (cdr ext))) ; override name607 mods)608 (map (lambda (mod)609 (apply install-import-library-source610 mod (cdr ext))) ; s.a.611 mods))612 (if (get-keyword types-file: (cdr ext))613 (list (apply install-types-file ext))614 '())615 (if (get-keyword inline-file: (cdr ext))616 (list (apply install-inline-file ext))617 '()))))618 exts)619 (map (lambda (obj) (apply install-object obj)) objs)620 (map (lambda (prg) (apply install-program prg)) prgs)621 (map (lambda (data) (apply install-data data)) data)622 (map (lambda (cinc) (apply install-c-include cinc)) cinc)623 (map (lambda (scminc) (apply install-data scminc)) scminc))624 ;; augmented egg-info625 (append `((installed-files ,@ifiles))626 (if version `((version ,version)) '())627 info)))))628629630;;; shell code generation - build operations631632(define ((compile-static-extension name #!key mode dependencies633 source-dependencies634 source (options '())635 predefined-types eggfile636 link-objects modules637 custom types-file inline-file)638 srcdir platform)639 (let* ((cmd (or (custom-cmd custom srcdir platform)640 default-csc))641 (sname (prefix srcdir name))642 (tfile (prefix srcdir (conc types-file ".types")))643 (ifile (prefix srcdir (conc inline-file ".inline")))644 (lfile (conc sname +link-file-extension+))645 (opts (append (if (null? options)646 default-static-compilation-options647 options)648 (if (and types-file649 (not predefined-types))650 (list "-emit-types-file" tfile)651 '())652 (if inline-file653 (list "-emit-inline-file" ifile)654 '())))655 (out1 (conc sname ".static"))656 (out2 (target-file (conc out1657 (object-extension platform))658 mode))659 (out3 (if (null? link-objects)660 out2661 (target-file (conc out1662 (archive-extension platform))663 mode)))664 (imps (map (lambda (m)665 (prefix srcdir (conc m ".import.scm")))666 (or modules '())))667 (targets (append (list out3 lfile)668 (maybe types-file tfile)669 (maybe inline-file ifile)670 imps))671 (src (or source (conc name ".scm"))))672 (when custom673 (prepare-custom-command cmd platform))674 (print-build-command targets675 `(,@(filelist srcdir source-dependencies) ,src ,eggfile676 ,@(if custom (list cmd) '())677 ,@(get-dependency-targets dependencies))678 `(,@(if custom '("sh") '())679 ,cmd ,@(if keep-generated-files '("-k") '())680 "-regenerate-import-libraries"681 ,@(if modules '("-J") '()) "-M"682 "-setup-mode" "-static" "-I" ,srcdir683 "-emit-link-file" ,lfile684 ,@(if (eq? mode 'host) '("-host") '())685 "-D" "compiling-extension"686 "-c" "-unit" ,name687 "-D" "compiling-static-extension"688 "-C" ,(conc "-I" srcdir)689 ,@opts ,src "-o" ,out2)690 platform)691 (when (pair? link-objects)692 (let ((lobjs (filelist srcdir693 (map (cut conc <> ".static" (object-extension platform))694 link-objects))))695 (print-build-command (list out3)696 `(,out2 ,@lobjs)697 `(,target-librarian ,target-librarian-options ,out3 ,out2 ,@lobjs)698 platform)))699 (print-end-command platform)))700701(define ((compile-dynamic-extension name #!key mode mode dependencies702 source (options '())703 (link-options '())704 predefined-types eggfile705 link-objects706 source-dependencies modules707 custom types-file inline-file)708 srcdir platform)709 (let* ((cmd (or (custom-cmd custom srcdir platform)710 default-csc))711 (sname (prefix srcdir name))712 (tfile (prefix srcdir (conc types-file ".types")))713 (ifile (prefix srcdir (conc inline-file ".inline")))714 (opts (append (if (null? options)715 default-dynamic-compilation-options716 options)717 (if (and types-file718 (not predefined-types))719 (list "-emit-types-file" tfile)720 '())721 (if inline-file722 (list "-emit-inline-file" ifile)723 '())))724 (out (target-file (conc sname ".so") mode))725 (src (or source (conc name ".scm")))726 (lobjs (map (lambda (lo)727 (target-file (conc lo728 (object-extension platform))729 mode))730 link-objects))731 (imps (map (lambda (m)732 (prefix srcdir (conc m ".import.scm")))733 modules))734 (targets (append (list out)735 (maybe inline-file ifile)736 (maybe (and types-file737 (not predefined-types)) tfile)738 imps)))739 (add-dependency-target name out)740 (when custom741 (prepare-custom-command cmd platform))742 (print-build-command targets743 `(,src ,eggfile ,@(if custom (list cmd) '())744 ,@(filelist srcdir lobjs)745 ,@(filelist srcdir source-dependencies)746 ,@(get-dependency-targets dependencies))747 `(,@(if custom '("sh") '())748 ,cmd ,@(if keep-generated-files '("-k") '())749 ,@(if (eq? mode 'host) '("-host") '())750 "-D" "compiling-extension"751 "-J" "-s" "-regenerate-import-libraries"752 "-setup-mode" "-I" ,srcdir753 "-C" ,(conc "-I" srcdir)754 ,@opts755 ,@link-options756 ,src757 ,@(filelist srcdir lobjs)758 "-o" ,out)759 platform)760 (print-end-command platform)))761762(define ((compile-import-library name #!key mode763 source-dependencies764 (options '()) (link-options '()))765 srcdir platform)766 (let* ((cmd default-csc)767 (sname (prefix srcdir name))768 (opts (if (null? options)769 default-import-library-compilation-options770 options))771 (out (target-file (conc sname ".import.so") mode))772 (src (conc name ".import.scm")))773 (print-build-command (list out)774 ;; TODO: eggfile not part of dependencies?775 `(,src #;,eggfile ,@(filelist srcdir source-dependencies))776 `(,cmd ,@(if keep-generated-files '("-k") '())777 "-setup-mode" "-s"778 ,@(if (eq? mode 'host) '("-host") '())779 "-I" ,srcdir "-C" ,(conc "-I" srcdir)780 ,@opts ,@link-options781 ,src782 "-o" ,out)783 platform)784 (print-end-command platform)))785786(define ((compile-static-object name #!key mode dependencies787 source-dependencies788 source (options '())789 eggfile custom)790 srcdir platform)791 (let* ((cmd (or (custom-cmd custom srcdir platform)792 default-csc))793 (sname (prefix srcdir name))794 (ssname (and source (prefix srcdir source)))795 (opts (if (null? options)796 default-static-compilation-options797 options))798 (out (target-file (conc sname799 ".static"800 (object-extension platform))801 mode))802 (src (or ssname (conc sname ".c"))))803 (when custom804 (prepare-custom-command cmd platform))805 (print-build-command (list out)806 `(,@(filelist srcdir source-dependencies) ,src ,eggfile807 ,@(if custom (list cmd) '())808 ,@(get-dependency-targets dependencies))809 `(,@(if custom '("sh") '())810 ,cmd "-setup-mode" "-static" "-I" ,srcdir811 ,@(if (eq? mode 'host) '("-host") '())812 "-c" "-C" ,(conc "-I" srcdir)813 ,@opts ,src "-o" ,out)814 platform)815 (print-end-command platform)))816817(define ((compile-dynamic-object name #!key mode mode dependencies818 source (options '())819 eggfile820 source-dependencies821 custom)822 srcdir platform)823 (let* ((cmd (or (custom-cmd custom srcdir platform)824 default-csc))825 (opts (if (null? options)826 default-dynamic-compilation-options827 options))828 (sname (prefix srcdir name))829 (ssname (and source (prefix srcdir source)))830 (out (target-file (conc sname831 (object-extension platform))832 mode))833 (src (or ssname (conc sname ".c"))))834 (add-dependency-target name out)835 (when custom836 (prepare-custom-command cmd platform))837 (print-build-command (list out)838 `(,src ,eggfile ,@(if custom (list cmd) '())839 ,@(filelist srcdir source-dependencies)840 ,@(get-dependency-targets dependencies))841 `(,@(if custom '("sh") '())842 ,cmd "-setup-mode"843 ,@(if (eq? mode 'host) '("-host") '())844 "-s" "-c" "-C" ,(conc "-I" srcdir)845 ,@opts ,src "-o" ,out)846 platform)847 (print-end-command platform)))848849(define ((compile-dynamic-program name #!key source mode dependencies850 (options '()) (link-options '())851 source-dependencies852 custom eggfile link-objects)853 srcdir platform)854 (let* ((cmd (or (custom-cmd custom srcdir platform)855 default-csc))856 (sname (prefix srcdir name))857 (opts (if (null? options)858 default-dynamic-compilation-options859 options))860 (out (target-file (conc sname861 (executable-extension platform))862 mode))863 (lobjs (map (lambda (lo)864 (target-file (conc lo865 (object-extension platform))866 mode))867 link-objects))868 (src (or source (conc name ".scm"))))869 (when custom870 (prepare-custom-command cmd platform))871 (print-build-command (list out)872 `(,src ,eggfile ,@(if custom (list cmd) '())873 ,@(filelist srcdir source-dependencies)874 ,@(filelist srcdir lobjs)875 ,@(get-dependency-targets dependencies))876 `(,@(if custom '("sh") '())877 ,cmd ,@(if keep-generated-files '("-k") '())878 "-setup-mode"879 ,@(if (eq? mode 'host) '("-host") '())880 "-I" ,srcdir881 "-C" ,(conc "-I" srcdir)882 ,@opts ,@link-options ,src883 ,@(filelist srcdir lobjs)884 "-o" ,out)885 platform)886 (print-end-command platform)))887888(define ((compile-static-program name #!key source dependencies889 (options '()) (link-options '())890 source-dependencies891 custom mode eggfile link-objects)892 srcdir platform)893 (let* ((cmd (or (custom-cmd custom srcdir platform)894 default-csc))895 (sname (prefix srcdir name))896 (opts (if (null? options)897 default-static-compilation-options898 options))899 (out (target-file (conc sname900 (executable-extension platform))901 mode))902 (lobjs (map (lambda (lo)903 (target-file (conc lo904 (object-extension platform))905 mode))906 link-objects))907 (src (or source (conc name ".scm"))))908 (when custom909 (prepare-custom-command cmd platform))910 (print-build-command (list out)911 `(,src ,eggfile ,@(if custom (list cmd) '())912 ,@(filelist srcdir lobjs)913 ,@(filelist srcdir source-dependencies)914 ,@(get-dependency-targets dependencies))915 `(,@(if custom '("sh") '())916 ,cmd ,@(if keep-generated-files '("-k") '())917 ,@(if (eq? mode 'host) '("-host") '())918 "-static" "-setup-mode" "-I" ,srcdir919 "-C" ,(conc "-I" srcdir)920 ,@opts ,@link-options ,src921 ,@(filelist srcdir lobjs)922 "-o" ,out)923 platform)924 (print-end-command platform)))925926(define ((compile-generated-file name #!key source custom dependencies927 source-dependencies eggfile)928 srcdir platform)929 (let ((cmd (custom-cmd custom srcdir platform))930 (out (or source name)))931 (add-dependency-target name out)932 (prepare-custom-command cmd platform)933 (print-build-command (list out)934 (append935 (filelist srcdir source-dependencies)936 (get-dependency-targets dependencies))937 `("sh" ,cmd ,eggfile)938 platform)939 (print-end-command platform)))940941942;; installation operations943944(define ((install-static-extension name #!key mode output-file945 link-objects)946 srcdir platform)947 (let* ((cmd (install-file-command platform))948 (mkdir (mkdir-command platform))949 (ext (if (null? link-objects)950 (object-extension platform)951 (archive-extension platform)))952 (sname (prefix srcdir name))953 (out (qs* (target-file (conc sname ".static" ext) mode)))954 (outlnk (qs* (conc sname +link-file-extension+)))955 (dest (effective-destination-repository mode))956 (dfile (qs* dest))957 (ddir (shell-variable "DESTDIR")))958 (print "\n" mkdir " " ddir dfile)959 (print cmd " " out " " ddir960 (qs* (conc dest "/" output-file ext)))961 (print cmd " " outlnk " " ddir962 (qs* (conc dest "/" output-file +link-file-extension+)))963 (print-end-command platform)))964965(define ((install-dynamic-extension name #!key mode (ext ".so")966 output-file)967 srcdir platform)968 (let* ((cmd (install-executable-command platform))969 (mkdir (mkdir-command platform))970 (sname (prefix srcdir name))971 (out (qs* (target-file (conc sname ext) mode)))972 (dest (effective-destination-repository mode))973 (dfile (qs* dest))974 (ddir (shell-variable "DESTDIR"))975 (destf (qs* (conc dest "/" output-file ext))))976 (print "\n" mkdir " " ddir dfile)977 (print cmd " " out " " ddir destf)978 (print-end-command platform)))979980(define ((install-import-library name #!key mode)981 srcdir platform)982 ((install-dynamic-extension name mode: mode ext: ".import.so"983 output-file: name)984 srcdir platform))985986(define ((install-import-library-source name #!key mode)987 srcdir platform)988 (let* ((cmd (install-file-command platform))989 (mkdir (mkdir-command platform))990 (sname (prefix srcdir name))991 (out (qs* (target-file (conc sname ".import.scm") mode)))992 (dest (effective-destination-repository mode))993 (dfile (qs* dest))994 (ddir (shell-variable "DESTDIR")))995 (print "\n" mkdir " " ddir dfile)996 (print cmd " " out " " ddir997 (qs* (conc dest "/" name ".import.scm")))998 (print-end-command platform)))9991000(define ((install-types-file name #!key mode types-file)1001 srcdir platform)1002 (let* ((cmd (install-file-command platform))1003 (mkdir (mkdir-command platform))1004 (out (qs* (prefix srcdir (conc types-file ".types"))))1005 (dest (effective-destination-repository mode))1006 (dfile (qs* dest))1007 (ddir (shell-variable "DESTDIR")))1008 (print "\n" mkdir " " ddir dfile)1009 (print cmd " " out " " ddir1010 (qs* (conc dest "/" types-file ".types")))1011 (print-end-command platform)))10121013(define ((install-inline-file name #!key mode inline-file)1014 srcdir platform)1015 (let* ((cmd (install-file-command platform))1016 (mkdir (mkdir-command platform))1017 (out (qs* (prefix srcdir (conc inline-file ".inline"))))1018 (dest (effective-destination-repository mode))1019 (dfile (qs* dest))1020 (ddir (shell-variable "DESTDIR")))1021 (print "\n" mkdir " " ddir dfile)1022 (print cmd " " out " " ddir1023 (qs* (conc dest "/" inline-file ".inline")))1024 (print-end-command platform)))10251026(define ((install-program name #!key mode output-file) srcdir platform)1027 (let* ((cmd (install-executable-command platform))1028 (mkdir (mkdir-command platform))1029 (ext (executable-extension platform))1030 (sname (prefix srcdir name))1031 (out (qs* (target-file (conc sname ext) mode)))1032 (dest (if (eq? mode 'target)1033 default-bindir1034 (override-prefix "/bin" host-bindir)))1035 (dfile (qs* dest))1036 (ddir (shell-variable "DESTDIR"))1037 (destf (qs* (conc dest "/" output-file ext))))1038 (print "\n" mkdir " " ddir dfile)1039 (print cmd " " out " " ddir destf)1040 (print-end-command platform)))10411042(define ((install-object name #!key mode output-file) srcdir platform)1043 (let* ((cmd (install-file-command platform))1044 (mkdir (mkdir-command platform))1045 (ext (object-extension platform))1046 (sname (prefix srcdir name))1047 (out (qs* (target-file (conc sname ext) mode)))1048 (dest (effective-destination-repository mode))1049 (dfile (qs* dest))1050 (ddir (shell-variable "DESTDIR")))1051 (print "\n" mkdir " " ddir dfile)1052 (print cmd " " out " " ddir1053 (qs* (conc dest "/" output-file ext)))1054 (print-end-command platform)))10551056(define (install-random-files dest files mode srcdir platform)1057 (let* ((fcmd (install-file-command platform))1058 (dcmd (copy-directory-command platform))1059 (root (string-append srcdir "/"))1060 (mkdir (mkdir-command platform))1061 (sfiles (map (cut prefix srcdir <>) files))1062 (dfile (qs* dest))1063 (ddir (shell-variable "DESTDIR")))1064 (print "\n" mkdir " " ddir dfile)1065 (let-values (((ds fs) (partition directory? sfiles)))1066 (for-each1067 (lambda (d)1068 (let* ((ds (strip-dir-prefix srcdir d))1069 (fdir (pathname-directory ds)))1070 (when fdir1071 (print mkdir " " ddir1072 (qs* (make-pathname dest fdir))))1073 (print dcmd " " (qs* d)1074 " " ddir1075 (if fdir1076 (qs* (make-pathname dest fdir))1077 dfile))1078 (print-end-command platform)))1079 ds)1080 (when (pair? fs)1081 (for-each1082 (lambda (f)1083 (let* ((fs (strip-dir-prefix srcdir f))1084 (fdir (pathname-directory fs)))1085 (when fdir1086 (print mkdir " " ddir1087 (qs* (make-pathname dest fdir))))1088 (print fcmd " " (qs* f)1089 " " ddir1090 (if fdir1091 (qs* (make-pathname dest fdir))1092 dfile)))1093 (print-end-command platform))1094 fs)))))10951096(define ((install-data name #!key files destination mode)1097 srcdir platform)1098 (install-random-files (or destination1099 (if (eq? mode 'target)1100 default-sharedir1101 (override-prefix "/share"1102 host-sharedir)))1103 files mode srcdir platform))11041105(define ((install-c-include name #!key deps files destination mode)1106 srcdir platform)1107 (install-random-files (or destination1108 (if (eq? mode 'target)1109 default-incdir1110 (override-prefix "/include"1111 host-incdir)))1112 files mode srcdir platform))11131114;; manage dependency-targets11151116(define (add-dependency-target target output)1117 (cond ((assq target dependency-targets) =>1118 (lambda (a)1119 (set-cdr! a output)))1120 (else (set! dependency-targets1121 (cons (cons target output) dependency-targets)))))11221123(define (get-dependency-targets targets)1124 (append-map1125 (lambda (t)1126 (cond ((assq t dependency-targets) => (lambda (a) (list (cdr a))))1127 (else '())))1128 targets))112911301131;;; Generate shell or batch commands from abstract build/install operations11321133(define (generate-shell-commands platform cmds dest srcdir prefix suffix keep)1134 (fluid-let ((keep-generated-files keep))1135 (with-output-to-file dest1136 (lambda ()1137 (prefix platform)1138 (print (cd-command platform) " " (qs* srcdir))1139 (for-each1140 (lambda (cmd) (cmd srcdir platform))1141 cmds)1142 (suffix platform)))))114311441145;;; affixes for build- and install-scripts11461147(define ((build-prefix mode name info) platform)1148 (printf #<<EOF1149#!/bin/sh~%1150set -e1151PATH=~a:$PATH1152export CHICKEN_CC=~a1153export CHICKEN_CXX=~a1154export CHICKEN_CSC=~a1155export CHICKEN_CSI=~a11561157EOF1158 (qs* default-bindir) (qs* default-cc)1159 (qs* default-cxx) (qs* default-csc)1160 (qs* default-csi)))11611162(define ((build-suffix mode name info) platform)1163 (printf #<<EOF1164EOF1165 ))11661167(define ((install-prefix mode name info) platform)1168 (printf #<<EOF1169#!/bin/sh~%1170set -e11711172EOF1173 ))11741175(define ((install-suffix mode name info) platform)1176 (let* ((infostr (with-output-to-string (cut pp info)))1177 (dcmd (remove-file-command platform))1178 (mkdir (mkdir-command platform))1179 (dir (destination-repository mode))1180 (qdir (qs* dir))1181 (dest (qs* (make-pathname dir name +egg-info-extension+)))1182 (ddir (shell-variable "DESTDIR")))1183 (printf #<<EOF11841185~a ~a~a1186~a ~a~a1187cat >~a~a <<'ENDINFO'1188~aENDINFO~%1189EOF1190 mkdir ddir qdir1191 dcmd ddir dest1192 ddir dest infostr)))11931194;;; some utilities for mangling + quoting11951196(define (qs* arg)1197 (qs (->string arg)))11981199(define (prefix dir name)1200 (make-pathname dir (->string name)))12011202(define (system+ str platform)1203 (system (if (eq? platform 'windows)1204 (string-append "sh -c \"" str "\"")1205 str)))12061207(define (target-file fname mode)1208 (if (eq? mode 'target) (string-append fname ".target") fname))12091210(define (joins strs platform)1211 (string-intersperse (map qs* strs) " "))12121213(define (filelist dir lst)1214 (map (cut prefix dir <>) lst))12151216(define (shell-variable var)1217 (string-append "\"${" var "}\""))12181219(define prepare-custom-command void)12201221(define (custom-cmd custom srcdir platform)1222 (and custom (prefix srcdir custom)))12231224(define (print-build-command targets sources command-and-args platform)1225 (print "\n" (qs* default-builder) " "1226 (joins targets platform)1227 " : " (joins sources platform) " "1228 " : " (joins command-and-args platform)))12291230(define print-end-command void)12311232(define (strip-dir-prefix prefix fname)1233 (let* ((plen (string-length prefix))1234 (p1 (substring fname 0 plen)))1235 (assert (string=? prefix p1) "wrong prefix" prefix p1)1236 (substring fname (add1 plen))))12371238(define (maybe f x) (if f (list x) '()))12391240(define (ensure-line-limit str lim)1241 (when (>= (string-length str) lim)1242 (error "line length exceeds platform limit: " str))1243 str)