1################################################################################ 2# Cargo package infrastructure 3# 4# This file implements an infrastructure that eases development of package 5# .mk files for Cargo packages. It should be used for all packages that use 6# Cargo as their build system. 7# 8# See the Buildroot documentation for details on the usage of this 9# infrastructure 10# 11# In terms of implementation, this Cargo infrastructure requires the .mk file 12# to only specify metadata information about the package: name, version, 13# download URL, etc. 14# 15# We still allow the package .mk file to override what the different steps 16# are doing, if needed. For example, if <PKG>_BUILD_CMDS is already defined, 17# it is used as the list of commands to perform to build the package, 18# instead of the default Cargo behaviour. The package can also define some 19# post operation hooks. 20# 21################################################################################ 22 23BR_CARGO_HOME = $(DL_DIR)/br-cargo-home 24 25PKG_COMMON_CARGO_ENV = \ 26 CARGO_HOME=$(BR_CARGO_HOME) 27 28# __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS is needed to allow 29# passing the -Z target-applies-to-host, which is needed together with 30# CARGO_TARGET_APPLIES_TO_HOST to fix build problems when target 31# architecture == host architecture. 32 33# __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly" is to allow 34# using nighly features on stable releases, i.e features that are not 35# yet considered stable. 36# 37# CARGO_UNSTABLE_HOST_CONFIG="true" enables the host specific 38# configuration feature 39# 40# CARGO_UNSTABLE_TARGET_APPLIES_TO_HOST="true" enables the nightly 41# configuration option target-applies-to-host value to be set 42# 43# CARGO_TARGET_APPLIES_TO_HOST="false" is actually setting the value 44# for this feature, which we disable, to make sure builds where target 45# arch == host arch work correctly 46PKG_CARGO_ENV = \ 47 $(PKG_COMMON_CARGO_ENV) \ 48 __CARGO_TEST_CHANNEL_OVERRIDE_DO_NOT_USE_THIS="nightly" \ 49 CARGO_UNSTABLE_HOST_CONFIG="true" \ 50 CARGO_UNSTABLE_TARGET_APPLIES_TO_HOST="true" \ 51 CARGO_TARGET_APPLIES_TO_HOST="false" \ 52 CARGO_BUILD_TARGET="$(RUSTC_TARGET_NAME)" \ 53 CARGO_HOST_RUSTFLAGS="$(addprefix -C link-args=,$(HOST_LDFLAGS))" \ 54 CARGO_TARGET_$(call UPPERCASE,$(RUSTC_TARGET_NAME))_LINKER=$(notdir $(TARGET_CROSS))gcc 55 56# We always set both CARGO_PROFILE_DEV and CARGO_PROFILE_RELEASE 57# as we are unable to select a build profile using the environment. 58# 59# Other cargo profiles generally derive from these two profiles. 60 61# Disable incremental compilation to match release default. 62# 63# Set codegen-units to release default. 64# 65# Set split-debuginfo to default off for ELF platforms. 66PKG_CARGO_ENV += \ 67 CARGO_PROFILE_DEV_INCREMENTAL="false" \ 68 CARGO_PROFILE_RELEASE_INCREMENTAL="false" \ 69 CARGO_PROFILE_DEV_CODEGEN_UNITS="16" \ 70 CARGO_PROFILE_RELEASE_CODEGEN_UNITS="16" \ 71 CARGO_PROFILE_DEV_SPLIT_DEBUGINFO="off" \ 72 CARGO_PROFILE_RELEASE_SPLIT_DEBUGINFO="off" 73 74# Set the optimization level with the release default as fallback. 75ifeq ($(BR2_OPTIMIZE_0),y) 76PKG_CARGO_ENV += \ 77 CARGO_PROFILE_DEV_OPT_LEVEL="0" \ 78 CARGO_PROFILE_RELEASE_OPT_LEVEL="0" 79else ifeq ($(BR2_OPTIMIZE_1),y) 80PKG_CARGO_ENV += \ 81 CARGO_PROFILE_DEV_OPT_LEVEL="1" \ 82 CARGO_PROFILE_RELEASE_OPT_LEVEL="1" 83else ifeq ($(BR2_OPTIMIZE_2),y) 84PKG_CARGO_ENV += \ 85 CARGO_PROFILE_DEV_OPT_LEVEL="2" \ 86 CARGO_PROFILE_RELEASE_OPT_LEVEL="2" 87else ifeq ($(BR2_OPTIMIZE_3),y) 88PKG_CARGO_ENV += \ 89 CARGO_PROFILE_DEV_OPT_LEVEL="3" \ 90 CARGO_PROFILE_RELEASE_OPT_LEVEL="3" 91else ifeq ($(BR2_OPTIMIZE_G),y) 92PKG_CARGO_ENV += \ 93 CARGO_PROFILE_DEV_OPT_LEVEL="0" \ 94 CARGO_PROFILE_RELEASE_OPT_LEVEL="0" 95else ifeq ($(BR2_OPTIMIZE_S),y) 96PKG_CARGO_ENV += \ 97 CARGO_PROFILE_DEV_OPT_LEVEL="s" \ 98 CARGO_PROFILE_RELEASE_OPT_LEVEL="s" 99else ifeq ($(BR2_OPTIMIZE_FAST),y) 100PKG_CARGO_ENV += \ 101 CARGO_PROFILE_DEV_OPT_LEVEL="3" \ 102 CARGO_PROFILE_RELEASE_OPT_LEVEL="3" 103else 104PKG_CARGO_ENV += \ 105 CARGO_PROFILE_DEV_OPT_LEVEL="3" \ 106 CARGO_PROFILE_RELEASE_OPT_LEVEL="3" 107endif 108 109ifeq ($(BR2_ENABLE_LTO),y) 110PKG_CARGO_ENV += \ 111 CARGO_PROFILE_DEV_LTO="true" \ 112 CARGO_PROFILE_RELEASE_LTO="true" 113else 114PKG_CARGO_ENV += \ 115 CARGO_PROFILE_DEV_LTO="false" \ 116 CARGO_PROFILE_RELEASE_LTO="false" 117endif 118 119 120ifeq ($(BR2_ENABLE_DEBUG),y) 121ifeq ($(BR2_DEBUG_3),y) 122# full debug info 123PKG_CARGO_ENV += \ 124 CARGO_PROFILE_DEV_DEBUG="2" \ 125 CARGO_PROFILE_RELEASE_DEBUG="2" 126else 127# line tables only 128PKG_CARGO_ENV += \ 129 CARGO_PROFILE_DEV_DEBUG="1" \ 130 CARGO_PROFILE_RELEASE_DEBUG="1" 131endif 132else 133# no debug info 134PKG_CARGO_ENV += \ 135 CARGO_PROFILE_DEV_DEBUG="0" \ 136 CARGO_PROFILE_RELEASE_DEBUG="0" 137endif 138 139# Enabling debug-assertions enables the runtime debug_assert! macro. 140# 141# Enabling overflow-checks enables runtime panic on integer overflow. 142ifeq ($(BR2_ENABLE_RUNTIME_DEBUG),y) 143PKG_CARGO_ENV += \ 144 CARGO_PROFILE_DEV_DEBUG_ASSERTIONS="true" \ 145 CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="true" \ 146 CARGO_PROFILE_DEV_OVERFLOW_CHECKS="true" \ 147 CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="true" 148else 149PKG_CARGO_ENV += \ 150 CARGO_PROFILE_DEV_DEBUG_ASSERTIONS="false" \ 151 CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS="false" \ 152 CARGO_PROFILE_DEV_OVERFLOW_CHECKS="false" \ 153 CARGO_PROFILE_RELEASE_OVERFLOW_CHECKS="false" 154endif 155 156# 157# This is a workaround for https://github.com/rust-lang/compiler-builtins/issues/420 158# and should be removed when fixed upstream 159# 160ifeq ($(NORMALIZED_ARCH),arm) 161 PKG_CARGO_ENV += \ 162 CARGO_TARGET_$(call UPPERCASE,$(RUSTC_TARGET_NAME))_RUSTFLAGS="-Clink-arg=-Wl,--allow-multiple-definition" 163endif 164 165HOST_PKG_CARGO_ENV = \ 166 $(PKG_COMMON_CARGO_ENV) \ 167 RUSTFLAGS="$(addprefix -C link-args=,$(HOST_LDFLAGS))" 168 169################################################################################ 170# inner-cargo-package -- defines how the configuration, compilation and 171# installation of a cargo package should be done, implements a few hooks 172# to tune the build process for cargo specifities and calls the generic 173# package infrastructure to generate the necessary make targets 174# 175# argument 1 is the lowercase package name 176# argument 2 is the uppercase package name, including a HOST_ prefix 177# for host packages 178# argument 3 is the uppercase package name, without the HOST_ prefix 179# for host packages 180# argument 4 is the type (target or host) 181################################################################################ 182 183define inner-cargo-package 184 185# We need host-rustc to run cargo at download time (for vendoring), 186# and at build and install time. 187$(2)_DOWNLOAD_DEPENDENCIES += host-rustc 188$(2)_DEPENDENCIES += host-rustc 189 190$(2)_DOWNLOAD_POST_PROCESS = cargo 191$(2)_DL_ENV += CARGO_HOME=$$(BR_CARGO_HOME) 192 193# If building in a sub directory, use that to find the Cargo.toml 194ifneq ($$($(2)_SUBDIR),) 195$(2)_DL_ENV += BR_CARGO_MANIFEST_PATH=$$($(2)_SUBDIR)/Cargo.toml 196endif 197 198# Because we append vendored info, we can't rely on the values being empty 199# once we eventually get into the generic-package infra. So, we duplicate 200# the heuristics here 201ifndef $(2)_LICENSE 202 ifdef $(3)_LICENSE 203 $(2)_LICENSE = $$($(3)_LICENSE) 204 endif 205endif 206 207# Due to vendoring, it is pretty likely that not all licenses are 208# listed in <pkg>_LICENSE. If the license is unset, it is "unknown" 209# so adding unknowns to some unknown is still some other unkown, 210# so don't append the blurb in that case. 211ifneq ($$($(2)_LICENSE),) 212$(2)_LICENSE += , vendored dependencies licenses probably not listed 213endif 214 215# Note: in all the steps below, we "cd" into the build directory to 216# execute the "cargo" tool instead of passing $(@D)/Cargo.toml as the 217# manifest-path. Indeed while the latter seems to work, it in fact 218# breaks in subtle ways as the way cargo searches for its 219# configuration file is based (among other rules) on the current 220# directory. This means that if cargo is started outside of a package 221# directory, its configuration file will not be taken into account. 222# 223# Also, we pass: 224# * --offline to prevent cargo from downloading anything: all 225# dependencies should have been built by the download post 226# process logic 227# * --locked to force cargo to use the Cargo.lock file, which ensures 228# that a fixed set of dependency versions is used 229 230# 231# Build step. Only define it if not already defined by the package .mk 232# file. 233# 234ifndef $(2)_BUILD_CMDS 235ifeq ($(4),target) 236define $(2)_BUILD_CMDS 237 cd $$($$(PKG)_SRCDIR) && \ 238 $$(TARGET_MAKE_ENV) \ 239 $$(TARGET_CONFIGURE_OPTS) \ 240 $$(PKG_CARGO_ENV) \ 241 $$($(2)_CARGO_ENV) \ 242 cargo build \ 243 --offline \ 244 $$(if $$(BR2_ENABLE_DEBUG),,--release) \ 245 --manifest-path Cargo.toml \ 246 --locked \ 247 $$($(2)_CARGO_BUILD_OPTS) 248endef 249else # ifeq ($(4),target) 250define $(2)_BUILD_CMDS 251 cd $$($$(PKG)_SRCDIR) && \ 252 $$(HOST_MAKE_ENV) \ 253 $$(HOST_CONFIGURE_OPTS) \ 254 $$(HOST_PKG_CARGO_ENV) \ 255 $$($(2)_CARGO_ENV) \ 256 cargo build \ 257 --offline \ 258 --release \ 259 --manifest-path Cargo.toml \ 260 --locked \ 261 $$($(2)_CARGO_BUILD_OPTS) 262endef 263endif # ifeq ($(4),target) 264endif # ifndef $(2)_BUILD_CMDS 265 266# 267# Target installation step. Only define it if not already defined by 268# the package .mk file. 269# 270ifndef $(2)_INSTALL_TARGET_CMDS 271define $(2)_INSTALL_TARGET_CMDS 272 cd $$($$(PKG)_SRCDIR) && \ 273 $$(TARGET_MAKE_ENV) \ 274 $$(TARGET_CONFIGURE_OPTS) \ 275 $$(PKG_CARGO_ENV) \ 276 $$($(2)_CARGO_ENV) \ 277 cargo install \ 278 --offline \ 279 --root $$(TARGET_DIR)/usr/ \ 280 --bins \ 281 --path ./ \ 282 --force \ 283 --locked \ 284 -Z target-applies-to-host \ 285 $$($(2)_CARGO_INSTALL_OPTS) 286endef 287endif 288 289ifndef $(2)_INSTALL_CMDS 290define $(2)_INSTALL_CMDS 291 cd $$($$(PKG)_SRCDIR) && \ 292 $$(HOST_MAKE_ENV) \ 293 $$(HOST_CONFIGURE_OPTS) \ 294 $$(HOST_PKG_CARGO_ENV) \ 295 $$($(2)_CARGO_ENV) \ 296 cargo install \ 297 --offline \ 298 --root $$(HOST_DIR) \ 299 --bins \ 300 --path ./ \ 301 --force \ 302 --locked \ 303 $$($(2)_CARGO_INSTALL_OPTS) 304endef 305endif 306 307# Call the generic package infrastructure to generate the necessary 308# make targets 309$(call inner-generic-package,$(1),$(2),$(3),$(4)) 310 311endef 312 313################################################################################ 314# cargo-package -- the target generator macro for Cargo packages 315################################################################################ 316 317cargo-package = $(call inner-cargo-package,$(pkgname),$(call UPPERCASE,$(pkgname)),$(call UPPERCASE,$(pkgname)),target) 318host-cargo-package = $(call inner-cargo-package,host-$(pkgname),$(call UPPERCASE,host-$(pkgname)),$(call UPPERCASE,$(pkgname)),host) 319