# -*- coding: utf-8 -*- import os import sys import time ''' 修改编译脚本之后需要全编译一次 ''' # CC = 'gcc' CC = 'arm-none-eabi-gcc' AS = CC + ' -x assembler-with-cpp' HEX = 'arm-none-eabi-objcopy' + ' -O ihex' BIN = 'arm-none-eabi-objcopy' + ' -O binary -S' OD = 'arm-none-eabi-objdump' + ' -dS' CSRC = [] CINC = [ '-Isource/cmsis', '-Isource/core', '-Isource/stm32lib/inc' ] CDEF = [ "-DSTM32F429_439xx" ] ASRC = [] BUILD_DIR = 'build' TARGET = 'hello' CFLAG = [ "-Wall -pedantic -mcpu=cortex-m4 -mthumb -lc -lm -lnosys -Og", "-pie", # "-fPIC", # "-fPIE", "-msingle-pic-base", "-specs=nano.specs", # "-nostdlib -emain", "", "-Tstm32_app.ld", f"-Wl,-Map={BUILD_DIR}/{TARGET}.map,--cref -Wl,--gc-sections" ] # 找到指定后缀的文件 def find_type(path:str,fix:list[str]): dlist=os.listdir(path) file_list=[] for i in dlist: ps=os.path.join(path, i) if os.path.isdir(ps): file_list+=find_type(ps,fix) else: suf=ps.split('.')[-1] if(suf in fix): file_list.append(ps) return file_list ''' 将.c编译为.o文件, 编译脚本需要实现 如果.c文件有修改 则重新编译对应文件的.o文件 gcc -c test.c -o test.o 输出依赖关系到.d文件 gcc -MM main.c -o build/main.d ''' def tran_path(path:str): p=path.replace('\\','/') p=p.replace('/','_') if(p[0]=='.'): return p[1:] else: return p # 判断是否需要重新生成 def check_rebuild(dst:str,src:list[str]): if(not os.path.exists(dst)): return True dst_time=os.path.getmtime(dst) src_time=[] for i in src: src_time.append(os.path.getmtime(i)) src_time.sort() if(src_time[-1]>dst_time): return True return False # 读取.d文件,返回依赖文件列表 def read_depend_files(name:str): with open(name) as f: t=f.readline() t=t.split(':')[-1].strip() t=t.split(' ') # print(f"依赖列表{t}") return t # 生成依赖关系 def build_depend(src:list[str]): flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" for i in src: name=tran_path(i).split('.')[0] dst='.'.join([name,'d']) dst=os.path.join(BUILD_DIR,dst) if(check_rebuild(dst,[i])): cmd=f"{CC} -MM {i} -o {dst} {flags}" print(cmd) ret=os.system(cmd) if(ret): exit() # 生成中间文件 def build_object(src:list[str]): flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" for i in src: name_l=tran_path(i).split('.') name=name_l[0] file_type=name_l[-1] dst='.'.join([name,'o']) dst=os.path.join(BUILD_DIR,dst) cd='.'.join([name,'d']) cmd = '' if(file_type in ['c','.C']): cd=os.path.join(BUILD_DIR,cd) if(check_rebuild(dst,read_depend_files(cd))): cmd=f"{CC} -c {i} -o {dst} {flags}" elif(file_type in ['s','S','asm','ASM']): if(check_rebuild(dst,[i])): cmd=f"{AS} -c {i} -o {dst} {flags}" if(len(cmd)>0): print(cmd) ret=os.system(cmd) if(ret): exit() # 生成可执行文件 def build_target(src:list[str]): flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}" obj_list=[] for i in src: name=tran_path(i).split('.')[0] obj_list.append(BUILD_DIR+'/'+'.'.join([name,'o'])) dst=os.path.join(BUILD_DIR,TARGET) if(check_rebuild(dst,obj_list)): cmd=f"{CC} {' '.join(obj_list)} -o {dst} {flags}" print(cmd) ret=os.system(cmd) if(ret): exit() else: print("已是最新,无需要重新生成的目标") def main(): global CSRC global ASRC if(os.path.exists(f"{TARGET}.s")): os.remove(f"{TARGET}.s") CSRC+=find_type('./',['c','C']) ASRC+=find_type('./',['s','S','asm','ASM']) if(not os.path.exists(BUILD_DIR)): os.makedirs(BUILD_DIR) print("生成依赖关系") build_depend(CSRC) print("生成对象文件") build_object(CSRC) build_object(ASRC) print("生成目标文件") build_target(CSRC+ASRC) os.system(f"{HEX} {BUILD_DIR}/{TARGET} {BUILD_DIR}/{TARGET}.hex") os.system(f"{BIN} {BUILD_DIR}/{TARGET} {BUILD_DIR}/{TARGET}.bin") os.system(f"{OD} {BUILD_DIR}/{TARGET} > {TARGET}.s") if __name__ == "__main__": main()