Files
c_soft/make_riscv.py

253 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import sys
import time
import shutil
import dataclasses
from multiprocessing import Process,Queue,Value
CC="riscv64-unknown-elf-gcc"
OBJCPY="riscv64-unknown-elf-objcopy"
OBJDUMP="riscv64-unknown-elf-objdump"
CFLAG=[
"-march=rv32i_zicsr",
"-mabi=ilp32",
"-ffunction-sections",
"-fdata-sections",
"-ffast-math",
"-fno-common",
"-fno-builtin-printf",
"-Wall",
"-Werror",
"-g",
"-O0",
"-fno-omit-frame-pointer",
"-msave-restore"
]
DEF=[]
INC=[
"-I./riscv/rtthread/libcpu/risc-v/common",
"-I./riscv/rtthread/include",
"-I./riscv/startup",
"-I./riscv/rtthread/components/drivers/include"
]
SRC=[
"riscv/startup/main.c",
"riscv/startup/test.c",
# "riscv/startup/interrupt.c",
"riscv/startup/start.S",
# "riscv/startup/trap.S",
"riscv/startup/rtthread_irq.c",
"riscv/rtthread/libcpu/risc-v/common/atomic_riscv.c",
"riscv/rtthread/libcpu/risc-v/common/context_gcc.S",
"riscv/rtthread/libcpu/risc-v/common/cpuport.c",
"riscv/rtthread/libcpu/risc-v/common/interrupt_gcc.S",
"riscv/rtthread/libcpu/risc-v/common/trap_common.c",
"riscv/rtthread/src/clock.c",
"riscv/rtthread/src/components.c",
"riscv/rtthread/src/cpu.c",
"riscv/rtthread/src/idle.c",
"riscv/rtthread/src/ipc.c",
"riscv/rtthread/src/irq.c",
"riscv/rtthread/src/kservice.c",
"riscv/rtthread/src/mem.c",
"riscv/rtthread/src/memheap.c",
"riscv/rtthread/src/mempool.c",
"riscv/rtthread/src/object.c",
"riscv/rtthread/src/scheduler_comm.c",
# "riscv/rtthread/src/scheduler_mp.c",
"riscv/rtthread/src/scheduler_up.c",
"riscv/rtthread/src/signal.c",
"riscv/rtthread/src/slab.c",
"riscv/rtthread/src/thread.c",
"riscv/rtthread/src/timer.c",
"riscv/rtthread/src/klibc/kstdio.c",
"riscv/rtthread/src/klibc/kstring.c",
"riscv/rtthread/components/drivers/core/device.c"
]
LD_FILE="riscv/riscv.ld"
TARGET="riscv"
OUTPUT="output"
def tran_path(path:str):
path=os.path.normpath(os.path.join(OUTPUT,path))
base_path=os.path.dirname(path)
if not os.path.exists(base_path):
os.makedirs(base_path)
return path
# 判断是否需要重新生成
def check_rebuild(dst:str,src:list):
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:
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(' ')
return t
@dataclasses.dataclass
class cmd_item_t:
cmd:str
info:str
def run_cmd(cmd_queue:Queue,cpu_index:int,return_list:Queue,failed_num):
while(not cmd_queue.empty()):
if(failed_num.value>0):
return
try:
cmd=cmd_queue.get_nowait()
except Exception:
return_list.put((cpu_index,True))
return
print(f"[{cpu_index}] {cmd.info}")
ret=os.system(cmd.cmd)
if(ret):
return_list.put((cpu_index,False))
failed_num.value+=1
return
return_list.put((cpu_index,True))
def run_cmd_queue(cmd_queue:Queue,cpu_num:int=4):
if(cmd_queue.empty()):
return
process_list = []
return_list=Queue()
failed_num=Value('i',0)
for i in range(cpu_num):
p = Process(target=run_cmd,args=(cmd_queue,i,return_list,failed_num,))
p.start()
process_list.append(p)
for i in process_list:
p.join()
while not return_list.empty():
i=return_list.get()
if(not i[1]):
print(f"子进程 [{i[0]}] 运行失败")
exit(-1)
# 保证目标都存在
def check_exists(src:list):
for item in src:
for i in range(10):
if(os.path.exists(item)):
break
time.sleep(0.1)
# 生成依赖关系
def build_depend(src:list):
CmdQueue=Queue()
dst_list=[]
flags=f"{' '.join(INC)} {' '.join(DEF)} {' '.join(CFLAG)}"
for i in src:
name=os.path.splitext(tran_path(i))[0]
dst='.'.join([name,'d'])
if(check_rebuild(dst,[i])):
cmd=f"{CC} -MM {i} -o {dst} {flags}"
CmdQueue.put(cmd_item_t(cmd,f"更新 {dst}"))
dst_list.append(dst)
run_cmd_queue(CmdQueue)
check_exists(dst_list)
# 生成中间文件
def build_object(src:list):
CmdQueue=Queue()
dst_list=[]
flags=f"{' '.join(INC)} {' '.join(DEF)} {' '.join(CFLAG)}"
for i in src:
name_t=os.path.splitext(tran_path(i))
name=name_t[0]
file_type=name_t[-1]
dst='.'.join([name,'o'])
cd='.'.join([name,'d'])
cmd = ''
if(file_type in ['.c','.C']):
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,read_depend_files(cd))):
cmd=f"{CC} -c {i} -o {dst} {flags}"
if(len(cmd)>0):
CmdQueue.put(cmd_item_t(cmd,f"编译 {dst}"))
dst_list.append(dst)
run_cmd_queue(CmdQueue)
check_exists(dst_list)
# 生成可执行文件
def build_target(src:list):
flags=f"{' '.join(INC)} {' '.join(DEF)} {' '.join(CFLAG)}"
obj_list=[]
for i in src:
name=os.path.splitext(tran_path(i))[0]
obj_list.append('.'.join([name,'o']))
dst=os.path.join(OUTPUT,TARGET)+".elf"
if(check_rebuild(dst,obj_list)):
cmd=f"{CC} {' '.join(obj_list)} -o {dst} {flags} -T{LD_FILE} -Wall -Wextra -nostartfiles -Wl,-Map,\"{OUTPUT}/{TARGET}.map\""
print(f"链接 {dst}")
ret=os.system(cmd)
if(ret):
exit()
def main():
global SRC
if not os.path.exists(OUTPUT):
os.mkdir(OUTPUT)
build_depend(SRC)
build_object(SRC)
build_target(SRC)
os.system(f"{OBJCPY} -O binary {OUTPUT}/{TARGET}.elf {OUTPUT}/{TARGET}.bin")
os.system(f"{OBJCPY} -O ihex {OUTPUT}/{TARGET}.elf {OUTPUT}/{TARGET}.hex")
os.system(f"{OBJDUMP} -d {OUTPUT}/{TARGET}.elf > {OUTPUT}/{TARGET}.lst")
if __name__ == "__main__":
tick_start=time.time()
main()
tick_end=time.time()
print(f"cost: {tick_end-tick_start}")