From: Efraim Flashner <efraim@flashner.co.il>
To: "Ludovic Courtès" <ludo@gnu.org>
Cc: guix-devel@gnu.org
Subject: Re: Use and abuse of ‘computed-origin-method’: the ‘rust-ring’ case
Date: Sun, 15 Dec 2024 10:41:07 +0200 [thread overview]
Message-ID: <Z16WI0gUKM1APIMo@3900XT> (raw)
In-Reply-To: <87cyhtlwla.fsf@inria.fr>
[-- Attachment #1.1: Type: text/plain, Size: 3965 bytes --]
Thanks for bringing this up! rust-ring, while an interesting experiment
in how to package software which doesn't play well with rebuilding
sources, is certainly not something we want to have be the norm.
On Sat, Dec 14, 2024 at 11:37:53PM +0100, Ludovic Courtès wrote:
> Hello Guix,
>
> ‘rust-ring-0.16-sources’ & co. are origins that use
> ‘computed-origin-method’ (the thing that’s internal and undocumented) to
> generate object files from assembly source, things like that.
>
> An origin is supposed to represent source code, and clearly, the end
> result here is not source by any stretch.
>
> I believe it’s done this way simply because ‘cargo-build-system’ then
> embarks that “source” to build leaf package(s) that use ‘rust-ring’,
> directly or indirectly; this is where Rust compilation actually takes
> place and, IIUC, the reason why a build phase in ‘rust-ring’ would be of
> no use.
That's correct. If we went the normal route and removed all the
pre-generated files in a snippet and rebuilt them during the actual
package build that would only work for that package, and we'd have to
duplicate that for each package which uses rust-ring.
> Anyway, the ‘computed-origin-method’ hack prevents input rewriting from
> working as expected because the inputs of that big gexp aren’t visible
> by just traversing the package graph. That’s a problem.
Are we talking about the inputs used for the computed-origin? (perl,
nasm, go, etc?)
> Ideas on how to fix that?
>
> An idea that comes to mind is to turn ‘rust-ring-0.16-sources’ into a
> package using ‘trivial-build-system’, though I’m not sure it would work
> well with ‘cargo-build-system’.
The main problem we're faced with here is that "the source" (as rustc
defines it) isn't to be touched during the build. Hence almost
everything that is rebuilt is put into the pregenerated folder in the
sources. There are a couple of files that are generated outside of the
pregenerated directory, and none that are expected to be generated in
the target directory.
I'm pretty sure there are 3 options here:
1. Stop rebuilding the generated files. This is what we did in the past,
and it allows rust-ring-0.14 to be used on riscv64-linux. I haven't
talked with the Debian folks about it but I'm pretty sure this is what
they currently do. I don't like it because we have instructions on how
to do the rebuild and it's already implemented. I also really like that
everything can be regenerated from (nearly) any architecture, which
makes it a much nicer build than qemu, which needs many cross compilers.
2. Use the trivial-build-system instead of a computed-origin-method.
I'm pretty sure we can use the output of the trivial-build-system (or
any other package build) as the source for another package. I
currently think this is the best option.
3. Adjust the build.rs file in rust-ring to call a custom shell script
which will build all the missing files that we would remove in a
snippet. This is probably best from a "the source is ready to hack on"
perspective, but it means we're carrying around a custom build script
with no chance of being upstreamed. It also means that each package
which uses rust-ring will need to have all the rust-ring build
dependencies added and it will need to be built each time.
I've attached a patch that I tested locally to build the sources in an
actual package, and then use that to build rust-ring. I tested it by
building librsvg. Currently it still requires go itself as using gccgo
needs gccgo-toolchain.
On a side note, I would like to point out that we also use this for
linux-libre and for icecat.
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #1.2: 0001-gnu-rust-ring-0.17-Build-source-using-trivial-build-.patch --]
[-- Type: text/plain, Size: 22403 bytes --]
From bd33099bc04dc3663554ebe68d1d70345aceaef3 Mon Sep 17 00:00:00 2001
Message-ID: <bd33099bc04dc3663554ebe68d1d70345aceaef3.1734251982.git.efraim@flashner.co.il>
From: Efraim Flashner <efraim@flashner.co.il>
Date: Sun, 15 Dec 2024 10:38:11 +0200
Subject: [PATCH] gnu: rust-ring-0.17: Build source using trivial-build-system.
This removes this use of computed-origin-method.
* gnu/packages/crates-crypto.scm (rust-ring-0.17-sources): Replace use
of computed-origin-method with an actual package.
Change-Id: I195805492d61e7a1294926a047b0332265ae8187
---
gnu/packages/crates-crypto.scm | 339 +++++++++++++++++----------------
1 file changed, 172 insertions(+), 167 deletions(-)
diff --git a/gnu/packages/crates-crypto.scm b/gnu/packages/crates-crypto.scm
index 995b183652a..982f6d1eeb1 100644
--- a/gnu/packages/crates-crypto.scm
+++ b/gnu/packages/crates-crypto.scm
@@ -35,6 +35,7 @@
(define-module (gnu packages crates-crypto)
#:use-module (guix build-system cargo)
+ #:use-module (guix build-system trivial)
#:use-module (guix download)
#:use-module (guix git-download)
#:use-module ((guix licenses) #:prefix license:)
@@ -4135,11 +4136,11 @@ (define-public rust-rfc6979-0.3
("rust-zeroize" ,rust-zeroize-1))
#:cargo-development-inputs (("rust-sha2" ,rust-sha2-0.10))))))
-(define computed-origin-method (@@ (guix packages) computed-origin-method))
(define rust-ring-0.17-sources
- (let* ((version "0.17.8")
- (upstream-source
- (origin
+ (package
+ (name "rust-ring")
+ (version "0.17.8.tar.gz") ; Hack to adjust the output name.
+ (source (origin
(method git-fetch)
(uri (git-reference
(url "https://github.com/briansmith/ring")
@@ -4147,182 +4148,185 @@ (define rust-ring-0.17-sources
(file-name (git-file-name "rust-ring" version))
(sha256
(base32 "0rqfal81bf4l3dja98cajfjq2jbz1rcx7xdp2r33cxrm5y5psr28"))
- (patches (search-patches "rust-ring-0.17-ring-core.patch")))))
- (origin
- (method computed-origin-method)
- (file-name (string-append "rust-ring-" version ".tar.gz"))
- (sha256 #f)
- (uri
- (delay
- (with-imported-modules '((guix build utils))
- #~(begin
- (use-modules (guix build utils))
- (set-path-environment-variable
- "PATH" '("bin")
- (list #+(canonical-package gzip)
- #+(canonical-package tar)
- #+perl
- #+nasm
- #+go
- #+clang ; clang-format
- #+python-minimal))
- (setenv "HOME" (getcwd))
- (copy-recursively #+upstream-source
- (string-append "ring-" #$version))
- (with-directory-excursion (string-append "ring-" #$version)
- (begin
- ;; It turns out Guix's nasm works just fine here.
- (substitute* "build.rs"
- (("./target/tools/windows/nasm/nasm") "nasm"))
- ;; Files which would be deleted in a snippet:
- (delete-file "crypto/curve25519/curve25519_tables.h")
- (delete-file "crypto/fipsmodule/ec/p256-nistz-table.h")
- (delete-file "crypto/fipsmodule/ec/p256_table.h")
- ;; This file causes problems during the 'package phase and
- ;; is not distributed with the packaged crate.
- (substitute* "Cargo.toml"
- (("\"bench\",") ""))
- (delete-file "bench/Cargo.toml")
- ;; Files to be generated in the sources:
- (format #t "Generating the missing files ...~%")
- (force-output)
- (with-directory-excursion "crypto/curve25519"
- (with-output-to-file "curve25519_tables.h"
- (lambda _ (invoke "python3" "make_curve25519_tables.py")))
- ;; As seen in git between 0.17.0 and 0.17.1.
- (substitute* "curve25519_tables.h"
- (("static const uint8_t k25519Precomp")
- "const uint8_t k25519Precomp")))
- (with-directory-excursion "crypto/fipsmodule/ec"
- (invoke "go" "run" "make_tables.go")
- (invoke "go" "run" "make_ec_scalar_base_mult_tests.go"))
- (format #t "Generating the pregenerated files ...~%")
- (force-output)
- (mkdir-p "pregenerated/tmp/ring_core_generated")
+ (patches (search-patches "rust-ring-0.17-ring-core.patch"))
+ (snippet
+ #~(begin (use-modules (guix build utils))
+ ;; It turns out Guix's nasm works just fine here.
+ (substitute* "build.rs"
+ (("./target/tools/windows/nasm/nasm") "nasm"))
+ ;; These files are pregenerated:
+ (delete-file "crypto/curve25519/curve25519_tables.h")
+ (delete-file "crypto/fipsmodule/ec/p256-nistz-table.h")
+ (delete-file "crypto/fipsmodule/ec/p256_table.h")
+ ;; As seen in git between 0.17.0 and 0.17.1.
+ (substitute* "crypto/curve25519/make_curve25519_tables.py"
+ (("static const uint8_t k25519Precomp")
+ "const uint8_t k25519Precomp"))
+ ;; This file causes problems during the 'package phase and
+ ;; is not distributed with the packaged crate.
+ (substitute* "Cargo.toml"
+ (("\"bench\",") ""))
+ (delete-file "bench/Cargo.toml")))))
+ (build-system trivial-build-system)
+ (arguments
+ (list
+ #:modules '((guix build utils))
+ #:builder
+ #~(begin
+ (use-modules (guix build utils))
+ (setenv "PATH"
+ (string-join
+ (list (assoc-ref %build-inputs "clang") ; for clang-format
+ (assoc-ref %build-inputs "go")
+ (assoc-ref %build-inputs "gzip")
+ (assoc-ref %build-inputs "nasm")
+ (assoc-ref %build-inputs "perl")
+ (assoc-ref %build-inputs "python-minimal")
+ (assoc-ref %build-inputs "tar"))
+ "/bin:" 'suffix))
- ;; We generate all the files which upstream would normally be
- ;; generate by using 'RING_PREGENERATE_ASM=1 cargo build
- ;; --target-dir=target/pregenerate_asm' in order to not include
- ;; a dependency on cargo when generating the sources.
- (define (prefix script)
- (string-append
- "pregenerated/"
- (string-drop-right
- (string-drop script
- (string-index-right script #\/)) 3)))
+ (setenv "HOME" (getcwd))
+ (copy-recursively #+source (string-append "ring-" #$version))
+ (with-directory-excursion (string-append "ring-" #$version)
+ (begin
+ (with-directory-excursion "crypto/curve25519"
+ (with-output-to-file "curve25519_tables.h"
+ (lambda _ (invoke "python3" "make_curve25519_tables.py"))))
+ (with-directory-excursion "crypto/fipsmodule/ec"
+ (invoke "go" "run" "make_tables.go")
+ (invoke "go" "run" "make_ec_scalar_base_mult_tests.go"))
+ (format #t "Generating the pregenerated files ...~%")
+ (force-output)
+ (mkdir-p "pregenerated/tmp/ring_core_generated")
- (for-each
- (lambda (script)
- (invoke "perl" script "ios64"
- (string-append (prefix script) "-ios64.S"))
- (invoke "perl" script "linux64"
- (string-append (prefix script) "-linux64.S"))
- (invoke "perl" script "win64"
- (string-append (prefix script) "-win64.S")))
- '("crypto/fipsmodule/aes/asm/aesv8-armx.pl"
- "crypto/fipsmodule/modes/asm/ghashv8-armx.pl"
- "crypto/chacha/asm/chacha-armv8.pl"
- "crypto/cipher_extra/asm/chacha20_poly1305_armv8.pl"
- "crypto/fipsmodule/aes/asm/vpaes-armv8.pl"
- "crypto/fipsmodule/bn/asm/armv8-mont.pl"
- "crypto/fipsmodule/ec/asm/p256-armv8-asm.pl"
- "crypto/fipsmodule/modes/asm/ghash-neon-armv8.pl"
- "crypto/fipsmodule/modes/asm/aesv8-gcm-armv8.pl"
- "crypto/fipsmodule/sha/asm/sha512-armv8.pl"))
+ ;; We generate all the files which upstream would normally be
+ ;; generate by using 'RING_PREGENERATE_ASM=1 cargo build
+ ;; --target-dir=target/pregenerate_asm' in order to not include
+ ;; a dependency on cargo when generating the sources.
+ (define (prefix script)
+ (string-append
+ "pregenerated/"
+ (string-drop-right
+ (string-drop script
+ (string-index-right script #\/)) 3)))
- (for-each
- (lambda (arch)
- (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-armv8.pl"
- arch (string-append
- "pregenerated/sha256-armv8-" arch ".S")))
- '("ios64" "linux64" "win64"))
+ (for-each
+ (lambda (script)
+ (invoke "perl" script "ios64"
+ (string-append (prefix script) "-ios64.S"))
+ (invoke "perl" script "linux64"
+ (string-append (prefix script) "-linux64.S"))
+ (invoke "perl" script "win64"
+ (string-append (prefix script) "-win64.S")))
+ '("crypto/fipsmodule/aes/asm/aesv8-armx.pl"
+ "crypto/fipsmodule/modes/asm/ghashv8-armx.pl"
+ "crypto/chacha/asm/chacha-armv8.pl"
+ "crypto/cipher_extra/asm/chacha20_poly1305_armv8.pl"
+ "crypto/fipsmodule/aes/asm/vpaes-armv8.pl"
+ "crypto/fipsmodule/bn/asm/armv8-mont.pl"
+ "crypto/fipsmodule/ec/asm/p256-armv8-asm.pl"
+ "crypto/fipsmodule/modes/asm/ghash-neon-armv8.pl"
+ "crypto/fipsmodule/modes/asm/aesv8-gcm-armv8.pl"
+ "crypto/fipsmodule/sha/asm/sha512-armv8.pl"))
- (for-each
- (lambda (script)
- (invoke "perl" script "linux32"
- (string-append (prefix script) "-linux32.S")))
- '("crypto/fipsmodule/aes/asm/aesv8-armx.pl"
- "crypto/fipsmodule/modes/asm/ghashv8-armx.pl"
- "crypto/fipsmodule/aes/asm/bsaes-armv7.pl"
- "crypto/fipsmodule/aes/asm/vpaes-armv7.pl"
- "crypto/fipsmodule/bn/asm/armv4-mont.pl"
- "crypto/chacha/asm/chacha-armv4.pl"
- "crypto/fipsmodule/modes/asm/ghash-armv4.pl"
- "crypto/fipsmodule/sha/asm/sha256-armv4.pl"
- "crypto/fipsmodule/sha/asm/sha512-armv4.pl"))
+ (for-each
+ (lambda (arch)
+ (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-armv8.pl"
+ arch (string-append
+ "pregenerated/sha256-armv8-" arch ".S")))
+ '("ios64" "linux64" "win64"))
- (for-each
- (lambda (script)
- (invoke "perl" script "elf"
- "-fPIC" "-DOPENSSL_IA32_SSE2"
- (string-append (prefix script) "-elf.S"))
- (invoke "perl" script "win32n"
- "-fPIC" "-DOPENSSL_IA32_SSE2"
- (string-append
- "pregenerated/tmp/"
- (string-drop (prefix script) 13) "-win32n.asm")))
- '("crypto/fipsmodule/aes/asm/aesni-x86.pl"
- "crypto/fipsmodule/aes/asm/vpaes-x86.pl"
- "crypto/fipsmodule/bn/asm/x86-mont.pl"
- "crypto/chacha/asm/chacha-x86.pl"
- "crypto/fipsmodule/modes/asm/ghash-x86.pl"))
+ (for-each
+ (lambda (script)
+ (invoke "perl" script "linux32"
+ (string-append (prefix script) "-linux32.S")))
+ '("crypto/fipsmodule/aes/asm/aesv8-armx.pl"
+ "crypto/fipsmodule/modes/asm/ghashv8-armx.pl"
+ "crypto/fipsmodule/aes/asm/bsaes-armv7.pl"
+ "crypto/fipsmodule/aes/asm/vpaes-armv7.pl"
+ "crypto/fipsmodule/bn/asm/armv4-mont.pl"
+ "crypto/chacha/asm/chacha-armv4.pl"
+ "crypto/fipsmodule/modes/asm/ghash-armv4.pl"
+ "crypto/fipsmodule/sha/asm/sha256-armv4.pl"
+ "crypto/fipsmodule/sha/asm/sha512-armv4.pl"))
- (for-each
- (lambda (script)
- (invoke "perl" script "elf"
- (string-append (prefix script) "-elf.S"))
- (invoke "perl" script "macosx"
- (string-append (prefix script) "-macosx.S"))
- (invoke "perl" script "nasm"
- (string-append
- "pregenerated/tmp/"
- (string-drop (prefix script) 13) "-nasm.asm")))
- '("crypto/chacha/asm/chacha-x86_64.pl"
- "crypto/fipsmodule/aes/asm/aesni-x86_64.pl"
- "crypto/fipsmodule/aes/asm/vpaes-x86_64.pl"
- "crypto/fipsmodule/bn/asm/x86_64-mont.pl"
- "crypto/fipsmodule/bn/asm/x86_64-mont5.pl"
- "crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl"
- "crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl"
- "crypto/fipsmodule/modes/asm/ghash-x86_64.pl"
- "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
- "crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl"))
+ (for-each
+ (lambda (script)
+ (invoke "perl" script "elf"
+ "-fPIC" "-DOPENSSL_IA32_SSE2"
+ (string-append (prefix script) "-elf.S"))
+ (invoke "perl" script "win32n"
+ "-fPIC" "-DOPENSSL_IA32_SSE2"
+ (string-append
+ "pregenerated/tmp/"
+ (string-drop (prefix script) 13) "-win32n.asm")))
+ '("crypto/fipsmodule/aes/asm/aesni-x86.pl"
+ "crypto/fipsmodule/aes/asm/vpaes-x86.pl"
+ "crypto/fipsmodule/bn/asm/x86-mont.pl"
+ "crypto/chacha/asm/chacha-x86.pl"
+ "crypto/fipsmodule/modes/asm/ghash-x86.pl"))
- (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
- "elf" "pregenerated/sha256-x86_64-elf.S")
+ (for-each
+ (lambda (script)
+ (invoke "perl" script "elf"
+ (string-append (prefix script) "-elf.S"))
+ (invoke "perl" script "macosx"
+ (string-append (prefix script) "-macosx.S"))
+ (invoke "perl" script "nasm"
+ (string-append
+ "pregenerated/tmp/"
+ (string-drop (prefix script) 13) "-nasm.asm")))
+ '("crypto/chacha/asm/chacha-x86_64.pl"
+ "crypto/fipsmodule/aes/asm/aesni-x86_64.pl"
+ "crypto/fipsmodule/aes/asm/vpaes-x86_64.pl"
+ "crypto/fipsmodule/bn/asm/x86_64-mont.pl"
+ "crypto/fipsmodule/bn/asm/x86_64-mont5.pl"
+ "crypto/fipsmodule/ec/asm/p256-x86_64-asm.pl"
+ "crypto/fipsmodule/modes/asm/aesni-gcm-x86_64.pl"
+ "crypto/fipsmodule/modes/asm/ghash-x86_64.pl"
+ "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
+ "crypto/cipher_extra/asm/chacha20_poly1305_x86_64.pl"))
- (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
- "macosx" "pregenerated/sha256-x86_64-macosx.S")
+ (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
+ "elf" "pregenerated/sha256-x86_64-elf.S")
- (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
- "nasm" "pregenerated/tmp/sha256-x86_64-nasm.asm")
+ (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
+ "macosx" "pregenerated/sha256-x86_64-macosx.S")
- ;; TODO: Extract ring_core_generated/prefix_symbols_nasm.inc
- ;; and ring_core_generated/prefix_symbols_asm.h from build.rs.
+ (invoke "perl" "crypto/fipsmodule/sha/asm/sha512-x86_64.pl"
+ "nasm" "pregenerated/tmp/sha256-x86_64-nasm.asm")
- (for-each
- (lambda (script)
- (invoke "nasm" "-o" (string-append (prefix script) "o")
- "-f" "win32" "-i" "include/" "-i" "pregenerated/tmp/"
- "-Xgnu" "-gcv8" script))
- (find-files "pregenerated/tmp" "win32n\\.asm"))
+ ;; TODO: Extract ring_core_generated/prefix_symbols_nasm.inc
+ ;; and ring_core_generated/prefix_symbols_asm.h from build.rs.
- (for-each
- (lambda (script)
- (invoke "nasm" "-o" (string-append (prefix script) "o")
- "-f" "win64" "-i" "include/" "-i" "pregenerated/tmp/"
- "-Xgnu" "-gcv8" script))
- (find-files "pregenerated/tmp" "nasm\\.asm"))
+ (for-each
+ (lambda (script)
+ (invoke "nasm" "-o" (string-append (prefix script) "o")
+ "-f" "win32" "-i" "include/" "-i" "pregenerated/tmp/"
+ "-Xgnu" "-gcv8" script))
+ (find-files "pregenerated/tmp" "win32n\\.asm"))
- (format #t "Creating the tarball ...~%")
- (force-output)
- ;; The other option is to use cargo package --allow-dirty
- (with-directory-excursion "../"
- (invoke "tar" "czf" #$output
- ;; avoid non-determinism in the archive
- "--sort=name" "--mtime=@0"
- "--owner=root:0" "--group=root:0"
- (string-append "ring-" #$version))))))))))))
+ (for-each
+ (lambda (script)
+ (invoke "nasm" "-o" (string-append (prefix script) "o")
+ "-f" "win64" "-i" "include/" "-i" "pregenerated/tmp/"
+ "-Xgnu" "-gcv8" script))
+ (find-files "pregenerated/tmp" "nasm\\.asm"))
+
+ (format #t "Creating the tarball ...~%")
+ (force-output)
+ (with-directory-excursion "../"
+ (invoke "tar" "czf" #$output
+ ;; avoid non-determinism in the archive
+ "--sort=name" "--mtime=@0"
+ "--owner=root:0" "--group=root:0"
+ (string-append "ring-" #$version))))))))
+ (native-inputs
+ (list clang go gzip nasm perl python-minimal tar))
+ (home-page "https://github.com/briansmith/ring")
+ (synopsis "Safe, fast, small crypto using Rust")
+ (description "This package provided safe, fast, small crypto using Rust.")
+ (license (list license:isc license:openssl))))
(define-public rust-ring-0.17
(package
@@ -4346,6 +4350,7 @@ (define-public rust-ring-0.17
(description "This package provided safe, fast, small crypto using Rust.")
(license (list license:isc license:openssl))))
+(define computed-origin-method (@@ (guix packages) computed-origin-method))
(define rust-ring-0.16-sources
(let* ((version "0.16.20")
(upstream-source
base-commit: cfd4f56f75a20b6732d463180d211f796c9032e5
--
Efraim Flashner <efraim@flashner.co.il> אפרים פלשנר
GPG key = A28B F40C 3E55 1372 662D 14F7 41AA E7DC CA3D 8351
Confidentiality cannot be guaranteed on emails sent or received unencrypted
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2024-12-15 10:53 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-12-14 22:37 Use and abuse of ‘computed-origin-method’: the ‘rust-ring’ case Ludovic Courtès
2024-12-15 8:41 ` Efraim Flashner [this message]
2024-12-15 13:50 ` Ludovic Courtès
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z16WI0gUKM1APIMo@3900XT \
--to=efraim@flashner.co.il \
--cc=guix-devel@gnu.org \
--cc=ludo@gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/guix.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.