Makefile 共通化
RX マイコンの各プロジェクトで、Makefile で共有出来る部分を抜き出して、共通化を行った。
今まで、同じような「手順」を各プロジェクト毎にコピーしていたが、二度手間だし、プロジェクト数が多く、作業が大変だった。
※Makefile を複数に別けたく無かったとゆーこだわりがあったのだが、現在のように手順がそこそこ複雑だと、そうする「こだわり」はあまり意味が無い。
共通部分
# -*- tab-width : 4 -*-
#=======================================================================
# @file
# @brief RX microcontroller share Makefile
# @author 平松邦仁 (hira@rvf-rc45.net)
# @copyright Copyright (C) 2021 Kunihito Hiramatsu @n
# Released under the MIT license @n
# https://github.com/hirakuni45/RX/blob/master/LICENSE
#=======================================================================
# System include path for each environment
ifeq ($(OS),Windows_NT)
SYSTEM := WIN
# C++.boost root
LOCAL_PATH = /mingw64
else
UNAME := $(shell uname -s)
ifeq ($(UNAME),Linux)
SYSTEM := LINUX
LOCAL_PATH = /usr/local
endif
ifeq ($(UNAME),Darwin)
SYSTEM := OSX
OSX_VER := $(shell sw_vers -productVersion | sed 's/^\([0-9]*.[0-9]*\).[0-9]*/\1/')
LOCAL_PATH = /opt/local
endif
endif
まず、これは、Windows、Linux、OS-X の環境を判断して、微妙な違いを吸収する。
※一番重要な事は、boost のパスを各環境で同じように扱う事。
LIB_ROOT = ../../rxlib/lib
INC_SYS = ../../rxlib/include $(LOCAL_PATH)/include
PROG_VERIFY = --verify
- LIB_ROOT は、RX マイコン専用ライブラリのパスを設定している。
- INC_SYS は、RX マイコン専用ライブラリのインクルードパスと、ローカルのインクルードパス(boost)などを設定している。
- PROG_VERIFY は、rx_prog でフラッシュ書き込みする際に、「VERIFY」を行う場合のキーワードとなっている。
- RX24T は、通常の手順で、VERIFY が行われない為、無効にする必要がある。
ifeq ($(RX_DEF),SIG_RX24T)
RX_CPU = RX24T
RX_OPT = v2
LDSCRIPT = ../../RX24T/$(DEVICE).ld
PROG_VERIFY =
endif
ifeq ($(RX_DEF),SIG_RX64M)
RX_CPU = RX64M
RX_OPT = v2
LDSCRIPT = ../../RX64M/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX71M)
AS_OPT += --defsym MEMWAIT=1
RX_CPU = RX71M
RX_OPT = v2
LDSCRIPT = ../../RX71M/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX65N)
LIB_ROOT += ../../RX600/drw2d
INC_APP += ../../RX600/drw2d/inc/tes
USER_LIBS += drw2d
RX_CPU = RX65N
RX_OPT = v2
LDSCRIPT = ../../RX65x/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX66T)
RX_CPU = RX66T
RX_OPT = v3
LDSCRIPT = ../../RX66T/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX72T)
RX_CPU = RX72T
RX_OPT = v3
LDSCRIPT = ../../RX72T/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX72N)
LIB_ROOT += ../../RX600/drw2d
INC_APP += ../../RX600/drw2d/inc/tes
USER_LIBS += drw2d
RX_CPU = RX72N
RX_OPT = v3
LDSCRIPT = ../../RX72N/$(DEVICE).ld
endif
ifeq ($(RX_DEF),SIG_RX72M)
LIB_ROOT += ../../RX600/drw2d
INC_APP += ../../RX600/drw2d/inc/tes
USER_LIBS += drw2d
RX_CPU = RX72M
RX_OPT = v3
LDSCRIPT = ../../RX72M/$(DEVICE).ld
endif
この条件文で、RX マイコン毎に異なる設定を行っている。
現状では、「SIG_xxx」のキーワード毎に行っているが、将来的には、DEVICE で IC の型番を設定しているので、それに従って行うのが妥当だと思う。
※型番で行えば、ピン数の違いによる変更をソースコードへ伝達する事が出来る。
RX71M だけは、ちょっと特殊で、スーパーバイザーモードでしかアクセス出来ないレジスタがある。
そこで、そのレジスタを、start.s アセンブラブログラム内で行っている。「--defsym MEMWAIT=1」
FreeRTOS の場合、ユーザーモードに移行しない事が重要だが、それは、各プロジェクト毎に設定する。
# for FreeRTOS option
AS_OPT = --defsym NOT_USER=1
# Renesas GNU-RX gcc compiler version check
TARGET_ISA_TEXT := $(shell rx-elf-gcc --target-help | grep ISA)
# Renesas GNU-RX (8.3.0) compiler
ifeq ($(TARGET_ISA_TEXT),)
# for gcc-7.5.0 current gcc source build
AS_DEFS = -mcpu=rx600
CC_DEFS = -mcpu=rx600 -Wa,-mcpu=rxv2
CP_DEFS = -mcpu=rx600
else # Renesas GNU-RX gcc 8.3.0
AS_DEFS = -misa=$(RX_OPT)
CC_DEFS = -misa=$(RX_OPT)
CP_DEFS = -misa=$(RX_OPT)
endif
これは、Renesas GNU-RX gcc コンパイラと、プレーンな gcc コンパイラで、オプションが異なるので、それを自動判別する。
# You should not have to change anything below here.
AS = rx-elf-as
CC = rx-elf-gcc
CP = rx-elf-g++
AR = rx-elf-ar
LD = rx-elf-ld
OBJCOPY = rx-elf-objcopy
OBJDUMP = rx-elf-objdump
SIZE = rx-elf-size
AFLAGS = $(AS_OPT) $(AS_DEFS)
CFLAGS = -std=gnu99 $(CC_OPT) $(OPTIMIZE) $(CC_DEFS) $(DEFS)
PFLAGS = -std=c++17 $(CP_OPT) $(OPTIMIZE) $(CP_DEFS) $(DEFS)
FLAGS = $(AS_OPT) $(AS_DEFS) $(CC_OPT) $(CP_OPT) $(OPTIMIZE) $(CC_DEFS) $(CP_DEFS) $(DEFS)
# FLAGS_CMP := $(shell cat $(TARGET).opt)
override LDFLAGS = $(MCU_TARGET) -nostartfiles -Wl,-Map,$(TARGET).map -T $(LDSCRIPT)
OBJCOPY_OPT = --srec-forceS3 --srec-len 32
OBJECTS = $(addprefix $(BUILD)/,$(patsubst %.s,%.o,$(ASOURCES))) \
$(addprefix $(BUILD)/,$(patsubst %.c,%.o,$(CSOURCES))) \
$(addprefix $(BUILD)/,$(patsubst %.cpp,%.o,$(PSOURCES)))
DOBJECTS = $(addprefix $(BUILD)/,$(patsubst %.c,%.o,$(CSOURCES))) \
$(addprefix $(BUILD)/,$(patsubst %.cpp,%.o,$(PSOURCES)))
DEPENDS = $(patsubst %.o,%.d, $(DOBJECTS))
# all, clean: optional make command
.PHONY: all clean clean_depend run text
.SUFFIXES :
.SUFFIXES : .hpp .s .h .c .cpp .d .o
all: $(BUILD) $(TARGET).elf text
$(TARGET).elf: $(OBJECTS) $(LDSCRIPT) Makefile
$(CC) $(LDFLAGS) $(LIBINCS) -o $@ $(OBJECTS) $(LIBS)
$(SIZE) $@
$(BUILD)/%.o: %.s
mkdir -p $(dir $@); \
$(AS) -c $(AOPT) $(AFLAGS) $(AINCS) -o $@ $<
$(BUILD)/%.o : %.c
mkdir -p $(dir $@); \
$(CC) -c $(COPT) $(CFLAGS) $(CINCS) $(CCWARN) -o $@ $<
$(BUILD)/%.o : %.cpp
mkdir -p $(dir $@); \
$(CP) -c $(POPT) $(PFLAGS) $(PINCS) $(CPWARN) -o $@ $<
$(BUILD)/%.d: %.c
mkdir -p $(dir $@); \
$(CC) -MM -DDEPEND_ESCAPE $(COPT) $(CFLAGS) $(APPINCS) $< \
| sed 's/$(notdir $*)\.o:/$(subst /,\/,$(patsubst %.d,%.o,$@) $@):/' > $@ ; \
[ -s $@ ] || rm -f $@
$(BUILD)/%.d: %.cpp
mkdir -p $(dir $@); \
$(CP) -MM -DDEPEND_ESCAPE $(POPT) $(PFLAGS) $(APPINCS) $< \
| sed 's/$(notdir $*)\.o:/$(subst /,\/,$(patsubst %.d,%.o,$@) $@):/' > $@ ; \
[ -s $@ ] || rm -f $@
clean:
rm -rf $(BUILD) $(TARGET).elf $(TARGET).mot $(TARGET).lst $(TARGET).map
clean_depend:
rm -f $(DEPENDS)
これは、gcc の設定で、従属規則を自動生成する仕組みを内包する。
lst: $(TARGET).lst
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
# Rules for building the .text rom images
text: mot lst
lst: $(TARGET).lst
mot: $(TARGET).mot
bin: $(TARGET).bin
%.lst: %.elf
$(OBJDUMP) -h -S $< > $@
%.mot: %.elf
$(OBJCOPY) $(OBJCOPY_OPT) -O srec $< $@
%.bin: %.elf
$(OBJCOPY) -O binary $< $@
これは、リンカーで実行バイナリーを作成後、リストファイル、モトローラーファイル、バイナリーファイルを作成する手順だ。
# Serial Flash write
run:
$(MAKE)
rx_prog -d $(RX_CPU) --progress --erase --write $(PROG_VERIFY) $(TARGET).mot
最後は、シリアル接続で、フラッシュ書き込みを行うツールの設定などになっている。
個別部分
上記のように、共通出来る部分を追い出したので、個別部分はシンプルとなった。
# -*- tab-width : 4 -*-
#=======================================================================
# @file
# @brief RX72N Makefile
# @author 平松邦仁 (hira@rvf-rc45.net)
# @copyright Copyright (C) 2020, 2021 Kunihito Hiramatsu @n
# Released under the MIT license @n
# https://github.com/hirakuni45/RX/blob/master/LICENSE
#=======================================================================
TARGET = raytracer_sample
DEVICE = R5F572NN
RX_DEF = SIG_RX72N
BUILD = release
# BUILD = debug
VPATH = ../../
ASOURCES = common/start.s
CSOURCES = common/init.c \
common/vect.c \
common/syscalls.c
PSOURCES = RAYTRACER_sample/main.cpp \
graphics/font8x16.cpp \
graphics/color.cpp \
common/stdapi.cpp
USER_LIBS =
USER_DEFS =
INC_APP = . ../ ../../
AS_OPT =
CP_OPT = -Wall -Werror \
-Wno-unused-variable \
-Wno-unused-function \
-fno-exceptions
CC_OPT = -Wall -Werror \
-Wno-unused-variable \
-fno-exceptions
ifeq ($(BUILD),debug)
CC_OPT += -g -DDEBUG
CP_OPT += -g -DDEBUG
OPTIMIZE = -O0
endif
ifeq ($(BUILD),release)
CC_OPT += -DNDEBUG
CP_OPT += -DNDEBUG
OPTIMIZE = -O3
endif
-include ../../common/makefile
-include $(DEPENDS)
これは、RX72T の RAYTRACER_sample の Makefile で、基本、リンクするファイルの記述が殆どだ。
リリースビルドと、デバッグビルドの違いで切り替える部分は共通化しなかった。
最適化を変えたり、プロジェクト毎に微妙な違いを許容する事が出来るように配慮した。
まとめ
共通化する過程で、オプションなどを変更した場合に、フルコンパイルが自動で行えるように出来ないか検討したが、make を完全に理解していない為、思ったように作れなかった・・
これは今後の課題にしたいと思う。