(zilch lang ninja build): add support for secondary VFS roots

These are used for implementing cross-project incremental builds.
This commit is contained in:
puck 2025-07-26 15:42:17 +00:00
parent 7acb3005f8
commit 8e711a4b0b

View file

@ -40,14 +40,15 @@
(phony-inputs built-edge-phony-inputs)) (phony-inputs built-edge-phony-inputs))
(define-record-type <build-env> (define-record-type <build-env>
(make-build-env config vfs header-files build-dir parsed-depfiles collected-deps) (make-build-env config vfs header-files build-dir parsed-depfiles collected-deps secondary-vfs-setup)
build-env? build-env?
(config build-env-config) (config build-env-config)
(vfs build-env-vfs set-build-env-vfs!) (vfs build-env-vfs set-build-env-vfs!)
(header-files build-env-header-files set-build-env-header-files!) (header-files build-env-header-files set-build-env-header-files!)
(build-dir build-env-build-dir) (build-dir build-env-build-dir)
(parsed-depfiles build-env-parsed-depfiles) (parsed-depfiles build-env-parsed-depfiles)
(collected-deps build-env-collected-deps set-build-env-collected-deps!)) (collected-deps build-env-collected-deps set-build-env-collected-deps!)
(secondary-vfs-setup build-env-secondary-vfs-setup))
;; normalize a POSIX-y path. Ninja doesn't have an internal concept of path normalisation, ;; normalize a POSIX-y path. Ninja doesn't have an internal concept of path normalisation,
;; so this is necessary for proper file-finding behavior. ;; so this is necessary for proper file-finding behavior.
@ -98,6 +99,7 @@
(cond (cond
; if input-file is 'base, this is part of the base vfs; we don't filter that right now. ; if input-file is 'base, this is part of the base vfs; we don't filter that right now.
((eq? input-file 'base) #f) ((eq? input-file 'base) #f)
((and (pair? input-file) (eq? (car input-file) 'base-vfs)) #f)
; Phony rule; pass through the inputs literally. ; Phony rule; pass through the inputs literally.
((eq? input-file 'phony) (for-each append-file (built-edge-phony-inputs input-edge))) ((eq? input-file 'phony) (for-each append-file (built-edge-phony-inputs input-edge)))
@ -105,7 +107,9 @@
; This file is produced by another build edge. Add it to our input vfs. ; This file is produced by another build edge. Add it to our input vfs.
(input-file (input-file
(let ((prev-copy-input-files copy-input-files)) (let ((prev-copy-input-files copy-input-files))
(set! copy-input-files #~,(string-append #$prev-copy-input-files "\n" "$COREUTILS/mkdir -p bdir/" (build-env-build-dir env) "/$($COREUTILS/dirname " path "); $COREUTILS/cp -rf --preserve=timestamps " #$(force input-file) " bdir/" (build-env-build-dir env) "/" path)))) (if (string-prefix? "/nix/store" path)
(set! copy-input-files #~,(string-append #$prev-copy-input-files "\n" "$COREUTILS/mkdir -p $($COREUTILS/dirname " path "); $COREUTILS/cp -rf --preserve=timestamps " #$(force input-file) " /" path))
(set! copy-input-files #~,(string-append #$prev-copy-input-files "\n" "$COREUTILS/mkdir -p bdir/" (build-env-build-dir env) "/$($COREUTILS/dirname " path "); $COREUTILS/cp -rf --preserve=timestamps " #$(force input-file) " bdir/" (build-env-build-dir env) "/" path)))))
(else (else
(unless (string-prefix? "/nix/store" path) (unless (string-prefix? "/nix/store" path)
@ -215,7 +219,7 @@
#$coreutils "/bin/chmod ugo+rw -R bdir\n" #$coreutils "/bin/chmod ugo+rw -R bdir\n"
; Copy over the other input files. ; Copy over the other input files.
"(COREUTILS=" #$coreutils "/bin; " #$copy-input-files ")\n" "(COREUTILS=" #$coreutils "/bin; " #$(build-env-secondary-vfs-setup env) #$copy-input-files ")\n"
#$coreutils "/bin/chmod ugo+rw -R bdir\n" #$coreutils "/bin/chmod ugo+rw -R bdir\n"
; Run any patches we have received. ; Run any patches we have received.
@ -242,7 +246,13 @@
(define parsed-depfile (parse-depfile depfile-bytes)) (define parsed-depfile (parse-depfile depfile-bytes))
(define data (cdar (mapping->alist parsed-depfile))) (define data (cdar (mapping->alist parsed-depfile)))
(define filtered '()) (define filtered '())
(for-each (lambda (item) (unless (string-prefix? "/nix/store/" item) (set! filtered (cons item filtered)))) data) (for-each
(lambda (item)
(define is-in-store (string-prefix? "/nix/store" item))
(when is-in-store (set! item (normalize-path item)))
(when (or (not is-in-store) (member item (build-env-header-files env) string=?))
(set! filtered (cons item filtered))))
data)
(set-build-env-collected-deps! env (mapping-set! (build-env-collected-deps env) depfile filtered))))) (set-build-env-collected-deps! env (mapping-set! (build-env-collected-deps env) depfile filtered)))))
outpath) outpath)
@ -335,11 +345,19 @@
;; handle this Ninja file. ;; handle this Ninja file.
;; - `relative-to`: The directory in which the Ninja file was found. Used to ;; - `relative-to`: The directory in which the Ninja file was found. Used to
;; resolve relative references in the Ninja file. ;; resolve relative references in the Ninja file.
(define (process-ninja-file file conf relative-to) ;; - `secondary-roots`: A list of (store-path-map finalized base-vfs-store-path-map (overlay-path-0 . promise-to-store-path) ... . (overlay-path-n . promise-to-store-path)) alists. i _guess_.
(define (process-ninja-file file conf relative-to secondary-roots)
(unless (or (string=? relative-to "") (string-suffix? "/" relative-to)) (set! relative-to (string-append relative-to "/"))) (unless (or (string=? relative-to "") (string-suffix? "/" relative-to)) (set! relative-to (string-append relative-to "/")))
(define edges (mapping (make-default-comparator))) (define edges (mapping (make-default-comparator)))
(define (setup-secondary-vfs k v)
#~,(string-append
"$COREUTILS/cp -rf --no-preserve=ownership " #$v " " k "; "
"$COREUTILS/chmod ugo+rw -R " k "; "))
(define all-rewrites (apply append (map (lambda (v) (mapping-map->list setup-secondary-vfs (car (cddr v)))) secondary-roots)))
(define secondary-vfs-setup #~,(apply string-append #$all-rewrites))
(define path-to-vfs (define path-to-vfs
(mapping (make-default-comparator))) (mapping (make-default-comparator)))
(mapping-for-each (mapping-for-each
@ -358,7 +376,7 @@
(set! path-to-vfs (mapping-set! path-to-vfs path kv))) (set! path-to-vfs (mapping-set! path-to-vfs path kv)))
(vfs-contents (ninja-build-config-root-dir conf))) (vfs-contents (ninja-build-config-root-dir conf)))
(define filtered-vfs (mapping-copy (vfs-contents (ninja-build-config-root-dir conf)))) (define filtered-vfs (mapping-copy (vfs-contents (ninja-build-config-root-dir conf))))
(define env (make-build-env conf #f '() relative-to (or (ninja-build-config-depfile conf) (mapping (make-default-comparator))) (mapping (make-default-comparator)))) (define env (make-build-env conf #f '() relative-to (or (ninja-build-config-depfile conf) (mapping (make-default-comparator))) (mapping (make-default-comparator)) secondary-vfs-setup))
(define (elide-vfs rel-path kv) (define (elide-vfs rel-path kv)
(define vfs-path (if (string=? (car kv) "") (cdr kv) (string-append (car kv) "/" (cdr kv)))) (define vfs-path (if (string=? (car kv) "") (cdr kv) (string-append (car kv) "/" (cdr kv))))
@ -425,6 +443,16 @@
all-outputs))) all-outputs)))
(build-file-build-edges file)) (build-file-build-edges file))
; Register elided header files from secondary roots
(for-each
(lambda (secondary-root)
(for-each
(lambda (path-promise-pair)
(set! edges (mapping-set! edges (car path-promise-pair) (cons (cdr path-promise-pair) #f)))
(set-build-env-header-files! env (cons (car path-promise-pair) (build-env-header-files env))))
(cdr (cddr secondary-root))))
secondary-roots)
; Finish VFS filtering by taking out everything under build/meson-private. ; Finish VFS filtering by taking out everything under build/meson-private.
; This operates on the absolute VFS paths. ; This operates on the absolute VFS paths.
(set! filtered-vfs (set! filtered-vfs
@ -440,7 +468,7 @@
(define edge-ref (define edge-ref
(lambda (path) (lambda (path)
(define edge (mapping-ref edges path (lambda () (error "Target doesn't exist" path)))) (define edge (mapping-ref edges path (lambda () (mapping-ref edges (normalize-path path) (lambda () (error "Target doesn't exist" path))))))
(cons (if (promise? (car edge)) (force (car edge)) (car edge)) (force (cdr edge))))) (cons (if (promise? (car edge)) (force (car edge)) (car edge)) (force (cdr edge)))))
(define defaults (build-file-default-targets file)) (define defaults (build-file-default-targets file))
(values edge-ref defaults (lambda () (build-env-collected-deps env)))))) (values edge-ref defaults (lambda () (build-env-collected-deps env))))))