tech-pkg archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Cross-building rusty packages



Not finished yet, but I thought I'd share some patches I drafted for
cross-building packages written in Rust, so that when you use
doc/HOWTO-use-crosscompile, it just works to build those packages.
(crossrust.patch is a series of individual changes with commit
messages; crossrust.diff is a single giant diff combining them all.)

Doesn't yet work to cross-compile lang/rust itself but has some
progress toward that -- and with a little more work (and a lot more
waiting for builds!) we should be able to have a lang/rust-bootstrap
package or something that automagically creates the bootstrap kits.

Many rusty packages install things like

	${INSTALL_PROGRAM} ${WRKSRC}/target/release/foo ...

which will have to be adjusted because the path is different when
cross-building -- I added a new variable CARGO_OUTPUT_DIR to cargo.mk
so this can just be:

	${INSTALL_PROGRAM} ${CARGO_OUTPUT_DIR}/foo ...

Some of the patches are ready for commit (like some initial tidying
around PREFIX vs TOOLBASE, PYTHONBIN vs TOOL_PYTHONBIN, adding the
initial version of CARGO_OUTPUT_DIR) but I'm waiting to do a bit more
testing and apply them uniformly to lang/rust, lang/rust176, and
wip/rust*, and see what's wrong with rpaths in wip/rust183.

Feedback welcome!
>From cfcc436f038af95ec0281f0bdaf55eab99ff596c Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Thu, 9 Jan 2025 12:08:01 +0000
Subject: [PATCH 1/6] lang/rust: Need python and cmake as tool deps, not build
 deps.

These are both executed natively as tools at build-time; we don't use
cross-built Python or cmake for reference like a header file or
library at build-time.

Use TOOL_PYTHONBIN (path to Python executable which we can run at
build-time), not PYTHONBIN (path to Python executable to be baked
into the package for use at at run-time).
---
 lang/rust/Makefile | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/lang/rust/Makefile b/lang/rust/Makefile
index 001da1136e21..a9ec0d763a8b 100644
--- a/lang/rust/Makefile
+++ b/lang/rust/Makefile
@@ -32,13 +32,13 @@ USE_TOOLS+=		bash grep gmake perl:build pkg-config
 BROKEN_ON_PLATFORM+=	NetBSD-[1-8].*-*
 
 HAS_CONFIGURE=		yes
-PYTHON_FOR_BUILD_ONLY=	yes
-CONFIG_SHELL=		${PYTHONBIN}
+PYTHON_FOR_BUILD_ONLY=	tool
+CONFIG_SHELL=		${TOOL_PYTHONBIN}
 CONFIGURE_SCRIPT=	src/bootstrap/configure.py
 CONFIGURE_ARGS+=	--prefix=${PREFIX}
 CONFIGURE_ARGS+=	--mandir=${PREFIX}/${PKGMANDIR}
 CONFIGURE_ARGS+=	--sysconfdir=${PKG_SYSCONFDIR}
-CONFIGURE_ARGS+=	--python=${PYTHONBIN}
+CONFIGURE_ARGS+=	--python=${TOOL_PYTHONBIN}
 CONFIGURE_ARGS+=	--release-channel=stable
 CONFIGURE_ARGS+=	--local-rust-root=${RUST_BOOTSTRAP_PATH}
 CONFIGURE_ARGS+=	--enable-extended	# Build and install cargo too.
@@ -561,12 +561,12 @@ do-build:
 	${SETENV} ${MAKE_ENV}						\
 	sh -c "if [ \"${BUILD_TARGET}\" = \"dist\" ]; then		\
 		unset DESTDIR;						\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    ${BUILD_TARGET} -j ${_MAKE_JOBS_N};			\
 	else								\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    ${BUILD_TARGET} --stage 2 -j ${_MAKE_JOBS_N} &&	\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    doc --stage 2 -j ${_MAKE_JOBS_N};			\
 	fi"
 
@@ -574,13 +574,13 @@ do-test:
 	${RUN}${_ULIMIT_CMD}						\
 	cd ${WRKSRC} &&							\
 	${SETENV} ${MAKE_ENV}						\
-		${PYTHONBIN} ./x.py -v test -j ${_MAKE_JOBS_N}
+		${TOOL_PYTHONBIN} ./x.py -v test -j ${_MAKE_JOBS_N}
 
 do-install:
 	${RUN}${_ULIMIT_CMD}						\
 	cd ${WRKSRC} &&							\
 	${SETENV} ${MAKE_ENV} ${INSTALL_ENV} 				\
-		${PYTHONBIN} ./x.py -v install -j ${_MAKE_JOBS_N}
+		${TOOL_PYTHONBIN} ./x.py -v install -j ${_MAKE_JOBS_N}
 
 SUBST_CLASSES+=		destdir
 SUBST_STAGE.destdir=	post-install
@@ -715,7 +715,7 @@ DEPENDS+=	libatomic-links>=0:../../devel/libatomic-links
 .endif
 
 TOOL_DEPENDS+= cmake-[0-9]*:../../devel/cmake
-.include "../../devel/cmake/buildlink3.mk"
+
 .include "../../devel/zlib/buildlink3.mk"
 .include "../../lang/python/tool.mk"
 .include "../../mk/bsd.pkg.mk"

>From 5d7e4a9ee5ba6e28b7527feb419cac0c1d7553eb Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 11 Jan 2025 11:36:47 +0000
Subject: [PATCH 2/6] lang/rust: Use TOOLBASE, not PREFIX, for tools paths.

In cross-builds, TOOLBASE is where tools that can be executed at
build-time live.  In native builds, it is the same as LOCALBASE,
which is almost always -- as in this case -- the same as PREFIX, so
no change to native builds.
---
 lang/rust/Makefile | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/lang/rust/Makefile b/lang/rust/Makefile
index a9ec0d763a8b..234947eb3b3e 100644
--- a/lang/rust/Makefile
+++ b/lang/rust/Makefile
@@ -398,8 +398,8 @@ RUST_BOOTSTRAP_PATH?=	${WRKDIR}/rust-bootstrap
 TOOL_DEPENDS+=		coreutils>=0:../../sysutils/coreutils
 TOOL_DEPENDS+=		gzip>=0:../../archivers/gzip
 TOOLS_CREATE+=		md5sum
-TOOLS_PATH.md5sum=	${PREFIX}/bin/gmd5sum
-TOOLS_PLATFORM.gzcat=	${PREFIX}/bin/gzip -cd
+TOOLS_PATH.md5sum=	${TOOLBASE}/bin/gmd5sum
+TOOLS_PLATFORM.gzcat=	${TOOLBASE}/bin/gzip -cd
 .endif
 
 SUBST_CLASSES+=		prefix

>From 8486ef5c9249ccd1174bfacd09689cdc521d633b Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 11 Jan 2025 09:01:53 +0000
Subject: [PATCH 3/6] lang/rust/cargo.mk: New variable CARGO_OUTPUT_DIR.

This is where cargo puts its build products.  Packages can use this,
e.g., for do-install recipes that install executables into
${PREFIX}/bin.

This variable is useful because for native builds it is
${WRKSRC}/target/release, but for cross builds (once supported) it
will have to be ${WRKSRC}/target/${RUST_ARCH}/release instead.
---
 lang/rust/cargo.mk | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/lang/rust/cargo.mk b/lang/rust/cargo.mk
index 5a3ed0cf8306..cd8a04192afc 100644
--- a/lang/rust/cargo.mk
+++ b/lang/rust/cargo.mk
@@ -82,6 +82,9 @@ DEFAULT_CARGO_ARGS=	--offline -j${_MAKE_JOBS_N}	\
 CARGO_ARGS?=		build --release ${DEFAULT_CARGO_ARGS}
 CARGO_INSTALL_ARGS?=	install --path . --root ${DESTDIR}${PREFIX} ${DEFAULT_CARGO_ARGS}
 
+CARGO_OUTPUT_SUBDIR=	target/release
+CARGO_OUTPUT_DIR=	${WRKSRC}/${CARGO_OUTPUT_SUBDIR}
+
 MAKE_ENV+=		RUSTFLAGS=${RUSTFLAGS:Q}
 ALL_ENV+=		CARGO_HOME=${WRKDIR}
 

>From e420f07e6a1c9ff33d2340d61a4c55a3969f7744 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Fri, 10 Jan 2025 19:40:41 +0000
Subject: [PATCH 4/6] WIP: cargo.mk: Disable network access.

XXX Need to explain what this does and why, and why some packages
have this already in spite of the `--offline' we pass to cargo.
---
 lang/rust/cargo.mk | 1 +
 1 file changed, 1 insertion(+)

diff --git a/lang/rust/cargo.mk b/lang/rust/cargo.mk
index cd8a04192afc..513e9d83a9b1 100644
--- a/lang/rust/cargo.mk
+++ b/lang/rust/cargo.mk
@@ -87,6 +87,7 @@ CARGO_OUTPUT_DIR=	${WRKSRC}/${CARGO_OUTPUT_SUBDIR}
 
 MAKE_ENV+=		RUSTFLAGS=${RUSTFLAGS:Q}
 ALL_ENV+=		CARGO_HOME=${WRKDIR}
+ALL_ENV+=		${defined(ALLOW_NETWORK_ACCESS):?:CARGO_NET_OFFLINE=true}
 
 .if !target(do-build)
 do-build: do-cargo-build

>From ac09ac9ff19dbae0fae18c3678b5ef4dc1491145 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Wed, 14 Jun 2023 11:29:21 +0000
Subject: [PATCH 5/6] WIP: rust cross-compilation

---
 lang/rust/Makefile                            | 147 +++++++++++++++---
 lang/rust/arch.mk                             |  32 ++++
 lang/rust/cargo.mk                            |  21 ++-
 lang/rust/distinfo                            |   4 +-
 .../patches/patch-src_bootstrap_bootstrap.py  |   3 +-
 .../patch-src_bootstrap_src_core_builder.rs   |   4 +-
 lang/rust/rust.mk                             |  24 +++
 7 files changed, 210 insertions(+), 25 deletions(-)
 create mode 100644 lang/rust/arch.mk

diff --git a/lang/rust/Makefile b/lang/rust/Makefile
index 234947eb3b3e..ab63860f0538 100644
--- a/lang/rust/Makefile
+++ b/lang/rust/Makefile
@@ -1,7 +1,7 @@
 # $NetBSD: Makefile,v 1.321 2024/11/24 16:13:42 he Exp $
 
 DISTNAME=	rustc-1.81.0-src
-PKGNAME=	${DISTNAME:S/rustc/rust/:S/-src//}
+PKGNAME=	${DISTNAME:S/rustc/rust${empty(TARGET_MACHINE_PLATFORM):?:-${TARGET_MACHINE_PLATFORM}}/:S/-src//}
 CATEGORIES=	lang
 MASTER_SITES=	https://static.rust-lang.org/dist/
 
@@ -31,13 +31,19 @@ USE_TOOLS+=		bash grep gmake perl:build pkg-config
 # or 9 (as in riscv64).  Therefore, mark earlier versions as broken.
 BROKEN_ON_PLATFORM+=	NetBSD-[1-8].*-*
 
+# XXX should use ${TARGET_MACHINE_PLATFORM} so this has the OS version
+# embedded too; otherwise, e.g., 9.0 and 10.0 packages will collide --
+# alternatively, package should be named with ${TARGET_RUST_ARCH}
+# instead of ${TARGET_MACHINE_PLATFORM}
+RUST_PREFIX=		${PREFIX}${empty(TARGET_RUST_ARCH):?:/rust-${TARGET_RUST_ARCH}}
+
 HAS_CONFIGURE=		yes
 PYTHON_FOR_BUILD_ONLY=	tool
 CONFIG_SHELL=		${TOOL_PYTHONBIN}
 CONFIGURE_SCRIPT=	src/bootstrap/configure.py
-CONFIGURE_ARGS+=	--prefix=${PREFIX}
-CONFIGURE_ARGS+=	--mandir=${PREFIX}/${PKGMANDIR}
-CONFIGURE_ARGS+=	--sysconfdir=${PKG_SYSCONFDIR}
+CONFIGURE_ARGS+=	--prefix=${RUST_PREFIX}
+CONFIGURE_ARGS+=	--mandir=${RUST_PREFIX}/${PKGMANDIR}
+CONFIGURE_ARGS+=	--sysconfdir=${PKG_SYSCONFDIR} # XXX RUST_PREFIX?
 CONFIGURE_ARGS+=	--python=${TOOL_PYTHONBIN}
 CONFIGURE_ARGS+=	--release-channel=stable
 CONFIGURE_ARGS+=	--local-rust-root=${RUST_BOOTSTRAP_PATH}
@@ -51,6 +57,19 @@ CONFIGURE_ARGS+=	--dist-compression-formats=xz
 # Ref. issue #130708 & backport of pull-request 130110
 CONFIGURE_ARGS+=	--set dist.vendor=false
 
+# Include both the target and the native architectures.  This is
+# necessary, e.g., to natively compile build.rs scripts while
+# cross-building.
+CONFIGURE_ARGS+=	\
+	${empty(TARGET_RUST_ARCH):?:--target=${TARGET_RUST_ARCH:Q},${RUST_ARCH:Q}}
+CONFIGURE_ARGS+=	\
+	${"${USE_CROSS_COMPILE:tl}" == "yes":?--host=${RUST_ARCH:Q}:}
+
+LDFLAGS+=			\
+	${empty(TARGET_RUST_ARCH):?:${COMPILER_RPATH_FLAG}${RUST_PREFIX}/lib}
+BUILDLINK_PASSTHRU_RPATHDIRS+=	\
+	${empty(TARGET_RUST_ARCH):?:${RUST_PREFIX}/lib}
+
 # Include (optional) settings to cross-build rust
 .include "cross.mk"
 
@@ -103,7 +122,7 @@ MAKE_JOBS_SAFE=		yes
 BUILD_TARGET=	${rust.BUILD_TARGET}
 .endif
 
-.if !empty(TARGET)
+.if !empty(TARGET) || !empty(TARGET_MACHINE_PLATFORM)
 # Use "dist" build target for cross compile of bootstrap
 BUILD_TARGET?=		dist
 .else
@@ -145,9 +164,12 @@ CONFIGURE_ARGS+=	--set llvm.targets="Mips"
 CONFIGURE_ARGS+=	--set llvm.targets="Mips;X86"
 .endif
 
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/backtrace/ci/*.sh
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/core/src/unicode/printable.py
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/stdarch/ci/*.sh
+# XXX make me a PLIST substitution
+RUST_PREFIX_SUBDIR=	${empty(TARGET_RUST_ARCH):?:rust-${TARGET_RUST_ARCH}/}
+
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/backtrace/ci/*.sh
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/core/src/unicode/printable.py
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/stdarch/ci/*.sh
 CHECK_PORTABILITY_SKIP+=	tests/run-make/dump-ice-to-disk/check.sh
 CHECK_PORTABILITY_SKIP+=	vendor/libdbus-sys-0.2.5/vendor/dbus/tools/cmake-format
 
@@ -201,12 +223,88 @@ BUILDLINK_TRANSFORM.NetBSD+=	rm:-Wl,--enable-new-dtags
 BUILDLINK_TRANSFORM+=	opt:x86_64:arm64
 .endif
 
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+RUST_MACHINE_ARCH.i386=		i586		# not really
+RUST_MACHINE_ARCH.aarch64eb=	aarch64_be
+RUST_MACHINE_ARCH.riscv64=	riscv64gc
+
+RUST_LOWER_OPSYS.solaris=	illumos
+
+#
+# Transform TARGET_* into TARGET_RUST_ARCH and pass the rest of the
+# cross-toolchain through.
+#
+.if !empty(TARGET_MACHINE_PLATFORM)
+
+# Avoid conflicts when you want native-rust-native-compiler vs
+# native-rust-cross-compiler (vs native-rust-cross-compiler targeting
+# another architecture).
+#
+# XXX Find a better way to do this -- shouldn't stomp on user's
+# WRKDIR_BASENAME or ignore OBJHOSTNAME.
+WRKDIR_BASENAME=	work-${TARGET_MACHINE_PLATFORM}${_CROSSDIR_SUFFIX}
+
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+TARGET_RUST_ARCH=	${empty(TARGET_MACHINE_PLATFORM):?:${RUST_MACHINE_ARCH.${TARGET_MACHINE_ARCH}:U${TARGET_MACHINE_ARCH}}-${empty(TARGET_LOWER_VENDOR):?unknown:${TARGET_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${TARGET_LOWER_OPSYS}:U${TARGET_LOWER_OPSYS}}${TARGET_APPEND_ABI}}
+
+MAKE_ENV+=		GNU_CROSS_TARGET=${TARGET_MACHINE_GNU_PLATFORM:Q}
+
+# XXX Maybe this should use TOOLS_USE_CROSS_COMPILE like cross-libtool
+# instead of hard-coding the NetBSD layout of tooldir.
+CROSS_ROOT=	${WRKDIR}/root
+MAKE_ENV+=	CROSS_ROOT=${CROSS_ROOT:Q}
+pre-configure: pre-configure-setup-root
+pre-configure-setup-root: .PHONY
+	${RUN}${MKDIR} ${CROSS_ROOT:Q}
+	${RUN}${LN} -sf ${CROSS_DESTDIR:Q} ${CROSS_ROOT:Q}/dest
+	${RUN}${LN} -sf ${TOOLDIR:Q} ${CROSS_ROOT:Q}/tools
+
+# Note that these tools -- target-cc, target-cxx -- do not go through
+# the wrappers framework, because we're building the cross-compiler
+# right now rather than using it -- the wrappers apply to the native
+# cc/cxx/linker.  So we have to set sysroot ourselves.  But fortunately
+# the C cross-compiler is only used for a small part of this, to
+# cross-compile compiler-rt, so the risk of bypassing pkgsrc wrappers
+# is minimal -- in fact, since this cross-compiler doesn't even know
+# about pkgsrc's cross-localbase, it is even less likely to
+# accidentally pick anything up it shouldn't anyway.
+TOOLS_CREATE+=		target-cc
+TOOLS_PATH.target-cc=	${TOOLDIR}/bin/${TARGET_MACHINE_GNU_PLATFORM}-gcc # XXX shouldn't hard-code gcc
+TOOLS_ARGS.target-cc=	--sysroot=${CROSS_DESTDIR:Q}
+TOOLS_CREATE+=		target-cxx
+TOOLS_PATH.target-cxx=	${TOOLDIR}/bin/${TARGET_MACHINE_GNU_PLATFORM}-c++
+TOOLS_ARGS.target-cxx=	--sysroot=${CROSS_DESTDIR:Q}
+
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.cc=${TOOLS_CMD.target-cc:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.cxx=${TOOLS_CMD.target-cxx:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.linker=${TOOLS_CMD.target-cc:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.ar=${TOOLDIR:Q}/bin/${TARGET_MACHINE_GNU_PLATFORM:Q}-ar
+
+.endif				# !empty(TARGET_MACHINE_PLATFORM)
+
 #
 # Rust unfortunately requires itself to build.  On platforms which aren't
 # supported by upstream (where they offer binary bootstraps), or where we do
 # not trust random binaries from the Internet, we need to build and provide our
 # own bootstrap.  See the stage0-bootstrap below for more details.
 #
+.if ${USE_CROSS_COMPILE:tl} == "yes"	# {
+
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+RUST_ARCH=		${RUST_MACHINE_ARCH.${MACHINE_ARCH}:U${MACHINE_ARCH}}-${empty(LOWER_VENDOR):?unknown:${LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${LOWER_OPSYS}:U${LOWER_OPSYS}}${APPEND_ABI}
+NATIVE_RUST_ARCH=	${RUST_MACHINE_ARCH.${NATIVE_MACHINE_ARCH}:U${NATIVE_MACHINE_ARCH}}-${empty(NATIVE_LOWER_VENDOR):?unknown:${NATIVE_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${NATIVE_LOWER_OPSYS}:U${NATIVE_LOWER_OPSYS}}${NATIVE_APPEND_ABI}
+
+TOOL_DEPENDS+=		rust-${MACHINE_PLATFORM}:../../${PKGPATH}
+RUST_BOOTSTRAP_PATH=	${TOOLBASE}/rust-${RUST_ARCH}
+
+# XXX Maybe omit this if rust-internal-llvm option is enabled?
+CONFIGURE_ARGS+=	--set=target.${NATIVE_RUST_ARCH:Q}.llvm-config=${TOOLBASE:Q}/bin/llvm-config
+
+.else					# } {
+
 DISTFILES:=		${DEFAULT_DISTFILES}
 
 .if ${MACHINE_PLATFORM:MDarwin-*-aarch64} || make(distinfo) || make (makesum) || make(mdi)
@@ -386,10 +484,12 @@ SITES.${RUST_STAGE0}=		${MASTER_SITE_LOCAL:=rust/}
 SITES.${RUST_STD_STAGE0}=	${MASTER_SITE_LOCAL:=rust/}
 .endif
 
+.endif					# }
+
 # You may override RUST_BOOTSTRAP_PATH and RUST_ARCH in mk.conf
 # if you have a local bootstrap compiler.
 .if !defined(RUST_ARCH) && !defined(RUST_BOOTSTRAP_PATH)
-NOT_FOR_PLATFORM+=	${MACHINE_PLATFORM}
+NOT_FOR_PLATFORM+=	${MACHINE_PLATFORM} # XXX NATIVE_MACHINE_PLATFORM
 .else
 RUST_BOOTSTRAP_PATH?=	${WRKDIR}/rust-bootstrap
 .endif
@@ -409,7 +509,7 @@ SUBST_FILES.prefix+=	compiler/rustc_target/src/spec/base/netbsd.rs
 SUBST_FILES.prefix+=	src/bootstrap/src/core/build_steps/compile.rs
 SUBST_FILES.prefix+=	src/bootstrap/src/core/builder.rs
 SUBST_FILES.prefix+=	src/bootstrap/bootstrap.py
-SUBST_VARS.prefix=	PREFIX
+SUBST_VARS.prefix=	PREFIX RUST_PREFIX
 
 #
 # Generate list of subst entries for various .cargo-checksum.json files.  These
@@ -581,11 +681,20 @@ do-install:
 	cd ${WRKSRC} &&							\
 	${SETENV} ${MAKE_ENV} ${INSTALL_ENV} 				\
 		${TOOL_PYTHONBIN} ./x.py -v install -j ${_MAKE_JOBS_N}
+.if !empty(TARGET_MACHINE_PLATFORM)
+	${RUN}								\
+	${GTAR} -C ${WRKDIR:Q}						\
+		-xzf ${WRKSRC:Q}/build/dist/rust-std-${PKGVERSION_NOREV:Q}-${TARGET_RUST_ARCH:Q}.tar.xz
+	${RUN}								\
+	cd ${WRKDIR:Q}/rust-std-${PKGVERSION_NOREV:Q}-${TARGET_RUST_ARCH:Q} && \
+	${SETENV} ${MAKE_ENV} ${INSTALL_ENV}				\
+		./install.sh --prefix=${RUST_PREFIX:Q} --destdir=${DESTDIR:Q}
+.endif
 
 SUBST_CLASSES+=		destdir
 SUBST_STAGE.destdir=	post-install
-SUBST_FILES.destdir=	${DESTDIR}${PREFIX}/lib/rustlib/manifest-*
-SUBST_SED.destdir=	-e 's|file:${DESTDIR}${PREFIX}|file:${PREFIX}|'
+SUBST_FILES.destdir=	${DESTDIR}${RUST_PREFIX}/lib/rustlib/manifest-*
+SUBST_SED.destdir=	-e 's|file:${DESTDIR}${RUST_PREFIX}|file:${RUST_PREFIX}|'
 
 GENERATE_PLIST+=	${FIND} ${DESTDIR}${PREFIX} \( -type f -o -type l \) -print | \
 			${SED} -e 's,${DESTDIR}${PREFIX}/,,' | ${SORT} ;
@@ -640,8 +749,8 @@ stage0-bootstrap: install
 	)
 .endif
 .if ${OS_VARIANT} == "SmartOS"
-	${CP} -R ${DESTDIR}/${PREFIX}/bin ${BOOTSTRAP_TMPDIR}/
-	${CP} -R ${DESTDIR}/${PREFIX}/lib ${BOOTSTRAP_TMPDIR}/
+	${CP} -R ${DESTDIR}/${RUST_PREFIX}/bin ${BOOTSTRAP_TMPDIR}/
+	${CP} -R ${DESTDIR}/${RUST_PREFIX}/lib ${BOOTSTRAP_TMPDIR}/
 	${MKDIR} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc
 	set -e; \
 	for lib in libgcc_s.so.1 libstdc++.so.6; do \
@@ -650,12 +759,12 @@ stage0-bootstrap: install
 	done; \
 	for lib in libLLVM.so.18.1 libcrypto.so.3 libcurl.so.4 \
 		   libssl.so.3 libz.so.1 libzstd.so.1; do \
-		${CP} ${PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
+		${CP} ${RUST_PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
 	done; \
 	for lib in libiconv.so.2 libidn2.so.0 libintl.so.8 liblber.so.2 \
 		   libldap.so.2 libnghttp2.so.14 libsasl2.so.3 \
 		   libssh2.so.1 libunistring.so.5; do \
-		${CP} ${PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
+		${CP} ${RUST_PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
 	done; \
 	for f in ${BOOTSTRAP_TMPDIR}/bin/*; do \
 		/bin/file -b "$$f" | grep ^ELF >/dev/null || continue; \
@@ -675,7 +784,7 @@ stage0-bootstrap: install
 	@${ECHO} "Verify correct library paths using the following:"
 	@${ECHO} ""
 	@${ECHO} "	cd ${BOOTSTRAP_TMPDIR}"
-	@${ECHO} "	find . -type f | xargs ldd 2>/dev/null | egrep 'not.found|${PREFIX}'"
+	@${ECHO} "	find . -type f | xargs ldd 2>/dev/null | egrep 'not.found|${RUST_PREFIX}'"
 	@${ECHO} ""
 	@${ECHO} "If there is no output then this bootstrap kit is ready to go:"
 	@${ECHO} ""
@@ -698,8 +807,8 @@ stage0-bootstrap: install
 # rust i386 and sparc64 bootstraps are built for 8.0
 # and still depend on libstdc++.so.8.
 # Pull in compat80 on 9.x and newer.
-.if (${MACHINE_PLATFORM:MNetBSD-*-i386} || \
-     ${MACHINE_PLATFORM:MNetBSD-*-sparc64}) \
+.if (${NATIVE_MACHINE_PLATFORM:MNetBSD-*-i386} || \
+     ${NATIVE_MACHINE_PLATFORM:MNetBSD-*-sparc64}) \
     && empty(OS_VERSION:M8.*)
 TOOL_DEPENDS+=	compat80>=0:../../emulators/compat80
 .endif
diff --git a/lang/rust/arch.mk b/lang/rust/arch.mk
new file mode 100644
index 000000000000..ad0dfa72f149
--- /dev/null
+++ b/lang/rust/arch.mk
@@ -0,0 +1,32 @@
+#	$NetBSD$
+#
+# Common logic to map pkgsrc idea of machine platforms into Rust idea
+# of architectures.
+#
+# System-provided variables:
+#
+# RUST_ARCH
+#	The Rust architecture triple that this package is built for.
+#
+# NATIVE_RUST_ARCH
+#	The Rust architecture triple that we are doing the build on.
+#
+# TARGET_RUST_ARCH
+#	If nonempty, the Rust architecture triple that this package may
+#	be intended to support as a cross-compiler target.
+#
+#	Nonempty if and only if TARGET_MACHINE_PLATFORM is nonempty,
+#	i.e., this package is being built as a TOOL_DEPENDS dependency
+#	of another package and thus may be being built as a
+#	cross-compiler.
+
+RUST_MACHINE_ARCH.i386=		i586		# not really
+RUST_MACHINE_ARCH.aarch64eb=	aarch64_be
+RUST_MACHINE_ARCH.riscv64=	riscv64gc
+
+RUST_LOWER_OPSYS.solaris=	illumos
+
+RUST_ARCH=		${RUST_MACHINE_ARCH.${MACHINE_ARCH}:U${MACHINE_ARCH}}-${empty(LOWER_VENDOR):?unknown:${LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${LOWER_OPSYS}:U${LOWER_OPSYS}}${APPEND_ABI}
+NATIVE_RUST_ARCH=	${RUST_MACHINE_ARCH.${NATIVE_MACHINE_ARCH}:U${NATIVE_MACHINE_ARCH}}-${empty(NATIVE_LOWER_VENDOR):?unknown:${NATIVE_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${NATIVE_LOWER_OPSYS}:U${NATIVE_LOWER_OPSYS}}${NATIVE_APPEND_ABI}
+
+TARGET_RUST_ARCH=	${empty(TARGET_MACHINE_PLATFORM):?:${RUST_MACHINE_ARCH.${TARGET_MACHINE_ARCH}:U${TARGET_MACHINE_ARCH}}-${empty(TARGET_LOWER_VENDOR):?unknown:${TARGET_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${TARGET_LOWER_OPSYS}:U${TARGET_LOWER_OPSYS}}${TARGET_APPEND_ABI}}
diff --git a/lang/rust/cargo.mk b/lang/rust/cargo.mk
index 513e9d83a9b1..23194c7a3187 100644
--- a/lang/rust/cargo.mk
+++ b/lang/rust/cargo.mk
@@ -72,13 +72,32 @@ print-cargo-depends:
 
 .if ${RUST_TYPE} == "native"
 CARGO=			cargo
+.elif ${USE_CROSS_COMPILE:tl} == "yes"
+# XXX Nix this conditional once we verify no fallout for native builds:
+# using TOOLS_CREATE to create a cargo tool, and writing
+# ${TOOLBASE}/bin/cargo instead of ${PREFIX}/bin/cargo, and similarly
+# for rustc, should all work just fine for native builds.
+.  include "arch.mk"
+TOOLS_CREATE+=		cargo
+TOOLS_PATH.cargo=	${TOOLBASE}${"${USE_CROSS_COMPILE:tl}" == "yes":?/rust-${RUST_ARCH}:}/bin/cargo
+TOOLS_CREATE+=		rustc
+TOOLS_PATH.rustc=	${TOOLBASE}${"${USE_CROSS_COMPILE:tl}" == "yes":?/rust-${RUST_ARCH}:}/bin/rustc
 .else
 CARGO=			${PREFIX}/bin/cargo
 .endif
+
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+ALL_ENV+=		CARGO_TARGET_${NATIVE_RUST_ARCH:S/-/_/g:tu}_LINKER=native-cc
+TOOLS_CREATE+=		native-cc
+TOOLS_PATH.native-cc=	${NATIVE_CC:[1]}
+TOOLS_ARGS.native-cc=	${NATIVE_CC:[2..-1]}
+.endif				# ${USE_CROSS_COMPILE:tl} == "yes"
+
 DEFAULT_CARGO_ARGS=	--offline -j${_MAKE_JOBS_N}	\
 			  ${CARGO_NO_DEFAULT_FEATURES:M[yY][eE][sS]:C/[yY][eE][sS]/--no-default-features/}	\
 			  ${CARGO_FEATURES:C/.*/--features/W}	\
-			  ${CARGO_FEATURES:S/ /,/Wg}
+			  ${CARGO_FEATURES:S/ /,/Wg} \
+			  ${"${USE_CROSS_COMPILE:tl}" == "yes":?--target ${RUST_ARCH}:}
 CARGO_ARGS?=		build --release ${DEFAULT_CARGO_ARGS}
 CARGO_INSTALL_ARGS?=	install --path . --root ${DESTDIR}${PREFIX} ${DEFAULT_CARGO_ARGS}
 
diff --git a/lang/rust/distinfo b/lang/rust/distinfo
index 991b8ab88c85..b79a69394c08 100644
--- a/lang/rust/distinfo
+++ b/lang/rust/distinfo
@@ -121,11 +121,11 @@ SHA1 (patch-config.example.toml) = 520ad7a26249780ae79a5dc1d2b534a8c6aef0a5
 SHA1 (patch-library_backtrace_src_symbolize_gimli.rs) = 9d5ef634c5a454e474ea5fee76da9bb768f5b3d9
 SHA1 (patch-library_backtrace_src_symbolize_gimli_elf.rs) = 3b84a462c6bc8245d579452e4c37e3ce13314952
 SHA1 (patch-library_std_src_sys_pal_unix_mod.rs) = bfc59ae4568547e3ed71c8b31ba5b5b5363d5d40
-SHA1 (patch-src_bootstrap_bootstrap.py) = 6f1d3068da49f19c3e092230ba1c7d99af628d3a
+SHA1 (patch-src_bootstrap_bootstrap.py) = 6ce15a434d163f921cc77c15c4b0c759a4de39f5
 SHA1 (patch-src_bootstrap_src_core_build__steps_compile.rs) = e928203ed4734c93cc33c5a3f7879cf18dcecc83
 SHA1 (patch-src_bootstrap_src_core_build__steps_dist.rs) = eb228d43e1cf21ec646b516b8c67c648c7183f8a
 SHA1 (patch-src_bootstrap_src_core_build__steps_install.rs) = cc6558df42c9c9ac28fdb2ff180bdaa7f22ce816
-SHA1 (patch-src_bootstrap_src_core_builder.rs) = e3fd19e0a18f1e79e287c85035ea431b98d91d9a
+SHA1 (patch-src_bootstrap_src_core_builder.rs) = b077845e04d83a500eeac3cae4d4b0baa5b3bafe
 SHA1 (patch-src_bootstrap_src_core_config_config.rs) = fa9d93602693bce064aa155ad0a204b176b47d99
 SHA1 (patch-src_bootstrap_src_lib.rs) = d29bc3c0b335d5e788eecbb02fc08966beef0fb1
 SHA1 (patch-src_llvm-project_llvm_CMakeLists.txt) = 7abfabb6ec70df229a69355f8c76825610165c37
diff --git a/lang/rust/patches/patch-src_bootstrap_bootstrap.py b/lang/rust/patches/patch-src_bootstrap_bootstrap.py
index 3166c52a7f37..f29c058d0056 100644
--- a/lang/rust/patches/patch-src_bootstrap_bootstrap.py
+++ b/lang/rust/patches/patch-src_bootstrap_bootstrap.py
@@ -36,10 +36,11 @@ Also use @PREFIX@ and not $ORIGIN in rpath.
          else:
              kernel += 'eabihf'
      elif cputype == 'mips':
-@@ -734,6 +745,7 @@ class RustBuild(object):
+@@ -734,6 +745,8 @@ class RustBuild(object):
  
          patchelf = "{}/bin/patchelf".format(nix_deps_dir)
          rpath_entries = [
++            "@RUST_PREFIX@/lib",
 +	    "@PREFIX@/lib",
              os.path.join(os.path.realpath(nix_deps_dir), "lib")
          ]
diff --git a/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs b/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
index 7db4e8beb1ac..e2c076d2850c 100644
--- a/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
+++ b/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
@@ -1,7 +1,7 @@
 $NetBSD: patch-src_bootstrap_src_core_builder.rs,v 1.5 2024/07/27 02:35:24 tnn Exp $
 
 Find external libunwind on Linux.
-Use @PREFIX@, not $ORIGIN in rpath.
+Use @RUST_PREFIX@ and @PREFIX@, not $ORIGIN in rpath.
 
 --- src/bootstrap/src/core/builder.rs.orig	2006-07-24 01:21:28.000000000 +0000
 +++ src/bootstrap/src/core/builder.rs
@@ -22,7 +22,7 @@ Use @PREFIX@, not $ORIGIN in rpath.
              } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") {
                  self.rustflags.arg("-Clink-args=-Wl,-z,origin");
 -                Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}"))
-+                Some(format!("-Wl,-rpath,@PREFIX@/{libdir}"))
++                Some(format!("-Wl,-rpath,@RUST_PREFIX@/{libdir},-rpath,@PREFIX@/lib"))
              } else {
                  None
              };
diff --git a/lang/rust/rust.mk b/lang/rust/rust.mk
index 82185914b67b..9b3be3ec6e35 100644
--- a/lang/rust/rust.mk
+++ b/lang/rust/rust.mk
@@ -40,17 +40,41 @@ RUST_RUNTIME?=	no
 RUST_TYPE?=	src
 
 .if ${RUST_TYPE} == "bin"
+# XXX Remove this ${USE_CROSS_COMPILE} conditional once we confirm no
+# fallout in native builds from the TOOL_DEPENDS approach.
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+.  include "arch.mk"
+TOOL_DEPENDS+=			rust${"${USE_CROSS_COMPILE:U:tl}" == "yes":?-${MACHINE_PLATFORM}:}-bin>=${RUST_REQ}:../../lang/rust-bin
+BUILDLINK_PASSTHRU_DIRS+=	${"${USE_CROSS_COMPILE:tl}" == "yes":?${TOOLBASE}/rust-${RUST_ARCH}:${PREFIX}}/lib/rustlib
+.  if ${RUST_RUNTIME} != "no"
+BUILDLINK_API_DEPENDS.rust-bin+=	rust-bin>=${RUST_REQ}
+.    include "${RUST_DIR}-bin/buildlink3.mk"
+.  endif
+.else
 .  if ${RUST_RUNTIME} == "no"
 BUILDLINK_DEPMETHOD.rust-bin?=		build
 .  endif
 BUILDLINK_API_DEPENDS.rust-bin+=	rust-bin>=${RUST_REQ}
 .  include "${RUST_DIR}-bin/buildlink3.mk"
 .endif
+.endif
 
 .if ${RUST_TYPE} == "src"
+# XXX Remove this ${USE_CROSS_COMPILE} conditional once we confirm no
+# fallout in native builds from the TOOL_DEPENDS approach.
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+.  include "arch.mk"
+TOOL_DEPENDS+=			rust${"${USE_CROSS_COMPILE:U:tl}" == "yes":?-${MACHINE_PLATFORM}:}>=${RUST_REQ}:../../lang/rust
+BUILDLINK_PASSTHRU_DIRS+=	${"${USE_CROSS_COMPILE:tl}" == "yes":?${TOOLBASE}/rust-${RUST_ARCH}:${PREFIX}}/lib/rustlib
+.  if ${RUST_RUNTIME} != "no"
+BUILDLINK_API_DEPENDS.rust+=		rust>=${RUST_REQ}
+.    include "${RUST_DIR}/buildlink3.mk"
+.  endif
+.else
 .  if ${RUST_RUNTIME} == "no"
 BUILDLINK_DEPMETHOD.rust?=		build
 .  endif
 BUILDLINK_API_DEPENDS.rust+=		rust>=${RUST_REQ}
 .  include "${RUST_DIR}/buildlink3.mk"
 .endif
+.endif

>From 1b754fd19e12bf9a1cec1e3dc96258f09a5381e6 Mon Sep 17 00:00:00 2001
From: Taylor R Campbell <riastradh%NetBSD.org@localhost>
Date: Sat, 11 Jan 2025 11:21:37 +0000
Subject: [PATCH 6/6] lang/rust/cargo.mk: Make CARGO_OUTPUT_DIR work in
 cross-builds.

---
 lang/rust/cargo.mk | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lang/rust/cargo.mk b/lang/rust/cargo.mk
index 23194c7a3187..d0493a4f0162 100644
--- a/lang/rust/cargo.mk
+++ b/lang/rust/cargo.mk
@@ -101,7 +101,7 @@ DEFAULT_CARGO_ARGS=	--offline -j${_MAKE_JOBS_N}	\
 CARGO_ARGS?=		build --release ${DEFAULT_CARGO_ARGS}
 CARGO_INSTALL_ARGS?=	install --path . --root ${DESTDIR}${PREFIX} ${DEFAULT_CARGO_ARGS}
 
-CARGO_OUTPUT_SUBDIR=	target/release
+CARGO_OUTPUT_SUBDIR=	${"${USE_CROSS_COMPILE:tl}" == "yes":?target/${RUST_ARCH}/release:target/release}
 CARGO_OUTPUT_DIR=	${WRKSRC}/${CARGO_OUTPUT_SUBDIR}
 
 MAKE_ENV+=		RUSTFLAGS=${RUSTFLAGS:Q}
diff --git a/lang/rust/Makefile b/lang/rust/Makefile
index 001da1136e21..ab63860f0538 100644
--- a/lang/rust/Makefile
+++ b/lang/rust/Makefile
@@ -1,7 +1,7 @@
 # $NetBSD: Makefile,v 1.321 2024/11/24 16:13:42 he Exp $
 
 DISTNAME=	rustc-1.81.0-src
-PKGNAME=	${DISTNAME:S/rustc/rust/:S/-src//}
+PKGNAME=	${DISTNAME:S/rustc/rust${empty(TARGET_MACHINE_PLATFORM):?:-${TARGET_MACHINE_PLATFORM}}/:S/-src//}
 CATEGORIES=	lang
 MASTER_SITES=	https://static.rust-lang.org/dist/
 
@@ -31,14 +31,20 @@ USE_TOOLS+=		bash grep gmake perl:build pkg-config
 # or 9 (as in riscv64).  Therefore, mark earlier versions as broken.
 BROKEN_ON_PLATFORM+=	NetBSD-[1-8].*-*
 
+# XXX should use ${TARGET_MACHINE_PLATFORM} so this has the OS version
+# embedded too; otherwise, e.g., 9.0 and 10.0 packages will collide --
+# alternatively, package should be named with ${TARGET_RUST_ARCH}
+# instead of ${TARGET_MACHINE_PLATFORM}
+RUST_PREFIX=		${PREFIX}${empty(TARGET_RUST_ARCH):?:/rust-${TARGET_RUST_ARCH}}
+
 HAS_CONFIGURE=		yes
-PYTHON_FOR_BUILD_ONLY=	yes
-CONFIG_SHELL=		${PYTHONBIN}
+PYTHON_FOR_BUILD_ONLY=	tool
+CONFIG_SHELL=		${TOOL_PYTHONBIN}
 CONFIGURE_SCRIPT=	src/bootstrap/configure.py
-CONFIGURE_ARGS+=	--prefix=${PREFIX}
-CONFIGURE_ARGS+=	--mandir=${PREFIX}/${PKGMANDIR}
-CONFIGURE_ARGS+=	--sysconfdir=${PKG_SYSCONFDIR}
-CONFIGURE_ARGS+=	--python=${PYTHONBIN}
+CONFIGURE_ARGS+=	--prefix=${RUST_PREFIX}
+CONFIGURE_ARGS+=	--mandir=${RUST_PREFIX}/${PKGMANDIR}
+CONFIGURE_ARGS+=	--sysconfdir=${PKG_SYSCONFDIR} # XXX RUST_PREFIX?
+CONFIGURE_ARGS+=	--python=${TOOL_PYTHONBIN}
 CONFIGURE_ARGS+=	--release-channel=stable
 CONFIGURE_ARGS+=	--local-rust-root=${RUST_BOOTSTRAP_PATH}
 CONFIGURE_ARGS+=	--enable-extended	# Build and install cargo too.
@@ -51,6 +57,19 @@ CONFIGURE_ARGS+=	--dist-compression-formats=xz
 # Ref. issue #130708 & backport of pull-request 130110
 CONFIGURE_ARGS+=	--set dist.vendor=false
 
+# Include both the target and the native architectures.  This is
+# necessary, e.g., to natively compile build.rs scripts while
+# cross-building.
+CONFIGURE_ARGS+=	\
+	${empty(TARGET_RUST_ARCH):?:--target=${TARGET_RUST_ARCH:Q},${RUST_ARCH:Q}}
+CONFIGURE_ARGS+=	\
+	${"${USE_CROSS_COMPILE:tl}" == "yes":?--host=${RUST_ARCH:Q}:}
+
+LDFLAGS+=			\
+	${empty(TARGET_RUST_ARCH):?:${COMPILER_RPATH_FLAG}${RUST_PREFIX}/lib}
+BUILDLINK_PASSTHRU_RPATHDIRS+=	\
+	${empty(TARGET_RUST_ARCH):?:${RUST_PREFIX}/lib}
+
 # Include (optional) settings to cross-build rust
 .include "cross.mk"
 
@@ -103,7 +122,7 @@ MAKE_JOBS_SAFE=		yes
 BUILD_TARGET=	${rust.BUILD_TARGET}
 .endif
 
-.if !empty(TARGET)
+.if !empty(TARGET) || !empty(TARGET_MACHINE_PLATFORM)
 # Use "dist" build target for cross compile of bootstrap
 BUILD_TARGET?=		dist
 .else
@@ -145,9 +164,12 @@ CONFIGURE_ARGS+=	--set llvm.targets="Mips"
 CONFIGURE_ARGS+=	--set llvm.targets="Mips;X86"
 .endif
 
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/backtrace/ci/*.sh
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/core/src/unicode/printable.py
-CHECK_INTERPRETER_SKIP+=	lib/rustlib/src/rust/library/stdarch/ci/*.sh
+# XXX make me a PLIST substitution
+RUST_PREFIX_SUBDIR=	${empty(TARGET_RUST_ARCH):?:rust-${TARGET_RUST_ARCH}/}
+
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/backtrace/ci/*.sh
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/core/src/unicode/printable.py
+CHECK_INTERPRETER_SKIP+=	${RUST_PREFIX_SUBDIR}lib/rustlib/src/rust/library/stdarch/ci/*.sh
 CHECK_PORTABILITY_SKIP+=	tests/run-make/dump-ice-to-disk/check.sh
 CHECK_PORTABILITY_SKIP+=	vendor/libdbus-sys-0.2.5/vendor/dbus/tools/cmake-format
 
@@ -201,12 +223,88 @@ BUILDLINK_TRANSFORM.NetBSD+=	rm:-Wl,--enable-new-dtags
 BUILDLINK_TRANSFORM+=	opt:x86_64:arm64
 .endif
 
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+RUST_MACHINE_ARCH.i386=		i586		# not really
+RUST_MACHINE_ARCH.aarch64eb=	aarch64_be
+RUST_MACHINE_ARCH.riscv64=	riscv64gc
+
+RUST_LOWER_OPSYS.solaris=	illumos
+
+#
+# Transform TARGET_* into TARGET_RUST_ARCH and pass the rest of the
+# cross-toolchain through.
+#
+.if !empty(TARGET_MACHINE_PLATFORM)
+
+# Avoid conflicts when you want native-rust-native-compiler vs
+# native-rust-cross-compiler (vs native-rust-cross-compiler targeting
+# another architecture).
+#
+# XXX Find a better way to do this -- shouldn't stomp on user's
+# WRKDIR_BASENAME or ignore OBJHOSTNAME.
+WRKDIR_BASENAME=	work-${TARGET_MACHINE_PLATFORM}${_CROSSDIR_SUFFIX}
+
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+TARGET_RUST_ARCH=	${empty(TARGET_MACHINE_PLATFORM):?:${RUST_MACHINE_ARCH.${TARGET_MACHINE_ARCH}:U${TARGET_MACHINE_ARCH}}-${empty(TARGET_LOWER_VENDOR):?unknown:${TARGET_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${TARGET_LOWER_OPSYS}:U${TARGET_LOWER_OPSYS}}${TARGET_APPEND_ABI}}
+
+MAKE_ENV+=		GNU_CROSS_TARGET=${TARGET_MACHINE_GNU_PLATFORM:Q}
+
+# XXX Maybe this should use TOOLS_USE_CROSS_COMPILE like cross-libtool
+# instead of hard-coding the NetBSD layout of tooldir.
+CROSS_ROOT=	${WRKDIR}/root
+MAKE_ENV+=	CROSS_ROOT=${CROSS_ROOT:Q}
+pre-configure: pre-configure-setup-root
+pre-configure-setup-root: .PHONY
+	${RUN}${MKDIR} ${CROSS_ROOT:Q}
+	${RUN}${LN} -sf ${CROSS_DESTDIR:Q} ${CROSS_ROOT:Q}/dest
+	${RUN}${LN} -sf ${TOOLDIR:Q} ${CROSS_ROOT:Q}/tools
+
+# Note that these tools -- target-cc, target-cxx -- do not go through
+# the wrappers framework, because we're building the cross-compiler
+# right now rather than using it -- the wrappers apply to the native
+# cc/cxx/linker.  So we have to set sysroot ourselves.  But fortunately
+# the C cross-compiler is only used for a small part of this, to
+# cross-compile compiler-rt, so the risk of bypassing pkgsrc wrappers
+# is minimal -- in fact, since this cross-compiler doesn't even know
+# about pkgsrc's cross-localbase, it is even less likely to
+# accidentally pick anything up it shouldn't anyway.
+TOOLS_CREATE+=		target-cc
+TOOLS_PATH.target-cc=	${TOOLDIR}/bin/${TARGET_MACHINE_GNU_PLATFORM}-gcc # XXX shouldn't hard-code gcc
+TOOLS_ARGS.target-cc=	--sysroot=${CROSS_DESTDIR:Q}
+TOOLS_CREATE+=		target-cxx
+TOOLS_PATH.target-cxx=	${TOOLDIR}/bin/${TARGET_MACHINE_GNU_PLATFORM}-c++
+TOOLS_ARGS.target-cxx=	--sysroot=${CROSS_DESTDIR:Q}
+
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.cc=${TOOLS_CMD.target-cc:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.cxx=${TOOLS_CMD.target-cxx:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.linker=${TOOLS_CMD.target-cc:Q}
+CONFIGURE_ARGS+=--set=target.${TARGET_RUST_ARCH:Q}.ar=${TOOLDIR:Q}/bin/${TARGET_MACHINE_GNU_PLATFORM:Q}-ar
+
+.endif				# !empty(TARGET_MACHINE_PLATFORM)
+
 #
 # Rust unfortunately requires itself to build.  On platforms which aren't
 # supported by upstream (where they offer binary bootstraps), or where we do
 # not trust random binaries from the Internet, we need to build and provide our
 # own bootstrap.  See the stage0-bootstrap below for more details.
 #
+.if ${USE_CROSS_COMPILE:tl} == "yes"	# {
+
+# XXX Copypasta of arch.mk -- remove me and use arch.mk once we verify
+# that it produces the same RUST_ARCH on all platforms.
+RUST_ARCH=		${RUST_MACHINE_ARCH.${MACHINE_ARCH}:U${MACHINE_ARCH}}-${empty(LOWER_VENDOR):?unknown:${LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${LOWER_OPSYS}:U${LOWER_OPSYS}}${APPEND_ABI}
+NATIVE_RUST_ARCH=	${RUST_MACHINE_ARCH.${NATIVE_MACHINE_ARCH}:U${NATIVE_MACHINE_ARCH}}-${empty(NATIVE_LOWER_VENDOR):?unknown:${NATIVE_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${NATIVE_LOWER_OPSYS}:U${NATIVE_LOWER_OPSYS}}${NATIVE_APPEND_ABI}
+
+TOOL_DEPENDS+=		rust-${MACHINE_PLATFORM}:../../${PKGPATH}
+RUST_BOOTSTRAP_PATH=	${TOOLBASE}/rust-${RUST_ARCH}
+
+# XXX Maybe omit this if rust-internal-llvm option is enabled?
+CONFIGURE_ARGS+=	--set=target.${NATIVE_RUST_ARCH:Q}.llvm-config=${TOOLBASE:Q}/bin/llvm-config
+
+.else					# } {
+
 DISTFILES:=		${DEFAULT_DISTFILES}
 
 .if ${MACHINE_PLATFORM:MDarwin-*-aarch64} || make(distinfo) || make (makesum) || make(mdi)
@@ -386,10 +484,12 @@ SITES.${RUST_STAGE0}=		${MASTER_SITE_LOCAL:=rust/}
 SITES.${RUST_STD_STAGE0}=	${MASTER_SITE_LOCAL:=rust/}
 .endif
 
+.endif					# }
+
 # You may override RUST_BOOTSTRAP_PATH and RUST_ARCH in mk.conf
 # if you have a local bootstrap compiler.
 .if !defined(RUST_ARCH) && !defined(RUST_BOOTSTRAP_PATH)
-NOT_FOR_PLATFORM+=	${MACHINE_PLATFORM}
+NOT_FOR_PLATFORM+=	${MACHINE_PLATFORM} # XXX NATIVE_MACHINE_PLATFORM
 .else
 RUST_BOOTSTRAP_PATH?=	${WRKDIR}/rust-bootstrap
 .endif
@@ -398,8 +498,8 @@ RUST_BOOTSTRAP_PATH?=	${WRKDIR}/rust-bootstrap
 TOOL_DEPENDS+=		coreutils>=0:../../sysutils/coreutils
 TOOL_DEPENDS+=		gzip>=0:../../archivers/gzip
 TOOLS_CREATE+=		md5sum
-TOOLS_PATH.md5sum=	${PREFIX}/bin/gmd5sum
-TOOLS_PLATFORM.gzcat=	${PREFIX}/bin/gzip -cd
+TOOLS_PATH.md5sum=	${TOOLBASE}/bin/gmd5sum
+TOOLS_PLATFORM.gzcat=	${TOOLBASE}/bin/gzip -cd
 .endif
 
 SUBST_CLASSES+=		prefix
@@ -409,7 +509,7 @@ SUBST_FILES.prefix+=	compiler/rustc_target/src/spec/base/netbsd.rs
 SUBST_FILES.prefix+=	src/bootstrap/src/core/build_steps/compile.rs
 SUBST_FILES.prefix+=	src/bootstrap/src/core/builder.rs
 SUBST_FILES.prefix+=	src/bootstrap/bootstrap.py
-SUBST_VARS.prefix=	PREFIX
+SUBST_VARS.prefix=	PREFIX RUST_PREFIX
 
 #
 # Generate list of subst entries for various .cargo-checksum.json files.  These
@@ -561,12 +661,12 @@ do-build:
 	${SETENV} ${MAKE_ENV}						\
 	sh -c "if [ \"${BUILD_TARGET}\" = \"dist\" ]; then		\
 		unset DESTDIR;						\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    ${BUILD_TARGET} -j ${_MAKE_JOBS_N};			\
 	else								\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    ${BUILD_TARGET} --stage 2 -j ${_MAKE_JOBS_N} &&	\
-		${PYTHONBIN} ./x.py -v					\
+		${TOOL_PYTHONBIN} ./x.py -v				\
 		    doc --stage 2 -j ${_MAKE_JOBS_N};			\
 	fi"
 
@@ -574,18 +674,27 @@ do-test:
 	${RUN}${_ULIMIT_CMD}						\
 	cd ${WRKSRC} &&							\
 	${SETENV} ${MAKE_ENV}						\
-		${PYTHONBIN} ./x.py -v test -j ${_MAKE_JOBS_N}
+		${TOOL_PYTHONBIN} ./x.py -v test -j ${_MAKE_JOBS_N}
 
 do-install:
 	${RUN}${_ULIMIT_CMD}						\
 	cd ${WRKSRC} &&							\
 	${SETENV} ${MAKE_ENV} ${INSTALL_ENV} 				\
-		${PYTHONBIN} ./x.py -v install -j ${_MAKE_JOBS_N}
+		${TOOL_PYTHONBIN} ./x.py -v install -j ${_MAKE_JOBS_N}
+.if !empty(TARGET_MACHINE_PLATFORM)
+	${RUN}								\
+	${GTAR} -C ${WRKDIR:Q}						\
+		-xzf ${WRKSRC:Q}/build/dist/rust-std-${PKGVERSION_NOREV:Q}-${TARGET_RUST_ARCH:Q}.tar.xz
+	${RUN}								\
+	cd ${WRKDIR:Q}/rust-std-${PKGVERSION_NOREV:Q}-${TARGET_RUST_ARCH:Q} && \
+	${SETENV} ${MAKE_ENV} ${INSTALL_ENV}				\
+		./install.sh --prefix=${RUST_PREFIX:Q} --destdir=${DESTDIR:Q}
+.endif
 
 SUBST_CLASSES+=		destdir
 SUBST_STAGE.destdir=	post-install
-SUBST_FILES.destdir=	${DESTDIR}${PREFIX}/lib/rustlib/manifest-*
-SUBST_SED.destdir=	-e 's|file:${DESTDIR}${PREFIX}|file:${PREFIX}|'
+SUBST_FILES.destdir=	${DESTDIR}${RUST_PREFIX}/lib/rustlib/manifest-*
+SUBST_SED.destdir=	-e 's|file:${DESTDIR}${RUST_PREFIX}|file:${RUST_PREFIX}|'
 
 GENERATE_PLIST+=	${FIND} ${DESTDIR}${PREFIX} \( -type f -o -type l \) -print | \
 			${SED} -e 's,${DESTDIR}${PREFIX}/,,' | ${SORT} ;
@@ -640,8 +749,8 @@ stage0-bootstrap: install
 	)
 .endif
 .if ${OS_VARIANT} == "SmartOS"
-	${CP} -R ${DESTDIR}/${PREFIX}/bin ${BOOTSTRAP_TMPDIR}/
-	${CP} -R ${DESTDIR}/${PREFIX}/lib ${BOOTSTRAP_TMPDIR}/
+	${CP} -R ${DESTDIR}/${RUST_PREFIX}/bin ${BOOTSTRAP_TMPDIR}/
+	${CP} -R ${DESTDIR}/${RUST_PREFIX}/lib ${BOOTSTRAP_TMPDIR}/
 	${MKDIR} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc
 	set -e; \
 	for lib in libgcc_s.so.1 libstdc++.so.6; do \
@@ -650,12 +759,12 @@ stage0-bootstrap: install
 	done; \
 	for lib in libLLVM.so.18.1 libcrypto.so.3 libcurl.so.4 \
 		   libssl.so.3 libz.so.1 libzstd.so.1; do \
-		${CP} ${PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
+		${CP} ${RUST_PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
 	done; \
 	for lib in libiconv.so.2 libidn2.so.0 libintl.so.8 liblber.so.2 \
 		   libldap.so.2 libnghttp2.so.14 libsasl2.so.3 \
 		   libssh2.so.1 libunistring.so.5; do \
-		${CP} ${PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
+		${CP} ${RUST_PREFIX}/lib/$${lib} ${BOOTSTRAP_TMPDIR}/lib/pkgsrc/; \
 	done; \
 	for f in ${BOOTSTRAP_TMPDIR}/bin/*; do \
 		/bin/file -b "$$f" | grep ^ELF >/dev/null || continue; \
@@ -675,7 +784,7 @@ stage0-bootstrap: install
 	@${ECHO} "Verify correct library paths using the following:"
 	@${ECHO} ""
 	@${ECHO} "	cd ${BOOTSTRAP_TMPDIR}"
-	@${ECHO} "	find . -type f | xargs ldd 2>/dev/null | egrep 'not.found|${PREFIX}'"
+	@${ECHO} "	find . -type f | xargs ldd 2>/dev/null | egrep 'not.found|${RUST_PREFIX}'"
 	@${ECHO} ""
 	@${ECHO} "If there is no output then this bootstrap kit is ready to go:"
 	@${ECHO} ""
@@ -698,8 +807,8 @@ stage0-bootstrap: install
 # rust i386 and sparc64 bootstraps are built for 8.0
 # and still depend on libstdc++.so.8.
 # Pull in compat80 on 9.x and newer.
-.if (${MACHINE_PLATFORM:MNetBSD-*-i386} || \
-     ${MACHINE_PLATFORM:MNetBSD-*-sparc64}) \
+.if (${NATIVE_MACHINE_PLATFORM:MNetBSD-*-i386} || \
+     ${NATIVE_MACHINE_PLATFORM:MNetBSD-*-sparc64}) \
     && empty(OS_VERSION:M8.*)
 TOOL_DEPENDS+=	compat80>=0:../../emulators/compat80
 .endif
@@ -715,7 +824,7 @@ DEPENDS+=	libatomic-links>=0:../../devel/libatomic-links
 .endif
 
 TOOL_DEPENDS+= cmake-[0-9]*:../../devel/cmake
-.include "../../devel/cmake/buildlink3.mk"
+
 .include "../../devel/zlib/buildlink3.mk"
 .include "../../lang/python/tool.mk"
 .include "../../mk/bsd.pkg.mk"
diff --git a/lang/rust/arch.mk b/lang/rust/arch.mk
new file mode 100644
index 000000000000..ad0dfa72f149
--- /dev/null
+++ b/lang/rust/arch.mk
@@ -0,0 +1,32 @@
+#	$NetBSD$
+#
+# Common logic to map pkgsrc idea of machine platforms into Rust idea
+# of architectures.
+#
+# System-provided variables:
+#
+# RUST_ARCH
+#	The Rust architecture triple that this package is built for.
+#
+# NATIVE_RUST_ARCH
+#	The Rust architecture triple that we are doing the build on.
+#
+# TARGET_RUST_ARCH
+#	If nonempty, the Rust architecture triple that this package may
+#	be intended to support as a cross-compiler target.
+#
+#	Nonempty if and only if TARGET_MACHINE_PLATFORM is nonempty,
+#	i.e., this package is being built as a TOOL_DEPENDS dependency
+#	of another package and thus may be being built as a
+#	cross-compiler.
+
+RUST_MACHINE_ARCH.i386=		i586		# not really
+RUST_MACHINE_ARCH.aarch64eb=	aarch64_be
+RUST_MACHINE_ARCH.riscv64=	riscv64gc
+
+RUST_LOWER_OPSYS.solaris=	illumos
+
+RUST_ARCH=		${RUST_MACHINE_ARCH.${MACHINE_ARCH}:U${MACHINE_ARCH}}-${empty(LOWER_VENDOR):?unknown:${LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${LOWER_OPSYS}:U${LOWER_OPSYS}}${APPEND_ABI}
+NATIVE_RUST_ARCH=	${RUST_MACHINE_ARCH.${NATIVE_MACHINE_ARCH}:U${NATIVE_MACHINE_ARCH}}-${empty(NATIVE_LOWER_VENDOR):?unknown:${NATIVE_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${NATIVE_LOWER_OPSYS}:U${NATIVE_LOWER_OPSYS}}${NATIVE_APPEND_ABI}
+
+TARGET_RUST_ARCH=	${empty(TARGET_MACHINE_PLATFORM):?:${RUST_MACHINE_ARCH.${TARGET_MACHINE_ARCH}:U${TARGET_MACHINE_ARCH}}-${empty(TARGET_LOWER_VENDOR):?unknown:${TARGET_LOWER_VENDOR}}-${RUST_LOWER_OPSYS.${TARGET_LOWER_OPSYS}:U${TARGET_LOWER_OPSYS}}${TARGET_APPEND_ABI}}
diff --git a/lang/rust/cargo.mk b/lang/rust/cargo.mk
index 5a3ed0cf8306..d0493a4f0162 100644
--- a/lang/rust/cargo.mk
+++ b/lang/rust/cargo.mk
@@ -72,18 +72,41 @@ print-cargo-depends:
 
 .if ${RUST_TYPE} == "native"
 CARGO=			cargo
+.elif ${USE_CROSS_COMPILE:tl} == "yes"
+# XXX Nix this conditional once we verify no fallout for native builds:
+# using TOOLS_CREATE to create a cargo tool, and writing
+# ${TOOLBASE}/bin/cargo instead of ${PREFIX}/bin/cargo, and similarly
+# for rustc, should all work just fine for native builds.
+.  include "arch.mk"
+TOOLS_CREATE+=		cargo
+TOOLS_PATH.cargo=	${TOOLBASE}${"${USE_CROSS_COMPILE:tl}" == "yes":?/rust-${RUST_ARCH}:}/bin/cargo
+TOOLS_CREATE+=		rustc
+TOOLS_PATH.rustc=	${TOOLBASE}${"${USE_CROSS_COMPILE:tl}" == "yes":?/rust-${RUST_ARCH}:}/bin/rustc
 .else
 CARGO=			${PREFIX}/bin/cargo
 .endif
+
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+ALL_ENV+=		CARGO_TARGET_${NATIVE_RUST_ARCH:S/-/_/g:tu}_LINKER=native-cc
+TOOLS_CREATE+=		native-cc
+TOOLS_PATH.native-cc=	${NATIVE_CC:[1]}
+TOOLS_ARGS.native-cc=	${NATIVE_CC:[2..-1]}
+.endif				# ${USE_CROSS_COMPILE:tl} == "yes"
+
 DEFAULT_CARGO_ARGS=	--offline -j${_MAKE_JOBS_N}	\
 			  ${CARGO_NO_DEFAULT_FEATURES:M[yY][eE][sS]:C/[yY][eE][sS]/--no-default-features/}	\
 			  ${CARGO_FEATURES:C/.*/--features/W}	\
-			  ${CARGO_FEATURES:S/ /,/Wg}
+			  ${CARGO_FEATURES:S/ /,/Wg} \
+			  ${"${USE_CROSS_COMPILE:tl}" == "yes":?--target ${RUST_ARCH}:}
 CARGO_ARGS?=		build --release ${DEFAULT_CARGO_ARGS}
 CARGO_INSTALL_ARGS?=	install --path . --root ${DESTDIR}${PREFIX} ${DEFAULT_CARGO_ARGS}
 
+CARGO_OUTPUT_SUBDIR=	${"${USE_CROSS_COMPILE:tl}" == "yes":?target/${RUST_ARCH}/release:target/release}
+CARGO_OUTPUT_DIR=	${WRKSRC}/${CARGO_OUTPUT_SUBDIR}
+
 MAKE_ENV+=		RUSTFLAGS=${RUSTFLAGS:Q}
 ALL_ENV+=		CARGO_HOME=${WRKDIR}
+ALL_ENV+=		${defined(ALLOW_NETWORK_ACCESS):?:CARGO_NET_OFFLINE=true}
 
 .if !target(do-build)
 do-build: do-cargo-build
diff --git a/lang/rust/distinfo b/lang/rust/distinfo
index 991b8ab88c85..b79a69394c08 100644
--- a/lang/rust/distinfo
+++ b/lang/rust/distinfo
@@ -121,11 +121,11 @@ SHA1 (patch-config.example.toml) = 520ad7a26249780ae79a5dc1d2b534a8c6aef0a5
 SHA1 (patch-library_backtrace_src_symbolize_gimli.rs) = 9d5ef634c5a454e474ea5fee76da9bb768f5b3d9
 SHA1 (patch-library_backtrace_src_symbolize_gimli_elf.rs) = 3b84a462c6bc8245d579452e4c37e3ce13314952
 SHA1 (patch-library_std_src_sys_pal_unix_mod.rs) = bfc59ae4568547e3ed71c8b31ba5b5b5363d5d40
-SHA1 (patch-src_bootstrap_bootstrap.py) = 6f1d3068da49f19c3e092230ba1c7d99af628d3a
+SHA1 (patch-src_bootstrap_bootstrap.py) = 6ce15a434d163f921cc77c15c4b0c759a4de39f5
 SHA1 (patch-src_bootstrap_src_core_build__steps_compile.rs) = e928203ed4734c93cc33c5a3f7879cf18dcecc83
 SHA1 (patch-src_bootstrap_src_core_build__steps_dist.rs) = eb228d43e1cf21ec646b516b8c67c648c7183f8a
 SHA1 (patch-src_bootstrap_src_core_build__steps_install.rs) = cc6558df42c9c9ac28fdb2ff180bdaa7f22ce816
-SHA1 (patch-src_bootstrap_src_core_builder.rs) = e3fd19e0a18f1e79e287c85035ea431b98d91d9a
+SHA1 (patch-src_bootstrap_src_core_builder.rs) = b077845e04d83a500eeac3cae4d4b0baa5b3bafe
 SHA1 (patch-src_bootstrap_src_core_config_config.rs) = fa9d93602693bce064aa155ad0a204b176b47d99
 SHA1 (patch-src_bootstrap_src_lib.rs) = d29bc3c0b335d5e788eecbb02fc08966beef0fb1
 SHA1 (patch-src_llvm-project_llvm_CMakeLists.txt) = 7abfabb6ec70df229a69355f8c76825610165c37
diff --git a/lang/rust/patches/patch-src_bootstrap_bootstrap.py b/lang/rust/patches/patch-src_bootstrap_bootstrap.py
index 3166c52a7f37..f29c058d0056 100644
--- a/lang/rust/patches/patch-src_bootstrap_bootstrap.py
+++ b/lang/rust/patches/patch-src_bootstrap_bootstrap.py
@@ -36,10 +36,11 @@ Also use @PREFIX@ and not $ORIGIN in rpath.
          else:
              kernel += 'eabihf'
      elif cputype == 'mips':
-@@ -734,6 +745,7 @@ class RustBuild(object):
+@@ -734,6 +745,8 @@ class RustBuild(object):
  
          patchelf = "{}/bin/patchelf".format(nix_deps_dir)
          rpath_entries = [
++            "@RUST_PREFIX@/lib",
 +	    "@PREFIX@/lib",
              os.path.join(os.path.realpath(nix_deps_dir), "lib")
          ]
diff --git a/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs b/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
index 7db4e8beb1ac..e2c076d2850c 100644
--- a/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
+++ b/lang/rust/patches/patch-src_bootstrap_src_core_builder.rs
@@ -1,7 +1,7 @@
 $NetBSD: patch-src_bootstrap_src_core_builder.rs,v 1.5 2024/07/27 02:35:24 tnn Exp $
 
 Find external libunwind on Linux.
-Use @PREFIX@, not $ORIGIN in rpath.
+Use @RUST_PREFIX@ and @PREFIX@, not $ORIGIN in rpath.
 
 --- src/bootstrap/src/core/builder.rs.orig	2006-07-24 01:21:28.000000000 +0000
 +++ src/bootstrap/src/core/builder.rs
@@ -22,7 +22,7 @@ Use @PREFIX@, not $ORIGIN in rpath.
              } else if !target.is_windows() && !target.contains("aix") && !target.contains("xous") {
                  self.rustflags.arg("-Clink-args=-Wl,-z,origin");
 -                Some(format!("-Wl,-rpath,$ORIGIN/../{libdir}"))
-+                Some(format!("-Wl,-rpath,@PREFIX@/{libdir}"))
++                Some(format!("-Wl,-rpath,@RUST_PREFIX@/{libdir},-rpath,@PREFIX@/lib"))
              } else {
                  None
              };
diff --git a/lang/rust/rust.mk b/lang/rust/rust.mk
index 82185914b67b..9b3be3ec6e35 100644
--- a/lang/rust/rust.mk
+++ b/lang/rust/rust.mk
@@ -40,17 +40,41 @@ RUST_RUNTIME?=	no
 RUST_TYPE?=	src
 
 .if ${RUST_TYPE} == "bin"
+# XXX Remove this ${USE_CROSS_COMPILE} conditional once we confirm no
+# fallout in native builds from the TOOL_DEPENDS approach.
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+.  include "arch.mk"
+TOOL_DEPENDS+=			rust${"${USE_CROSS_COMPILE:U:tl}" == "yes":?-${MACHINE_PLATFORM}:}-bin>=${RUST_REQ}:../../lang/rust-bin
+BUILDLINK_PASSTHRU_DIRS+=	${"${USE_CROSS_COMPILE:tl}" == "yes":?${TOOLBASE}/rust-${RUST_ARCH}:${PREFIX}}/lib/rustlib
+.  if ${RUST_RUNTIME} != "no"
+BUILDLINK_API_DEPENDS.rust-bin+=	rust-bin>=${RUST_REQ}
+.    include "${RUST_DIR}-bin/buildlink3.mk"
+.  endif
+.else
 .  if ${RUST_RUNTIME} == "no"
 BUILDLINK_DEPMETHOD.rust-bin?=		build
 .  endif
 BUILDLINK_API_DEPENDS.rust-bin+=	rust-bin>=${RUST_REQ}
 .  include "${RUST_DIR}-bin/buildlink3.mk"
 .endif
+.endif
 
 .if ${RUST_TYPE} == "src"
+# XXX Remove this ${USE_CROSS_COMPILE} conditional once we confirm no
+# fallout in native builds from the TOOL_DEPENDS approach.
+.if ${USE_CROSS_COMPILE:tl} == "yes"
+.  include "arch.mk"
+TOOL_DEPENDS+=			rust${"${USE_CROSS_COMPILE:U:tl}" == "yes":?-${MACHINE_PLATFORM}:}>=${RUST_REQ}:../../lang/rust
+BUILDLINK_PASSTHRU_DIRS+=	${"${USE_CROSS_COMPILE:tl}" == "yes":?${TOOLBASE}/rust-${RUST_ARCH}:${PREFIX}}/lib/rustlib
+.  if ${RUST_RUNTIME} != "no"
+BUILDLINK_API_DEPENDS.rust+=		rust>=${RUST_REQ}
+.    include "${RUST_DIR}/buildlink3.mk"
+.  endif
+.else
 .  if ${RUST_RUNTIME} == "no"
 BUILDLINK_DEPMETHOD.rust?=		build
 .  endif
 BUILDLINK_API_DEPENDS.rust+=		rust>=${RUST_REQ}
 .  include "${RUST_DIR}/buildlink3.mk"
 .endif
+.endif


Home | Main Index | Thread Index | Old Index