openwrt/tools/rust/Makefile

235 lines
7.0 KiB
Makefile

# SPDX-License-Identifier: GPL-2.0-only
#
# Copyright (C) 2023 Luca Barbato and Donald Hoskins
include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/rust-values.mk
PKG_NAME:=rust
PKG_VERSION:=$(RUST_VERSION)
PKG_RELEASE:=1
PKG_LICENSE:=Apache-2.0 MIT
PKG_LICENSE_FILES:=LICENSE-APACHE LICENSE-MIT
PKG_CPE_ID:=cpe:/a:rust-lang:rust
ifdef CONFIG_USE_RUST_BUILD
PKG_SOURCE:=rustc-$(PKG_VERSION)-src.tar.xz
PKG_SOURCE_URL:=https://static.rust-lang.org/dist/
PKG_HASH:=$(RUST_SRC_TARBALL_HASH)
endif
# All modes share one build directory, so that a mode change prepares anew.
HOST_PREPARED_DEPENDS:= \
CONFIG_USE_RUST_BUILD CONFIG_USE_RUST_PREBUILT CONFIG_USE_RUST_HOST \
CONFIG_RUST_TOOLCHAIN_HOST_PATH
include $(INCLUDE_DIR)/host-build.mk
TAR_OPTIONS+= --strip-components 1
TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
RUST_PREFIX_DIR:=$(HOST_BUILD_DIR)/prefix
RUST_FILE_LIST:=$(STAGING_DIR_HOST)/stamp/.rust_files
RUST_DIR_LIST:=$(STAGING_DIR_HOST)/stamp/.rust_dirs
RUST_CC_WRAPPER:=$(subst $(space),,$(foreach dir, \
$(subst /, ,$(patsubst $(TOPDIR)/%,%,$(STAGING_DIR_HOST)/bin)),../))scripts/rust-cc-wrapper.sh
# The rust-installer manifests name absolute paths, which its uninstaller
# and the next install.sh into the same prefix delete.
RUST_INSTALLER_DATA:=$(addprefix $(RUST_PREFIX_DIR)/lib/rustlib/, \
components install.log uninstall.sh rust-installer-version manifest-*)
define Host/Install/RemoveInstallerData
rm -f $(RUST_INSTALLER_DATA)
endef
# Cargo reads .cargo/config.toml in every parent of its working directory.
define Host/CheckCargoConfig
dir="$$$$(cd $(TOPDIR) && pwd -P)"; \
while :; do \
for file in "$$$$dir/.cargo/config" "$$$$dir/.cargo/config.toml"; do \
[ ! -e "$$$$file" ] || { echo "Cargo would read $$$$file"; exit 1; }; \
done; \
[ "$$$$dir" != / ] || break; \
dir="$$$$(dirname "$$$$dir")"; \
done
endef
Hooks/HostPrepare/Pre += Host/CheckCargoConfig
define Host/Uninstall
if [ -f $(RUST_FILE_LIST) ]; then \
cd $(STAGING_DIR_HOST) && \
while read -r file; do rm -f "$$$$file"; done < $(RUST_FILE_LIST) && \
while read -r dir; do rmdir "$$$$dir" 2>/dev/null || true; done < $(RUST_DIR_LIST); \
fi
rm -f $(RUST_FILE_LIST) $(RUST_DIR_LIST)
endef
ifdef CONFIG_USE_RUST_BUILD
HOST_CONFIGURE_VARS += CARGO_HOME="$(CARGO_HOME)"
# Only the host compiler is built here; libstd-rust builds the cross rust-std.
HOST_CONFIGURE_ARGS = \
--build=$(RUSTC_HOST_ARCH) \
--target=$(RUSTC_HOST_ARCH) \
--host=$(RUSTC_HOST_ARCH) \
--prefix=$(STAGING_DIR_HOST) \
--bindir=$(STAGING_DIR_HOST)/bin \
--libdir=$(STAGING_DIR_HOST)/lib \
--sysconfdir=$(STAGING_DIR_HOST)/etc \
--datadir=$(STAGING_DIR_HOST)/share \
--mandir=$(STAGING_DIR_HOST)/man \
--dist-compression-formats=gz \
--disable-sanitizers \
--release-channel=stable \
--enable-cargo-native-static \
--bootstrap-cache-path=$(DL_DIR)/rustc \
"--set=llvm.targets=$(RUST_LLVM_TARGETS)" \
"--set=llvm.experimental-targets=$(RUST_LLVM_EXPERIMENTAL_TARGETS)" \
--set=llvm.download-ci-llvm=false
# bootstrap leaves the job count of ninja and cargo to the jobserver named in
# MAKEFLAGS, and runs one job per CPU without one.
define Host/Compile
+CARGO_HOME=$(CARGO_HOME) \
MAKEFLAGS="$(MAKE_JOBSERVER)" \
$(PYTHON) $(HOST_BUILD_DIR)/x.py \
--build-dir $(HOST_BUILD_DIR)/build \
$(if $(MAKE_JOBSERVER),,--jobs 1) \
dist rustc cargo rust-std llvm-tools rust-src
endef
define Host/Install/Prefix
rm -rf $(RUST_PREFIX_DIR)
( \
cd $(HOST_BUILD_DIR)/build/dist ; \
for targz in rustc-* cargo-* rust-std-* llvm-tools-* rust-src-*.tar.gz; do \
[ -f "$$$$targz" ] || continue; \
$(STAGING_DIR_HOST)/bin/libdeflate-gzip -dc "$$$$targz" | tar -xf - ; \
done ; \
find . -mindepth 2 -maxdepth 2 -type f -name install.sh \
-execdir bash '{}' --prefix=$(RUST_PREFIX_DIR) --disable-ldconfig \; ; \
)
endef
else
RUST_UNPACK_DIR:=$(HOST_BUILD_DIR)/unpacked
$(if $(RUST_RUSTC_HASH),,$(error No prebuilt Rust components for the build host $(RUSTC_HOST_ARCH)))
define Download/rust-src
FILE:=rust-src-$(PKG_VERSION).tar.xz
URL:=$(RUST_DIST_URL)
HASH:=$(RUST_SRC_HASH)
endef
$(eval $(call Download,rust-src))
define Download/rust-llvm-tools
FILE:=llvm-tools-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
URL:=$(RUST_DIST_URL)
HASH:=$(RUST_LLVM_TOOLS_HASH)
endef
$(eval $(call Download,rust-llvm-tools))
RUST_DIST_FILES:= \
$(DL_DIR)/rust-src-$(PKG_VERSION).tar.xz \
$(DL_DIR)/llvm-tools-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
ifdef CONFIG_USE_RUST_PREBUILT
define Download/rustc
FILE:=rustc-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
URL:=$(RUST_DIST_URL)
HASH:=$(RUST_RUSTC_HASH)
endef
$(eval $(call Download,rustc))
define Download/cargo
FILE:=cargo-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
URL:=$(RUST_DIST_URL)
HASH:=$(RUST_CARGO_HASH)
endef
$(eval $(call Download,cargo))
define Download/rust-std
FILE:=rust-std-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
URL:=$(RUST_DIST_URL)
HASH:=$(RUST_STD_HASH)
endef
$(eval $(call Download,rust-std))
RUST_DIST_FILES+= \
$(DL_DIR)/rustc-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz \
$(DL_DIR)/cargo-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz \
$(DL_DIR)/rust-std-$(PKG_VERSION)-$(RUSTC_HOST_ARCH).tar.xz
define Host/Prepare/Toolchain
endef
else
RUST_HOST_SYSROOT:=$(or $(call qstrip,$(CONFIG_RUST_TOOLCHAIN_HOST_PATH)),$(shell PATH=$(ORIG_PATH) rustc --print sysroot 2>/dev/null))
define Host/Prepare/Toolchain
[ "$$$$($(RUST_HOST_SYSROOT)/bin/rustc --version | cut -d' ' -f2)" = "$(PKG_VERSION)" ] || { \
echo "rustc in '$(RUST_HOST_SYSROOT)' is not version $(PKG_VERSION)"; \
exit 1; \
}
$(INSTALL_DIR) $(RUST_PREFIX_DIR)/bin
$(INSTALL_BIN) $(RUST_HOST_SYSROOT)/bin/rustc $(RUST_HOST_SYSROOT)/bin/cargo \
$(RUST_PREFIX_DIR)/bin/
$(CP) $(RUST_HOST_SYSROOT)/lib $(RUST_PREFIX_DIR)/
endef
define Host/Install/Check
[ "$$$$($(STAGING_DIR_HOST)/bin/rustc --print sysroot)" = "$(shell realpath $(STAGING_DIR_HOST))" ] || { \
echo "rustc from '$(RUST_HOST_SYSROOT)' is not relocatable, use a rustup toolchain or an unpacked official Rust distribution"; \
exit 1; \
}
endef
endif
# install.sh renames every file it finds in the prefix to *.old, so the host
# toolchain is copied over the installed components.
define Host/Prepare
$(INSTALL_DIR) $(RUST_PREFIX_DIR) $(RUST_UNPACK_DIR)
for tarball in $(RUST_DIST_FILES); do \
tar -xf "$$$$tarball" -C $(RUST_UNPACK_DIR); \
done
for installer in $(RUST_UNPACK_DIR)/*/install.sh; do \
$(BASH) "$$$$installer" --prefix=$(RUST_PREFIX_DIR) --disable-ldconfig; \
done
$(call Host/Prepare/Toolchain)
endef
define Host/Patch
endef
define Host/Configure
endef
define Host/Compile
endef
endif
define Host/Install
$(call Host/Install/Prefix)
$(call Host/Install/RemoveInstallerData)
ln -sf $(RUST_CC_WRAPPER) $(RUST_PREFIX_DIR)/bin/rust-cc-wrapper
ln -sf $(RUST_CC_WRAPPER) $(RUST_PREFIX_DIR)/bin/rust-cxx-wrapper
$(call Host/Uninstall)
$(INSTALL_DIR) $(STAGING_DIR_HOST)/stamp
cd $(RUST_PREFIX_DIR) && \
find . ! -type d > $(RUST_FILE_LIST) && \
find . -mindepth 1 -depth -type d > $(RUST_DIR_LIST)
$(CP) $(RUST_PREFIX_DIR)/. $(STAGING_DIR_HOST)/
$(call Host/Install/Check)
endef
$(eval $(call HostBuild))