From b0e68dde5cc0d99efe41d2270c4ebae702204e27 Mon Sep 17 00:00:00 2001 From: Romain TISSERAND Date: Mon, 27 Jan 2025 12:39:39 +0100 Subject: [PATCH] Add REG specific pkg-rust infrastructure --- package/Makefile.in | 2 + package/pkg-rust.mk | 309 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 311 insertions(+) create mode 100644 package/pkg-rust.mk diff --git a/package/Makefile.in b/package/Makefile.in index 829636900b..2366fff335 100644 --- a/package/Makefile.in +++ b/package/Makefile.in @@ -466,3 +466,5 @@ include package/pkg-golang.mk include package/pkg-meson.mk include package/pkg-qmake.mk include package/pkg-cargo.mk +# REG add rust pkg infrastructure +include package/pkg-rust.mk diff --git a/package/pkg-rust.mk b/package/pkg-rust.mk new file mode 100644 index 0000000000..aa09198f1f --- /dev/null +++ b/package/pkg-rust.mk @@ -0,0 +1,309 @@ +################################################################################ +# +# REG-Linux +# +################################################################################ +# Rust package infrastructure +# +# This file implements an infrastructure that eases development of package +# .mk files for Rust packages. It should be used for all Rust packages that use +# Cargo as their build system. +# +# See the Buildroot documentation for details on the usage of this +# infrastructure +# +# In terms of implementation, this Cargo infrastructure requires the .mk file +# to only specify metadata information about the package: name, version, +# download URL, etc. +# +# We still allow the package .mk file to override what the different steps +# are doing, if needed. For example, if _BUILD_CMDS is already defined, +# it is used as the list of commands to perform to build the package, +# instead of the default Cargo behaviour. The package can also define some +# post operation hooks. +# +################################################################################ + +BR_CARGO_HOME = $(DL_DIR)/br-cargo-home + +PKG_COMMON_RUST_ENV = \ + CARGO_HOME=$(BR_CARGO_HOME) + +# __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS is needed to allow +# passing the -Z target-applies-to-host, which is needed together with +# CARGO_TARGET_APPLIES_TO_HOST to fix build problems when target +# architecture == host architecture. + +# __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly" is to allow +# using nighly features on stable releases, i.e features that are not +# yet considered stable. +# +# CARGO_UNSTABLE_HOST_CONFIG="true" enables the host specific +# configuration feature +# +# CARGO_UNSTABLE_TARGET_APPLIES_TO_HOST="true" enables the nightly +# configuration option target-applies-to-host value to be set +# +# CARGO_TARGET_APPLIES_TO_HOST="false" is actually setting the value +# for this feature, which we disable, to make sure builds where target +# arch == host arch work correctly +PKG_RUST_ENV = \ + $(PKG_COMMON_RUST_ENV) \ + __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly" \ + CARGO_UNSTABLE_HOST_CONFIG="true" \ + CARGO_UNSTABLE_TARGET_APPLIES_TO_HOST="true" \ + CARGO_TARGET_APPLIES_TO_HOST="false" \ + CARGO_BUILD_TARGET="$(RUSTC_TARGET_NAME)" \ + CARGO_HOST_RUSTFLAGS="$(addprefix -C link-args=,$(HOST_LDFLAGS))" \ + CARGO_TARGET_$(call UPPERCASE,$(RUSTC_TARGET_NAME))_LINKER=$(notdir $(TARGET_CROSS))gcc + +# We always set both CARGO_PROFILE_DEV and CARGO_PROFILE_RELEASE +# as we are unable to select a build profile using the environment. +# +# Other cargo profiles generally derive from these two profiles. + +# Disable incremental compilation to match release default. +# +# Set codegen-units to release default. +# +# Set split-debuginfo to default off for ELF platforms. +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_INCREMENTAL="false" \ + CARGO_PROFILE_RELEASE_INCREMENTAL="false" \ + CARGO_PROFILE_DEV_CODEGEN_UNITS="16" \ + CARGO_PROFILE_RELEASE_CODEGEN_UNITS="16" \ + CARGO_PROFILE_DEV_SPLIT_DEBUGINFO="off" \ + CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO="off" + +# Set the optimization level with the release default as fallback. +ifeq ($(BR2_OPTIMIZE_0),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="0" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="0" +else ifeq ($(BR2_OPTIMIZE_1),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="1" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="1" +else ifeq ($(BR2_OPTIMIZE_2),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="2" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="2" +else ifeq ($(BR2_OPTIMIZE_3),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="3" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="3" +else ifeq ($(BR2_OPTIMIZE_G),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="0" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="0" +else ifeq ($(BR2_OPTIMIZE_S),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="s" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="s" +else ifeq ($(BR2_OPTIMIZE_FAST),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="3" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="3" +else +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_OPT_LEVEL="3" \ + CARGO_PROFILE_RELEASE_OPT_LEVEL="3" +endif + +ifeq ($(BR2_ENABLE_LTO),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_LTO="true" \ + CARGO_PROFILE_RELEASE_LTO="true" +else +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_LTO="false" \ + CARGO_PROFILE_RELEASE_LTO="false" +endif + + +ifeq ($(BR2_ENABLE_DEBUG),y) +ifeq ($(BR2_DEBUG_3),y) +# full debug info +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_DEBUG="2" \ + CARGO_PROFILE_RELEASE_DEBUG="2" +else +# line tables only +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_DEBUG="1" \ + CARGO_PROFILE_RELEASE_DEBUG="1" +endif +else +# no debug info +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_DEBUG="0" \ + CARGO_PROFILE_RELEASE_DEBUG="0" +endif + +# Enabling debug-assertions enables the runtime debug_assert! macro. +# +# Enabling overflow-checks enables runtime panic on integer overflow. +ifeq ($(BR2_ENABLE_RUNTIME_DEBUG),y) +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_DEBUG_ASSERTIONS="true" \ + CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="true" \ + CARGO_PROFILE_DEV_OVERFLOW_CHECKS="true" \ + CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="true" +else +PKG_RUST_ENV += \ + CARGO_PROFILE_DEV_DEBUG_ASSERTIONS="false" \ + CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="false" \ + CARGO_PROFILE_DEV_OVERFLOW_CHECKS="false" \ + CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="false" +endif + +# +# This is a workaround for https://github.com/rust-lang/compiler-builtins/issues/420 +# and should be removed when fixed upstream +# +ifeq ($(NORMALIZED_ARCH),arm) + PKG_RUST_ENV += \ + CARGO_TARGET_$(call UPPERCASE,$(RUSTC_TARGET_NAME))_RUSTFLAGS="-Clink-arg=-Wl,--allow-multiple-definition" +endif + +HOST_PKG_RUST_ENV = \ + $(PKG_COMMON_RUST_ENV) \ + RUSTFLAGS="$(addprefix -C link-args=,$(HOST_LDFLAGS))" + +################################################################################ +# inner-cargo-package -- defines how the configuration, compilation and +# installation of a cargo package should be done, implements a few hooks +# to tune the build process for cargo specifities and calls the generic +# package infrastructure to generate the necessary make targets +# +# argument 1 is the lowercase package name +# argument 2 is the uppercase package name, including a HOST_ prefix +# for host packages +# argument 3 is the uppercase package name, without the HOST_ prefix +# for host packages +# argument 4 is the type (target or host) +################################################################################ + +define inner-cargo-package + +# We need host-rustc to run cargo at download time (for vendoring), +# and at build and install time. +$(2)_DOWNLOAD_DEPENDENCIES += host-rustc +$(2)_DEPENDENCIES += host-rustc + +$(2)_DOWNLOAD_POST_PROCESS = cargo +$(2)_DL_ENV += CARGO_HOME=$$(BR_CARGO_HOME) + +# If building in a sub directory, use that to find the Cargo.toml +ifneq ($$($(2)_SUBDIR),) +$(2)_DOWNLOAD_POST_PROCESS_OPTS += -m$$($(2)_SUBDIR)/Cargo.toml +endif + +# Because we append vendored info, we can't rely on the values being empty +# once we eventually get into the generic-package infra. So, we duplicate +# the heuristics here +ifndef $(2)_LICENSE + ifdef $(3)_LICENSE + $(2)_LICENSE = $$($(3)_LICENSE) + endif +endif + +# Due to vendoring, it is pretty likely that not all licenses are +# listed in _LICENSE. If the license is unset, it is "unknown" +# so adding unknowns to some unknown is still some other unknown, +# so don't append the blurb in that case. +ifneq ($$($(2)_LICENSE),) +$(2)_LICENSE += , vendored dependencies licenses probably not listed +endif + +# Note: in all the steps below, we "cd" into the build directory to +# execute the "cargo" tool instead of passing $(@D)/Cargo.toml as the +# manifest-path. Indeed while the latter seems to work, it in fact +# breaks in subtle ways as the way cargo searches for its +# configuration file is based (among other rules) on the current +# directory. This means that if cargo is started outside of a package +# directory, its configuration file will not be taken into account. +# + +# +# Build step. Only define it if not already defined by the package .mk +# file. +# +ifndef $(2)_BUILD_CMDS +ifeq ($(4),target) +define $(2)_BUILD_CMDS + cd $$($$(PKG)_SRCDIR) && \ + $$(TARGET_MAKE_ENV) \ + $$(TARGET_CONFIGURE_OPTS) \ + $$(PKG_RUST_ENV) \ + $$($(2)_CARGO_ENV) \ + cargo build \ + $$(if $$(BR2_ENABLE_DEBUG),,--release) \ + --manifest-path Cargo.toml \ + $$($(2)_CARGO_BUILD_OPTS) +endef +else # ifeq ($(4),target) +define $(2)_BUILD_CMDS + cd $$($$(PKG)_SRCDIR) && \ + $$(HOST_MAKE_ENV) \ + $$(HOST_CONFIGURE_OPTS) \ + $$(HOST_PKG_RUST_ENV) \ + $$($(2)_CARGO_ENV) \ + cargo build \ + --release \ + --manifest-path Cargo.toml \ + $$($(2)_CARGO_BUILD_OPTS) +endef +endif # ifeq ($(4),target) +endif # ifndef $(2)_BUILD_CMDS + +# +# Target installation step. Only define it if not already defined by +# the package .mk file. +# +ifndef $(2)_INSTALL_TARGET_CMDS +define $(2)_INSTALL_TARGET_CMDS + cd $$($$(PKG)_SRCDIR) && \ + $$(TARGET_MAKE_ENV) \ + $$(TARGET_CONFIGURE_OPTS) \ + $$(PKG_RUST_ENV) \ + $$($(2)_CARGO_ENV) \ + cargo install \ + --root $$(TARGET_DIR)/usr/ \ + --bins \ + --no-track \ + --force \ + --locked \ + -Z target-applies-to-host \ + $$($(2)_CARGO_INSTALL_OPTS) +endef +endif + +ifndef $(2)_INSTALL_CMDS +define $(2)_INSTALL_CMDS + cd $$($$(PKG)_SRCDIR) && \ + $$(HOST_MAKE_ENV) \ + $$(HOST_CONFIGURE_OPTS) \ + $$(HOST_PKG_RUST_ENV) \ + $$($(2)_CARGO_ENV) \ + cargo install \ + --root $$(HOST_DIR) \ + --bins \ + --no-track \ + --force \ + $$($(2)_CARGO_INSTALL_OPTS) +endef +endif + +# Call the generic package infrastructure to generate the necessary +# make targets +$(call inner-generic-package,$(1),$(2),$(3),$(4)) + +endef + +################################################################################ +# rust-package -- the target generator macro for Cargo packages +################################################################################ + +rust-package = $(call inner-cargo-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target) +host-rust-package = $(call inner-cargo-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host)