Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ rootfs:
curl -f -L $(ROOTFS_URL)/$(ROOTFS_IMG).xz -O; \
xz -d $(ROOTFS_IMG).xz; \
fi
@cp $(ROOTFS_IMG) arceos/disk.img
@cp $(ROOTFS_IMG) make/disk.img

img:
@echo -e "\033[33mWARN: The 'img' target is deprecated. Please use 'rootfs' instead.\033[0m"
@$(MAKE) --no-print-directory rootfs

defconfig justrun clean:
@make -C arceos $@
@$(MAKE) -C make $@

build run debug disasm: defconfig
@make -C arceos $@
@$(MAKE) -C make $@

# Aliases
rv:
Expand Down
208 changes: 208 additions & 0 deletions make/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
# Available arguments:
# * General options:
# - `ARCH`: Target architecture: x86_64, riscv64, aarch64, loongarch64
# - `MYPLAT`: Package name of the target platform crate.
# - `PLAT_CONFIG`: Path to the platform configuration file.
# - `SMP`: Override maximum CPU number specified in the platform config. For
# statically configured platforms, this is also the number of CPUs to boot
# and for platforms with runtime CPU detection, this is the upper limit of
# CPUs.
# - `MODE`: Build mode: release, debug
# - `LOG:` Logging level: warn, error, info, debug, trace
# - `V`: Verbose level: (empty), 1, 2
# - `TARGET_DIR`: Artifact output directory (cargo target directory)
# - `EXTRA_CONFIG`: Extra config specification file
# - `OUT_CONFIG`: Final config file that takes effect
# - `UIMAGE`: To generate U-Boot image
# - `LD_SCRIPT`: Use a custom linker script file.
# * App options:
# - `A` or `APP`: Path to the application
# - `FEATURES`: Features os ArceOS modules to be enabled.
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doc comment typo: “Features os ArceOS modules” should be “Features of ArceOS modules”.

Suggested change
# - `FEATURES`: Features os ArceOS modules to be enabled.
# - `FEATURES`: Features of ArceOS modules to be enabled.

Copilot uses AI. Check for mistakes.
# - `APP_FEATURES`: Features of (rust) apps to be enabled.
# * QEMU options:
# - `BLK`: Enable storage devices (virtio-blk)
# - `NET`: Enable network devices (virtio-net)
# - `GRAPHIC`: Enable display devices and graphic output (virtio-gpu)
# - `BUS`: Device bus type: mmio, pci
# - `MEM`: Memory size (default is 128M)
# - `DISK_IMG`: Path to the virtual disk image
# - `ACCEL`: Enable hardware acceleration (KVM on linux)
# - `QEMU_LOG`: Enable QEMU logging (log file is "qemu.log")
# - `NET_DUMP`: Enable network packet dump (log file is "netdump.pcap")
# - `NET_DEV`: QEMU netdev backend types: user, tap, bridge
# - `VFIO_PCI`: PCI device address in the format "bus:dev.func" to passthrough
# - `VHOST`: Enable vhost-net for tap backend (only for `NET_DEV=tap`)
# * Network options:
# - `IP`: ArceOS IPv4 address (default is 10.0.2.15 for QEMU user netdev)
# - `GW`: Gateway IPv4 address (default is 10.0.2.2 for QEMU user netdev)

# General options
ARCH ?= x86_64
MYPLAT ?=
PLAT_CONFIG ?=
SMP ?=
MODE ?= release
LOG ?= warn
V ?=
DWARF ?=
LTO ?=
TARGET_DIR ?= $(PWD)/target
EXTRA_CONFIG ?=
OUT_CONFIG ?= $(PWD)/.axconfig.toml
UIMAGE ?= n

# App options
A ?= examples/helloworld
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default app path is set to examples/helloworld, but that path doesn’t exist in this repository. As a result, running make -C make with defaults fails immediately; consider defaulting APP to an existing crate (e.g. . or kernel) or making APP mandatory with a clearer error message.

Suggested change
A ?= examples/helloworld
A ?= .

Copilot uses AI. Check for mistakes.
APP ?= $(A)
FEATURES ?=
APP_FEATURES ?=
NO_AXSTD ?= n

# QEMU options
BLK ?= n
NET ?= n
GRAPHIC ?= n
INPUT ?= n
VSOCK ?= n
BUS ?= pci
MEM ?=
ACCEL ?=
ICOUNT ?= n
QEMU_ARGS ?=

DISK_IMG ?= disk.img
QEMU_LOG ?= n
NET_DUMP ?= n
NET_DEV ?= user
VFIO_PCI ?=
VHOST ?= n

# Network options
IP ?= 10.0.2.15
GW ?= 10.0.2.2

# App type
ifeq ($(wildcard $(APP)),)
$(error Application path "$(APP)" is not valid)
endif

ifneq ($(wildcard $(APP)/Cargo.toml),)
APP_TYPE := rust
AX_LIB ?= axstd
else
APP_TYPE := c
AX_LIB ?= axlibc
endif

.DEFAULT_GOAL := all

ifneq ($(filter $(or $(MAKECMDGOALS), $(.DEFAULT_GOAL)), all build disasm run justrun debug defconfig oldconfig),)
# Install dependencies
include deps.mk
# Platform resolving
include platform.mk
# Configuration generation
include config.mk
# Feature parsing
include features.mk
endif

# Target
ifeq ($(ARCH), x86_64)
TARGET := x86_64-unknown-none
else ifeq ($(ARCH), aarch64)
TARGET := aarch64-unknown-none-softfloat
else ifeq ($(ARCH), riscv64)
TARGET := riscv64gc-unknown-none-elf
else ifeq ($(ARCH), loongarch64)
TARGET := loongarch64-unknown-none-softfloat
else
$(error "ARCH" must be one of "x86_64", "riscv64", "aarch64" or "loongarch64")
endif

export AX_ARCH=$(ARCH)
export AX_PLATFORM=$(PLAT_NAME)
export AX_MODE=$(MODE)
export AX_LOG=$(LOG)
export AX_TARGET=$(TARGET)
export AX_IP=$(IP)
export AX_GW=$(GW)

ifneq ($(filter $(MAKECMDGOALS),unittest unittest_no_fail_fast clippy doc doc_check_missing),)
# When running unit tests or other tests unrelated to a specific platform,
# set `AX_CONFIG_PATH` to empty for dummy config
unexport AX_CONFIG_PATH
else
export AX_CONFIG_PATH=$(OUT_CONFIG)
endif

# Binutils
CROSS_COMPILE ?= $(ARCH)-linux-musl-
CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
RANLIB := $(CROSS_COMPILE)ranlib
LD := rust-lld -flavor gnu

OBJDUMP ?= rust-objdump -d --print-imm-hex --x86-asm-syntax=intel
OBJCOPY ?= rust-objcopy --binary-architecture=$(ARCH)
GDB ?= gdb

# Paths
OUT_DIR ?= $(APP)
LD_SCRIPT ?= $(TARGET_DIR)/$(TARGET)/$(MODE)/linker_$(PLAT_NAME).lds

APP_NAME := $(shell basename $(APP))
OUT_ELF := $(OUT_DIR)/$(APP_NAME)_$(PLAT_NAME).elf
OUT_BIN := $(patsubst %.elf,%.bin,$(OUT_ELF))
OUT_UIMG := $(patsubst %.elf,%.uimg,$(OUT_ELF))
ifeq ($(UIMAGE), y)
FINAL_IMG := $(OUT_UIMG)
else
FINAL_IMG := $(OUT_BIN)
endif

all: build

include utils.mk
include build.mk
include qemu.mk

defconfig:
$(call defconfig)

oldconfig:
$(call oldconfig)

build: $(OUT_DIR) $(FINAL_IMG)

disasm:
$(OBJDUMP) $(OUT_ELF) | less

run: build justrun

justrun:
$(call run_qemu)

debug: build
$(call run_qemu_debug) &
$(GDB) $(OUT_ELF) \
-ex 'target remote localhost:1234' \
-ex 'b __axplat_main' \
-ex 'continue' \
-ex 'disp /16i $$pc'

disk_img:
ifneq ($(wildcard $(DISK_IMG)),)
@printf "$(YELLOW_C)warning$(END_C): disk image \"$(DISK_IMG)\" already exists!\n"
else
$(call make_disk_image,fat32,$(DISK_IMG))
endif

clean: clean_c
rm -rf $(APP)/*.bin $(APP)/*.elf $(OUT_CONFIG)
Comment on lines +201 to +202
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clean depends on clean_c, but no clean_c target/rule is provided in the current make system. This makes make clean fail with “No rule to make target 'clean_c'”; either define clean_c (likely in the missing build_c.mk) or remove it from the prerequisite list.

Copilot uses AI. Check for mistakes.
cargo clean

.PHONY: all defconfig oldconfig \
build disasm run justrun debug \
clippy doc doc_check_missing fmt fmt_c unittest unittest_no_fail_fast \
disk_img clean
86 changes: 86 additions & 0 deletions make/build.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Main building script

include cargo.mk

ifeq ($(APP_TYPE), c)
include build_c.mk
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

build.mk includes build_c.mk when APP_TYPE is c, but make/build_c.mk is not present in this PR/repo. Any C app build will fail at include time; either add build_c.mk (and its targets) or remove/guard the C path until it’s supported.

Suggested change
include build_c.mk
$(error C app builds are not supported in this repository (missing make/build_c.mk))

Copilot uses AI. Check for mistakes.
else
rust_package := $(shell cat $(APP)/Cargo.toml | sed -n 's/^name = "\([a-z0-9A-Z_\-]*\)"/\1/p')
rust_elf := $(TARGET_DIR)/$(TARGET)/$(MODE)/$(rust_package)
endif

ifneq ($(filter $(MAKECMDGOALS),doc doc_check_missing),)
# run `make doc`
$(if $(V), $(info RUSTFLAGS: "$(RUSTFLAGS)") $(info RUSTDOCFLAGS: "$(RUSTDOCFLAGS)"))
export RUSTFLAGS
export RUSTDOCFLAGS
else ifneq ($(filter $(MAKECMDGOALS),unittest unittest_no_fail_fast),)
# run `make unittest`
$(if $(V), $(info RUSTFLAGS: "$(RUSTFLAGS)"))
export RUSTFLAGS
else ifneq ($(filter $(or $(MAKECMDGOALS), $(.DEFAULT_GOAL)), all build run justrun debug),)
# run `make build` and other above goals
ifneq ($(V),)
$(info APP: "$(APP)")
$(info APP_TYPE: "$(APP_TYPE)")
$(info FEATURES: "$(FEATURES)")
$(info PLAT_CONFIG: "$(PLAT_CONFIG)")
$(info arceos features: "$(AX_FEAT)")
$(info lib features: "$(LIB_FEAT)")
$(info app features: "$(APP_FEAT)")
endif
ifeq ($(APP_TYPE), c)
$(if $(V), $(info CFLAGS: "$(CFLAGS)") $(info LDFLAGS: "$(LDFLAGS)"))
else ifeq ($(APP_TYPE), rust)
RUSTFLAGS += $(RUSTFLAGS_LINK_ARGS)
endif
ifeq ($(DWARF), y)
RUSTFLAGS += -C force-frame-pointers -C debuginfo=2 -C strip=none
endif
$(if $(V), $(info RUSTFLAGS: "$(RUSTFLAGS)"))
export RUSTFLAGS
ifeq ($(LTO), y)
export CARGO_PROFILE_RELEASE_LTO=true
export CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1
endif
endif

_cargo_build: oldconfig
@printf " $(GREEN_C)Building$(END_C) App: $(APP_NAME), Arch: $(ARCH), Platform: $(PLAT_NAME), App type: $(APP_TYPE)\n"
ifeq ($(APP_TYPE), rust)
$(call cargo_build,$(APP),$(AX_FEAT) $(LIB_FEAT) $(APP_FEAT))
@cp $(rust_elf) $(OUT_ELF)
else ifeq ($(APP_TYPE), c)
$(call cargo_build,ulib/axlibc,$(AX_FEAT) $(LIB_FEAT))
endif

$(OUT_DIR):
$(call run_cmd,mkdir,-p $@)

_dwarf: $(OUT_ELF)
ifeq ($(DWARF), y)
$(call run_cmd,./dwarf.sh,$(OUT_ELF) $(OBJCOPY))
endif

$(OUT_BIN): _cargo_build $(OUT_ELF) _dwarf
$(call run_cmd,$(OBJCOPY),$(OUT_ELF) --strip-all -O binary $@)
@if [ ! -s $(OUT_BIN) ]; then \
echo 'Empty kernel image "$(notdir $(FINAL_IMG))" is built, please check your build configuration'; \
exit 1; \
fi

ifeq ($(ARCH), aarch64)
uimg_arch := arm64
else ifeq ($(ARCH), riscv64)
uimg_arch := riscv
else
uimg_arch := $(ARCH)
endif

$(OUT_UIMG): $(OUT_BIN)
$(call run_cmd,mkimage,\
-A $(uimg_arch) -O linux -T kernel -C none \
-a $(subst _,,$(shell axconfig-gen "$(OUT_CONFIG)" -r plat.kernel-base-paddr)) \
-d $(OUT_BIN) $@)

.PHONY: _cargo_build _dwarf
29 changes: 29 additions & 0 deletions make/cargo.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Cargo features and build args

ifeq ($(V),1)
verbose := -v
else ifeq ($(V),2)
verbose := -vv
else
verbose :=
endif

build_args-release := --release

build_args := \
-Z unstable-options \
--target $(TARGET) \
--target-dir $(TARGET_DIR) \
$(build_args-$(MODE)) \
$(verbose)

RUSTFLAGS_LINK_ARGS := -C link-arg=-T$(LD_SCRIPT) -C link-arg=-no-pie -C link-arg=-znostart-stop-gc
RUSTDOCFLAGS := -Z unstable-options --enable-index-page -D rustdoc::broken_intra_doc_links

ifeq ($(MAKECMDGOALS), doc_check_missing)
RUSTDOCFLAGS += -D missing-docs
endif

define cargo_build
$(call run_cmd,cargo -C $(1) build,$(build_args) --features "$(strip $(2))")
endef
39 changes: 39 additions & 0 deletions make/config.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Config generation

config_args := \
defconfig.toml $(PLAT_CONFIG) $(EXTRA_CONFIG) \
-w 'arch="$(ARCH)"' \
-w 'platform="$(PLAT_NAME)"' \
-o "$(OUT_CONFIG)"

ifneq ($(MEM),)
config_args += -w 'plat.phys-memory-size=$(shell ./strtosz.py $(MEM))'
Copy link

Copilot AI Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$(shell ./strtosz.py $(MEM)) runs inside $(shell ...), which ignores the command’s exit status. If parsing fails, Make will keep going with an empty/partial value (and Python will emit a stack trace). Consider validating MEM in Make (and using $(error ...) on failure) or reworking this so a parsing failure reliably stops the build with a concise message.

Suggested change
config_args += -w 'plat.phys-memory-size=$(shell ./strtosz.py $(MEM))'
MEM_PARSED := $(shell ./strtosz.py $(MEM))
ifeq ($(MEM_PARSED),)
$(error "Failed to parse MEM='$(MEM)'. Please specify a valid memory size (e.g. 1G, 512M).")
endif
config_args += -w 'plat.phys-memory-size=$(MEM_PARSED)'

Copilot uses AI. Check for mistakes.
else
MEM := $(shell axconfig-gen $(PLAT_CONFIG) -r plat.phys-memory-size 2>/dev/null | tr -d _ | xargs printf "%dB")
endif

ifneq ($(SMP),)
config_args += -w 'plat.max-cpu-num=$(SMP)'
else
SMP := $(shell axconfig-gen $(PLAT_CONFIG) -r plat.max-cpu-num 2>/dev/null)
ifeq ($(SMP),)
$(error "`plat.max-cpu-num` is not defined in the platform configuration file, \
this option must be specified even for platforms with runtime CPU detection.")
endif
endif

define defconfig
$(call run_cmd,axconfig-gen,$(config_args))
endef

ifeq ($(wildcard $(OUT_CONFIG)),)
define oldconfig
$(call defconfig)
endef
else
define oldconfig
$(if $(filter "$(PLAT_NAME)",$(shell axconfig-gen "$(OUT_CONFIG)" -r platform)),\
$(call run_cmd,axconfig-gen,$(config_args) -c "$(OUT_CONFIG)"),\
$(error "ARCH" or "MYPLAT" has been changed, please run "make defconfig" again))
endef
endif
6 changes: 6 additions & 0 deletions make/defconfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Stack size of each task.
task-stack-size = 0x40000 # uint

# Number of timer ticks per second (Hz). A timer tick may contain several timer
# interrupts.
ticks-per-sec = 100 # uint
Loading