| # Force the Shell to be bash as some systems have strange default shells |
| SHELL := bash |
| |
| # Remove built-in rules and variables |
| # n.b. no-op for make --version < 4.0 |
| MAKEFLAGS += -r |
| MAKEFLAGS += -R |
| |
| # The absolute path of the directory containing this `Makefile.common` file. |
| MAKEFILE_COMMON_PATH := $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) |
| |
| # The absolute path of Tock's root directory. |
| # This is currently the parent directory of MAKEFILE_COMMON_PATH. |
| #TOCK_ROOT_DIRECTORY := $(dir $(abspath $(MAKEFILE_COMMON_PATH))) |
| TOCK_ROOT_DIRECTORY := /usr/local/google/home/aappleby/shodan/sw/tock/ |
| |
| |
| # Common defaults that specific boards can override, but likely do not need to. |
| TOOLCHAIN ?= llvm |
| CARGO ?= cargo |
| RUSTUP ?= rustup |
| |
| # Default location of target directory (relative to board makefile) |
| # passed to cargo --target_dir |
| TARGET_DIRECTORY ?= $(TOCK_ROOT_DIRECTORY)target/ |
| |
| # RUSTC_FLAGS allows boards to define board-specific options. |
| # This will hopefully move into Cargo.toml (or Cargo.toml.local) eventually. |
| # lld uses the page size to align program sections. It defaults to 4096 and this |
| # puts a gap between before the .relocate section. `zmax-page-size=512` tells |
| # lld the actual page size so it doesn't have to be conservative. |
| RUSTC_FLAGS ?= \ |
| -C link-arg=-Tlayout.ld \ |
| -C linker=rust-lld \ |
| -C linker-flavor=ld.lld \ |
| -C relocation-model=dynamic-no-pic \ |
| -C link-arg=-zmax-page-size=512 \ |
| -C link-arg=-icf=all \ |
| |
| # RISC-V-specific flags. |
| ifneq ($(findstring riscv32i, $(TARGET)),) |
| # NOTE: This flag causes kernel panics on some ARM cores. Since the |
| # size benefit is almost exclusively for RISC-V, we only apply it for |
| # those targets. |
| RUSTC_FLAGS += -C force-frame-pointers=no |
| endif |
| |
| # RUSTC_FLAGS_TOCK by default extends RUSTC_FLAGS with options |
| # that are global to all Tock boards. |
| # |
| # We use `remap-path-prefix` to remove user-specific filepath strings for error |
| # reporting from appearing in the generated binary. |
| RUSTC_FLAGS_TOCK ?= \ |
| $(RUSTC_FLAGS) \ |
| --remap-path-prefix=$(TOCK_ROOT_DIRECTORY)= \ |
| |
| # Disallow warnings for continuous integration builds. Disallowing them here |
| # ensures that warnings during testing won't prevent compilation from succeeding. |
| ifeq ($(CI),true) |
| RUSTC_FLAGS_TOCK += -D warnings |
| endif |
| |
| # The following flags should only be passed to the board's binary crate, but |
| # not to any of its dependencies (the kernel, capsules, chips, etc.). The |
| # dependencies wouldn't use it, but because the link path is different for each |
| # board, Cargo wouldn't be able to cache builds of the dependencies. |
| # |
| # Indeed, as far as Cargo is concerned, building the kernel with |
| # `-C link-arg=-L/tock/boards/imix` is different than building the kernel with |
| # `-C link-arg=-L/tock/boards/hail`, so Cargo would have to rebuild the kernel |
| # for each board instead of caching it per board (even if in reality the same |
| # kernel is built because the link-arg isn't used by the kernel). |
| # |
| # Ultimately, this should move to the Cargo.toml, for example when |
| # https://github.com/rust-lang/cargo/pull/7811 is merged into Cargo. |
| # |
| # The difference between `RUSTC_FLAGS_TOCK` and `RUSTC_FLAGS_FOR_BIN` is that |
| # the former is forwarded to all the dependencies (being passed to cargo via |
| # the `RUSTFLAGS` environment variable), whereas the latter is only applied to |
| # the final binary crate (being passed as parameter to `cargo rustc`). |
| RUSTC_FLAGS_FOR_BIN ?= \ |
| -C link-arg=-L$(abspath .) \ |
| |
| # http://stackoverflow.com/questions/10858261/abort-makefile-if-variable-not-set |
| # Check that given variables are set and all have non-empty values, print an |
| # error otherwise. |
| check_defined = $(strip $(foreach 1,$1,$(if $(value $1),,$(error Undefined variable "$1")))) |
| |
| # Check that we know the basics of what we are compiling for. |
| # `PLATFORM`: The name of the board that the kernel is being compiled for. |
| # `TARGET` : The Rust target architecture the kernel is being compiled for. |
| $(call check_defined, PLATFORM) |
| $(call check_defined, TARGET) |
| |
| # Location of target-specific build |
| TARGET_PATH := $(TARGET_DIRECTORY)$(TARGET) |
| |
| # If environment variable V is non-empty, be verbose. |
| ifneq ($(V),) |
| Q = |
| VERBOSE = --verbose |
| else |
| Q = @ |
| VERBOSE = |
| endif |
| |
| # Ask git what version of the Tock kernel we are compiling, so we can include |
| # this within the binary. If Tock is not within a git repo then we fallback to |
| # a set string which should be updated with every release. |
| export TOCK_KERNEL_VERSION := $(shell git describe --tags --always 2> /dev/null || echo "1.4+") |
| |
| # Validate that rustup is new enough. |
| MINIMUM_RUSTUP_VERSION := 1.11.0 |
| RUSTUP_VERSION := $(strip $(word 2, $(shell $(RUSTUP) --version))) |
| ifeq ($(shell $(TOCK_ROOT_DIRECTORY)tools/semver.sh $(RUSTUP_VERSION) \< $(MINIMUM_RUSTUP_VERSION)), true) |
| $(warning Required tool `$(RUSTUP)` is out-of-date.) |
| $(warning Running `$(RUSTUP) update` in 3 seconds (ctrl-c to cancel)) |
| $(shell sleep 3s) |
| DUMMY := $(shell $(RUSTUP) update) |
| endif |
| |
| # Verify that various required Rust components are installed. All of these steps |
| # only have to be done once per Rust version, but will take some time when |
| # compiling for the first time. |
| LLVM_TOOLS_INSTALLED := $(shell $(RUSTUP) component list | grep 'llvm-tools-preview.*(installed)' > /dev/null; echo $$?) |
| ifeq ($(LLVM_TOOLS_INSTALLED),1) |
| $(shell $(RUSTUP) component add llvm-tools-preview) |
| endif |
| ifneq ($(shell $(RUSTUP) component list | grep rust-src),rust-src (installed)) |
| $(shell $(RUSTUP) component add rust-src) |
| endif |
| ifneq ($(shell $(RUSTUP) target list | grep "$(TARGET) (installed)"),$(TARGET) (installed)) |
| $(shell $(RUSTUP) target add $(TARGET)) |
| endif |
| |
| # If the user is using the standard toolchain we need to get the full path. |
| # rustup should take care of this for us by putting in a proxy in .cargo/bin, |
| # but until that is setup we workaround it. |
| ifeq ($(TOOLCHAIN),llvm) |
| TOOLCHAIN = "$(shell dirname $(shell find `rustc --print sysroot` -name llvm-size))/llvm" |
| endif |
| |
| # Set variables of the key tools we need to compile a Tock kernel. |
| SIZE ?= $(TOOLCHAIN)-size |
| OBJCOPY ?= $(TOOLCHAIN)-objcopy |
| OBJDUMP ?= $(TOOLCHAIN)-objdump |
| |
| # Set additional flags to produce binary from .elf. |
| # * --strip-sections prevents enormous binaries when SRAM is below flash. |
| # * --remove-section .apps prevents the .apps section from being included in the |
| # kernel binary file. This section is a placeholder for optionally including |
| # application binaries, and only needs to exist in the .elf. By removing it, |
| # we prevent the kernel binary from overwriting applications. |
| OBJCOPY_FLAGS ?= --strip-sections -S --remove-section .apps |
| # This make variable allows board-specific Makefiles to pass down options to |
| # the Cargo build command. For example, in boards/<custom_board>/Makefile: |
| # `CARGO_FLAGS += --features=foo` would pass feature `foo` to the top level |
| # Cargo.toml. |
| CARGO_FLAGS ?= |
| # Add default flags to cargo. Boards can add additional options in CARGO_FLAGS |
| CARGO_FLAGS_TOCK ?= $(VERBOSE) --target=$(TARGET) --package $(PLATFORM) --target-dir=$(TARGET_DIRECTORY) $(CARGO_FLAGS) |
| # Set the default flags we need for objdump to get a .lst file. |
| OBJDUMP_FLAGS ?= --disassemble-all --source --section-headers --demangle |
| # Set default flags for size |
| SIZE_FLAGS ?= |
| |
| # Need an extra flag for OBJDUMP if we are on a thumb platform. |
| ifneq (,$(findstring thumb,$(TARGET))) |
| OBJDUMP_FLAGS += --arch-name=thumb |
| endif |
| |
| # Check whether the system already has a sha256sum application |
| # present, if not use the custom shipped one |
| ifeq (, $(shell sha256sum --version 2>/dev/null)) |
| # No system sha256sum available |
| SHA256SUM := $(CARGO) run --manifest-path $(TOCK_ROOT_DIRECTORY)tools/sha256sum/Cargo.toml -- 2>/dev/null |
| else |
| # Use system sha256sum |
| SHA256SUM := sha256sum |
| endif |
| |
| # Dump configuration for verbose builds |
| ifneq ($(V),) |
| $(info ) |
| $(info *******************************************************) |
| $(info TOCK KERNEL BUILD SYSTEM -- VERBOSE BUILD CONFIGURATION) |
| $(info *******************************************************) |
| $(info MAKEFILE_COMMON_PATH = $(MAKEFILE_COMMON_PATH)) |
| $(info TOCK_ROOT_DIRECTORY = $(TOCK_ROOT_DIRECTORY)) |
| $(info TARGET_DIRECTORY = $(TARGET_DIRECTORY)) |
| $(info ) |
| $(info PLATFORM = $(PLATFORM)) |
| $(info TARGET = $(TARGET)) |
| $(info TOCK_KERNEL_VERSION = $(TOCK_KERNEL_VERSION)) |
| $(info RUSTC_FLAGS = $(RUSTC_FLAGS)) |
| $(info RUSTC_FLAGS_TOCK = $(RUSTC_FLAGS_TOCK)) |
| $(info MAKEFLAGS = $(MAKEFLAGS)) |
| $(info OBJDUMP_FLAGS = $(OBJDUMP_FLAGS)) |
| $(info OBJCOPY_FLAGS = $(OBJCOPY_FLAGS)) |
| $(info CARGO_FLAGS = $(CARGO_FLAGS)) |
| $(info CARGO_FLAGS_TOCK = $(CARGO_FLAGS_TOCK)) |
| $(info SIZE_FLAGS = $(SIZE_FLAGS)) |
| $(info ) |
| $(info TOOLCHAIN = $(TOOLCHAIN)) |
| $(info SIZE = $(SIZE)) |
| $(info OBJCOPY = $(OBJCOPY)) |
| $(info OBJDUMP = $(OBJDUMP)) |
| $(info CARGO = $(CARGO)) |
| $(info RUSTUP = $(RUSTUP)) |
| $(info SHA256SUM = $(SHA256SUM)) |
| $(info ) |
| $(info cargo --version = $(shell $(CARGO) --version)) |
| $(info rustc --version = $(shell rustc --version)) |
| $(info rustup --version = $(shell $(RUSTUP) --version)) |
| $(info *******************************************************) |
| $(info ) |
| endif |
| |
| .PRECIOUS: %.elf |
| # Support rules |
| |
| # User-facing targets |
| .PHONY: all |
| all: release |
| |
| # `make check` runs the Rust compiler but does not actually output the final |
| # binary. This makes checking for Rust errors much faster. |
| .PHONY: check |
| check: |
| $(Q)$(CARGO) check $(VERBOSE) $(CARGO_FLAGS_TOCK) |
| |
| |
| .PHONY: clean |
| clean:: |
| $(Q)$(CARGO) clean $(VERBOSE) --target-dir=$(TARGET_DIRECTORY) |
| |
| .PHONY: release |
| release: $(TARGET_PATH)/release/$(PLATFORM).bin |
| |
| .PHONY: debug |
| debug: $(TARGET_PATH)/debug/$(PLATFORM).bin |
| |
| .PHONY: debug-lst |
| debug-lst: $(TARGET_PATH)/debug/$(PLATFORM).lst |
| |
| .PHONY: doc |
| doc: | target |
| @# This mess is all to work around rustdoc giving no way to return an |
| @# error if there are warnings. This effectively simulates that. |
| $(Q)RUSTDOCFLAGS='-Z unstable-options --document-hidden-items -D warnings' $(CARGO) --color=always doc $(VERBOSE) --release --package $(PLATFORM) --target-dir=$(TARGET_DIRECTORY) 2>&1 | tee /dev/tty | grep -q warning && (echo "Warnings detected during doc build" && if [[ $$CI == "true" ]]; then echo "Erroring due to CI context" && exit 33; fi) || if [ $$? -eq 33 ]; then exit 1; fi |
| |
| |
| .PHONY: lst |
| lst: $(TARGET_PATH)/release/$(PLATFORM).lst |
| |
| # Helper rule for showing the TARGET used by this board. Useful when building |
| # the documentation for all boards. |
| .PHONY: show-target |
| show-target: |
| $(info $(TARGET)) |
| |
| # Support rules |
| |
| target: |
| @mkdir -p $(TARGET_PATH) |
| |
| # Cargo outputs an elf file (just without a file extension) |
| %.elf: % |
| $(Q)cp $< $@ |
| |
| |
| %.bin: %.elf |
| $(Q)$(OBJCOPY) --output-target=binary $(OBJCOPY_FLAGS) $< $@ |
| $(Q)$(SHA256SUM) $@ |
| |
| %.lst: %.elf |
| $(Q)$(OBJDUMP) $(OBJDUMP_FLAGS) $< > $@ |
| |
| |
| $(TOCK_ROOT_DIRECTORY)tools/sha256sum/target/debug/sha256sum: |
| $(Q)$(CARGO) build $(VERBOSE) --manifest-path $(TOCK_ROOT_DIRECTORY)tools/sha256sum/Cargo.toml |
| |
| |
| # Cargo-drivers |
| # We want to always invoke cargo (yay nested build systems), so these need to |
| # be phony, which means they can't be pattern rules. |
| |
| .PHONY: $(TARGET_PATH)/release/$(PLATFORM) |
| $(TARGET_PATH)/release/$(PLATFORM): |
| $(Q)RUSTFLAGS="$(RUSTC_FLAGS_TOCK)" $(CARGO) rustc $(CARGO_FLAGS_TOCK) --bin $(PLATFORM) --release -- $(RUSTC_FLAGS_FOR_BIN) |
| $(Q)$(SIZE) $(SIZE_FLAGS) $@ |
| |
| .PHONY: $(TARGET_PATH)/debug/$(PLATFORM) |
| $(TARGET_PATH)/debug/$(PLATFORM): |
| $(Q)RUSTFLAGS="$(RUSTC_FLAGS_TOCK)" $(CARGO) rustc $(CARGO_FLAGS_TOCK) --bin $(PLATFORM) -- $(RUSTC_FLAGS_FOR_BIN) |
| $(Q)$(SIZE) $(SIZE_FLAGS) $@ |