(zilch lang rust): document
Change-Id: I6a6a6964c8aaff8d5f3e18bc5c7486746b5a2952
This commit is contained in:
parent
ae774da043
commit
0340f6e830
10 changed files with 597 additions and 82 deletions
|
|
@ -1,3 +1,4 @@
|
|||
;; Helper procedure to call a build script with the right working directory.
|
||||
(define-library (zilch lang rust build-script)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -26,7 +27,9 @@
|
|||
#:crate-name "runner"
|
||||
#:edition "2021"
|
||||
#:emits '(#:link #t))))
|
||||
|
||||
|
||||
;; Call a build script with specified current working directory (as string)
|
||||
;; and environment (as alist).
|
||||
(define (call-runner input-script cwd env)
|
||||
(define output (store-path-for-ca-drv* "build.rs-run" "x86_64-linux"
|
||||
`(,runner-runner)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
;; Procedures to parse Cargo files.
|
||||
(define-library (zilch lang rust cargo)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -13,21 +14,6 @@
|
|||
(zilch vfs))
|
||||
|
||||
(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
|
||||
|
|
@ -38,6 +24,21 @@
|
|||
cargo-workspace-members cargo-workspace-exclude cargo-workspace-dependencies
|
||||
cargo-workspace-version cargo-workspace-edition
|
||||
|
||||
<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-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-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
|
||||
|
||||
cfg-values
|
||||
|
||||
parse-cargo-toml)
|
||||
|
|
@ -56,7 +57,22 @@
|
|||
; (define-values (_ _ _) (process-wait pid))
|
||||
parsed)
|
||||
|
||||
;; dependencies here is a list of (name . version-or-#f). if #f, use any version (should be unambiguous!)
|
||||
;; A single target for a crate.
|
||||
;;
|
||||
;; Each crate consists of multiple targets; e.g. `lib`, ``bin``s, and things like test/doctest.
|
||||
;;
|
||||
;; The fields of this record closely match the Cargo.toml. For more information on these, see https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target:[the Cargo documentation].
|
||||
;;
|
||||
;; - `name`: The name of this target. By default, the name of the binary or
|
||||
;; of the crate, if lib.
|
||||
;; - `path`: The root source file for this target (e.g. `"src/lib.rs"`, `"src/bin/example.rs"`).
|
||||
;; Relative to the crate's root.
|
||||
;; - `crate-type`: The type of crate, as a symbol (bin, lib, rlib, etc).
|
||||
;; - `edition`: The target's edition
|
||||
;; - `required-features`: A specifying which features on the `lib` have to be set.
|
||||
;; (non-lib targets implicitly depend on the lib target)
|
||||
;;
|
||||
;; Based on the `crate-type` the other fields may be valid; these closely match the `Cargo.toml`'s definitions as well.
|
||||
(define-record-type <cargo-target>
|
||||
(make-cargo-target name path test doctest bench doc proc-macro harness edition crate-type required-features)
|
||||
cargo-target?
|
||||
|
|
@ -71,7 +87,7 @@
|
|||
(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)
|
||||
|
|
@ -85,7 +101,7 @@
|
|||
(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)
|
||||
|
|
@ -98,7 +114,10 @@
|
|||
; - package (used for resolving against the registry)
|
||||
; - optional (only if feature is enabled!)
|
||||
; or like, workspace (+ optional/features, whee)
|
||||
|
||||
|
||||
;; A Git cargo dependency.
|
||||
;; `rev-type` is either `'tag`, `'rev`, `'branch`, or `#f`, and specifies
|
||||
;; how `rev` is interpreted.
|
||||
(define-record-type <cargo-dep-git>
|
||||
(make-cargo-dep-git url rev-type rev)
|
||||
cargo-dep-git?
|
||||
|
|
@ -111,7 +130,9 @@
|
|||
(cargo-dep-git-url entry)
|
||||
(cargo-dep-git-rev-type entry)
|
||||
(cargo-dep-git-rev entry)))
|
||||
|
||||
|
||||
;; A path cargo dependency.
|
||||
;; The path is relative to the crate root.
|
||||
(define-record-type <cargo-dep-path>
|
||||
(make-cargo-dep-path path)
|
||||
cargo-dep-path?
|
||||
|
|
@ -120,7 +141,8 @@
|
|||
(define-record-printer (<cargo-dep-path> entry out)
|
||||
(fprintf out "#<cargo-dep-path ~S>"
|
||||
(cargo-dep-path-path entry)))
|
||||
|
||||
|
||||
;; A registry dependency.
|
||||
(define-record-type <cargo-dep-registry>
|
||||
(make-cargo-dep-registry name)
|
||||
cargo-dep-registry?
|
||||
|
|
@ -129,6 +151,17 @@
|
|||
(fprintf out "#<cargo-dep-registry ~S>"
|
||||
(cargo-dep-registry-name entry)))
|
||||
|
||||
;; A crate's dependency.
|
||||
;;
|
||||
;; - `name`: the name this dependency has in the Rust code.
|
||||
;; - `origin`: a `<cargo-dep-git>`, `<cargo-dep-path>`, or
|
||||
;; `<cargo-dep-registry>`, specifying the source of the dependency.
|
||||
;; - `version`: The version requirements, as a string. Optional for
|
||||
;; non-registry depndencies.
|
||||
;; - `default-features`: Whether default features are requested on this dependency.
|
||||
;; - `features`: A list of features requested.
|
||||
;; - `package`: The name of the crate being depended upon.
|
||||
;; - `optional`: Whether this dependency is optional.
|
||||
(define-record-type <cargo-dependency>
|
||||
(make-cargo-dependency name origin version default-features features package optional)
|
||||
cargo-dependency?
|
||||
|
|
@ -148,7 +181,39 @@
|
|||
(cargo-dependency-features entry)
|
||||
(cargo-dependency-package entry)
|
||||
(cargo-dependency-optional entry)))
|
||||
|
||||
|
||||
;; A representation of a Cargo crate.
|
||||
;;
|
||||
;; - `name`: The name of the crate
|
||||
;; - `version`: The version of the crate
|
||||
;; - `edition`: The edition of Rust this crate uses. Can be overridden by
|
||||
;; individual targets.
|
||||
;; - `workspace`: A reference to the workspace this crate is part of, or
|
||||
;; `#f` if none.
|
||||
;; - `dependencies`: A list of `<cargo-dependency>` records.
|
||||
;; - `build-dependencies`: A list of `<cargo-dependency>` records, used for
|
||||
;; the `build-script` only.
|
||||
;; - `features`: An alist of feature names to any features it depends on.
|
||||
;; A feature dependency is represented as a triple `((crate-name . activates-crate) . crate-feature)`.
|
||||
;; `crate-name` and `activates-crate` govern the target crate. If
|
||||
;; `crate-name` is `#f`, the feature depends on another feature in the
|
||||
;; same crate. `activates-crate` specifies whether this is a required
|
||||
;; dependency, or whether the feature should be enabled when another
|
||||
;; feature requires the crate. `crate-feature` specifies the name of the
|
||||
;; feature in the target crate, or `#f` if this feature only depends on
|
||||
;; the crate itself. As examples:
|
||||
;; +
|
||||
;; ** "dep:foo" resolves to (("foo" . #t) . #f)
|
||||
;; ** "foo/bar" resolves to (("foo" . #t) . "bar")
|
||||
;; ** "foo?/bar" resolves to (("foo" . #f) . "bar")
|
||||
;;
|
||||
;; - `lib-target`: the `<cargo-target>` of the library of the crate, or `#f` if this crate
|
||||
;; has no library.
|
||||
;; - `build-script`: the `<cargo-target>` of the build script, if any is present.
|
||||
;; - `links`: the name of a native library being linked to, or `#f` if none.
|
||||
;; - `check-cfg-lint`: A list of `--check-cfg` flags to be set on compiling
|
||||
;; this crate. These values are sourced from `lints.rust.unexpected_cfgs`
|
||||
;; in the `Cargo.toml`.
|
||||
(define-record-type <cargo-crate>
|
||||
(make-cargo-crate name version edition workspace dependencies build-dependencies features lib-target build-script targets links check-cfg-lint)
|
||||
cargo-crate?
|
||||
|
|
@ -175,6 +240,15 @@
|
|||
(cargo-crate-lib-target entry)
|
||||
(cargo-crate-targets entry)))
|
||||
|
||||
;; A representation of a Cargo.toml's workspace.
|
||||
;;
|
||||
;; - `members`: A list of members of this workspace.
|
||||
;; - `exclude`: A list of globs that should be excluded, even when mentioned
|
||||
;; in `members`.
|
||||
;; - `dependencies`: A list of ``<cargo-dependency>``s that any crate part
|
||||
;; of this workspace can reference.
|
||||
;; - `edition`, `version`, `check-cfg-lint`: Default values for the
|
||||
;; equivalent fields in this workspace's ``<cargo-crate>``s.
|
||||
(define-record-type <cargo-workspace>
|
||||
(make-cargo-workspace members exclude dependencies edition version check-cfg-lint)
|
||||
cargo-workspace?
|
||||
|
|
@ -190,7 +264,7 @@
|
|||
(cargo-workspace-members entry)
|
||||
(cargo-workspace-exclude entry)
|
||||
(cargo-workspace-dependencies entry)))
|
||||
|
||||
|
||||
(foreign-declare "#include \"cfgfetch_source.h\"")
|
||||
(define cfgfetch-bin
|
||||
(cdar
|
||||
|
|
@ -210,6 +284,8 @@
|
|||
(let* ((line (cfg-parse line)))
|
||||
(read-cfg-value port (cons (cdr line) rest)))))
|
||||
|
||||
;; The list of config values that `rustc` sets by default, processed by xref:zilch.lang.rust.cfg.adoc#cfg-parse[`cfg-parse`].
|
||||
;; These are used to parse `Cargo.toml` conditional dependencies.
|
||||
(define cfg-values
|
||||
(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 '())))))
|
||||
|
|
@ -224,7 +300,7 @@
|
|||
|
||||
(define (and-cdr-default val default)
|
||||
(if val (cdr val) default))
|
||||
|
||||
|
||||
(define (find-dependency-in-list l dep-name)
|
||||
(cond
|
||||
((null? l) #f)
|
||||
|
|
@ -238,12 +314,12 @@
|
|||
(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)))
|
||||
|
||||
|
|
@ -310,7 +386,7 @@
|
|||
(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")
|
||||
|
|
@ -343,7 +419,7 @@
|
|||
(unless vfs (error "no vfs"))
|
||||
(define package (vector->list (cdr (assoc "package" internals))))
|
||||
(define package-name (cdr (assoc "name" package)))
|
||||
(define package-version (cdr (assoc "version" package)))
|
||||
(define package-version (or (and-cdr (assoc "version" package)) "0.0.0"))
|
||||
(define package-links (and-cdr (assoc "links" package)))
|
||||
(define package-edition (or (and-cdr (assoc "edition" package)) "2015"))
|
||||
|
||||
|
|
@ -363,7 +439,7 @@
|
|||
(define lib-target #f)
|
||||
(when (or (assoc "lib" internals) (vfs-file-ref vfs "src" "lib.rs"))
|
||||
(set! lib-target (cargo-target-from-toml vfs (or (and-cdr (assoc "lib" internals)) #()) package-name 'lib package-edition)))
|
||||
|
||||
|
||||
(define other-targets '())
|
||||
(cond
|
||||
((assoc "bin" internals)
|
||||
|
|
@ -445,6 +521,14 @@
|
|||
(set-cargo-workspace-dependencies! workspace-record dependencies)
|
||||
workspace-record)
|
||||
|
||||
;; Parse the contents of a `Cargo.toml`. Returns two values: A `<cargo-crate>`
|
||||
;; representing the crate (or `#f` if this is purely a workspace), and a
|
||||
;; `<cargo-workspace>` the `Cargo.toml` defined (or the workspace passed in,
|
||||
;; if any).
|
||||
;;
|
||||
;; - `vfs`: The VFS to use to automatically detect `bin` and `lib` targets.
|
||||
;; - `cargo-file`: A string representing the contents of the `Cargo.toml` to use.
|
||||
;; - `workspace`: A workspace that this rcate is part of, or `#f` if none.
|
||||
(define (parse-cargo-toml vfs cargo-file workspace)
|
||||
(define internals (vector->list (parse-toml cargo-file)))
|
||||
(define crate #f)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
;; Procedures to parse `cfg` attributes, as well as match them against
|
||||
;; conditionals found in crate definitions.
|
||||
(define-library (zilch lang rust cfg)
|
||||
(import
|
||||
(scheme base)
|
||||
|
|
@ -35,6 +37,12 @@
|
|||
(let ((end (or (string-skip strval is-ident-rest (+ index 1)) (string-length strval))))
|
||||
(tokenize-cfg strval end (cons (cons 'ident (string-copy strval index end)) tail)))
|
||||
(error "Unexpected character in cfg() string" strval))))))
|
||||
|
||||
;; Parses a configuration string or expression.
|
||||
;;
|
||||
;; - `key="value"` is represented as `('value . (key . value))`, where value can be `#f`.
|
||||
;; - `all` and `any` are represented as `('all/'any . items)`, where `items` is a list of sub-expressions.
|
||||
;; - `not(...)` is represented as `('not . value)`, where `value` is a sub-expression.
|
||||
(define (cfg-parse str)
|
||||
(define tokens (tokenize-cfg str 0 '()))
|
||||
(define (expect token)
|
||||
|
|
@ -100,6 +108,8 @@
|
|||
(cons 'value (cons left right))))))
|
||||
(parse-expr))
|
||||
|
||||
;; Checks whether the parsed expression `expr` matches against the list of
|
||||
;; config value pairs in `cfgs`.
|
||||
(define (cfg-matches expr cfgs)
|
||||
(define (parse-any tail)
|
||||
(cond
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
;; Procedures to parse lockfiles, and fetch crates from lockfile entries.
|
||||
(define-library (zilch lang rust registry)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -11,8 +12,10 @@
|
|||
|
||||
(export
|
||||
parse-lockfile fetch-and-unpack-crate
|
||||
|
||||
lockfile-entry? lockfile-entry-name lockfile-entry-version lockfile-entry-source lockfile-entry-checksum lockfile-entry-dependencies)
|
||||
|
||||
<lockfile-entry> lockfile-entry? lockfile-entry-name
|
||||
lockfile-entry-version lockfile-entry-source
|
||||
lockfile-entry-checksum lockfile-entry-dependencies)
|
||||
|
||||
(begin
|
||||
(define yj-path (foreign-value "YJ_PATH" nonnull-c-string))
|
||||
|
|
@ -26,9 +29,19 @@
|
|||
(close-input-port read-port)
|
||||
; (define-values (_ _ _) (process-wait pid))
|
||||
parsed)
|
||||
|
||||
;; TODO(puck): source here should probably be a record?
|
||||
;; dependencies here is a list of (name . version-or-#f). if #f, use any version (should be unambiguous!)
|
||||
|
||||
|
||||
;; The contents of a single lockfile entry.
|
||||
;;
|
||||
;; - `name`: The name of the crate
|
||||
;; - `version`: The version of the crate.
|
||||
;; - `source`: The source of the crate, as raw URL from the `Cargo.lock`.
|
||||
;; - `checksum`: A bytevector containing the sha256 of the `.crate` file, if
|
||||
;; one is available.
|
||||
;; - `dependencies`: A list of dependencies for this crate. Each dependency
|
||||
;; is a pair `(crate-name . crate-version)`, where `crate-version` is only
|
||||
;; set if there is more than one version of the depended crate in the
|
||||
;; lockfile.
|
||||
(define-record-type <lockfile-entry>
|
||||
(make-lockfile-entry name version source checksum dependencies)
|
||||
lockfile-entry?
|
||||
|
|
@ -37,7 +50,7 @@
|
|||
(source lockfile-entry-source)
|
||||
(checksum lockfile-entry-checksum)
|
||||
(dependencies lockfile-entry-dependencies))
|
||||
|
||||
|
||||
(define-record-printer (<lockfile-entry> entry out)
|
||||
(fprintf out "#<lockfile-entry ~A ~A ~A csum:~A deps:~A>"
|
||||
(lockfile-entry-name entry)
|
||||
|
|
@ -152,6 +165,8 @@
|
|||
|
||||
(define git-dir (or (get-environment-variable "XDG_CACHE_HOME") (string-append (get-environment-variable "HOME") "/.cache/zilch/git")))
|
||||
|
||||
;; Fetch a crate from the internet. Supports the `crates.io` registry source,
|
||||
;; as well as `git` dependencies. Returns a store path.
|
||||
(define (fetch-and-unpack-crate lockfile-entry)
|
||||
(define src (lockfile-entry-source lockfile-entry))
|
||||
(cond
|
||||
|
|
@ -162,6 +177,7 @@
|
|||
((equal? src "registry+https://github.com/rust-lang/crates.io-index") (fetch-from-registry lockfile-entry))
|
||||
(else (error "unknown source " lockfile-entry))))
|
||||
|
||||
;; Parse a `Cargo.lock`, returning a list of ``<lockfile-entry>``s.
|
||||
(define (parse-lockfile file-contents)
|
||||
(define inputs (vector->list (parse-toml file-contents)))
|
||||
(define lockfile-version (assoc "version" inputs))
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
;; Implements the resolver, which takes in a lockfile and other crates, and
|
||||
;; allows resolving the dependencies for said crates.
|
||||
(define-library (zilch lang rust resolver)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -13,16 +15,17 @@
|
|||
|
||||
(export
|
||||
<resolver> make-resolver resolver? resolver-locked-dependencies resolver-selected-dependencies
|
||||
<resolved-package-build-data> make-resolved-package-build-data resolved-package-build-data?
|
||||
resolved-package-build-data-dep-info resolved-package-build-data-metadata resolved-package-build-data-rlib
|
||||
resolved-package-build-data-transitive-dependencies
|
||||
|
||||
<resolved-package> make-resolved-package resolved-package?
|
||||
resolved-package-name resolved-package-version resolved-package-fs
|
||||
resolved-package-cargo-target resolved-package-enabled-features resolved-package-pending-features
|
||||
resolved-package-dependencies
|
||||
resolved-package-crate resolved-package-build-data
|
||||
|
||||
|
||||
<resolved-package-build-data> make-resolved-package-build-data resolved-package-build-data?
|
||||
resolved-package-build-data-dep-info resolved-package-build-data-metadata resolved-package-build-data-rlib
|
||||
resolved-package-build-data-transitive-dependencies resolved-package-build-data-build-script-out
|
||||
|
||||
resolver-download
|
||||
resolver-resolve-nonoptional
|
||||
resolver-resolve-resolved-package
|
||||
|
|
@ -49,28 +52,58 @@
|
|||
#:crate-name "false"
|
||||
#:edition "2021"
|
||||
#:emits '(#:link #t)))))
|
||||
|
||||
; Used to select a set of crates plus their versions.
|
||||
|
||||
;; A helper record used to select a set of crates plus their versions.
|
||||
;;
|
||||
;; - `locked-dependencies`: An SRFI 146 mapping of package names to a mapping
|
||||
;; of version to a pair of `(<lockfile-entry> . unpack-promise)`, where
|
||||
;; `unpack-promise` is a promise that resolves to a store path containing
|
||||
;; the crate.
|
||||
;; - `selected-dependencies`: An SRFI 146 mapping of package names to a list
|
||||
;; of `(version . <resolved-package>)` pairs, representing the versions of
|
||||
;; this crate that have been activated.
|
||||
(define-record-type <resolver>
|
||||
; locked-dependencies is a mapping of package-name to a mapping of version to (version . (lockfile-entry . unpack-promise))
|
||||
; selected-dependencies is a mapping of package-name to a list of (version . resolved-package)(?)
|
||||
; pending-features is a mapping of (package-name . version) to a list of features
|
||||
(make-resolver locked-dependencies selected-dependencies)
|
||||
resolver?
|
||||
(locked-dependencies resolver-locked-dependencies set-resolver-locked-dependencies!)
|
||||
(selected-dependencies resolver-selected-dependencies set-resolver-selected-dependencies!))
|
||||
|
||||
|
||||
;; A list of store paths for a `'<resolved-package>`''s build output build output.
|
||||
;;
|
||||
;; - `dep-info`: Equivalent to the rustc `dep-info` emit.
|
||||
;; - `metadata`/`rlib`: A pair `(canonical-name . store-path)` for the
|
||||
;; `metadata` and `obj` emits respectively.
|
||||
;; - `transitive-dependencies`: A list of `<resolved-package>` for all
|
||||
;; transitive dependencies of this resolved package.
|
||||
;; - `build-script-out`: The store path output from the build script.
|
||||
;; The format for this output is defined by the `buildscript-runner`.
|
||||
(define-record-type <resolved-package-build-data>
|
||||
(make-resolved-package-build-data dep-info metadata rlib transitive-dependencies build-script-metadata bin-flags build-script-out)
|
||||
(make-resolved-package-build-data dep-info metadata rlib transitive-dependencies build-script-out)
|
||||
resolved-package-build-data?
|
||||
(dep-info resolved-package-build-data-dep-info set-resolved-package-build-data-dep-info!)
|
||||
(metadata resolved-package-build-data-metadata set-resolved-package-build-data-metadata!)
|
||||
(rlib resolved-package-build-data-rlib set-resolved-package-build-data-rlib!)
|
||||
(transitive-dependencies resolved-package-build-data-transitive-dependencies set-resolved-package-build-data-transitive-dependencies!)
|
||||
(build-script-metadata resolved-package-build-data-build-script-metadata)
|
||||
(bin-flags resolved-package-build-data-bin-flags)
|
||||
(build-script-out resolved-package-build-data-build-script-out))
|
||||
|
||||
|
||||
;; A crate target that has been activated.
|
||||
;;
|
||||
;; - `name`, `version`: Equivalent to the name and version of the crate this
|
||||
;; package is a part of.
|
||||
;; - `cargo-target`: The `<cargo-target>` this `<resolved-package>` is part of.
|
||||
;; - `target-dependencies': A list of `<cargo-dependency>` records for this
|
||||
;; package.
|
||||
;; - `crate`: The `<cargo-crate>` this `<resolved-package>` is part of.
|
||||
;; - `enabled-features`: A list of feature names that have been activated on
|
||||
;; this package.
|
||||
;; - `pending-features`: an SRFI 146 mapping of dependency names to feature
|
||||
;; names that are waiting for said optional dependency to be activated.
|
||||
;; - `dependencies`: An SRFI 146 mapping of dependency name to `<resolved-package>`
|
||||
;; record for said dependency.
|
||||
;; - `build-data`: `<resolved-package-build-data>`, set once `build-package`
|
||||
;; is called on it.
|
||||
;; - `build-script`: The `<resolved-package>` for the build script for this
|
||||
;; package, if a build script target exists.
|
||||
(define-record-type <resolved-package>
|
||||
(make-resolved-package name version fs cargo-target target-dependencies crate enabled-features pending-features dependencies build-data build-script)
|
||||
resolved-package?
|
||||
|
|
@ -85,8 +118,9 @@
|
|||
(dependencies resolved-package-dependencies set-resolved-package-dependencies!)
|
||||
(build-data resolved-package-build-data set-resolved-package-build-data!)
|
||||
(build-script resolved-package-build-script set-resolved-package-build-script!))
|
||||
|
||||
;; Download and activate a dependency from the registry.
|
||||
|
||||
;; Download and activate a dependency from the registry, in the context of `resolver`.
|
||||
;; `name` and `version` are used to find the necessary dependency from the `resolver-locked-dependencies`.
|
||||
(define (resolver-download resolver name version)
|
||||
(unless version
|
||||
(error "Resolver wanted non-versioned download" name))
|
||||
|
|
@ -99,7 +133,7 @@
|
|||
(define version (parse-version (cargo-crate-version parsed-cargo)))
|
||||
(unless (cargo-crate-lib-target parsed-cargo)
|
||||
(error "Crate does not have valid [lib] target" (list name)))
|
||||
|
||||
|
||||
(define build-script #f)
|
||||
(when (cargo-crate-build-script parsed-cargo)
|
||||
(set! build-script (make-resolved-package (string-append name "_build") version vfs (cargo-crate-build-script parsed-cargo) (cargo-crate-build-dependencies parsed-cargo) parsed-cargo '() (mapping (make-default-comparator)) (mapping (make-default-comparator)) #f #f))
|
||||
|
|
@ -113,16 +147,17 @@
|
|||
(resolver-resolve-nonoptional resolver pkg)
|
||||
pkg)
|
||||
|
||||
;; Preemptively resolve and activate all dependencies not marked optional.
|
||||
;; Resolve and activate all dependencies not marked optional in `<resolved-package>` `pkg`.
|
||||
(define (resolver-resolve-nonoptional resolver pkg)
|
||||
(for-each
|
||||
(lambda (dep)
|
||||
(unless (cargo-dependency-optional dep)
|
||||
(resolver-resolve-resolved-package resolver pkg (cargo-dependency-name dep) #t)))
|
||||
(resolved-package-target-dependencies pkg)))
|
||||
|
||||
|
||||
;; Resolve a name of a dependency of a <resolved-package>, activating it if `activate` is #t.
|
||||
|
||||
;; Resolve a dependency of `<resolved-package>` `pkg` by name, activating it if requested.
|
||||
;; Returns the resolved dependency.
|
||||
(define (resolver-resolve-resolved-package resolver pkg name activate)
|
||||
(define resolved-dep (mapping-ref/default (resolved-package-dependencies pkg) name #f))
|
||||
(define cargo-dep
|
||||
|
|
@ -141,9 +176,9 @@
|
|||
(resolver-activate-features resolver resolved-dep pending-features))))
|
||||
|
||||
resolved-dep)
|
||||
|
||||
;; Activate a series of features on an existing <resolved-package>. This will resolve and activate optional dependencies
|
||||
;; where needed.
|
||||
|
||||
;; Activate a list of features on `<resolved-package>` `resolved`,
|
||||
;; resolving and activating optional dependencies where needed.
|
||||
(define (resolver-activate-features resolver resolved to-activate)
|
||||
(for-each
|
||||
(lambda (feature)
|
||||
|
|
@ -188,8 +223,11 @@
|
|||
'())))))))
|
||||
(cdr (or (assoc feature (cargo-crate-features (resolved-package-crate resolved))) (cons '() '()))))))
|
||||
to-activate))
|
||||
|
||||
;; Register a non-registry crate+vfs with the resolver.
|
||||
|
||||
;; Register a non-registry `<cargo-crate>` and corresponding vfs with the
|
||||
;; resolver. If `delayed` is `#t`, does not resolve any non-optional
|
||||
;; dependency. This is used for loading multiple crates into the resolver in
|
||||
;; arbitrary order.
|
||||
(define (resolver-register resolver vfs crate delayed)
|
||||
(define target (cargo-crate-lib-target crate))
|
||||
(cond
|
||||
|
|
@ -201,6 +239,7 @@
|
|||
(map (lambda (target) (resolver-register-target resolver vfs crate target #f delayed)) (cargo-crate-targets crate)))))
|
||||
|
||||
;; Register a non-registry crate+vfs with the resolver.
|
||||
;; If `delayed`, do not resolve the crate's (non-optional) dependencies yet.
|
||||
(define (resolver-register-target resolver vfs crate target extra-dependencies delayed)
|
||||
(define build-script #f)
|
||||
(unless extra-dependencies
|
||||
|
|
@ -216,8 +255,8 @@
|
|||
(unless delayed
|
||||
(resolver-resolve-nonoptional resolver pkg))
|
||||
pkg)
|
||||
|
||||
;; Resolves a <cargo-dependency>, returning the <resolved-package>.
|
||||
|
||||
;; Resolves a `<cargo-dependency>` through the `resolver`, returning the `<resolved-package>`.
|
||||
(define (resolver-resolve resolver dep)
|
||||
(define package-name (cargo-dependency-package dep))
|
||||
(define requirements (apply append (map parse-version-requirement (if (cargo-dependency-version dep) (string-split (cargo-dependency-version dep) "," 'strict-infix) '()))))
|
||||
|
|
@ -243,7 +282,8 @@
|
|||
(when (cargo-dependency-features dep)
|
||||
(resolver-activate-features resolver resolved (cargo-dependency-features dep)))
|
||||
resolved)))
|
||||
|
||||
|
||||
;; Print the information of a `<resolved-package>` to `current-output-port`.
|
||||
(define (resolver-print-pkg resolver pkg)
|
||||
(printf " - version: ~S\n" (resolved-package-version pkg))
|
||||
(printf " features: ~S\n" (resolved-package-enabled-features pkg))
|
||||
|
|
@ -257,6 +297,7 @@
|
|||
(printf "\n")))
|
||||
(resolved-package-target-dependencies pkg)))
|
||||
|
||||
;; Print the information of this resolver to `current-output-port`.
|
||||
(define (resolver-print resolver)
|
||||
(mapping-for-each
|
||||
(lambda (k v)
|
||||
|
|
@ -272,6 +313,14 @@
|
|||
v))
|
||||
(resolver-selected-dependencies resolver)))
|
||||
|
||||
;; Resolve a single crate, using a `<resolver>` internally.
|
||||
;;
|
||||
;; - `vfs`: The VFS of the crate.
|
||||
;; - `cargo-file`: The `<cargo-crate>` to process.
|
||||
;; - `parsed-lockfile`: A list of ``<lockfile-entry>``s necessary to resolve the crate.
|
||||
;; - `activated-features`: A list of features to activate on the targets in `<cargo-crate>`
|
||||
;;
|
||||
;; Returns a list of ``<resolved-package>``s for the targets in `cargo-file`.
|
||||
(define (process-cargo-with-lockfile vfs cargo-file parsed-lockfile activated-features)
|
||||
(define locked-dependencies (mapping (make-default-comparator)))
|
||||
(for-each
|
||||
|
|
@ -293,6 +342,8 @@
|
|||
pkgs)
|
||||
pkgs)
|
||||
|
||||
;; Resolve a list of `(<cargo-crate> . vfs)` pairs plus a list of ``<lockfile-entry>``,
|
||||
;; returning a list of `<resolved-package>` for each target in the crates.
|
||||
(define (process-many-with-lockfile vfs-cargo-map parsed-lockfile)
|
||||
(define locked-dependencies (mapping (make-default-comparator)))
|
||||
(for-each
|
||||
|
|
@ -361,6 +412,14 @@
|
|||
(reverse envs))
|
||||
(mapping-map->list (lambda (k v) (cons k v)) final-env))
|
||||
|
||||
;; Builds a `<resolved-package>`, using specified build script and compiler overrides.
|
||||
;;
|
||||
;; - `build-script-env-overrides`: A procedure that takes two arguments `(proc crate-name is-dependency)`,
|
||||
;; and returns `#f`, or a list of pairs to add to the environment of the build script, if any is executed.
|
||||
;; - `compiler-env-overrides`: A procedure that takes two arguments `(proc crate-name is-dependency)`, and
|
||||
;; returns `#f` or a list of pairs to add to the environment of `rustc` when compiling said crate.
|
||||
;;
|
||||
;; Returns the `rlib` (or linked output, for binaries) of this `<resolved-package>`.
|
||||
(define (build-package resolved build-script-env-overrides compiler-env-overrides)
|
||||
; Info we need to collect:
|
||||
; - enabled features
|
||||
|
|
@ -377,11 +436,9 @@
|
|||
; These should probably be translated into distinct targets?
|
||||
(when (list? crate-type)
|
||||
(set! crate-type 'rlib))
|
||||
(define buildscript-metadata '())
|
||||
(define buildscript-out #f)
|
||||
(define crate-links '())
|
||||
(define dependency-metadata '())
|
||||
(define bin-flags '())
|
||||
|
||||
(define params `(#:crate-type ,crate-type
|
||||
#:remap-path-prefix (,crate-root . ,(string-append crate-name "-" (version-str (resolved-package-version resolved))))
|
||||
|
|
@ -524,7 +581,7 @@
|
|||
(set! params
|
||||
`(#:externs (,name . ,(cdr (resolved-package-build-data-rlib data))) . ,params)))
|
||||
(resolved-package-dependencies resolved))
|
||||
|
||||
|
||||
(define transitive-dependencies-meta
|
||||
(zdir (map (lambda (dep)
|
||||
(define data (resolved-package-build-data dep))
|
||||
|
|
@ -557,10 +614,8 @@
|
|||
(for-each (lambda (check) (set! params `(check-cfg: ,check . ,params))) (cargo-crate-check-cfg-lint (resolved-package-crate resolved)))
|
||||
|
||||
(define inherited-build-script-out '())
|
||||
(define transitive-bin-flags '())
|
||||
(for-each
|
||||
(lambda (dep)
|
||||
(set! transitive-bin-flags (append (resolved-package-build-data-bin-flags (resolved-package-build-data dep)) transitive-bin-flags))
|
||||
(when (resolved-package-build-data-build-script-out (resolved-package-build-data dep))
|
||||
(set! inherited-build-script-out (cons (resolved-package-build-data-build-script-out (resolved-package-build-data dep)) inherited-build-script-out))))
|
||||
transitive-dependencies)
|
||||
|
|
@ -570,33 +625,31 @@
|
|||
|
||||
(define path #~,(string-append #$(vfs-to-store (resolved-package-fs resolved)) "/" (cargo-target-path (resolved-package-cargo-target resolved))))
|
||||
(define dep-info (cdar (apply call-rustc `(,path ,rustc-env search-path: ("dependency" . ,transitive-dependencies-meta) emits: (dep-info: #t) . ,params-meta))))
|
||||
|
||||
|
||||
(define rlib-name (string-append "lib" crate-name "-v" crate-version ".rlib"))
|
||||
(define rmeta-name (string-append "lib" crate-name "-v" crate-version ".rmeta"))
|
||||
|
||||
|
||||
(when (eq? crate-type 'proc-macro)
|
||||
(set! rlib-name (string-append "lib" crate-name "-v" crate-version ".so")))
|
||||
(when (eq? crate-type 'bin)
|
||||
(set! rlib-name crate-name))
|
||||
|
||||
; (when (or (eq? crate-type 'proc-macro) (eq? crate-type 'bin))
|
||||
; (set! params (append transitive-bin-flags params)))
|
||||
(when (eq? crate-type 'bin)
|
||||
(set! params `(#:codegen-flags ("rpath" . "no") . ,params)))
|
||||
|
||||
|
||||
; Rust is nitpicky about the filenames, fix them with copious symlinking.
|
||||
(define rlib-file (cdar (apply call-rustc `(,path (("_zilch_inherit" . ,#~,(string-join #$inherited-build-script-out " ")) . ,rustc-env) search-path: ("dependency" . ,transitive-dependencies-rlib) emits: (link: #t) ,@bin-flags . ,params))))
|
||||
(define rlib-file (cdar (apply call-rustc `(,path (("_zilch_inherit" . ,#~,(string-join #$inherited-build-script-out " ")) . ,rustc-env) search-path: ("dependency" . ,transitive-dependencies-rlib) emits: (link: #t) . ,params))))
|
||||
(define rlib (cons rlib-name #~,(string-append #$(zdir rlib-name (zsymlink rlib-file)) "/" rlib-name)))
|
||||
(store-path-materialize rlib-file)
|
||||
|
||||
|
||||
(define metadata #f)
|
||||
(define metadata-file #f)
|
||||
(unless (eq? crate-type 'proc-macro)
|
||||
(set! metadata-file (cdar (apply call-rustc `(,path ,rustc-env search-path: ("dependency" . ,transitive-dependencies-meta) emits: (metadata: #t) . ,params-meta))))
|
||||
(set! metadata (cons rmeta-name #~,(string-append #$(zdir rmeta-name (zsymlink metadata-file)) "/" rmeta-name)))
|
||||
(store-path-materialize metadata-file))
|
||||
|
||||
(set-resolved-package-build-data! resolved (make-resolved-package-build-data dep-info metadata rlib transitive-dependencies buildscript-metadata bin-flags buildscript-out))
|
||||
|
||||
(set-resolved-package-build-data! resolved (make-resolved-package-build-data dep-info metadata rlib transitive-dependencies buildscript-out))
|
||||
rlib-file)
|
||||
|
||||
(define (matches-requirements ver req)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
;; Procedures to build code with `rustc`.
|
||||
(define-library (zilch lang rust)
|
||||
(import
|
||||
(scheme base) (scheme write) (scheme process-context) (scheme lazy)
|
||||
|
|
@ -6,10 +7,12 @@
|
|||
json
|
||||
(chicken foreign) (chicken format)
|
||||
(srfi 4))
|
||||
|
||||
|
||||
(export rustc call-rustc)
|
||||
|
||||
(begin
|
||||
;; Helper containing a store path for the `rustc` used by the rest of the
|
||||
;; Zilch Rust support.
|
||||
(define rustc (cdr (assoc "out" (nixpkgs "rustc"))))
|
||||
(define gcc (delay (cdr (assoc "out" (nixpkgs "gcc")))))
|
||||
(define linker (delay #~,(string-append #$(force gcc) "/bin/cc")))
|
||||
|
|
@ -59,7 +62,7 @@
|
|||
(check-one (rustc-emits-dep-info emits) "dep-info")
|
||||
(check-one (rustc-emits-mir emits) "mir")
|
||||
(values tail types))
|
||||
|
||||
|
||||
(define (parse-rustc-emits out items)
|
||||
(if (eq? items '())
|
||||
out
|
||||
|
|
@ -73,7 +76,7 @@
|
|||
((#:dep-info) (set-rustc-emits-dep-info! out (cadr items)) (parse-rustc-emits out (cddr items)))
|
||||
((#:mir) (set-rustc-emits-mir! out (cadr items)) (parse-rustc-emits out (cddr items)))
|
||||
(else (error "unknown rustc emits param" items)))))
|
||||
|
||||
|
||||
(define (parse-rustc-params out items)
|
||||
(if (eq? items '())
|
||||
out
|
||||
|
|
@ -91,11 +94,35 @@
|
|||
((#:remap-path-prefix) (set-rustc-params-remap-path-prefix! out (cons (cadr items) (rustc-params-remap-path-prefix out))) (parse-rustc-params out (cddr items)))
|
||||
((#:cap-lints) (set-rustc-params-cap-lints! out (cadr items)) (parse-rustc-params out (cddr items)))
|
||||
(else (error "unknown rustc param" (car items))))))
|
||||
|
||||
|
||||
(foreign-declare "#include \"rustc_wrap_source.h\"")
|
||||
(define rustc_wrap-bin
|
||||
#f)
|
||||
|
||||
;; Call rustc with a series of known parameters.
|
||||
;; `input` represents the input file to call. `env` is an alist of environment
|
||||
;; variables. The rest of the parameters are passed as two arguments, `foo: bar`,
|
||||
;; similar to SRFI 89.
|
||||
;;
|
||||
;; - `crate-type: 'bin/'lib/etc`: Required. The crate type.
|
||||
;; - `crate-name: "foo"`: Required. The crate name.
|
||||
;; - `edition: "2021"/etc`: Required. The edition of Rust to use.
|
||||
;; - `cfg: "val"`: equivalent to `--cfg val`
|
||||
;; - `check-cfg: "val"`: equivalent to `--check-cfg val`
|
||||
;; - `search-path: foo`: Adds `foo` to the library search path. If `foo` is a
|
||||
;; pair, the `car` is the kind (`"dependency"`, `"crate"`, `"all"`, etc),
|
||||
;; and the `cdr` is the value.
|
||||
;; - `link: foo`: Links the generated output with `foo`. If `foo` is a pair,
|
||||
;; the `car` represents the kind and the `cdr` is the value.
|
||||
;; - `emits: (..emits data..)`: Set the outputs that `rustc` will generate.
|
||||
;; Emits data is a list structured like this one. For example, `(asm: #t llvm-bc: "/foo")`
|
||||
;; will output assembly to a derivation output called "asm", while
|
||||
;; outputting LLVM bytecode to the path "/foo" in the derivation.
|
||||
;; - `codegen-flags: ("foo" . "bar")`: Append `-C foo=bar` to the rustc
|
||||
;; command line. the `cdr` of this pair may be a zexp.
|
||||
;; - `remap-path-prefix: ("foo" . "bar")`: Remaps the path `foo` to the path
|
||||
;; `bar` for all error traces. Both values can be a zexp.
|
||||
;; - `cap-lints: "warn"`: Set the most restrictive lint level.
|
||||
(define (call-rustc input env . params)
|
||||
(call-rustc-internal input env (parse-rustc-params (make-rustc-params '() '() '() '() #f #f #f #f '() '() '() #f) params)))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue