宏管理工具之lite-manager

Kconfig、menuconfig、makefile、macro

Views:  times Updated on December 6, 2024 Posted by elmagnifico on December 3, 2024

Foreword

体验一下群友的宏管理工具

lite-manager

https://gitee.com/li-shan-asked/lite-manager

群友的宏管理工具,主要在gitee上更新,github更新不及时,release文件可能不能用

主要是用来方便管理宏定义和生成Makefile,但是大部分设置还是要熟悉Makefile本身,你才能完成lm的配置文件编写,本质上并没有变换脚本语言或者什么的流程

lite-manager在这里有点类似于Kconfig

环境

至少需要一个make和gun c的环境,之前系统里一直有一个MinGW32 13年的版本,gcc大概只有6,编译过不去(后来发现应该不是这个问题)

通过下面的方式在线安装MinGW64

https://github.com/Vuniverse0/mingwInstaller/releases/download/1.2.1/mingwInstaller.exe

安装完成以后添加环境路径

如果环境里没有多的make,可以把mingw32-make.exe复制一个改名叫make.exe,不然最好还是保持原样,否则会影响到系统里其他地方的make使用

链接脚本问题

测试demo,发现无法正常运行,链接脚本无法识别-M的参数

image-20241202191533410

仔细看了一下Makefile,是生产的链接参数就是-M而不是-Map

image-20241202191650116

还好lite-manager源码也是有的,修改一下生成脚本

image-20241202191633425

再把生成的lm.exe拖到对应的测试目录下,进行测试,一切正常了

image-20241202191619373

  • 如果不修改lm,make config时也显示不出来当前宏的状态

先生成Makefile

./lm.exe -g Makefile -p hello

然后可以生成config文件,并且查看宏定义情况

make config

编译

make

规则

image-20241203110700613

lm.cfg,用来定义宏的定义以及宏之间的关系

proj.cfg,用户定义实际想要的宏

.lm.mk,缓存

config.h,最终处理完约束条件后实际定义出来的宏

lm.cfg中判断条件是自上而下的,遇到冲突点,首先会关闭自身,然后文件之间是从左向右流动的

其中n,表示宏关闭,‘n’是正常使用n这个关键字

同时下面的文件编译的约束也可以同时使用宏来管控

多模块、多组件的工程目录

├───build
├───subdirA
|   ├───mac_a.c
|   └───lm.cfg
├───subdirB
|   ├───mac_b.c
|   └───lm.cfg
└───lm.cfg

可以使用include直接把下面的配置加载进去

include "subdirA/lm.cfg"
include "subdirB/lm.cfg"

lm的工程实例可以参考这里,有些技巧example里没有用到,可以看看实例是怎么跑的

https://gitee.com/li-shan-asked/ebraid

lite-manager 同时也有类似tui的交互版本,不过作者说比较老、过时,所以不推荐用了

img

Makefile解析

# 自顶向下来看Makefile的设计
# 首先目标是hello 然后编译输出到build目录
TARGET    := hello
BUILD_DIR := build

# 定义一个伪指令,主要用来检测是否从lm的config中生成的
# 简单说基本上只要不是最终生成的目标,那都是伪指令
# 伪指令主要是完成一些辅助性的工作,比如clean,检测,切换配置,生成配置等等
# 检测是否有.lm.mk文件
.PHONY: check_lmmk
# wildcard自动寻找.lm.mk的文件 
ifneq ($(wildcard .lm.mk),)
-include .lm.mk
else
check_lmmk:
	@echo "Please run 'make config'"
endif

# 主要涉及使用的工具链,比如 arm-none-eabi-, 这里用默认gcc即可
CC_PREFIX ?= 
CC = $(CC_PREFIX)gcc
# 汇编编译的文件来源是C++ 支持的是.S 如果要支持.s 也在这里修改
AS = $(CC_PREFIX)gcc -x assembler-with-cpp
# copy命令
CP = $(CC_PREFIX)objcopy
# 文件size section 字段分析
SZ = $(CC_PREFIX)size
# 调试 debug的工具
OD = $(CC_PREFIX)objdump
# 生成hex文件
HEX = $(CP) -O ihex
# 生成bin文件
BIN = $(CP) -O binary -S
# 以上工具写的比较多,实际是为了以后适配使用,demo里可能没用到

# 定义额外的宏、库、等路径
CFLAGS    := $(C_PATH) $(C_DEFINE) $(C_FLAG) $(CPP_FLAG)
# 同上,定义链接文件的来源和参数
# 链接时生成map文件
LDFLAGS   := $(LD_FLAG) $(LIB_PATH) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map


# 这里定义生成全部的目标
.PHONY: all
all: $(BUILD_DIR)/$(TARGET).exe elf_info


#获取到所有要编译的目标对象,这里是从build目录中获取所有c和c++目标
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(patsubst %.c, %.o, $(patsubst %.cpp, %.o, $(C_SOURCE)))))
# 指定具体的.c文件的搜索路径
vpath %.c $(sort $(dir $(C_SOURCE)))
vpath %.cpp $(sort $(dir $(C_SOURCE)))
#获取到所有要编译的汇编对象
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCE:.S=.o)))
vpath %.S $(sort $(dir $(ASM_SOURCE)))

# 创建存储.o和.c文件依赖关系的.d文件
# -MMD -MP -MF $(@:%.o=%.d) 是利用gcc自动生成依赖关系
# 将build路径下的所有c文件编译成.o文件
# Makefile文件自身也是依赖文件,如果Makefile文件发生变动,也需要重新编译
# -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)):生成临时中间文件
# -c 仅仅编译,不进行链接
# $@是指这条指令的所有操作对象
# $<是第一个文件
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
	@echo "CC   $<"
	@$(CC) -c $(CFLAGS) -MMD -MP \
		-MF  $(BUILD_DIR)/$(notdir $(<:.c=.d)) \
		-Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

# 同上,只不过此处仅编译c++文件
$(BUILD_DIR)/%.o: %.cpp Makefile | $(BUILD_DIR)
	@echo "CC   $<"
	@$(CC) -c $(CFLAGS) -MMD -MP \
		-MF  $(BUILD_DIR)/$(notdir $(<:.cpp=.d)) \
		-Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.cpp=.lst)) $< -o $@

# 同上,此处仅编译.S的汇编文件
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
	@echo "AS   $<"
	@$(AS) -c $(CFLAGS) -MMD -MP  \
		-MF $(BUILD_DIR)/$(notdir $(<:.S=.d)) $< -o $@

# 生成exe文件
$(BUILD_DIR)/$(TARGET).exe: $(OBJECTS) Makefile
	@echo "LD   $@"
	@$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	@$(OD) $(BUILD_DIR)/$(TARGET).exe -xS > $(BUILD_DIR)/$(TARGET).s $@
	@echo ''
	@echo "Build Successful!"
	@echo "ELF   $@"


elf_info: $(BUILD_DIR)/$(TARGET).exe
	@echo "=================================================================="
	@$(SZ) $<
	@echo "=================================================================="


# 生成build文件夹
$(BUILD_DIR):
	@mkdir $@


# 清除指令
.PHONY: config clean

# 如果工程配置文件存在,那么就调用lm重新生成配置
# 这里主要是生成对应的 config.h,不是重新生成Makefile
config: proj.cfg
	@./lm.exe --projcfg proj.cfg --lmcfg lm.cfg --out config.h --mem 50
	@./lm.exe --rmdir $(BUILD_DIR)


# 清空编译
clean:
	@./lm.exe --rmdir $(BUILD_DIR)


lm.cfg解析

实际在hello的lm.cfg中只有一行,就是加了一个文件进去

SRC  += hello.c

这里指定了生成的目标是hello

./lm.exe -g Makefile -p hello

剩下的Makefile全都靠lm内部自动生成

以stm32f103的工程为例,相当于Makefile是一个通用的Makefile,而lm.cfg 相当于是一个PreMakefile,在这里直接定义Makefile要用的一些参数即可,剩下就是Makefile足够项目通用即可

# 添加link文件
LDS       += stm32f10x_64KB_flash.ld
# 添加汇编文件
ASM       += startup_stm32f10x_md.s
# 添加一些关联文件路径
PATH      += lib/cmsis
PATH      += ./

# 添加源文件
SRC       += stm32f10x_it.c
SRC       += main.c

# 增加宏定义
DEFINE    += STM32F10X_HD USE_STDPERIPH_DRIVER
# 编译参数
CFLAG     += -g -O2 -mthumb -mcpu=cortex-m3 -march=armv7-m -Wl,-Bstatic -ffunction-sections -fdata-sections -nostdlib -ffreestanding
# 链接参数
LDFLAG    += -lnosys -Wl,--cref -Wl,--no-relax -Wl,--gc-sections -ffreestanding -Wl,-Bstatic -Wl,--no-warn-rwx-segments
# 汇编参数
ASFLAG    += -Wl, -Bstatic

# 引入库文件里的lm
include   "hal/STM32F10x_StdPeriph_Driver/lm.cfg"

问题

使用当前比较通用的arm-none-eabi的老库

GNU Arm Embedded Toolchain\10 2021.10

STM32F103的工程是无法正常编译的

如果没有看过类似的例子或者直接参考Makefile原工程,不可能上手直接使用

如果使用Arm GNU Toolchain arm-none-eabi\13.3 rel1 确实可以直接编译过

在不同的使用情景下,lite-manager带来的效果还是有一些差别的,假如你是一个对工程特别熟悉的人,那么对应的lm.cfg或者是proj.cfg中的宏都是可以随手改的。但是并不是每个做工程的人都对整个宏特别熟悉,此时就会出现给了一个不熟悉的人去修改,那么他就得一一对照整个lm.cfg里的约束关系和宏定义的可能,再去设置proj.cfg,如果只是几个宏,那随手就改了(几个宏为什么还要用lm?)

如果是几十个宏,此时要查表,再去决定这个宏可以用什么

image-20241206151256866

这个时候lm的结构就变成负担了,虽然lm可以显示最终结果,但是当你发现结果不对的时候,你依然需要逐项去排查是哪里冲突了

类比传统的Makefile工程来说,lm省去了你手动Makefile里各种if条件的书写,确实简化了一部分Makefile复杂的地方

image-20241206152950792

这里提一点我的想法,有一个比较通用的UI显示,类似于xml或者json的UI化显示,定义好一些规则,直接就能把这种宏配置管理给做了

  • 事实上ESP32已经实现了这样的效果,VScode中一个插件就能把esp32的配置文件变成可视化的,极大方便了玩家DIY

Summary

lite-manager 总体还是挺小的,显示也还凑活,代码是开放的,完全可以自定义一些

总体来说lm简化了Makefile,但是想要使用起来依然需要懂Makefile,需要给项目下的每个文件夹增加配置文件,类比.mk文件

Quote

https://gitee.com/li-shan-asked/lite-manager/tree/noui/

https://blog.csdn.net/ysu_wangli/article/details/106677907