2024-06-28 21:34:36 +08:00
|
|
|
|
# -*- coding: utf-8 -*-
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import os
|
|
|
|
|
import sys
|
|
|
|
|
import time
|
2025-06-26 19:24:21 +08:00
|
|
|
|
import dataclasses
|
2025-06-28 10:18:18 +08:00
|
|
|
|
from multiprocessing import Process,Queue,Value,cpu_count
|
2025-06-20 15:50:39 +08:00
|
|
|
|
from create_lambda_fun import search_lambda
|
2025-06-24 16:32:32 +08:00
|
|
|
|
from create_signal_fun import moc_file_create
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
修改编译脚本之后需要全编译一次
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CC = 'gcc'
|
|
|
|
|
|
2025-06-26 16:15:07 +08:00
|
|
|
|
CSRC = ["main.c"]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
2025-06-24 17:59:23 +08:00
|
|
|
|
CINC = ['-Isoft',"-Iriscv_cpu", "-I./","-Itest"]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
2024-06-21 15:20:47 +08:00
|
|
|
|
CDEF = ["-DTEST","-DLINUX"]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
ASRC = []
|
|
|
|
|
|
|
|
|
|
BUILD_DIR = 'build'
|
|
|
|
|
|
2025-04-17 23:36:44 +08:00
|
|
|
|
TARGET = 'hello'
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
# 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"]
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# -pedantic 这一项是ISO语法检验
|
2025-04-17 23:36:44 +08:00
|
|
|
|
CFLAG = ["-Wall -g","-pthread"]
|
2024-06-21 15:20:47 +08:00
|
|
|
|
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 找到指定后缀的文件
|
2025-04-17 23:36:44 +08:00
|
|
|
|
def find_type(path:str,fix:list):
|
2024-06-18 19:37:43 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
2024-06-28 21:34:36 +08:00
|
|
|
|
将.c编译为.o文件,
|
|
|
|
|
编译脚本需要实现 如果.c文件有修改 则重新编译对应文件的.o文件
|
2024-06-18 19:37:43 +08:00
|
|
|
|
gcc -c test.c -o test.o
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
输出依赖关系到.d文件
|
2024-06-18 19:37:43 +08:00
|
|
|
|
gcc -MM main.c -o build/main.d
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def tran_path(path:str):
|
2025-06-26 17:41:33 +08:00
|
|
|
|
path=os.path.normpath(os.path.join(BUILD_DIR,path))
|
|
|
|
|
base_path=os.path.dirname(path)
|
|
|
|
|
if not os.path.exists(base_path):
|
|
|
|
|
os.makedirs(base_path)
|
|
|
|
|
return path
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 判断是否需要重新生成
|
2025-04-17 23:36:44 +08:00
|
|
|
|
def check_rebuild(dst:str,src:list):
|
2024-06-18 19:37:43 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 读取.d文件,返回依赖文件列表
|
2024-06-18 19:37:43 +08:00
|
|
|
|
def read_depend_files(name:str):
|
|
|
|
|
with open(name) as f:
|
2024-06-21 15:20:47 +08:00
|
|
|
|
lines=f.readlines()
|
|
|
|
|
t=''
|
|
|
|
|
for line in lines:
|
|
|
|
|
line=line.strip()
|
|
|
|
|
if(line[-1]=='\\'):
|
|
|
|
|
t+=line[:-1]
|
|
|
|
|
else:
|
|
|
|
|
t+=line
|
2024-06-18 19:37:43 +08:00
|
|
|
|
t=t.split(':')[-1].strip()
|
|
|
|
|
t=t.split(' ')
|
|
|
|
|
return t
|
|
|
|
|
|
|
|
|
|
|
2025-06-26 19:24:21 +08:00
|
|
|
|
@dataclasses.dataclass
|
|
|
|
|
class cmd_item_t:
|
|
|
|
|
cmd:str
|
|
|
|
|
info:str
|
|
|
|
|
|
2025-06-26 21:08:34 +08:00
|
|
|
|
def run_cmd(cmd_queue:Queue,cpu_index:int,return_list:Queue,failed_num):
|
2025-06-26 19:24:21 +08:00
|
|
|
|
while(not cmd_queue.empty()):
|
2025-06-26 21:08:34 +08:00
|
|
|
|
if(failed_num.value>0):
|
|
|
|
|
return
|
2025-06-26 19:24:21 +08:00
|
|
|
|
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))
|
2025-06-26 21:08:34 +08:00
|
|
|
|
failed_num.value+=1
|
2025-06-26 19:24:21 +08:00
|
|
|
|
return
|
|
|
|
|
return_list.put((cpu_index,True))
|
|
|
|
|
|
|
|
|
|
|
2025-06-28 10:18:18 +08:00
|
|
|
|
def run_cmd_queue(cmd_queue:Queue,cpu_num:int=cpu_count()):
|
2025-06-26 19:24:21 +08:00
|
|
|
|
if(cmd_queue.empty()):
|
|
|
|
|
return
|
|
|
|
|
process_list = []
|
|
|
|
|
return_list=Queue()
|
2025-06-26 21:08:34 +08:00
|
|
|
|
failed_num=Value('i',0)
|
2025-06-26 19:24:21 +08:00
|
|
|
|
for i in range(cpu_num):
|
2025-06-26 21:08:34 +08:00
|
|
|
|
p = Process(target=run_cmd,args=(cmd_queue,i,return_list,failed_num,))
|
2025-06-26 19:24:21 +08:00
|
|
|
|
p.start()
|
|
|
|
|
process_list.append(p)
|
|
|
|
|
for i in process_list:
|
2025-06-28 10:18:18 +08:00
|
|
|
|
i.join()
|
2025-06-28 13:30:57 +08:00
|
|
|
|
# 消耗掉所有数据防止进程无法退出
|
|
|
|
|
while not cmd_queue.empty():
|
|
|
|
|
cmd_queue.get()
|
2025-06-26 19:24:21 +08:00
|
|
|
|
while not return_list.empty():
|
|
|
|
|
i=return_list.get()
|
|
|
|
|
if(not i[1]):
|
|
|
|
|
print(f"子进程 [{i[0]}] 运行失败")
|
2025-06-28 13:30:57 +08:00
|
|
|
|
sys.exit(-1)
|
2025-06-26 19:24:21 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 保证目标都存在
|
|
|
|
|
def check_exists(src:list):
|
|
|
|
|
for item in src:
|
|
|
|
|
for i in range(10):
|
|
|
|
|
if(os.path.exists(item)):
|
|
|
|
|
break
|
|
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 生成依赖关系
|
2025-04-17 23:36:44 +08:00
|
|
|
|
def build_depend(src:list):
|
2025-06-26 19:24:21 +08:00
|
|
|
|
CmdQueue=Queue()
|
|
|
|
|
dst_list=[]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}"
|
|
|
|
|
for i in src:
|
2025-06-26 17:41:33 +08:00
|
|
|
|
name=os.path.splitext(tran_path(i))[0]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
dst='.'.join([name,'d'])
|
|
|
|
|
if(check_rebuild(dst,[i])):
|
|
|
|
|
cmd=f"{CC} -MM {i} -o {dst} {flags}"
|
2025-06-26 19:24:21 +08:00
|
|
|
|
CmdQueue.put(cmd_item_t(cmd,f"更新 {dst}"))
|
|
|
|
|
dst_list.append(dst)
|
|
|
|
|
run_cmd_queue(CmdQueue)
|
|
|
|
|
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 生成中间文件
|
2025-04-17 23:36:44 +08:00
|
|
|
|
def build_object(src:list):
|
2025-06-26 19:24:21 +08:00
|
|
|
|
CmdQueue=Queue()
|
|
|
|
|
dst_list=[]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}"
|
|
|
|
|
for i in src:
|
2025-06-26 17:41:33 +08:00
|
|
|
|
name_t=os.path.splitext(tran_path(i))
|
|
|
|
|
name=name_t[0]
|
|
|
|
|
file_type=name_t[-1]
|
2024-06-18 19:37:43 +08:00
|
|
|
|
dst='.'.join([name,'o'])
|
|
|
|
|
cd='.'.join([name,'d'])
|
2025-06-26 17:41:33 +08:00
|
|
|
|
if(file_type in ['.c','.C']):
|
2024-06-18 19:37:43 +08:00
|
|
|
|
if(check_rebuild(dst,read_depend_files(cd))):
|
|
|
|
|
cmd=f"{CC} -c {i} -o {dst} {flags}"
|
2025-06-26 19:24:21 +08:00
|
|
|
|
CmdQueue.put(cmd_item_t(cmd,f"编译 {dst}"))
|
|
|
|
|
dst_list.append(dst)
|
|
|
|
|
run_cmd_queue(CmdQueue)
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
2024-06-28 21:34:36 +08:00
|
|
|
|
# 生成可执行文件
|
2025-04-17 23:36:44 +08:00
|
|
|
|
def build_target(src:list):
|
2024-06-18 19:37:43 +08:00
|
|
|
|
flags=f"{' '.join(CINC)} {' '.join(CDEF)} {' '.join(CFLAG)}"
|
|
|
|
|
obj_list=[]
|
|
|
|
|
for i in src:
|
2025-06-26 17:41:33 +08:00
|
|
|
|
name=os.path.splitext(tran_path(i))[0]
|
|
|
|
|
obj_list.append('.'.join([name,'o']))
|
2024-06-18 19:37:43 +08:00
|
|
|
|
dst=os.path.join(BUILD_DIR,TARGET)
|
|
|
|
|
if(check_rebuild(dst,obj_list)):
|
|
|
|
|
cmd=f"{CC} {' '.join(obj_list)} -o {dst} {flags}"
|
2025-06-26 00:33:08 +08:00
|
|
|
|
print(f"链接 {dst}")
|
2024-06-18 19:37:43 +08:00
|
|
|
|
ret=os.system(cmd)
|
|
|
|
|
if(ret):
|
2025-06-28 13:30:57 +08:00
|
|
|
|
sys.exit(-1)
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
|
global CSRC
|
|
|
|
|
global ASRC
|
2025-06-20 17:26:36 +08:00
|
|
|
|
if(not os.path.exists(BUILD_DIR)):
|
|
|
|
|
os.makedirs(BUILD_DIR)
|
2025-06-26 16:15:07 +08:00
|
|
|
|
# 在命令行中传入的源文件
|
|
|
|
|
CSRC+=sys.argv[1:]
|
2025-04-17 23:36:44 +08:00
|
|
|
|
CSRC+=find_type('soft',['c','C'])
|
2025-06-24 17:59:23 +08:00
|
|
|
|
CSRC+=find_type('riscv_cpu',['c','C'])
|
2025-06-20 15:50:39 +08:00
|
|
|
|
CSRC=search_lambda(CSRC)
|
2025-06-24 16:32:32 +08:00
|
|
|
|
moc_file_create(f"{BUILD_DIR}/moc_tmp.c",list(item[2:] for item in CINC))
|
|
|
|
|
CSRC.append(f"{BUILD_DIR}/moc_tmp.c")
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
build_depend(CSRC)
|
|
|
|
|
build_object(CSRC)
|
|
|
|
|
build_target(CSRC+ASRC)
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
2025-06-26 19:24:21 +08:00
|
|
|
|
tick_start=time.time()
|
|
|
|
|
main()
|
|
|
|
|
tick_end=time.time()
|
|
|
|
|
print(f"cost: {tick_end-tick_start}")
|
2024-06-18 19:37:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|