public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
From: "Yoann Congal" <yoann.congal@smile.fr>
To: "Mohamad Alsadhan" <mo@sdhn.cc>,
	"Nathan Chancellor" <nathan@kernel.org>,
	"Nicolas Schier" <nsc@kernel.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>
Cc: <linux-kbuild@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
	<rust-for-linux@vger.kernel.org>
Subject: Re: [PATCH v6] kbuild: host: use single executable for rustc -C linker
Date: Wed, 01 Apr 2026 07:53:52 +0200	[thread overview]
Message-ID: <DHHL2VVCVYHU.5RMX7GJ73MDR@smile.fr> (raw)
In-Reply-To: <20260331000802.380-1-mo@sdhn.cc>

On Tue Mar 31, 2026 at 2:08 AM CEST, Mohamad Alsadhan wrote:
> rustc's -C linker= option expects a single executable path. When
> HOSTCC contains a wrapper (e.g. "ccache gcc"), passing
> `-Clinker=$(HOSTCC)` results in the shell splitting the value into
> multiple words, and rustc interprets the additional word as an
> input filename:
>
>   error: multiple input filenames provided ...
>
> Generate a small wrapper script and pass it to -Clinker e.g.
>
>   ```
>   #!/bin/sh
>   exec ccache gcc "$@"
>   ```
>
> This fix should be general enough to address most if not all cases
> (incl. wrappers or subcommands) and avoids surprises of simpler fixes
> like just defaulting to gcc.
>
> This avoids passing the user command as an environment variable as
> that would be more challenging to trace and debug shell expansions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1224
> Suggested-by: Yoann Congal <yoann.congal@smile.fr>

I tested this patch in the original environnement for the issue : a
ccache-enabled Yocto build. It works. Thanks!

Tested-by: Yoann Congal <yoann.congal@smile.fr>

> Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
> ---
> v5 -> v6:
>   - Add fix to `rust/Makefile` as well (Yoann)
>   - Include script to `.gitignore` and make clean (Nicolas)
>   - Add back the outer `exec` to the command
>
> v4 -> v5:
>   - Fix word splitting issues
>   - Remove unnecessary `exec sh -c` and simplify generated script
>
> v3 -> v4:
>   - Use filechk instead of if_changed macro to regenerate script
>   - Remove trailing space at EOL
>
> v2 -> v3:
>   - Scrap previous hacky approaches (e.g. using lastword) and go with
>     a proper fix (Gary) which turned out not that complex to
>     implement.
>
> v1 -> v2:
>   - Rename HOSTRUSTC_LINKER to HOSTRUSTC_LD for consistency
>   - Introduce explicit HOSTRUSTC_LD override
>   - Warn when falling back due to multi-argument HOSTCC
>   - Error out if a user-specified HOSTRUSTC_LD is not an executable
>
> v1: https://lore.kernel.org/all/20260225102819.16553-1-mo@sdhn.cc/
> v2: https://lore.kernel.org/all/20260227132713.23106-1-mo@sdhn.cc/
> v3: https://lore.kernel.org/all/20260312002852.11292-1-mo@sdhn.cc/
> v4: https://lore.kernel.org/all/20260317112021.14353-1-mo@sdhn.cc/
> v5: https://lore.kernel.org/all/20260321150034.9915-1-mo@sdhn.cc/
> ---
>  Makefile              |  3 ++-
>  rust/Makefile         |  8 +++++---
>  scripts/.gitignore    |  1 +
>  scripts/Makefile.host | 23 +++++++++++++++++++++--
>  4 files changed, 29 insertions(+), 6 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 1a219bf1c..5ebeef67f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1651,7 +1651,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
>  	       modules.builtin.ranges vmlinux.o.map vmlinux.unstripped \
>  	       compile_commands.json rust/test \
>  	       rust-project.json .vmlinux.objs .vmlinux.export.c \
> -               .builtin-dtbs-list .builtin-dtb.S
> +               .builtin-dtbs-list .builtin-dtb.S \
> +	       scripts/rustc-wrapper
>  
>  # Directories & files removed with 'make mrproper'
>  MRPROPER_FILES += include/config include/generated          \
> diff --git a/rust/Makefile b/rust/Makefile
> index 5eca6a817..6bc761a31 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -565,7 +565,7 @@ $(obj)/libsyn.rlib: $(src)/syn/lib.rs $(obj)/libquote.rlib FORCE
>  quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
>        cmd_rustc_procmacro = \
>  	$(RUSTC_OR_CLIPPY) $(rust_common_flags) $(rustc_target_flags) \
> -		-Clinker-flavor=gcc -Clinker=$(HOSTCC) \
> +		-Clinker-flavor=gcc -Clinker=scripts/rustc-wrapper \
>  		-Clink-args='$(call escsq,$(KBUILD_PROCMACROLDFLAGS))' \
>  		--emit=dep-info=$(depfile) --emit=link=$@ --extern proc_macro \
>  		--crate-type proc-macro -L$(objtree)/$(obj) \
> @@ -576,12 +576,14 @@ quiet_cmd_rustc_procmacro = $(RUSTC_OR_CLIPPY_QUIET) P $@
>  $(obj)/$(libmacros_name): private rustc_target_flags = \
>      --extern proc_macro2 --extern quote --extern syn
>  $(obj)/$(libmacros_name): $(src)/macros/lib.rs $(obj)/libproc_macro2.rlib \
> -    $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
> +    $(obj)/libquote.rlib $(obj)/libsyn.rlib \
> +    scripts/rustc-wrapper FORCE
>  	+$(call if_changed_dep,rustc_procmacro)
>  
>  $(obj)/$(libpin_init_internal_name): private rustc_target_flags = $(pin_init_internal-flags)
>  $(obj)/$(libpin_init_internal_name): $(src)/pin-init/internal/src/lib.rs \
> -    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib FORCE
> +    $(obj)/libproc_macro2.rlib $(obj)/libquote.rlib $(obj)/libsyn.rlib \
> +    scripts/rustc-wrapper FORCE
>  	+$(call if_changed_dep,rustc_procmacro)
>  
>  # `rustc` requires `-Zunstable-options` to use custom target specifications
> diff --git a/scripts/.gitignore b/scripts/.gitignore
> index 4215c2208..b3948b148 100644
> --- a/scripts/.gitignore
> +++ b/scripts/.gitignore
> @@ -6,6 +6,7 @@
>  /kallsyms
>  /module.lds
>  /recordmcount
> +/rustc-wrapper
>  /rustdoc_test_builder
>  /rustdoc_test_gen
>  /sign-file
> diff --git a/scripts/Makefile.host b/scripts/Makefile.host
> index c1dedf646..77a76c1d1 100644
> --- a/scripts/Makefile.host
> +++ b/scripts/Makefile.host
> @@ -87,11 +87,30 @@ hostcxx_flags  = -Wp,-MMD,$(depfile) \
>                   $(KBUILD_HOSTCXXFLAGS) $(HOST_EXTRACXXFLAGS) \
>                   $(HOSTCXXFLAGS_$(target-stem).o)
>  
> +# rustc's `-Clinker=` expects a single executable path, not a command line.
> +# `HOSTCC` may be a multi-word command when wrapped (e.g. "ccache gcc"), which
> +# would otherwise be split by the shell and mis-parsed by rustc.
> +# To work around this, we generate a wrapper script that forwards arguments to
> +# `HOSTRUSTC_LD` so that such commands can be used safely.
> +#
> +# Set `HOSTRUSTC_LD` for a different rustc linker command than `HOSTCC`
> +HOSTRUSTC_LD ?= $(HOSTCC)
> +
> +define filechk_rustc-wrapper
> +	printf "%s\n" \
> +		'#!/bin/sh' \
> +		'exec $(call escsq,$(HOSTRUSTC_LD)) "$$@"'
> +endef
> +
> +$(obj)/rustc-wrapper: FORCE
> +	$(call filechk,rustc-wrapper)
> +	$(Q)chmod +x $@
> +
>  # `--out-dir` is required to avoid temporaries being created by `rustc` in the
>  # current working directory, which may be not accessible in the out-of-tree
>  # modules case.
>  hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
> -		 -Clinker-flavor=gcc -Clinker=$(HOSTCC) \
> +		 -Clinker-flavor=gcc -Clinker=scripts/rustc-wrapper \

Does using "scripts/" without a $(obj)/$(srctree)/... prefix always works?
I know I've suggested this as a quick fix. But I did not think about it
a lot.

>  		 -Clink-args='$(call escsq,$(KBUILD_HOSTLDFLAGS))' \
>                   $(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
>                   $(HOSTRUSTFLAGS_$(target-stem))
> @@ -153,7 +172,7 @@ $(host-cxxobjs): $(obj)/%.o: $(obj)/%.cc FORCE
>  quiet_cmd_host-rust	= HOSTRUSTC $@
>        cmd_host-rust	= \
>  	$(HOSTRUSTC) $(hostrust_flags) --emit=link=$@ $<
> -$(host-rust): $(obj)/%: $(src)/%.rs FORCE
> +$(host-rust): $(obj)/%: $(src)/%.rs $(obj)/rustc-wrapper FORCE
>  	+$(call if_changed_dep,host-rust)
>  
>  targets += $(host-csingle) $(host-cmulti) $(host-cobjs) \


-- 
Yoann Congal
Smile ECS


  reply	other threads:[~2026-04-01  5:53 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-31  0:08 [PATCH v6] kbuild: host: use single executable for rustc -C linker Mohamad Alsadhan
2026-04-01  5:53 ` Yoann Congal [this message]
2026-04-07 20:29 ` Nicolas Schier
2026-04-12 14:19   ` Mohamad Alsadhan

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=DHHL2VVCVYHU.5RMX7GJ73MDR@smile.fr \
    --to=yoann.congal@smile.fr \
    --cc=a.hindborg@kernel.org \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun@kernel.org \
    --cc=dakr@kernel.org \
    --cc=gary@garyguo.net \
    --cc=linux-kbuild@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mo@sdhn.cc \
    --cc=nathan@kernel.org \
    --cc=nsc@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    /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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox