209 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			209 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| import os
 | ||
| import sys
 | ||
| import time
 | ||
| 
 | ||
| 
 | ||
| '''
 | ||
| 
 | ||
| 修改编译脚本之后需要全编译一次
 | ||
| 
 | ||
| '''
 | ||
| 
 | ||
| 
 | ||
| CC = 'gcc'
 | ||
| # CC = 'C:\\ARM_GCC\\bin\\arm-none-eabi-gcc'
 | ||
| 
 | ||
| # AS = CC + ' -x assembler-with-cpp'
 | ||
| 
 | ||
| # HEX = 'C:\\ARM_GCC\\bin\\arm-none-eabi-objcopy' + ' -O ihex'
 | ||
| # BIN = 'C:\\ARM_GCC\\bin\\arm-none-eabi-objcopy' + ' -O binary -S'
 | ||
| 
 | ||
| CSRC = ["main.c"]
 | ||
| 
 | ||
| CINC = ['-Isoft',"-Icpu"]
 | ||
| 
 | ||
| CDEF = ["-DTEST","-DLINUX"]
 | ||
| 
 | ||
| ASRC = []
 | ||
| 
 | ||
| BUILD_DIR = 'build'
 | ||
| 
 | ||
| TARGET = 'hello.exe'
 | ||
| 
 | ||
| # CFLAG = ["-Wall -pedantic -specs=nano.specs -mcpu=cortex-m3 -mthumb -lc -lm -lnosys -Og -Tstm32_boot.ld",
 | ||
| #          f"-Wl,-Map={BUILD_DIR}/{TARGET}.map,--cref -Wl,--gc-sections"]
 | ||
| # -pedantic 这一项是ISO语法检验
 | ||
| CFLAG = ["-Wall -g"]
 | ||
| 
 | ||
| 
 | ||
| # 找到指定后缀的文件
 | ||
| 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]):
 | ||
|   # print(f"src:{src}")
 | ||
|   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
 | ||
|   # for item in src_time:
 | ||
|   #   if(item>dst_time):
 | ||
|   #     return True
 | ||
|   return False
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| # 读取.d文件,返回依赖文件列表
 | ||
| def read_depend_files(name:str):
 | ||
|   with open(name) as f:
 | ||
|     lines=f.readlines()
 | ||
|     t=''
 | ||
|     for line in lines:
 | ||
|       line=line.strip()
 | ||
|       if(line[-1]=='\\'):
 | ||
|         t+=line[:-1]
 | ||
|       else:
 | ||
|         t+=line
 | ||
|     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()
 | ||
|     else:
 | ||
|       print(f"{i} 没有更新源文件")
 | ||
| 
 | ||
| # 生成中间文件
 | ||
| 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}"
 | ||
|       else:
 | ||
|         print(f"{i} 没有更新依赖关系")
 | ||
|     elif(file_type in ['s','S','asm','ASM']):
 | ||
|       if(check_rebuild(dst,[i])):
 | ||
|         # cmd=f"{AS} -c {i} -o {dst} {flags}"
 | ||
|         pass
 | ||
|       else:
 | ||
|         print(f"{i} 没有更新依赖关系")
 | ||
|     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(f"{dst} 没有更新的链接文件")
 | ||
| 
 | ||
| 
 | ||
| def main():
 | ||
|   global CSRC
 | ||
|   global ASRC
 | ||
|   CSRC+=find_type('.\\soft',['c','C'])
 | ||
|   CSRC+=find_type('.\\cpu',['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")
 | ||
| 
 | ||
| if __name__ == "__main__":
 | ||
|     main()
 | ||
| 
 | ||
| 
 | ||
| 
 |