diff mbox series

[bug#51845] Using ‘native-inputs’ and ‘inputs’ for Cargo packages?

Message ID Ya8zONvzYXJcgL53@3900XT
State Accepted
Headers show
Series [bug#51845] Using ‘native-inputs’ and ‘inputs’ for Cargo packages? | expand

Checks

Context Check Description
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue
cbaines/applying patch fail View Laminar job
cbaines/issue success View issue

Commit Message

Efraim Flashner Dec. 7, 2021, 10:11 a.m. UTC
On Mon, Dec 06, 2021 at 11:17:47PM +0100, Ludovic Courtès wrote:
> Efraim Flashner <efraim@flashner.co.il> skribis:
> 
> > On December 6, 2021 4:37:12 PM UTC, "Ludovic Courtès" <ludo@gnu.org> wrote:
> 
> [...]
> 
> >>Thinking out loud… would it work to change:
> >>
> >>  (arguments '(#:cargo-inputs X #:cargo-development-inputs Y))
> >>
> >>to:
> >>
> >>  (native-inputs (map package-source Y))
> >>  (inputs (map package-source X))
> >>
> >>?
> 
> [...]
> 
> > Then we lose the transitive package sources, which is how we ended up where we are today.
> 
> True.
> 
> With the minimal changes to (guix build-system cargo) below, one can use
> either the current style or pass “development inputs” as ‘native-inputs’
> and other dependencies as ‘inputs’.  Source transitivity is preserved
> but you can write packages the normal way.
> 
> I modified some of the dependencies of librsvg to use
> native-inputs/inputs and you can see when applying this part of the
> patch that the librsvg derivation is unchanged.  Good thing is that
> ‘guix graph’ and ‘guix refresh -l’ work for these packages.
> 
> Is this a direction we want to take?

I like the way it works out, and has Guix do the magic to give us the
crates in the graph. On the other hand I tried changing the cargo-inputs
from librsvg to regular inputs, and after 2.5 minutes of trying to run
`guix show librsvg` I still wasn't seeing the dependencies and my RAM
usage was still increasing. Also gnu/packages/gnome.scm didn't fail to
compile, so there was no notice of the loop.

I changed some more packages which are transitive inputs of
rust-encoding@0.2 and didn't see any slowdown. I was worried that this
would affect a future use of `guix shell -D rust-app` not pulling in any
of the crates but it still seems to work. I tried with rust-encoding@0.2
and got the crates for the packages I expected (only the ones I changed).

(ins)efraim@3900XT ~/workspace/guix-core-updates$ ./pre-inst-env guix shell -D rust-encoding@0.2
(ins)efraim@3900XT ~/workspace/guix-core-updates [env]$ ls $GUIX_ENVIRONMENT/share/cargo/registry/ | col
cc-1.0.66.crate
compiler_builtins-0.1.26.crate
encoding-index-japanese-1.20141219.5.crate
encoding-index-korean-1.20141219.5.crate
encoding-index-simpchinese-1.20141219.5.crate
encoding-index-singlebyte-1.20141219.5.crate
encoding_index_tests-0.1.4.crate
encoding-index-tradchinese-1.20141219.5.crate
getopts-0.2.21.crate
log-0.3.9.crate
rustc-std-workspace-core-1.0.0.crate
rustc-std-workspace-std-1.0.1.crate
unicode-width-0.1.9.crate

So to summarize, between your diff to treat inputs built using
cargo-build-system as cargo-inputs and my changes to save previous
crates for the next input we reach a place where we can start to change
the crates over to use inputs and native-inputs instead of cargo-inputs
and cargo-development-inputs without needing to flip everything at once.

So I'd go with it's good, but I'm not sure it directly works to fix the
problem we're having with librsvg.

> If so, we can have ‘guix style’ automate transformations.
> 
> Thanks,
> Ludo’.
> 

I've added some inline comments in the diff (and removed a bunch of
lines)

> diff --git a/guix/build-system/cargo.scm b/guix/build-system/cargo.scm
> index 60c35eed07..b2d97beb2f 100644
> --- a/guix/build-system/cargo.scm
> +++ b/guix/build-system/cargo.scm
> @@ -125,17 +125,21 @@ (define builder
>                      #:target #f
>                      #:guile-for-build guile))
>  
> +(define (cargo-input? input)
> +  (match input
> +    ((label (? package? p))
> +     (eq? cargo-build-system (package-build-system p)))
> +    (_ #f)))
> +

I would've sorted based on the name starting with 'rust-'.

I can't think of an example quickly where it would happen, but take
librsvg, which we currently build with cargo-build-system. If we need it
as an input for pango (or some other library) and we also build that
with the cargo-build-system then we'll just get the rust inputs, not the
actual library.

Can we check the arguments field for `#:install-source? #f` and use it
as a regular {propagated-,native-,}input in that case? Then we could
have cbindgen and rust-cbindgen, depending on if we needed the binary or
the sources.

>  (define (package-cargo-inputs p)
> -  (apply
> -    (lambda* (#:key (cargo-inputs '()) #:allow-other-keys)
> -      cargo-inputs)
> -    (package-arguments p)))
> +  (match (member #:cargo-inputs (package-arguments p))
> +    (#f (filter cargo-input? (package-inputs p)))
> +    ((_ inputs . _) inputs)))
>  
>  (define (package-cargo-development-inputs p)
> -  (apply
> -    (lambda* (#:key (cargo-development-inputs '()) #:allow-other-keys)
> -      cargo-development-inputs)
> -    (package-arguments p)))
> +  (match (member #:cargo-development-inputs (package-arguments p))
> +    (#f (filter cargo-input? (package-native-inputs p)))
> +    ((_ inputs . _) inputs)))

I see we don't get rid of #:cargo-inputs or #:cargo-development-inputs.
So even if applying the style change to all the crates causes circular
dependency problems we can fall back to the current method. I ran into
problems once I hit all the rust-bindgen crates.

>  
>  (define (crate-closure inputs)
>    "Return the closure of INPUTS when considering the 'cargo-inputs' and
> @@ -235,8 +239,8 @@ (define (expand-crate-sources cargo-inputs cargo-development-inputs)
>  (define* (lower name
>                  #:key source inputs native-inputs outputs system target
>                  (rust (default-rust))
> -                (cargo-inputs '())
> -                (cargo-development-inputs '())
> +                (cargo-inputs (filter cargo-input? inputs))
> +                (cargo-development-inputs (filter cargo-input? native-inputs))

I tried commenting the cargo-development-inputs out, but it only caused
problems for me when trying to compile rust-encoding@0.2.

>                  #:allow-other-keys
>                  #:rest arguments)
>    "Return a bag for NAME."
> @@ -260,7 +264,9 @@ (define private-keywords
>           (build-inputs `(("cargo" ,rust "cargo")
>                           ("rustc" ,rust)
>                           ,@(expand-crate-sources cargo-inputs cargo-development-inputs)
> -                         ,@native-inputs))
> +                         ,@(if (eq? native-inputs cargo-development-inputs)
> +                               '()
> +                               native-inputs)))
>           (outputs outputs)
>           (build cargo-build)
>           (arguments (strip-keyword-arguments private-keywords arguments)))))
> diff --git a/guix/packages.scm b/guix/packages.scm
> index b3c5a00011..275cc3675c 100644
> --- a/guix/packages.scm
> +++ b/guix/packages.scm
> @@ -660,7 +660,8 @@ (define (deprecated-package old-name p)
>      (name old-name)
>      (properties `((superseded . ,p)))))
>  
> -(define (package-field-location package field)
> +(define* (package-field-location package field
> +                                 #:key (value-location? #t))
>    "Return the source code location of the definition of FIELD for PACKAGE, or
>  #f if it could not be determined."
>    (match (package-location package)
> @@ -678,7 +679,10 @@ (define (package-field-location package field)
>                     (let ((field (assoc field inits)))
>                       (match field
>                         ((_ value)
> -                        (let ((loc (and=> (source-properties value)
> +                        (let ((loc (and=> (source-properties
> +                                           (if value-location?
> +                                               value
> +                                               field))
>                                            source-properties->location)))
>                            (and loc
>                                 ;; Preserve the original file name, which may be a
> diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm
> index 86a46f693c..dccc20d880 100644
> --- a/guix/scripts/style.scm
> +++ b/guix/scripts/style.scm
> @@ -29,6 +29,7 @@
>  
>  (define-module (guix scripts style)
>    #:autoload   (gnu packages) (specification->package fold-packages)
> +  #:autoload   (guix build-system cargo) (cargo-build-system)
>    #:use-module (guix scripts)
>    #:use-module ((guix scripts build) #:select (%standard-build-options))
>    #:use-module (guix combinators)
> @@ -212,6 +213,21 @@ (define (object->string* obj indent)
>        (pretty-print-with-comments port obj
>                                    #:indent indent))))
>  
> +(define (object-list->string lst indent)
> +  (call-with-output-string
> +    (lambda (port)
> +      (let loop ((lst lst))
> +        (match lst
> +          ((obj)
> +           (pretty-print-with-comments port obj
> +                                       #:indent indent))
> +          ((obj rest ...)
> +           (pretty-print-with-comments port obj
> +                                       #:indent indent)
> +           (newline port)
> +           (display (make-string indent #\space) port)
> +           (loop rest)))))))
> +
>  
>  ;;;
>  ;;; Simplifying input expressions.
> @@ -441,6 +457,49 @@ (define matches?
>              (list package-inputs package-native-inputs
>                    package-propagated-inputs)))
>  
> +
> +;;;
> +;;; Crates, Cargo, Rust, and all that.
> +;;;
> +
> +(define* (rewrite-cargo-inputs package
> +                               #:key (policy 'silent)
> +                               (edit-expression edit-expression))
> +  (when (eq? (package-build-system package) cargo-build-system)
> +    (match (package-field-location package 'arguments
> +                                   #:value-location? #f)
> +      (#f #f)
> +      (location
> +       (let* ((indent (location-column location)))
> +         (edit-expression
> +          (pk 'loc (location->source-properties location))
> +          (lambda (str)
> +            (define arguments
> +              (call-with-input-string (pk 'str str) read-with-comments))
> +
> +            (match arguments
> +              (('arguments ('quasiquote lst))
> +               (let ((inputs (match (member #:cargo-inputs lst)
> +                               (#f '())
> +                               ((_ inputs . _) inputs)))
> +                     (native (match (member #:cargo-development-inputs lst)
> +                               (#f '())
> +                               ((_ inputs . _) inputs)))
> +                     (rest (strip-keyword-arguments
> +                            '(#:cargo-inputs #:cargo-development-inputs)
> +                            lst)))
> +                 (object-list->string
> +                  `(,@(if (null? rest)
> +                          '()
> +                          `((arguments ,(list 'quasiquote rest))))
> +                    ,@(if (null? native)
> +                          '()
> +                          `((native-inputs ,(list 'quasiquote native))))
> +                    ,@(if (null? inputs)
> +                          '()
> +                          `((inputs ,(list 'quasiquote inputs)))))
> +                  indent)))))))))))
> +
>  (define (package-location<? p1 p2)
>    "Return true if P1's location is \"before\" P2's."
>    (let ((loc1 (package-location p1))
> @@ -536,7 +595,7 @@ (define (parse-options)
>                         edit-expression))
>           (policy   (assoc-ref opts 'input-simplification-policy)))
>      (for-each (lambda (package)
> -                (simplify-package-inputs package #:policy policy
> +                (rewrite-cargo-inputs package #:policy policy
>                                           #:edit-expression edit))
>                ;; Sort package by source code location so that we start editing
>                ;; files from the bottom and going upward.  That way, the

Comments

Ludovic Courtès Dec. 7, 2021, 7:48 p.m. UTC | #1
Howdy!

Efraim Flashner <efraim@flashner.co.il> skribis:

> On Mon, Dec 06, 2021 at 11:17:47PM +0100, Ludovic Courtès wrote:

[...]

>> With the minimal changes to (guix build-system cargo) below, one can use
>> either the current style or pass “development inputs” as ‘native-inputs’
>> and other dependencies as ‘inputs’.  Source transitivity is preserved
>> but you can write packages the normal way.
>> 
>> I modified some of the dependencies of librsvg to use
>> native-inputs/inputs and you can see when applying this part of the
>> patch that the librsvg derivation is unchanged.  Good thing is that
>> ‘guix graph’ and ‘guix refresh -l’ work for these packages.
>> 
>> Is this a direction we want to take?
>
> I like the way it works out, and has Guix do the magic to give us the
> crates in the graph. On the other hand I tried changing the cargo-inputs
> from librsvg to regular inputs, and after 2.5 minutes of trying to run
> `guix show librsvg` I still wasn't seeing the dependencies and my RAM
> usage was still increasing. Also gnu/packages/gnome.scm didn't fail to
> compile, so there was no notice of the loop.

Notice that the dependency cycle, as discussed on IRC, breaks things
like ‘guix show’ (?) and ‘guix graph’, but doesn’t break actual package
builds because it’s a <package> cycle that vanishes once packages are
lowered to bags and derivations.

Regardless, it would be nice not to have cycles in the first place.

[...]

> So to summarize, between your diff to treat inputs built using
> cargo-build-system as cargo-inputs and my changes to save previous
> crates for the next input we reach a place where we can start to change
> the crates over to use inputs and native-inputs instead of cargo-inputs
> and cargo-development-inputs without needing to flip everything at once.

What are the “changes to save previous crates for the next input”?

> So I'd go with it's good, but I'm not sure it directly works to fix the
> problem we're having with librsvg.

No no, it’s completely unrelated to the librsvg issue, which is why I
changed subject lines.  :-)  I think it’d be nice to have anyway.

>> +(define (cargo-input? input)
>> +  (match input
>> +    ((label (? package? p))
>> +     (eq? cargo-build-system (package-build-system p)))
>> +    (_ #f)))
>> +
>
> I would've sorted based on the name starting with 'rust-'.

OK.

[...]

>>  (define (package-cargo-inputs p)
>> -  (apply
>> -    (lambda* (#:key (cargo-inputs '()) #:allow-other-keys)
>> -      cargo-inputs)
>> -    (package-arguments p)))
>> +  (match (member #:cargo-inputs (package-arguments p))
>> +    (#f (filter cargo-input? (package-inputs p)))
>> +    ((_ inputs . _) inputs)))
>>  
>>  (define (package-cargo-development-inputs p)
>> -  (apply
>> -    (lambda* (#:key (cargo-development-inputs '()) #:allow-other-keys)
>> -      cargo-development-inputs)
>> -    (package-arguments p)))
>> +  (match (member #:cargo-development-inputs (package-arguments p))
>> +    (#f (filter cargo-input? (package-native-inputs p)))
>> +    ((_ inputs . _) inputs)))
>
> I see we don't get rid of #:cargo-inputs or #:cargo-development-inputs.
> So even if applying the style change to all the crates causes circular
> dependency problems we can fall back to the current method. I ran into
> problems once I hit all the rust-bindgen crates.

Right.  Support for #:cargo-development-inputs and #:cargo-inputs is
here so we could have a smooth “upgrade” without breaking compatibility.

Anyway, I think the priority is to get ‘core-updates-frozen’, which
probably involves either pinning librsvg dependencies or using the
bundled libraries as you showed at the beginning of this thread.
We can resume work on prettified Rust packages after that; it’ll be
useful to be able to use ‘guix refresh -l’.

Ludo’.
diff mbox series

Patch

diff --git a/gnu/packages/crates-io.scm b/gnu/packages/crates-io.scm
index b8c4c7bd39..ae717645d8 100644
--- a/gnu/packages/crates-io.scm
+++ b/gnu/packages/crates-io.scm
@@ -5728,18 +5728,18 @@  (define-public rust-bitflags-1.3
         (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32 "12ki6w8gn1ldq7yz9y680llwk5gmrhrzszaa17g1sbrw2r2qvwxy"))))
-    (arguments
-     `(#:tests? #f      ; Tests require rust-1.46 or newer.
-       #:cargo-inputs
-       (("rust-compiler-builtins" ,rust-compiler-builtins-0.1)
-        ("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1))
-       #:cargo-development-inputs
-       (("rust-rustversion" ,rust-rustversion-1)
+    (arguments `(#:tests? #f ; Tests require rust-1.46 or newer.
+                         ))
+    (native-inputs
+      `(("rust-rustversion" ,rust-rustversion-1)
         ("rust-serde" ,rust-serde-1)
         ("rust-serde-derive" ,rust-serde-derive-1)
         ("rust-serde-json" ,rust-serde-json-1)
         ("rust-trybuild" ,rust-trybuild-1)
-        ("rust-walkdir" ,rust-walkdir-2))))))
+        ("rust-walkdir" ,rust-walkdir-2)))
+    (inputs
+      `(("rust-compiler-builtins" ,rust-compiler-builtins-0.1)
+        ("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1)))))
 
 (define-public rust-bitflags-0.9
   (package
@@ -8391,12 +8391,9 @@  (define-public rust-cast-0.2
         (base32
          "1c5z7zryj0zwnhdgs6rw5dfvnlwc1vm19jzrlgx5055alnwk952b"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-rustc-version" ,rust-rustc-version-0.2))
-       #:cargo-development-inputs
-       (("rust-quickcheck" ,rust-quickcheck-0.9))))
+    (arguments `(#:skip-build? #t))
+    (native-inputs `(("rust-quickcheck" ,rust-quickcheck-0.9)))
+    (inputs `(("rust-rustc-version" ,rust-rustc-version-0.2)))
     (home-page "https://github.com/japaric/cast.rs")
     (synopsis
      "Ergonomic, checked cast functions for primitive types")
@@ -8434,7 +8431,7 @@  (define-public rust-cc-1
       (origin
         (method url-fetch)
         (uri (crate-uri "cc" version))
-        (file-name (string-append name "-" version ".crate"))
+        (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32
           "0j7d7h4n81z5f22l3v8ggjvvw8m64636nlaqax4x1y44da1rc12c"))))
@@ -8596,7 +8593,7 @@  (define-public rust-cfg-if-0.1
       (origin
         (method url-fetch)
         (uri (crate-uri "cfg-if" version))
-        (file-name (string-append name "-" version ".crate"))
+        (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32
           "08h80ihs74jcyp24cd75wwabygbbdgl05k6p5dmq8akbr78vv1a7"))))
@@ -10052,16 +10049,17 @@  (define-public rust-compiler-builtins-0.1
       (origin
         (method url-fetch)
         (uri (crate-uri "compiler_builtins" version))
-        (file-name (string-append name "-" version ".crate"))
+        (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32
           "1rhj6ccmfkh9gcxnxgjq4fg257yi4f9325nfzsphbmxwkrg06sq3"))))
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1)
-        ("rust-cc" ,rust-cc-1))))
+       ))
+       (inputs
+       `(("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1)
+        ("rust-cc" ,rust-cc-1)))
     (home-page "https://github.com/rust-lang/compiler-builtins")
     (synopsis "Compiler intrinsics used by the Rust compiler")
     (description
@@ -12459,10 +12457,9 @@  (define-public rust-cssparser-0.28
        (sha256
         (base32 "1h924c5g2rwlmgk8hllciyky3ih3z9vf04xz3xsp3cv1jyd5kf0x"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-cssparser-macros" ,rust-cssparser-macros-0.6)
+    (arguments `(#:skip-build? #t))
+    (inputs
+      `(("rust-cssparser-macros" ,rust-cssparser-macros-0.6)
         ("rust-dtoa-short" ,rust-dtoa-short-0.3)
         ("rust-itoa" ,rust-itoa-0.4)
         ("rust-matches" ,rust-matches-0.1)
@@ -12471,7 +12468,7 @@  (define-public rust-cssparser-0.28
         ("rust-quote" ,rust-quote-1)
         ("rust-serde" ,rust-serde-1)
         ("rust-smallvec" ,rust-smallvec-1)
-        ("rust-syn" ,rust-syn-1))))
+        ("rust-syn" ,rust-syn-1)))
     (home-page "https://github.com/servo/rust-cssparser")
     (synopsis "Rust implementation of CSS Syntax Level 3")
     (description
@@ -13601,13 +13598,11 @@  (define-public rust-data-url-0.1
          (base32
           "176wa1n8h71iwyaxhar4sqwrgrvb5sxk26az0fy88vnxrsffjgyk"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:cargo-inputs
-       (("rust-matches" ,rust-matches-0.1))
-       #:cargo-development-inputs
-       (("rust-rustc-test" ,rust-rustc-test-0.3)
+    (native-inputs
+      `(("rust-rustc-test" ,rust-rustc-test-0.3)
         ("rust-serde" ,rust-serde-1)
-        ("rust-serde-json" ,rust-serde-json-1))))
+        ("rust-serde-json" ,rust-serde-json-1)))
+    (inputs `(("rust-matches" ,rust-matches-0.1)))
     (home-page "https://github.com/servo/rust-url")
     (synopsis "Processing of data: URL according to WHATWG's Fetch Standard")
     (description
@@ -16334,23 +16329,24 @@  (define-public rust-encoding-0.2
         (string-append name "-" version ".tar.gz"))
        (sha256
         (base32
-         "1v1ndmkarh9z3n5hk53da4z56hgk9wa5kcsm7cnx345raqw983bb"))))
+         "1v1ndmkarh9z3n5hk53da4z56hgk9wa5kcsm7cnx345raqw983bb"))
+       (modules '((guix build utils)))
+       (snippet
+        '(begin
+           (substitute* "Cargo.toml"
+             (("path.*") ""))))))
     (build-system cargo-build-system)
     (arguments
-     `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-japanese"
-         ,rust-encoding-index-japanese-1.20141219)
-        ("rust-encoding-index-korean"
-         ,rust-encoding-index-korean-1.20141219)
-        ("rust-encoding-index-simpchinese"
-         ,rust-encoding-index-simpchinese-1.20141219)
-        ("rust-encoding-index-singlebyte"
-         ,rust-encoding-index-singlebyte-1.20141219)
-        ("rust-encoding-index-tradchinese"
-         ,rust-encoding-index-tradchinese-1.20141219))
-       #:cargo-development-inputs
-       (("rust-getopts" ,rust-getopts-0.2))))
+      `(;#:skip-build? #t
+        #:tests? #f
+        ))
+    (native-inputs `(("rust-getopts" ,rust-getopts-0.2)))
+    (inputs
+      `(("rust-encoding-index-japanese" ,rust-encoding-index-japanese-1.20141219)
+        ("rust-encoding-index-korean" ,rust-encoding-index-korean-1.20141219)
+        ("rust-encoding-index-simpchinese" ,rust-encoding-index-simpchinese-1.20141219)
+        ("rust-encoding-index-singlebyte" ,rust-encoding-index-singlebyte-1.20141219)
+        ("rust-encoding-index-tradchinese" ,rust-encoding-index-tradchinese-1.20141219)))
     (home-page
      "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Character encoding support for Rust")
@@ -16374,8 +16370,9 @@  (define-public rust-encoding-index-japanese-1.20141219
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1))))
+       ))
+       (inputs
+       `(("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1)))
     (home-page "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Index tables for Japanese character encodings")
     (description
@@ -16398,8 +16395,9 @@  (define-public rust-encoding-index-korean-1.20141219
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1))))
+       ))
+       (inputs
+       `(("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1)))
     (home-page "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Index tables for Korean character encodings")
     (description
@@ -16422,8 +16420,9 @@  (define-public rust-encoding-index-simpchinese-1.20141219
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1))))
+       ))
+       (inputs
+       `(("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1)))
     (home-page "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Index tables for simplified Chinese character encodings")
     (description
@@ -16446,8 +16445,9 @@  (define-public rust-encoding-index-singlebyte-1.20141219
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1))))
+       ))
+       (inputs
+       `(("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1)))
     (home-page "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Index tables for various single-byte character encodings")
     (description
@@ -16493,8 +16493,9 @@  (define-public rust-encoding-index-tradchinese-1.20141219
     (build-system cargo-build-system)
     (arguments
      `(#:skip-build? #t
-       #:cargo-inputs
-       (("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1))))
+       ))
+       (inputs
+       `(("rust-encoding-index-tests" ,rust-encoding-index-tests-0.1)))
     (home-page "https://github.com/lifthrasiir/rust-encoding")
     (synopsis "Index tables for traditional Chinese character encodings")
     (description
@@ -18388,8 +18389,7 @@  (define-public rust-float-cmp-0.8
          (base32
           "1i56hnzjn5pmrcm47fwkmfxiihk7wz5vvcgpb0kpfhzkqi57y9p1"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:cargo-inputs (("rust-num-traits" ,rust-num-traits-0.2))))
+    (inputs `(("rust-num-traits" ,rust-num-traits-0.2)))
     (home-page "https://github.com/mikedilger/float-cmp")
     (synopsis "Floating point approximate comparison traits")
     (description
@@ -20542,18 +20542,17 @@  (define-public rust-getopts-0.2
       (origin
         (method url-fetch)
         (uri (crate-uri "getopts" version))
-        (file-name (string-append name "-" version ".crate"))
+        (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32
           "1mgb3qvivi26gs6ihqqhh8iyhp3vgxri6vwyrwg28w0xqzavznql"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:cargo-inputs
-       (("rust-unicode-width" ,rust-unicode-width-0.1)
+     (inputs
+       `(("rust-unicode-width" ,rust-unicode-width-0.1)
         ("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1)
-        ("rust-rustc-std-workspace-std" ,rust-rustc-std-workspace-std-1))
-       #:cargo-development-inputs
-       (("rust-log" ,rust-log-0.3))))
+        ("rust-rustc-std-workspace-std" ,rust-rustc-std-workspace-std-1)))
+     (native-inputs
+       `(("rust-log" ,rust-log-0.4)))
     (home-page "https://github.com/rust-lang/getopts")
     (synopsis "Rust library for option parsing for CLI utilities")
     (description "This library provides getopts-like option parsing.")
@@ -26818,11 +26817,8 @@  (define-public rust-libm-0.2
         (base32
          "0akh56sh51adhagmk9l84dyrlz60gv8ri05xhr13i1b18czkpmy7"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:cargo-inputs
-       (("rust-rand" ,rust-rand-0.6))
-       #:cargo-development-inputs
-       (("rust-no-panic" ,rust-no-panic-0.1))))
+    (native-inputs `(("rust-no-panic" ,rust-no-panic-0.1)))
+    (inputs `(("rust-rand" ,rust-rand-0.6)))
     (home-page "https://github.com/rust-lang/libm")
     (synopsis "Libm in pure Rust")
     (description "This package provides an implementation of libm in pure Rust.")
@@ -27685,7 +27681,7 @@  (define-public rust-log-0.4
      (origin
        (method url-fetch)
        (uri (crate-uri "log" version))
-       (file-name (string-append name "-" version ".crate"))
+       (file-name (string-append name "-" version ".tar.gz"))
        (sha256
         (base32 "04175hv0v62shd82qydq58a48k3bjijmk54v38zgqlbxqkkbpfai"))))
     (build-system cargo-build-system)
@@ -44102,7 +44098,7 @@  (define-public rust-rustc-std-workspace-core-1
       (origin
         (method url-fetch)
         (uri (crate-uri "rustc-std-workspace-core" version))
-        (file-name (string-append name "-" version ".crate"))
+        (file-name (string-append name "-" version ".tar.gz"))
         (sha256
          (base32
           "1309xhwyai9xpz128xrfjqkmnkvgjwddznmj7brbd8i8f58zamhr"))))
@@ -58950,11 +58946,10 @@  (define-public rust-unicode-width-0.1
          (base32
           "0wq9wl69wlp6zwlxp660g9p4hm5gk91chwk14dp1gl9bxba45mry"))))
     (build-system cargo-build-system)
-    (arguments
-     `(#:cargo-inputs
-       (("rust-compiler-builtins" ,rust-compiler-builtins-0.1)
+     (inputs
+       `(("rust-compiler-builtins" ,rust-compiler-builtins-0.1)
         ("rust-rustc-std-workspace-core" ,rust-rustc-std-workspace-core-1)
-        ("rust-rustc-std-workspace-std" ,rust-rustc-std-workspace-std-1))))
+        ("rust-rustc-std-workspace-std" ,rust-rustc-std-workspace-std-1)))
     (home-page "https://github.com/unicode-rs/unicode-width")
     (synopsis "Determine displayed width according to Unicode rules")
     (description "This crate allows you to determine displayed width of
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index 2037ab9369..389b53eef0 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -3479,43 +3479,6 @@  (define-public librsvg
        ((guix build cargo-build-system)
         (guix build utils)
         ((guix build gnu-build-system) #:prefix gnu:))
-       #:cargo-inputs
-       (("rust-bitflags" ,rust-bitflags-1)
-        ("rust-cairo-rs" ,rust-cairo-rs-0.8)
-        ("rust-cairo-sys-rs" ,rust-cairo-sys-rs-0.9)
-        ("rust-cast" ,rust-cast-0.2)
-        ("rust-cssparser" ,rust-cssparser-0.27)
-        ("rust-data-url" ,rust-data-url-0.1)
-        ("rust-encoding" ,rust-encoding-0.2)
-        ("rust-float-cmp" ,rust-float-cmp-0.8)
-        ("rust-gdk-pixbuf" ,rust-gdk-pixbuf-0.8)
-        ("rust-gdk-pixbuf-sys" ,rust-gdk-pixbuf-sys-0.9)
-        ("rust-gio" ,rust-gio-0.8)
-        ("rust-gio-sys" ,rust-gio-sys-0.9)
-        ("rust-glib" ,rust-glib-0.9)
-        ("rust-glib-sys" ,rust-glib-sys-0.9)
-        ("rust-gobject-sys" ,rust-gobject-sys-0.9)
-        ("rust-itertools" ,rust-itertools-0.9)
-        ("rust-language-tags" ,rust-language-tags-0.2)
-        ("rust-libc" ,rust-libc-0.2)
-        ("rust-locale-config" ,rust-locale-config-0.3)
-        ("rust-markup5ever" ,rust-markup5ever-0.10)
-        ("rust-nalgebra" ,rust-nalgebra-0.21)
-        ("rust-num-traits" ,rust-num-traits-0.2)
-        ("rust-once-cell" ,rust-once-cell-1)
-        ("rust-pkg-config" ,rust-pkg-config-0.3)
-        ("rust-pango" ,rust-pango-0.8)
-        ("rust-pango-sys" ,rust-pango-sys-0.9)
-        ("rust-pangocairo" ,rust-pangocairo-0.9)
-        ("rust-rayon" ,rust-rayon-1)
-        ("rust-rctree" ,rust-rctree-0.3)
-        ("rust-rgb" ,rust-rgb-0.8)
-        ("rust-regex" ,rust-regex-1)
-        ("rust-selectors" ,rust-selectors-0.22)
-        ("rust-string-cache" ,rust-string-cache-0.8)
-        ("rust-tinyvec" ,rust-tinyvec-0.3)
-        ("rust-url" ,rust-url-2)
-        ("rust-xml5ever" ,rust-xml5ever-0.16))
        #:cargo-development-inputs
        (("rust-assert-cmd" ,rust-assert-cmd-1)
         ("rust-cairo-rs" ,rust-cairo-rs-0.8)
@@ -3621,7 +3584,43 @@  (define-public librsvg
            libcroco
            libgsf
            libxml2
-           pango))
+           pango
+           rust-bitflags-1
+           rust-cairo-rs-0.8
+           rust-cairo-sys-rs-0.9
+           rust-cast-0.2
+           rust-cssparser-0.27
+           rust-data-url-0.1
+           rust-encoding-0.2
+           rust-float-cmp-0.8
+           rust-gdk-pixbuf-0.8
+           rust-gdk-pixbuf-sys-0.9
+           rust-gio-0.8
+           rust-gio-sys-0.9
+           rust-glib-0.9
+           rust-glib-sys-0.9
+           rust-gobject-sys-0.9
+           rust-itertools-0.9
+           rust-language-tags-0.2
+           rust-libc-0.2
+           rust-locale-config-0.3
+           rust-markup5ever-0.10
+           rust-nalgebra-0.21
+           rust-num-traits-0.2
+           rust-once-cell-1
+           rust-pkg-config-0.3
+           rust-pango-0.8
+           rust-pango-sys-0.9
+           rust-pangocairo-0.9
+           rust-rayon-1
+           rust-rctree-0.3
+           rust-rgb-0.8
+           rust-regex-1
+           rust-selectors-0.22
+           rust-string-cache-0.8
+           rust-tinyvec-0.3
+           rust-url-2
+           rust-xml5ever-0.16))
     (propagated-inputs
      (list cairo gdk-pixbuf glib))
     (synopsis "SVG rendering library")
diff --git a/guix/build-system/cargo.scm b/guix/build-system/cargo.scm
index 60c35eed07..b2d97beb2f 100644
--- a/guix/build-system/cargo.scm
+++ b/guix/build-system/cargo.scm
@@ -125,17 +125,21 @@  (define builder
                     #:target #f
                     #:guile-for-build guile))
 
+(define (cargo-input? input)
+  (match input
+    ((label (? package? p))
+     (eq? cargo-build-system (package-build-system p)))
+    (_ #f)))
+
 (define (package-cargo-inputs p)
-  (apply
-    (lambda* (#:key (cargo-inputs '()) #:allow-other-keys)
-      cargo-inputs)
-    (package-arguments p)))
+  (match (member #:cargo-inputs (package-arguments p))
+    (#f (filter cargo-input? (package-inputs p)))
+    ((_ inputs . _) inputs)))
 
 (define (package-cargo-development-inputs p)
-  (apply
-    (lambda* (#:key (cargo-development-inputs '()) #:allow-other-keys)
-      cargo-development-inputs)
-    (package-arguments p)))
+  (match (member #:cargo-development-inputs (package-arguments p))
+    (#f (filter cargo-input? (package-native-inputs p)))
+    ((_ inputs . _) inputs)))
 
 (define (crate-closure inputs)
   "Return the closure of INPUTS when considering the 'cargo-inputs' and
@@ -235,8 +239,8 @@  (define (expand-crate-sources cargo-inputs cargo-development-inputs)
 (define* (lower name
                 #:key source inputs native-inputs outputs system target
                 (rust (default-rust))
-                (cargo-inputs '())
-                (cargo-development-inputs '())
+                (cargo-inputs (filter cargo-input? inputs))
+                (cargo-development-inputs (filter cargo-input? native-inputs))
                 #:allow-other-keys
                 #:rest arguments)
   "Return a bag for NAME."
@@ -260,7 +264,9 @@  (define private-keywords
          (build-inputs `(("cargo" ,rust "cargo")
                          ("rustc" ,rust)
                          ,@(expand-crate-sources cargo-inputs cargo-development-inputs)
-                         ,@native-inputs))
+                         ,@(if (eq? native-inputs cargo-development-inputs)
+                               '()
+                               native-inputs)))
          (outputs outputs)
          (build cargo-build)
          (arguments (strip-keyword-arguments private-keywords arguments)))))
diff --git a/guix/packages.scm b/guix/packages.scm
index b3c5a00011..275cc3675c 100644
--- a/guix/packages.scm
+++ b/guix/packages.scm
@@ -660,7 +660,8 @@  (define (deprecated-package old-name p)
     (name old-name)
     (properties `((superseded . ,p)))))
 
-(define (package-field-location package field)
+(define* (package-field-location package field
+                                 #:key (value-location? #t))
   "Return the source code location of the definition of FIELD for PACKAGE, or
 #f if it could not be determined."
   (match (package-location package)
@@ -678,7 +679,10 @@  (define (package-field-location package field)
                    (let ((field (assoc field inits)))
                      (match field
                        ((_ value)
-                        (let ((loc (and=> (source-properties value)
+                        (let ((loc (and=> (source-properties
+                                           (if value-location?
+                                               value
+                                               field))
                                           source-properties->location)))
                           (and loc
                                ;; Preserve the original file name, which may be a
diff --git a/guix/scripts/style.scm b/guix/scripts/style.scm
index 86a46f693c..dccc20d880 100644
--- a/guix/scripts/style.scm
+++ b/guix/scripts/style.scm
@@ -29,6 +29,7 @@ 
 
 (define-module (guix scripts style)
   #:autoload   (gnu packages) (specification->package fold-packages)
+  #:autoload   (guix build-system cargo) (cargo-build-system)
   #:use-module (guix scripts)
   #:use-module ((guix scripts build) #:select (%standard-build-options))
   #:use-module (guix combinators)
@@ -212,6 +213,21 @@  (define (object->string* obj indent)
       (pretty-print-with-comments port obj
                                   #:indent indent))))
 
+(define (object-list->string lst indent)
+  (call-with-output-string
+    (lambda (port)
+      (let loop ((lst lst))
+        (match lst
+          ((obj)
+           (pretty-print-with-comments port obj
+                                       #:indent indent))
+          ((obj rest ...)
+           (pretty-print-with-comments port obj
+                                       #:indent indent)
+           (newline port)
+           (display (make-string indent #\space) port)
+           (loop rest)))))))
+
 
 ;;;
 ;;; Simplifying input expressions.
@@ -441,6 +457,49 @@  (define matches?
             (list package-inputs package-native-inputs
                   package-propagated-inputs)))
 
+
+;;;
+;;; Crates, Cargo, Rust, and all that.
+;;;
+
+(define* (rewrite-cargo-inputs package
+                               #:key (policy 'silent)
+                               (edit-expression edit-expression))
+  (when (eq? (package-build-system package) cargo-build-system)
+    (match (package-field-location package 'arguments
+                                   #:value-location? #f)
+      (#f #f)
+      (location
+       (let* ((indent (location-column location)))
+         (edit-expression
+          (pk 'loc (location->source-properties location))
+          (lambda (str)
+            (define arguments
+              (call-with-input-string (pk 'str str) read-with-comments))
+
+            (match arguments
+              (('arguments ('quasiquote lst))
+               (let ((inputs (match (member #:cargo-inputs lst)
+                               (#f '())
+                               ((_ inputs . _) inputs)))
+                     (native (match (member #:cargo-development-inputs lst)
+                               (#f '())
+                               ((_ inputs . _) inputs)))
+                     (rest (strip-keyword-arguments
+                            '(#:cargo-inputs #:cargo-development-inputs)
+                            lst)))
+                 (object-list->string
+                  `(,@(if (null? rest)
+                          '()
+                          `((arguments ,(list 'quasiquote rest))))
+                    ,@(if (null? native)
+                          '()
+                          `((native-inputs ,(list 'quasiquote native))))
+                    ,@(if (null? inputs)
+                          '()
+                          `((inputs ,(list 'quasiquote inputs)))))
+                  indent)))))))))))
+
 (define (package-location<? p1 p2)
   "Return true if P1's location is \"before\" P2's."
   (let ((loc1 (package-location p1))
@@ -536,7 +595,7 @@  (define (parse-options)
                        edit-expression))
          (policy   (assoc-ref opts 'input-simplification-policy)))
     (for-each (lambda (package)
-                (simplify-package-inputs package #:policy policy
+                (rewrite-cargo-inputs package #:policy policy
                                          #:edit-expression edit))
               ;; Sort package by source code location so that we start editing
               ;; files from the bottom and going upward.  That way, the