2024-11-25 22:06:44 +00:00
|
|
|
(define-library (zilch lang rust cargo)
|
|
|
|
|
(import
|
|
|
|
|
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
|
|
|
|
(zilch file) (zilch magic) (zilch nix drv) (zilch nix path) (scheme char)
|
|
|
|
|
(zilch nixpkgs) (zilch zexpr) (zilch semver)
|
|
|
|
|
json
|
|
|
|
|
(chicken process)
|
2024-11-27 17:32:13 +00:00
|
|
|
(chicken base) (chicken format)
|
2024-11-25 22:06:44 +00:00
|
|
|
(chicken foreign)
|
|
|
|
|
(srfi 4) (srfi 128) (srfi 146) (srfi 152) (srfi 207)
|
|
|
|
|
(zilch lang rust registry) (zilch lang rust) (zilch lang rust cfg)
|
2024-11-27 14:18:18 +00:00
|
|
|
(zilch lang rust cfg)
|
2024-11-27 15:43:29 +00:00
|
|
|
(zilch vfs))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(export
|
|
|
|
|
<cargo-target> make-cargo-target cargo-target?
|
|
|
|
|
cargo-target-name cargo-target-path cargo-target-test cargo-target-doctest
|
|
|
|
|
cargo-target-bench cargo-target-doc cargo-target-proc-macro cargo-target-harness
|
|
|
|
|
cargo-target-edition cargo-target-crate-type cargo-target-required-features
|
|
|
|
|
|
|
|
|
|
<cargo-dep-git> make-cargo-dep-git cargo-dep-git?
|
|
|
|
|
cargo-dep-git-url cargo-dep-git-rev-type cargo-dep-git-rev
|
|
|
|
|
<cargo-dep-path> make-cargo-dep-path cargo-dep-path? cargo-dep-path-path
|
|
|
|
|
<cargo-dep-registry> make-cargo-dep-registry cargo-dep-registry? cargo-dep-registry-name
|
|
|
|
|
|
|
|
|
|
<cargo-dependency> make-cargo-dependency cargo-dependency?
|
|
|
|
|
cargo-dependency-name cargo-dependency-origin cargo-dependency-version
|
|
|
|
|
cargo-dependency-default-features cargo-dependency-features cargo-dependency-package
|
|
|
|
|
cargo-dependency-optional
|
|
|
|
|
|
|
|
|
|
<cargo-crate> make-cargo-crate cargo-crate?
|
|
|
|
|
cargo-crate-name cargo-crate-version cargo-crate-edition cargo-crate-dependencies
|
|
|
|
|
cargo-crate-features cargo-crate-lib-target cargo-crate-targets
|
|
|
|
|
cargo-crate-build-dependencies cargo-crate-build-script
|
2025-03-02 20:29:57 +00:00
|
|
|
cargo-crate-links cargo-crate-check-cfg-lint
|
2024-11-25 22:06:44 +00:00
|
|
|
|
2024-11-27 14:16:01 +00:00
|
|
|
<cargo-workspace> make-cargo-workspace cargo-workspace?
|
|
|
|
|
cargo-workspace-members cargo-workspace-exclude cargo-workspace-dependencies
|
2025-03-02 14:09:00 +00:00
|
|
|
cargo-workspace-version cargo-workspace-edition
|
2024-11-27 14:16:01 +00:00
|
|
|
|
2024-11-27 14:18:18 +00:00
|
|
|
cfg-values
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
parse-cargo-toml)
|
|
|
|
|
|
|
|
|
|
(begin
|
|
|
|
|
(define linker (delay (let ((v (cdr (assoc "out" (nixpkgs "gcc"))))) #~,(string-append #$v "/bin/cc"))))
|
|
|
|
|
|
|
|
|
|
;; Shell out to a TOML-to-JSON parser. This will be replaced with a Nix-native solution later(tm).
|
|
|
|
|
(define (parse-toml toml-to-parse)
|
|
|
|
|
(define-values (read-port write-port pid) (process "yj" '("yj" "-tj")))
|
|
|
|
|
(write-string toml-to-parse write-port)
|
|
|
|
|
(close-output-port write-port)
|
|
|
|
|
(define parsed (json-read read-port))
|
|
|
|
|
(close-input-port read-port)
|
|
|
|
|
; (define-values (_ _ _) (process-wait pid))
|
|
|
|
|
parsed)
|
|
|
|
|
|
|
|
|
|
;; dependencies here is a list of (name . version-or-#f). if #f, use any version (should be unambiguous!)
|
|
|
|
|
(define-record-type <cargo-target>
|
|
|
|
|
(make-cargo-target name path test doctest bench doc proc-macro harness edition crate-type required-features)
|
|
|
|
|
cargo-target?
|
|
|
|
|
(name cargo-target-name) ; required other than for [lib]
|
|
|
|
|
(path cargo-target-path) ; inferred
|
|
|
|
|
(test cargo-target-test) ; true for [lib, bin, test]
|
|
|
|
|
(doctest cargo-target-doctest) ; true for lib
|
|
|
|
|
(bench cargo-target-bench) ; true for lib, bin, benchmark
|
|
|
|
|
(doc cargo-target-doc) ; true for lib, bin
|
|
|
|
|
(proc-macro cargo-target-proc-macro) ; only valid for lib
|
|
|
|
|
(harness cargo-target-harness) ; defaults to true
|
|
|
|
|
(edition cargo-target-edition) ; defaults to package's edition field
|
|
|
|
|
(crate-type cargo-target-crate-type) ; [bin, lib, rlib, dylib, cdylib, staticlib, proc-macro]
|
|
|
|
|
(required-features cargo-target-required-features)) ; list. has no effect on lib
|
|
|
|
|
|
|
|
|
|
(define-record-printer (<cargo-target> entry out)
|
|
|
|
|
(fprintf out "#<cargo-target ~S ~S test:~S doctest:~S bench:~S doc:~S proc-macro:~S harness:~S edition:~S ~S required-features:~S>"
|
|
|
|
|
(cargo-target-name entry)
|
|
|
|
|
(cargo-target-path entry)
|
|
|
|
|
(cargo-target-test entry)
|
|
|
|
|
(cargo-target-doctest entry)
|
|
|
|
|
(cargo-target-bench entry)
|
|
|
|
|
(cargo-target-doc entry)
|
|
|
|
|
(cargo-target-proc-macro entry)
|
|
|
|
|
(cargo-target-harness entry)
|
|
|
|
|
(cargo-target-edition entry)
|
|
|
|
|
(cargo-target-crate-type entry)
|
|
|
|
|
(cargo-target-required-features entry)))
|
|
|
|
|
|
|
|
|
|
; either:
|
|
|
|
|
; - git + optionally tag/rev/branch (this supports looking at workspace.toml, as an exception)
|
|
|
|
|
; - path (relative)
|
|
|
|
|
; - no info (crates.io), or manual `registry` name (mapped using .cargo/config.toml)
|
|
|
|
|
;
|
|
|
|
|
; then also:
|
|
|
|
|
; - version (optional other than for registry uses)
|
|
|
|
|
; - default-features
|
|
|
|
|
; - features
|
|
|
|
|
; - package (used for resolving against the registry)
|
|
|
|
|
; - optional (only if feature is enabled!)
|
|
|
|
|
; or like, workspace (+ optional/features, whee)
|
|
|
|
|
|
|
|
|
|
(define-record-type <cargo-dep-git>
|
|
|
|
|
(make-cargo-dep-git url rev-type rev)
|
|
|
|
|
cargo-dep-git?
|
|
|
|
|
(url cargo-dep-git-url)
|
|
|
|
|
(rev-type cargo-dep-git-rev-type)
|
|
|
|
|
(rev cargo-dep-git-rev))
|
|
|
|
|
|
|
|
|
|
(define-record-printer (<cargo-dep-git> entry out)
|
|
|
|
|
(fprintf out "#<cargo-dep-git ~S ~S ~S>"
|
|
|
|
|
(cargo-dep-git-url entry)
|
|
|
|
|
(cargo-dep-git-rev-type entry)
|
|
|
|
|
(cargo-dep-git-rev entry)))
|
|
|
|
|
|
|
|
|
|
(define-record-type <cargo-dep-path>
|
|
|
|
|
(make-cargo-dep-path path)
|
|
|
|
|
cargo-dep-path?
|
|
|
|
|
(path cargo-dep-path-path))
|
|
|
|
|
|
|
|
|
|
(define-record-printer (<cargo-dep-path> entry out)
|
|
|
|
|
(fprintf out "#<cargo-dep-path ~S>"
|
|
|
|
|
(cargo-dep-path-path entry)))
|
|
|
|
|
|
|
|
|
|
(define-record-type <cargo-dep-registry>
|
|
|
|
|
(make-cargo-dep-registry name)
|
|
|
|
|
cargo-dep-registry?
|
|
|
|
|
(name cargo-dep-registry-name))
|
|
|
|
|
(define-record-printer (<cargo-dep-registry> entry out)
|
|
|
|
|
(fprintf out "#<cargo-dep-registry ~S>"
|
|
|
|
|
(cargo-dep-registry-name entry)))
|
|
|
|
|
|
|
|
|
|
(define-record-type <cargo-dependency>
|
|
|
|
|
(make-cargo-dependency name origin version default-features features package optional)
|
|
|
|
|
cargo-dependency?
|
|
|
|
|
(name cargo-dependency-name)
|
|
|
|
|
(origin cargo-dependency-origin)
|
|
|
|
|
(version cargo-dependency-version)
|
|
|
|
|
(default-features cargo-dependency-default-features)
|
|
|
|
|
(features cargo-dependency-features)
|
|
|
|
|
(package cargo-dependency-package)
|
|
|
|
|
(optional cargo-dependency-optional))
|
|
|
|
|
(define-record-printer (<cargo-dependency> entry out)
|
|
|
|
|
(fprintf out "#<cargo-dependency ~S ~S v:~S default-features:~S features:~S package:~S optional:~S>"
|
|
|
|
|
(cargo-dependency-name entry)
|
|
|
|
|
(cargo-dependency-origin entry)
|
|
|
|
|
(cargo-dependency-version entry)
|
|
|
|
|
(cargo-dependency-default-features entry)
|
|
|
|
|
(cargo-dependency-features entry)
|
|
|
|
|
(cargo-dependency-package entry)
|
|
|
|
|
(cargo-dependency-optional entry)))
|
|
|
|
|
|
|
|
|
|
(define-record-type <cargo-crate>
|
2025-03-02 20:29:57 +00:00
|
|
|
(make-cargo-crate name version edition workspace dependencies build-dependencies features lib-target build-script targets links check-cfg-lint)
|
2024-11-25 22:06:44 +00:00
|
|
|
cargo-crate?
|
|
|
|
|
(name cargo-crate-name)
|
|
|
|
|
(version cargo-crate-version)
|
|
|
|
|
(edition cargo-crate-edition)
|
2024-11-27 14:16:01 +00:00
|
|
|
(workspace cargo-crate-workspace)
|
2024-11-25 22:06:44 +00:00
|
|
|
(dependencies cargo-crate-dependencies)
|
|
|
|
|
(build-dependencies cargo-crate-build-dependencies)
|
|
|
|
|
(features cargo-crate-features)
|
|
|
|
|
(lib-target cargo-crate-lib-target)
|
|
|
|
|
(build-script cargo-crate-build-script)
|
|
|
|
|
(targets cargo-crate-targets)
|
2025-03-02 20:29:57 +00:00
|
|
|
(links cargo-crate-links)
|
|
|
|
|
(check-cfg-lint cargo-crate-check-cfg-lint))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(define-record-printer (<cargo-crate> entry out)
|
|
|
|
|
(fprintf out "#<cargo-crate ~S ~S edition:~S dependencies:~S features:~S lib-target:~S targets:~S>"
|
|
|
|
|
(cargo-crate-name entry)
|
|
|
|
|
(cargo-crate-version entry)
|
|
|
|
|
(cargo-crate-edition entry)
|
|
|
|
|
(cargo-crate-dependencies entry)
|
|
|
|
|
(cargo-crate-features entry)
|
|
|
|
|
(cargo-crate-lib-target entry)
|
|
|
|
|
(cargo-crate-targets entry)))
|
2024-11-27 14:16:01 +00:00
|
|
|
|
|
|
|
|
(define-record-type <cargo-workspace>
|
2025-03-02 20:29:57 +00:00
|
|
|
(make-cargo-workspace members exclude dependencies edition version check-cfg-lint)
|
2024-11-27 14:16:01 +00:00
|
|
|
cargo-workspace?
|
|
|
|
|
(members cargo-workspace-members)
|
|
|
|
|
(exclude cargo-workspace-exclude)
|
2025-03-02 14:09:00 +00:00
|
|
|
(dependencies cargo-workspace-dependencies set-cargo-workspace-dependencies!)
|
|
|
|
|
(edition cargo-workspace-edition)
|
2025-03-02 20:29:57 +00:00
|
|
|
(version cargo-workspace-version)
|
|
|
|
|
(check-cfg-lint cargo-workspace-check-cfg-lint))
|
2024-11-27 14:16:01 +00:00
|
|
|
|
|
|
|
|
(define-record-printer (<cargo-workspace> entry out)
|
|
|
|
|
(fprintf out "#<cargo-workspace members:~S exclude:~S deps:~S>"
|
|
|
|
|
(cargo-workspace-members entry)
|
|
|
|
|
(cargo-workspace-exclude entry)
|
|
|
|
|
(cargo-workspace-dependencies entry)))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
2024-11-27 14:18:18 +00:00
|
|
|
(foreign-declare "#include \"cfgfetch_source.h\"")
|
|
|
|
|
(define cfgfetch-bin
|
|
|
|
|
(cdar
|
|
|
|
|
(call-rustc
|
|
|
|
|
(zfile (foreign-value "cfgfetch_source" nonnull-c-string)) '()
|
|
|
|
|
#:codegen-flags (cons "linker" (force linker))
|
|
|
|
|
#:crate-type 'bin
|
|
|
|
|
#:crate-name "cfgfetch"
|
|
|
|
|
#:edition "2021"
|
|
|
|
|
#:emits '(#:link #t))))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(define cfg-target "x86_64-unknown-linux-gnu")
|
2024-11-27 14:18:18 +00:00
|
|
|
(define (read-cfg-value port rest)
|
|
|
|
|
(define line (read-line port))
|
|
|
|
|
(if (eof-object? line)
|
|
|
|
|
rest
|
|
|
|
|
(let* ((line (cfg-parse line)))
|
|
|
|
|
(read-cfg-value port (cons (cdr line) rest)))))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(define cfg-values
|
2024-11-27 14:18:18 +00:00
|
|
|
(let ((vals (cdar (store-path-for-ca-drv* "cfg-values" "x86_64-linux" #~(#$cfgfetch-bin) #~(("rustc" . ,(string-append #$rustc "/bin/rustc"))) '("out")))))
|
|
|
|
|
(call-with-port (store-path-open vals) (lambda (p) (read-cfg-value p '())))))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(define (cratify-name name)
|
|
|
|
|
; NOTE! string-map _has_ to return a char. non-chars are mistreated and cause memory corruption.
|
|
|
|
|
; TODO(puck): check this post-C6
|
|
|
|
|
(string-map (lambda (v) (if (char=? v #\-) #\_ v)) name))
|
|
|
|
|
|
|
|
|
|
(define (and-cdr val)
|
|
|
|
|
(and val (cdr val)))
|
|
|
|
|
|
|
|
|
|
(define (and-cdr-default val default)
|
|
|
|
|
(if val (cdr val) default))
|
|
|
|
|
|
2024-11-27 14:16:01 +00:00
|
|
|
(define (find-dependency-in-list l dep-name)
|
|
|
|
|
(cond
|
|
|
|
|
((null? l) #f)
|
|
|
|
|
((string=? dep-name (cargo-dependency-name (car l))) (car l))
|
|
|
|
|
(else (find-dependency-in-list (cdr l) dep-name))))
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(define (cargo-dependency-from-toml name object workspace for-workspace)
|
2024-11-25 22:06:44 +00:00
|
|
|
(define object-internals (vector->list object))
|
|
|
|
|
(define version (and-cdr (assoc "version" object-internals)))
|
2025-03-02 14:09:00 +00:00
|
|
|
(define default-features (and-cdr-default (or (assoc "default-features" object-internals) (assoc "default_features" object-internals)) #t))
|
2024-11-25 22:06:44 +00:00
|
|
|
(define pkg-features (and-cdr-default (assoc "features" object-internals) '()))
|
|
|
|
|
(define package (or (and-cdr (assoc "package" object-internals)) name))
|
|
|
|
|
(define optional (and-cdr (assoc "optional" object-internals)))
|
|
|
|
|
|
|
|
|
|
(define git-url (and-cdr (assoc "git" object-internals)))
|
|
|
|
|
(define git-tag (and-cdr (assoc "tag" object-internals)))
|
|
|
|
|
(define git-rev (and-cdr (assoc "rev" object-internals)))
|
|
|
|
|
(define git-branch (and-cdr (assoc "branch" object-internals)))
|
|
|
|
|
|
|
|
|
|
(define registry-name (and-cdr (assoc "registry" object-internals)))
|
|
|
|
|
(define path (and-cdr (assoc "path" object-internals)))
|
2024-11-27 14:16:01 +00:00
|
|
|
|
|
|
|
|
(define is-workspace (and-cdr (assoc "workspace" object-internals)))
|
|
|
|
|
(when (and is-workspace (not workspace))
|
|
|
|
|
(error "Dependency uses workspace=true, whilst not a workspace" (cons name object-internals)))
|
|
|
|
|
|
|
|
|
|
(define workspace-dep
|
|
|
|
|
(and is-workspace (find-dependency-in-list (cargo-workspace-dependencies workspace) name)))
|
|
|
|
|
(when (and is-workspace (not workspace-dep))
|
|
|
|
|
(error "Dependency could not be found in workspace" name))
|
|
|
|
|
(when workspace-dep
|
|
|
|
|
(set! version (cargo-dependency-version workspace-dep))
|
|
|
|
|
(set! default-features (cargo-dependency-default-features workspace-dep))
|
|
|
|
|
(for-each
|
|
|
|
|
(lambda (feature) (unless (member feature pkg-features)) (set! pkg-features (cons feature pkg-features)))
|
|
|
|
|
(cargo-dependency-features workspace-dep))
|
|
|
|
|
(set! package (cargo-dependency-package workspace-dep)))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(define origin (cond
|
2024-11-27 14:16:01 +00:00
|
|
|
(workspace-dep (cargo-dependency-origin workspace-dep))
|
2025-03-02 14:09:00 +00:00
|
|
|
(path (make-cargo-dep-path (if for-workspace (cons 'workspace path) path)))
|
2024-11-25 22:06:44 +00:00
|
|
|
(registry-name (make-cargo-dep-registry registry-name))
|
|
|
|
|
((and git-url git-tag) (make-cargo-dep-git git-url 'tag git-tag))
|
|
|
|
|
((and git-url git-rev) (make-cargo-dep-git git-url 'rev git-rev))
|
|
|
|
|
((and git-url git-branch) (make-cargo-dep-git git-url 'branch git-branch))
|
|
|
|
|
(git-url (make-cargo-dep-git git-url #f #f))
|
|
|
|
|
(else (make-cargo-dep-registry #f))))
|
2025-03-02 14:09:00 +00:00
|
|
|
(make-cargo-dependency name origin version default-features pkg-features package optional))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
;; base-type is lib/bin/example/test/benchmark
|
2025-03-02 14:09:00 +00:00
|
|
|
(define (cargo-target-from-toml vfs object crate-name base-type base-edition)
|
2024-11-25 22:06:44 +00:00
|
|
|
(define object-internals (vector->list object))
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(define (multifile-if-available base name)
|
|
|
|
|
(if (vfs-file-ref vfs (string-append base name) "main.rs")
|
|
|
|
|
(string-append base name "/main.rs")
|
|
|
|
|
(string-append base name ".rs")))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(unless (or (eq? base-type 'lib) (assoc "name" object-internals)) (error "cargo target has no name"))
|
2024-11-27 14:19:09 +00:00
|
|
|
(define name (cratify-name (or (and-cdr (assoc "name" object-internals)) crate-name)))
|
2024-11-25 22:06:44 +00:00
|
|
|
(define path (or (and-cdr (assoc "path" object-internals))
|
|
|
|
|
(case base-type
|
|
|
|
|
((lib) "src/lib.rs")
|
|
|
|
|
;; TODO(puck): multi-file
|
2025-03-02 14:09:00 +00:00
|
|
|
((bin) (multifile-if-available "src/bin/" name))
|
|
|
|
|
((example) (multifile-if-available "examples/" name))
|
|
|
|
|
((test) (multifile-if-available "tests/" name))
|
|
|
|
|
((benchmark) (multifile-if-available "benches/" name)))))
|
2024-11-25 22:06:44 +00:00
|
|
|
(define test (and-cdr-default (assoc "test" object-internals) (member base-type '(lib bin test))))
|
|
|
|
|
(define doctest (and-cdr-default (assoc "doctest" object-internals) (eq? base-type 'lib)))
|
|
|
|
|
(define bench (and-cdr-default (assoc "bench" object-internals) (member base-type '(lib bin benchmark))))
|
|
|
|
|
(define doc (and-cdr-default (assoc "doc" object-internals) (member base-type '(lib bin))))
|
|
|
|
|
(define proc-macro (and (eq? base-type 'lib) (and-cdr (assoc "proc-macro" object-internals))))
|
|
|
|
|
(define harness (and-cdr-default (assoc "harness" object-internals) #t))
|
|
|
|
|
(define edition (or (and-cdr (assoc "edition" object-internals)) base-edition))
|
|
|
|
|
(define crate-type (if (assoc "crate-type" object-internals)
|
|
|
|
|
(map string->symbol (cdr (assoc "crate-type" object-internals)))
|
|
|
|
|
(cond
|
|
|
|
|
(proc-macro 'proc-macro)
|
|
|
|
|
((eq? base-type 'lib) 'lib)
|
|
|
|
|
((eq? base-type 'example) 'bin)
|
|
|
|
|
(else 'bin))))
|
|
|
|
|
(define required-features (or (and-cdr (assoc "required-features" object-internals)) '()))
|
|
|
|
|
|
|
|
|
|
(make-cargo-target name path test doctest bench doc proc-macro harness edition crate-type required-features))
|
|
|
|
|
|
|
|
|
|
; A feature is two parts: ((crate-name . activates-crate) package-feature)
|
|
|
|
|
; "dep:foo" resolves to (("foo" . #t) . #f)
|
|
|
|
|
; "foo/bar" resolves to (("foo" . #t) . "bar")
|
|
|
|
|
; "foo?/bar" resolves to (("foo" . #f) . "bar")
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(define (parse-features feature-alist dependency-names build-dependency-names)
|
2024-11-25 22:06:44 +00:00
|
|
|
(define needs-implicit-dependency (mapping (make-default-comparator)))
|
|
|
|
|
(for-each (lambda (name) (set! needs-implicit-dependency (mapping-set! needs-implicit-dependency name #t))) dependency-names)
|
2025-03-02 14:09:00 +00:00
|
|
|
(for-each (lambda (name) (set! needs-implicit-dependency (mapping-set! needs-implicit-dependency name #t))) build-dependency-names)
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(define (parse-feature-string str)
|
|
|
|
|
(if (string-prefix? "dep:" str)
|
|
|
|
|
(let ((name (string-copy str 4)))
|
|
|
|
|
(set! needs-implicit-dependency (mapping-set! needs-implicit-dependency name #f))
|
|
|
|
|
(cons name (cons #t #f)))
|
|
|
|
|
(let* ((index (string-contains str "/"))
|
|
|
|
|
(first-half (if index (string-copy str 0 index) str))
|
|
|
|
|
(second-half (and index (string-copy str (+ index 1))))
|
|
|
|
|
(first-half-is-optional (string-suffix? "?" first-half))
|
|
|
|
|
(first-half-not-optional (if first-half-is-optional (string-copy str 0 (- index 1)) first-half)))
|
|
|
|
|
(if second-half
|
|
|
|
|
(cons first-half-not-optional (cons (not first-half-is-optional) second-half))
|
|
|
|
|
(cons #f (cons #t first-half))))))
|
|
|
|
|
|
|
|
|
|
(define parsed (map (lambda (kv) (cons (car kv) (map parse-feature-string (cdr kv)))) feature-alist))
|
|
|
|
|
(mapping-for-each (lambda (k v) (when v (set! parsed (cons (list k (cons k (cons #t #f))) parsed)))) needs-implicit-dependency)
|
|
|
|
|
parsed)
|
|
|
|
|
|
2024-11-27 14:16:01 +00:00
|
|
|
(define (parse-cargo-package vfs internals workspace)
|
2025-03-02 14:09:00 +00:00
|
|
|
(unless vfs (error "no vfs"))
|
2024-11-25 22:06:44 +00:00
|
|
|
(define package (vector->list (cdr (assoc "package" internals))))
|
|
|
|
|
(define package-name (cdr (assoc "name" package)))
|
|
|
|
|
(define package-version (cdr (assoc "version" package)))
|
|
|
|
|
(define package-links (and-cdr (assoc "links" package)))
|
|
|
|
|
(define package-edition (or (and-cdr (assoc "edition" package)) "2015"))
|
2024-11-27 14:20:55 +00:00
|
|
|
|
2025-03-02 20:29:57 +00:00
|
|
|
(define lints (vector->list (or (and-cdr (assoc "lints" internals)) #())))
|
|
|
|
|
(define lints-rust (vector->list (or (and-cdr (assoc "rust" lints)) #())))
|
|
|
|
|
(define lints-rust-unexpected-cfgs (vector->list (or (and-cdr (assoc "unexpected_cfgs" lints-rust)) #())))
|
|
|
|
|
(define check-cfg (or (and-cdr (assoc "check-cfg" lints-rust-unexpected-cfgs)) '()))
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(when (and (vector? package-edition) (and-cdr (assoc "workspace" (vector->list package-edition))))
|
|
|
|
|
(unless workspace (error "Package used edition.workspace = true, but no workspace provided" package-name))
|
|
|
|
|
(set! package-edition (cargo-workspace-edition workspace)))
|
|
|
|
|
|
|
|
|
|
(when (and (vector? package-version) (and-cdr (assoc "workspace" (vector->list package-version))))
|
|
|
|
|
(unless workspace (error "Package used version.workspace = true, but no workspace provided" package-name))
|
|
|
|
|
(set! package-version (cargo-workspace-version workspace)))
|
|
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(define lib-target #f)
|
2024-11-27 17:32:13 +00:00
|
|
|
(when (or (assoc "lib" internals) (vfs-file-ref vfs "src" "lib.rs"))
|
2025-03-02 14:09:00 +00:00
|
|
|
(set! lib-target (cargo-target-from-toml vfs (or (and-cdr (assoc "lib" internals)) #()) package-name 'lib package-edition)))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(define other-targets '())
|
2025-03-02 14:09:00 +00:00
|
|
|
(cond
|
|
|
|
|
((assoc "bin" internals)
|
|
|
|
|
(for-each
|
|
|
|
|
(lambda (bindata)
|
|
|
|
|
(set! other-targets (cons (cargo-target-from-toml vfs bindata package-name 'bin package-edition) other-targets)))
|
|
|
|
|
(cdr (assoc "bin" internals))))
|
|
|
|
|
((vfs-file-ref vfs "src" "main.rs")
|
|
|
|
|
(set! other-targets (cons (cargo-target-from-toml vfs (vector (cons "name" package-name) (cons "path" "src/main.rs")) package-name 'bin package-edition) other-targets))))
|
2024-11-27 14:19:09 +00:00
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
(define build-file-path (and-cdr (assoc "build" package)))
|
2024-11-27 17:32:13 +00:00
|
|
|
(when (vfs-file-ref vfs "" "build.rs")
|
2024-11-27 14:19:09 +00:00
|
|
|
(set! build-file-path "build.rs"))
|
2024-11-25 22:06:44 +00:00
|
|
|
(define build-script-target #f)
|
|
|
|
|
(when build-file-path
|
2024-11-27 14:19:09 +00:00
|
|
|
(set! build-script-target (make-cargo-target (cratify-name (string-append package-name "_buildscript")) build-file-path #f #f #f #f #f #f package-edition 'bin '("default"))))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
(define dependencies
|
|
|
|
|
(map
|
|
|
|
|
(lambda (kv)
|
2025-03-02 14:09:00 +00:00
|
|
|
(cargo-dependency-from-toml (car kv) (if (string? (cdr kv)) (vector (cons "version" (cdr kv))) (cdr kv)) workspace #f))
|
2024-11-25 22:06:44 +00:00
|
|
|
(vector->list (or (and-cdr (assoc "dependencies" internals)) #()))))
|
2024-11-27 14:19:09 +00:00
|
|
|
|
2024-11-25 22:06:44 +00:00
|
|
|
;; TODO(puck): target.{matching cfg}.build-dependencies???
|
|
|
|
|
(define build-dependencies
|
|
|
|
|
(map
|
|
|
|
|
(lambda (kv)
|
2025-03-02 14:09:00 +00:00
|
|
|
(cargo-dependency-from-toml (car kv) (if (string? (cdr kv)) (vector (cons "version" (cdr kv))) (cdr kv)) workspace #f))
|
|
|
|
|
(vector->list (or (and-cdr (or (assoc "build-dependencies" internals) (assoc "build_dependencies" internals))) #()))))
|
2024-11-25 22:06:44 +00:00
|
|
|
|
|
|
|
|
; Merge in dependencies in target.{matching cfg or target}.dependencies?
|
|
|
|
|
(for-each
|
|
|
|
|
(lambda (target-pair)
|
|
|
|
|
(define target (car target-pair))
|
|
|
|
|
(define contents (cdr target-pair))
|
|
|
|
|
(define matches
|
|
|
|
|
(if (and (string-prefix? "cfg(" target) (string-suffix? ")" target))
|
|
|
|
|
(cfg-matches (cfg-parse (string-copy target 4 (- (string-length target) 1))) cfg-values)
|
|
|
|
|
(string=? target cfg-target)))
|
|
|
|
|
(when matches
|
|
|
|
|
(set! dependencies
|
|
|
|
|
(append
|
|
|
|
|
(map
|
|
|
|
|
(lambda (kv)
|
2025-03-02 14:09:00 +00:00
|
|
|
(cargo-dependency-from-toml (car kv) (if (string? (cdr kv)) (vector (cons "version" (cdr kv))) (cdr kv)) workspace #f))
|
2024-11-25 22:06:44 +00:00
|
|
|
(vector->list (or (and-cdr (assoc "dependencies" (vector->list contents))) #())))
|
|
|
|
|
dependencies))))
|
|
|
|
|
(vector->list (or (and-cdr (assoc "target" internals)) #())))
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(define own-features (parse-features (vector->list (or (and-cdr (assoc "features" internals)) #())) (map cargo-dependency-name dependencies) (map cargo-dependency-name build-dependencies)))
|
2025-03-02 20:29:57 +00:00
|
|
|
(make-cargo-crate package-name package-version package-edition workspace dependencies build-dependencies own-features lib-target build-script-target other-targets package-links (append check-cfg (if workspace (cargo-workspace-check-cfg-lint workspace) '()))))
|
2024-11-27 14:16:01 +00:00
|
|
|
|
|
|
|
|
(define (parse-cargo-workspace internals)
|
|
|
|
|
(define workspace (vector->list (cdr (assoc "workspace" internals))))
|
|
|
|
|
(define workspace-members (or (and-cdr (assoc "members" workspace)) '()))
|
|
|
|
|
(define workspace-exclude (or (and-cdr (assoc "exclude" workspace)) '()))
|
|
|
|
|
|
2025-03-02 20:29:57 +00:00
|
|
|
(define lints (vector->list (or (and-cdr (assoc "lints" internals)) #())))
|
|
|
|
|
(define lints-rust (vector->list (or (and-cdr (assoc "rust" lints)) #())))
|
|
|
|
|
(define lints-rust-unexpected-cfgs (vector->list (or (and-cdr (assoc "unexpected_cfgs" lints-rust)) #())))
|
|
|
|
|
(define check-cfg (or (and-cdr (assoc "check-cfg" lints-rust-unexpected-cfgs)) '()))
|
|
|
|
|
|
2025-03-02 14:09:00 +00:00
|
|
|
(define package (vector->list (or (and-cdr (assoc "package" workspace)) #())))
|
|
|
|
|
(define package-edition (and-cdr (assoc "edition" package)))
|
|
|
|
|
(define package-version (and-cdr (assoc "version" package)))
|
|
|
|
|
|
2025-03-02 20:29:57 +00:00
|
|
|
(define workspace-record (make-cargo-workspace workspace-members workspace-exclude #f package-edition package-version check-cfg))
|
2024-11-27 14:16:01 +00:00
|
|
|
(define dependencies
|
|
|
|
|
(map
|
|
|
|
|
(lambda (kv)
|
2025-03-02 14:09:00 +00:00
|
|
|
(cargo-dependency-from-toml (car kv) (if (string? (cdr kv)) (vector (cons "version" (cdr kv))) (cdr kv)) #f #t))
|
2024-11-27 14:16:01 +00:00
|
|
|
(vector->list (or (and-cdr (assoc "dependencies" workspace)) #()))))
|
2025-03-02 14:09:00 +00:00
|
|
|
(set-cargo-workspace-dependencies! workspace-record dependencies)
|
|
|
|
|
workspace-record)
|
2024-11-27 14:16:01 +00:00
|
|
|
|
|
|
|
|
(define (parse-cargo-toml vfs cargo-file workspace)
|
|
|
|
|
(define internals (vector->list (parse-toml cargo-file)))
|
|
|
|
|
(define crate #f)
|
|
|
|
|
(when (assoc "workspace" internals)
|
|
|
|
|
(when workspace
|
|
|
|
|
(error "Crate already is in a workspace." cargo-file))
|
|
|
|
|
(set! workspace (parse-cargo-workspace internals)))
|
|
|
|
|
(when (assoc "package" internals)
|
|
|
|
|
(set! crate (parse-cargo-package vfs internals workspace)))
|
|
|
|
|
(values crate workspace))))
|
|
|
|
|
|