【Python】用python实现编译脚本

这个脚本可以自动扫描目录下的.c和.s文件并编译,同时生成hex和bin文件
,可以代替Makefile工作。cortex-m 单片机


# -*- coding: gbk -*-




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 = []

CINC = ['-Isoft']

CDEF = ["-DTEST"]

ASRC = []

BUILD_DIR = 'build'

TARGET = 'hello'

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"]


# 找到指定后缀的文件
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
  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")

if __name__ == "__main__":
    main()




  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值