aad79adab7
This commit adds a new tool called mpy_ld.py which is essentially a linker that builds .mpy files directly from .o files. A new header file (dynruntime.h) and makefile fragment (dynruntime.mk) are also included which allow building .mpy files from C source code. Such .mpy files can then be dynamically imported as though they were a normal Python module, even though they are implemented in C. Converting .o files directly (rather than pre-linked .elf files) allows the resulting .mpy to be more efficient because it has more control over the relocations; for example it can skip PLT indirection. Doing it this way also allows supporting more architectures, such as Xtensa which has specific needs for position-independent code and the GOT. The tool supports targets of x86, x86-64, ARM Thumb and Xtensa (windowed and non-windowed). BSS, text and rodata sections are supported, with relocations to all internal sections and symbols, as well as relocations to some external symbols (defined by dynruntime.h), and linking of qstrs.
135 lines
3.0 KiB
Makefile
135 lines
3.0 KiB
Makefile
# Makefile fragment for generating native .mpy files from C source
|
|
# MPY_DIR must be set to the top of the MicroPython source tree
|
|
|
|
BUILD ?= build
|
|
|
|
ECHO = @echo
|
|
RM = /bin/rm
|
|
MKDIR = /bin/mkdir
|
|
PYTHON = python3
|
|
MPY_CROSS = $(MPY_DIR)/mpy-cross/mpy-cross
|
|
MPY_TOOL = $(PYTHON) $(MPY_DIR)/tools/mpy-tool.py
|
|
MPY_LD = $(PYTHON) $(MPY_DIR)/tools/mpy_ld.py
|
|
|
|
Q = @
|
|
ifeq ("$(origin V)", "command line")
|
|
ifeq ($(V),1)
|
|
Q =
|
|
MPY_LD += '-vvv'
|
|
endif
|
|
endif
|
|
|
|
ARCH_UPPER = $(shell echo $(ARCH) | tr '[:lower:]' '[:upper:]')
|
|
CONFIG_H = $(BUILD)/$(MOD).config.h
|
|
|
|
CFLAGS += -I. -I$(MPY_DIR)
|
|
CFLAGS += -std=c99
|
|
CFLAGS += -Os
|
|
CFLAGS += -Wall -Werror -DNDEBUG
|
|
CFLAGS += -DNO_QSTR
|
|
CFLAGS += -DMP_CONFIGFILE='<$(CONFIG_H)>'
|
|
CFLAGS += -fpic -fno-common
|
|
CFLAGS += -U _FORTIFY_SOURCE # prevent use of __*_chk libc functions
|
|
#CFLAGS += -fdata-sections -ffunction-sections
|
|
|
|
MPY_CROSS_FLAGS += -march=$(ARCH)
|
|
|
|
SRC_O += $(addprefix $(BUILD)/, $(patsubst %.c,%.o,$(filter %.c,$(SRC))))
|
|
SRC_MPY += $(addprefix $(BUILD)/, $(patsubst %.py,%.mpy,$(filter %.py,$(SRC))))
|
|
|
|
################################################################################
|
|
# Architecture configuration
|
|
|
|
ifeq ($(ARCH),x86)
|
|
|
|
# x86
|
|
CROSS =
|
|
CFLAGS += -m32 -fno-stack-protector
|
|
MPY_CROSS_FLAGS += -mcache-lookup-bc
|
|
|
|
else ifeq ($(ARCH),x64)
|
|
|
|
# x64
|
|
CROSS =
|
|
CFLAGS += -fno-stack-protector
|
|
MPY_CROSS_FLAGS += -mcache-lookup-bc
|
|
|
|
else ifeq ($(ARCH),armv7m)
|
|
|
|
# thumb
|
|
CROSS = arm-none-eabi-
|
|
CFLAGS += -mthumb -mcpu=cortex-m3
|
|
|
|
else ifeq ($(ARCH),armv7emsp)
|
|
|
|
# thumb
|
|
CROSS = arm-none-eabi-
|
|
CFLAGS += -mthumb -mcpu=cortex-m4
|
|
CFLAGS += -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
|
|
|
else ifeq ($(ARCH),armv7emdp)
|
|
|
|
# thumb
|
|
CROSS = arm-none-eabi-
|
|
CFLAGS += -mthumb -mcpu=cortex-m7
|
|
CFLAGS += -mfpu=fpv5-d16 -mfloat-abi=hard
|
|
|
|
else ifeq ($(ARCH),xtensa)
|
|
|
|
# xtensa
|
|
CROSS = xtensa-lx106-elf-
|
|
CFLAGS += -mforce-l32
|
|
|
|
else ifeq ($(ARCH),xtensawin)
|
|
|
|
# xtensawin
|
|
CROSS = xtensa-esp32-elf-
|
|
CFLAGS +=
|
|
|
|
else
|
|
$(error architecture '$(ARCH)' not supported)
|
|
endif
|
|
|
|
CFLAGS += $(CFLAGS_EXTRA)
|
|
|
|
################################################################################
|
|
# Build rules
|
|
|
|
.PHONY: all clean
|
|
|
|
all: $(MOD).mpy
|
|
|
|
clean:
|
|
$(RM) -rf $(BUILD) $(CLEAN_EXTRA)
|
|
|
|
# Create build destination directories first
|
|
BUILD_DIRS = $(sort $(dir $(CONFIG_H) $(SRC_O) $(SRC_MPY)))
|
|
$(CONFIG_H) $(SRC_O) $(SRC_MPY): | $(BUILD_DIRS)
|
|
$(BUILD_DIRS):
|
|
$(Q)$(MKDIR) -p $@
|
|
|
|
# Preprocess all source files to generate $(CONFIG_H)
|
|
$(CONFIG_H): $(SRC)
|
|
$(ECHO) "GEN $@"
|
|
$(Q)$(MPY_LD) --arch $(ARCH) --preprocess -o $@ $^
|
|
|
|
# Build .o from .c source files
|
|
$(BUILD)/%.o: %.c $(CONFIG_H) Makefile
|
|
$(ECHO) "CC $<"
|
|
$(Q)$(CROSS)gcc $(CFLAGS) -o $@ -c $<
|
|
|
|
# Build .mpy from .py source files
|
|
$(BUILD)/%.mpy: %.py
|
|
$(ECHO) "MPY $<"
|
|
$(Q)$(MPY_CROSS) $(MPY_CROSS_FLAGS) -o $@ $<
|
|
|
|
# Build native .mpy from object files
|
|
$(BUILD)/$(MOD).native.mpy: $(SRC_O)
|
|
$(ECHO) "LINK $<"
|
|
$(Q)$(MPY_LD) --arch $(ARCH) --qstrs $(CONFIG_H) -o $@ $^
|
|
|
|
# Build final .mpy from all intermediate .mpy files
|
|
$(MOD).mpy: $(BUILD)/$(MOD).native.mpy $(SRC_MPY)
|
|
$(ECHO) "GEN $@"
|
|
$(Q)$(MPY_TOOL) --merge -o $@ $^
|