From b26cc2cc4694d883cc060c03c57d201753b4c72a Mon Sep 17 00:00:00 2001 From: Ha Thach Date: Wed, 13 Oct 2021 00:57:45 +0700 Subject: [PATCH] Add linkermap for size analysis (#1136) * add NO_LTO option to make * add linkermap submodule and linkermap target * add linkermap to ci build * linkermap doesn't work with esp32sx map file yet * add note for linkermap target --- .github/workflows/build.yml | 14 +++++++++++++ .github/workflows/build_esp.yml | 14 +++++++++++++ .github/workflows/build_msp430.yml | 14 +++++++++++++ .github/workflows/build_renesas.yml | 14 +++++++++++++ .github/workflows/build_riscv.yml | 14 +++++++++++++ docs/reference/getting_started.rst | 15 +++++++++++--- examples/rules.mk | 31 +++++++++++++++++++---------- hw/bsp/esp32s2/family.mk | 5 +---- 8 files changed, 104 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1ef0bf5ea..b16cf3f87 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,6 +66,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip lib/sct_neopixel + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Checkout pico-sdk if: matrix.family == 'rp2040' run: | @@ -95,6 +101,14 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done + # --------------------------------------- # Build all no-family (opharned) boards # --------------------------------------- diff --git a/.github/workflows/build_esp.yml b/.github/workflows/build_esp.yml index 93d582361..15071b178 100644 --- a/.github/workflows/build_esp.yml +++ b/.github/workflows/build_esp.yml @@ -30,5 +30,19 @@ jobs: - name: Checkout TinyUSB uses: actions/checkout@v2 + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Build run: docker run --rm -v $PWD:/project -w /project espressif/idf:latest python3 tools/build_esp32sx.py ${{ matrix.board }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -maxdepth 3 -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_msp430.yml b/.github/workflows/build_msp430.yml index ff2ce72c9..98dc36cd9 100644 --- a/.github/workflows/build_msp430.yml +++ b/.github/workflows/build_msp430.yml @@ -26,6 +26,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://software-dl.ti.com/msp430/msp430_public_sw/mcu/msp430/MSPGCC/9_2_0_0/export/msp430-gcc-9.2.0.50_linux64.tar.bz2 @@ -48,3 +54,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_renesas.yml b/.github/workflows/build_renesas.yml index ee9ba8289..6eb042d72 100644 --- a/.github/workflows/build_renesas.yml +++ b/.github/workflows/build_renesas.yml @@ -26,6 +26,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=http://gcc-renesas.com/downloads/get.php?f=rx/8.3.0.202004-gnurx/gcc-8.3.0.202004-GNURX-ELF.run @@ -49,3 +55,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/.github/workflows/build_riscv.yml b/.github/workflows/build_riscv.yml index 78510751c..0c7b2d154 100644 --- a/.github/workflows/build_riscv.yml +++ b/.github/workflows/build_riscv.yml @@ -27,6 +27,12 @@ jobs: - name: Checkout common submodules in lib run: git submodule update --init lib/FreeRTOS-Kernel lib/lwip + - name: Checkout hathach/linkermap + uses: actions/checkout@v2 + with: + repository: hathach/linkermap + path: linkermap + - name: Set Toolchain URL run: echo >> $GITHUB_ENV TOOLCHAIN_URL=https://github.com/xpack-dev-tools/riscv-none-embed-gcc-xpack/releases/download/v10.1.0-1.1/xpack-riscv-none-embed-gcc-10.1.0-1.1-linux-x64.tar.gz @@ -49,3 +55,11 @@ jobs: - name: Build run: python3 tools/build_family.py ${{ matrix.family }} + + - name: Linker Map + run: | + pip install linkermap/ + for ex in `ls -d examples/device/*/`; do \ + find ${ex} -name *.map -print -quit | \ + xargs -I % sh -c 'echo "::group::%"; linkermap -v %; echo "::endgroup::"'; \ + done diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst index be2e1b5ea..044792993 100644 --- a/docs/reference/getting_started.rst +++ b/docs/reference/getting_started.rst @@ -89,6 +89,15 @@ A MCU can support multiple operational speed. By default, the example build syst $ make BOARD=stm32f746disco SPEED=full all +Size Analysis +~~~~~~~~~~~~~ + +First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since -flto merges code across .o files and make it difficult to analyze. + +.. code-block:: + + $ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap + Debug ^^^^^ @@ -153,7 +162,7 @@ Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can $ make BOARD=feather_nrf52840_express all uf2 IAR Support ------------ +^^^^^^^^^^^ IAR Project Connection files are provided to import TinyUSB stack into your project. @@ -171,12 +180,12 @@ IAR Project Connection files are provided to import TinyUSB stack into your proj for example `C:\\tinyusb` Import stack only -^^^^^^^^^^^^^^^^^ +~~~~~~~~~~~~~~~~~ 1. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`. Run examples -^^^^^^^^^^^^ +~~~~~~~~~~~~ 1. (Python3 is needed) Run `iar_gen.py` to generate .ipcf files of examples: diff --git a/examples/rules.mk b/examples/rules.mk index 7e494b3d8..92fa4e14d 100644 --- a/examples/rules.mk +++ b/examples/rules.mk @@ -5,12 +5,11 @@ # Set all as default goal .DEFAULT_GOAL := all -# ESP32-SX and RP2040 has its own CMake build system -ifneq ($(FAMILY),esp32s2) -ifneq ($(FAMILY),esp32s3) -ifneq ($(FAMILY),rp2040) +# ESP32-Sx and RP2040 has its own CMake build system +ifeq (,$(findstring $(FAMILY),esp32s2 esp32s3 rp2040)) + # --------------------------------------- -# GNU Make build system +# Compiler Flags # --------------------------------------- # libc @@ -44,6 +43,12 @@ INC += $(TOP)/src CFLAGS += $(addprefix -I,$(INC)) +# LTO makes it difficult to analyze map file for optimizing size purpose +# We will run this option in ci +ifeq ($(NO_LTO),1) +CFLAGS := $(filter-out -flto,$(CFLAGS)) +endif + LDFLAGS += $(CFLAGS) -Wl,-T,$(TOP)/$(LD_FILE) -Wl,-Map=$@.map -Wl,-cref -Wl,-gc-sections ifneq ($(SKIP_NANOLIB), 1) LDFLAGS += -specs=nosys.specs -specs=nano.specs @@ -67,6 +72,10 @@ $(info LDFLAGS $(LDFLAGS)) $(info ) $(info ASFLAGS $(ASFLAGS)) $(info ) endif +# --------------------------------------- +# Rules +# --------------------------------------- + all: $(BUILD)/$(PROJECT).bin $(BUILD)/$(PROJECT).hex size uf2: $(BUILD)/$(PROJECT).uf2 @@ -126,11 +135,17 @@ $(BUILD)/obj/%_asm.o: %.S @echo AS $(notdir $@) @$(CC) -x assembler-with-cpp $(ASFLAGS) -c -o $@ $< +endif # GNU Make + size: $(BUILD)/$(PROJECT).elf -@echo '' @$(SIZE) $< -@echo '' +# linkermap must be install previously at https://github.com/hathach/linkermap +linkermap: $(BUILD)/$(PROJECT).elf + @linkermap -v $<.map + .PHONY: clean clean: ifeq ($(CMDEXE),1) @@ -139,10 +154,6 @@ else $(RM) -rf $(BUILD) endif -endif -endif -endif # GNU Make - # --------------------------------------- # Flash Targets # --------------------------------------- @@ -204,4 +215,4 @@ copy-artifact: $(BIN) # Print out the value of a make variable. # https://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile print-%: - @echo $* = $($*) + @echo $* = $($*) \ No newline at end of file diff --git a/hw/bsp/esp32s2/family.mk b/hw/bsp/esp32s2/family.mk index fb9b21641..4b9000a6a 100644 --- a/hw/bsp/esp32s2/family.mk +++ b/hw/bsp/esp32s2/family.mk @@ -7,14 +7,11 @@ all: build: all -clean: - idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) clean - fullclean: if test -f sdkconfig; then $(RM) -f sdkconfig ; fi if test -d $(BUILD); then $(RM) -rf $(BUILD) ; fi -flash bootloader-flash app-flash erase monitor dfu-flash dfu: +clean flash bootloader-flash app-flash erase monitor dfu-flash dfu size size-components size-files: idf.py -B$(BUILD) -DFAMILY=$(FAMILY) -DBOARD=$(BOARD) $(CMAKE_DEFSYM) $@ uf2: $(BUILD)/$(PROJECT).uf2