build/cargo: Support directory source inputs.

* guix/build/cargo-build-system.scm (cargo-package?): New procedure.
(crate-src?): Support directory source inputs.
(configure): Likewise.

Change-Id: If2bd318b44ed765baec69309f25d320edceee116

Fixes: https://codeberg.org/guix/guix/issues/753
This commit is contained in:
Hilton Chain 2025-03-07 10:59:11 +08:00
parent c8456eff68
commit a087db5f83
No known key found for this signature in database
GPG key ID: ACC66D09CA528292

View file

@ -34,6 +34,7 @@
#:use-module (ice-9 ftw) #:use-module (ice-9 ftw)
#:use-module (ice-9 format) #:use-module (ice-9 format)
#:use-module (ice-9 match) #:use-module (ice-9 match)
#:use-module (ice-9 textual-ports)
#:use-module (ice-9 threads) #:use-module (ice-9 threads)
#:use-module (srfi srfi-1) #:use-module (srfi srfi-1)
#:use-module (srfi srfi-26) #:use-module (srfi srfi-26)
@ -61,19 +62,33 @@
(bin-dep? (lambda (dep) (find bin? (get-kinds dep))))) (bin-dep? (lambda (dep) (find bin? (get-kinds dep)))))
(find bin-dep? (manifest-targets)))) (find bin-dep? (manifest-targets))))
(define (cargo-package? dir)
"Check if directory DIR contains a single package, or a Cargo workspace with
root package."
(let ((manifest-file (in-vicinity dir "Cargo.toml")))
(and (file-exists? manifest-file)
(string-contains
(call-with-input-file manifest-file get-string-all)
"[package]"))))
(define (crate-src? path) (define (crate-src? path)
"Check if PATH refers to a crate source, namely a gzipped tarball with a "Check if PATH refers to a crate source, namely a gzipped tarball with a
Cargo.toml file present at its root." Cargo.toml file present at its root."
(and (not (directory-exists? path)) ; not a tarball (if (directory-exists? path)
(not (string-suffix? "py" path)) ; sanity-check.py ;; The build system only handles sources containing single crate.
;; First we print out all file names within the tarball to see if it ;; Workspaces should be packaged into crates (via 'package phase)
;; looks like the source of a crate. However, the tarball will include ;; and used in inputs.
;; an extra path component which we would like to ignore (since we're (cargo-package? path)
;; interested in checking if a Cargo.toml exists at the root of the (and (not (string-suffix? "py" path)) ;sanity-check.py
;; archive, but not nested anywhere else). We do this by cutting up ;; First we print out all file names within the tarball to see
;; each output line and only looking at the second component. We then ;; if it looks like the source of a crate. However, the tarball
;; check if it matches Cargo.toml exactly and short circuit if it does. ;; will include an extra path component which we would like to
(apply invoke (list "sh" "-c" ;; ignore (since we're interested in checking if a Cargo.toml
;; exists at the root of the archive, but not nested anywhere
;; else). We do this by cutting up each output line and only
;; looking at the second component. We then check if it matches
;; Cargo.toml exactly and short circuit if it does.
(invoke "sh" "-c"
(string-append "tar -tf " path (string-append "tar -tf " path
" | cut -d/ -f2" " | cut -d/ -f2"
" | grep -q '^Cargo.toml$'"))))) " | grep -q '^Cargo.toml$'")))))
@ -161,14 +176,18 @@ libraries or executables."
(and (crate-src? path) (and (crate-src? path)
;; Gracefully handle duplicate inputs ;; Gracefully handle duplicate inputs
(not (file-exists? crate-dir)) (not (file-exists? crate-dir))
(if (directory-exists? path)
(copy-recursively path crate-dir)
(begin
(mkdir-p crate-dir) (mkdir-p crate-dir)
;; Cargo crates are simply gzipped tarballs but with a .crate ;; Cargo crates are simply gzipped tarballs but with a
;; extension. We expand the source to a directory name we control ;; .crate extension. We expand the source to a directory
;; so that we can generate any cargo checksums. ;; name we control so that we can generate any cargo
;; The --strip-components argument is needed to prevent creating ;; checksums. The --strip-components argument is needed to
;; an extra directory within `crate-dir`. ;; prevent creating an extra directory within `crate-dir`.
(format #t "Unpacking ~a~%" name) (format #t "Unpacking ~a~%" name)
(invoke "tar" "xf" path "-C" crate-dir "--strip-components" "1"))))) (invoke "tar" "xf" path "-C" crate-dir
"--strip-components" "1")))))))
inputs) inputs)
;; For cross-building ;; For cross-building