makefiles: Add mechanism to build modules through Cargo

... and to dissect the static libraries into invidial .o files to link
them the same way we link C.
This commit is contained in:
chrysn 2021-04-02 19:01:19 +02:00
parent a2e1b92e1d
commit 732c369b7e
4 changed files with 82 additions and 0 deletions

View File

@ -216,6 +216,8 @@ ifeq (,$(TOOLCHAIN))
override TOOLCHAIN := gnu override TOOLCHAIN := gnu
endif endif
include $(RIOTMAKE)/cargo-settings.inc.mk
GLOBAL_GOALS += buildtest \ GLOBAL_GOALS += buildtest \
buildtest-indocker \ buildtest-indocker \
info-boards-features-blacklisted \ info-boards-features-blacklisted \
@ -1033,6 +1035,8 @@ endif
endif endif
include $(RIOTMAKE)/cargo-targets.inc.mk
# include RIOT_MAKEFILES_GLOBAL_POST configuration files # include RIOT_MAKEFILES_GLOBAL_POST configuration files
# allows setting user specific system wide configuration parsed after the body # allows setting user specific system wide configuration parsed after the body
# of $(RIOTBASE)/Makefile.include # of $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,43 @@
# Rust's own version of the target triple / quadruple.
#
# This does not have a sane default, and needs to be set in the architecture
# files.
# RUST_TARGET = ...
# Flags that need to be added to the RIOT_CFLAGS passed to cargo in order to
# make bindgen happy
CARGO_EXTRACFLAGS ?=
# Setting anything other than "debug" or "release" will necessitate additional
# -Z unstable-options as of 2021-03 nightlies.
CARGO_PROFILE ?= release
# The Rust version to use.
#
# As long as C2Rust and riot-wrappers require nightly, the only alternative
# here is to pick a particular nightly when something breaks.
#
# (Default is empty, because the riotbuild container picks a particular nightly
# and sets it as a default; users without a nightly default need to either
# override this here or in rustup)
CARGO_CHANNEL ?=
# Note that if we did not set this explicitly, CARGO_LIB would have to
# understand which value cargo uses in absence of CARGO_TARGET_DIR, which would
# be $(APPDIR)/target.
#
# For many cases, it would be beneficial to base this on BINDIRBASE rather than
# BINDIR, for that would allow different boards using the same CPU to share
# compiled code (unless they they build conditionally on environment variables,
# like riot-sys does). This is not done for two reasons:
#
# * Overriding BINDIR (like is done in Murdock) would not take effect,
# requiring additional overrides to enable out-of-tree building.
#
# * Switching back and forth between two boards of the same CPU requires
# riot-sys rebuilds. (On its own, this would be outweighed by the shared
# compilation of other modules).
CARGO_TARGET_DIR = $(BINDIR)/target
# The single Rust library to be built.
CARGO_LIB = $(CARGO_TARGET_DIR)/$(RUST_TARGET)/${CARGO_PROFILE}/lib$(APPLICATION_RUST_MODULE).a

View File

@ -0,0 +1,34 @@
CARGO_COMPILE_COMMANDS = $(BINDIR)/cargo-compile-commands.json
CARGO_COMPILE_COMMANDS_FLAGS = --clang
# This is duplicating the compile-commands rule because unlike in the use case
# when a $(RIOTBASE)/compile_commands.json is built, we *want* this to be
# per-board and per-application. (The large mechanisms are shared anyway).
#
# Changes relative to the compile-commands rule: This uses lazysponge to keep
# Rust from rebuilding, and uses a custom output file and
# CARGO_COMPILE_COMMAND_FLAGS.
$(CARGO_COMPILE_COMMANDS): $(BUILDDEPS)
$(Q)DIRS="$(DIRS)" APPLICATION_BLOBS="$(BLOBS)" \
"$(MAKE)" -C $(APPDIR) -f $(RIOTMAKE)/application.inc.mk compile-commands
$(Q)$(RIOTTOOLS)/compile_commands/compile_commands.py $(CARGO_COMPILE_COMMANDS_FLAGS) $(BINDIR) \
| $(LAZYSPONGE) $@
$(CARGO_LIB): $(RIOTBUILD_CONFIG_HEADER_C) $(BUILDDEPS) $(CARGO_COMPILE_COMMANDS) FORCE
$(Q)[ x"${RUST_TARGET}" != x"" ] || (echo "Error: No RUST_TARGET was set for this platform. (Set FEATURES_REQUIRED+=rust_target to catch this earlier)."; exit 1)
$(Q)CC= CFLAGS= CPPFLAGS= CXXFLAGS= RIOT_COMPILE_COMMANDS_JSON="$(CARGO_COMPILE_COMMANDS)" RIOT_USEMODULE="$(USEMODULE)" cargo $(patsubst +,,+${CARGO_CHANNEL}) build --target $(RUST_TARGET) `if [ x$(CARGO_PROFILE) = xrelease ]; then echo --release; else if [ x$(CARGO_PROFILE) '!=' xdebug ]; then echo "--profile $(CARGO_PROFILE)"; fi; fi` $(CARGO_OPTIONS)
$(APPLICATION_RUST_MODULE).module: $(CARGO_LIB) FORCE
$(Q)# Ensure no old object files persist. These would lead to duplicate
$(Q)# symbols, or worse, lingering behaivor of XFA entries.
$(Q)rm -rf $(BINDIR)/$(APPLICATION_RUST_MODULE)/
$(Q)mkdir -p $(BINDIR)/$(APPLICATION_RUST_MODULE)/
$(Q)# On cortex-m0 boards like airfy-beacon, the archive contains a
$(Q)# bin/thumbv6m-none-eabi.o file; the directory must be present for
$(Q)# ar to unpack it...
$(Q)mkdir -p $(BINDIR)/$(APPLICATION_RUST_MODULE)/bin/
$(Q)cd $(BINDIR)/$(APPLICATION_RUST_MODULE)/ && $(AR) x $<
$(Q)# ... and move them back if any exist, careful to err if anything is duplicate
$(Q)rmdir $(BINDIR)/$(APPLICATION_RUST_MODULE)/bin/ || (mv -n $(BINDIR)/$(APPLICATION_RUST_MODULE)/bin/* $(BINDIR)/$(APPLICATION_RUST_MODULE)/ && rmdir $(BINDIR)/$(APPLICATION_RUST_MODULE)/bin/)

View File

@ -42,6 +42,7 @@ export RIOTMAKE # Location of all supplemental Makefiles (such as t
export RIOTKCONFIG # Location of all supplemental Kconfig files export RIOTKCONFIG # Location of all supplemental Kconfig files
export BINDIRBASE # This is the folder where the application should be built in. For each BOARD a different subfolder is used. export BINDIRBASE # This is the folder where the application should be built in. For each BOARD a different subfolder is used.
export BINDIR # This is the folder where the application should be built in. export BINDIR # This is the folder where the application should be built in.
export CARGO_TARGET_DIR # This is the folder where Rust parts of the application should be built in.
export BUILD_DIR # This is the base folder to store common build files and artifacts, e.g. test results. export BUILD_DIR # This is the base folder to store common build files and artifacts, e.g. test results.
export APPDIR # The base folder containing the application export APPDIR # The base folder containing the application
export PKGDIRBASE # The base folder for building packages export PKGDIRBASE # The base folder for building packages