feat(build): 引入新的 Python 构建系统并移除旧 Makefile

新增基于 Python 的构建脚本 `cbuild.py`,支持包管理、依赖解析和模块化编译。
同时添加 `.gitignore` 忽略 `build` 目录,并在 `justfile` 中更新构建命令。
移除了原有的 `lib/Makefile` 和主目录下的相关 make 规则,统一使用新构建系统。
This commit is contained in:
zzy
2025-11-20 10:44:59 +08:00
parent 8d97fe896c
commit e22811f2f5
140 changed files with 1996 additions and 10098 deletions

2
tests/cbuild/cbuild.toml Normal file
View File

@@ -0,0 +1,2 @@
[package]
name = "test_cbuild"

View File

@@ -0,0 +1,6 @@
#ifndef __ADD_H__
#define __ADD_H__
int add(int a, int b);
#endif

3
tests/cbuild/src/add.c Normal file
View File

@@ -0,0 +1,3 @@
int add(int a, int b) {
return a + b;
}

8
tests/cbuild/src/main.c Normal file
View File

@@ -0,0 +1,8 @@
#include <stdio.h>
#include <add.h>
int main() {
printf("Hello World!\n");
printf("Add 1 + 1 = %d\n", add(1, 1));
return 0;
}

View File

@@ -0,0 +1,10 @@
int add(int a, int b);
#include <assert.h>
int main() {
int a = 1;
int b = 2;
int c = add(a, b);
assert(c == 3);
return 0;
}

3
tests/simple/01_return.c Normal file
View File

@@ -0,0 +1,3 @@
int main() {
return 65536;
}

View File

@@ -0,0 +1,8 @@
int main() {
int a;
int b;
a = 1 + 2 * 3;
b = 7;
a = a - b + 1;
return a;
}

View File

@@ -0,0 +1,6 @@
int main() {
int x = 10;
x = x + 1;
return x;
}

10
tests/simple/04_if.c Normal file
View File

@@ -0,0 +1,10 @@
int main(void) {
int a;
a = 1;
if (a) {
a = 1;
} else {
a = 2;
}
return a;
}

10
tests/simple/05_else.c Normal file
View File

@@ -0,0 +1,10 @@
int main(void) {
int a;
a = 0;
if (a) {
a = 1;
} else {
a = 2;
}
return a;
}

9
tests/simple/06_fcall.c Normal file
View File

@@ -0,0 +1,9 @@
int add(int, int);
int main(void) {
return add(1, 2);
}
int add(int a, int b) {
return a + b;
}

5
tests/simple/07_while.c Normal file
View File

@@ -0,0 +1,5 @@
int main() {
int i = 0;
while (i < 10) i = i + 1;
return i;
}

View File

@@ -0,0 +1,12 @@
// #include <stdio.h>
int main() {
int i = 0;
int pow = 1;
do {
pow = pow * 2;
i = i + 1;
} while(i < 7);
// printf("%d", pow);
return pow;
}

7
tests/simple/09_for.c Normal file
View File

@@ -0,0 +1,7 @@
int main() {
int num = 0;
for (int i = 0; i < 10; i += 1) {
num = num + 1;
}
return num;
}

7
tests/simple/10_main.c Normal file
View File

@@ -0,0 +1,7 @@
int add(int a, int b) {
return a + b;
}
int main(void) {
return add(1, 2);
}

View File

@@ -0,0 +1,18 @@
// #include <stdio.h>
int factorial(int num);
int main() {
int num = 5;
int result = factorial(num);
// printf("%d", result);
return result;
}
int factorial(int num) {
if (num == 0) {
return 1;
} else {
return num * factorial(num - 1);
}
}

30
tests/simple/Makefile Normal file
View File

@@ -0,0 +1,30 @@
# VM := ../../rv32-vm
# CC := ../../ccompiler
# STD_CC := gcc
# TESTS := $(wildcard *.c)
# # 定义所有测试目标
# TEST_TARGETS := $(patsubst %.c, %_test, $(TESTS))
# all: $(TEST_TARGETS)
# %_test: %.c
# @$(STD_CC) -g -o $@ $<
# @$(CC) $< flat.bin
# @./$@ ; ret_gcc=$$?
# @$(VM) flat.bin ; ret_vm=$$?
# @echo "Testing $@"
# @if [ $$ret_gcc -eq $$ret_vm ]; then \
# echo "$@ passed"; \
# else \
# echo "$@ failed: GCC returned $$ret_gcc, VM returned $$ret_vm"; \
# exit 1; \
# fi
# clean:
# rm -f $(TEST_TARGETS) flat.bin
# .PHONY: all clean
all:
python test.py

6
tests/simple/hard_01.c Normal file
View File

@@ -0,0 +1,6 @@
int main() {
int a, b;
a = 1;
b = 2;
return a + b;
}

86
tests/simple/test.py Normal file
View File

@@ -0,0 +1,86 @@
import subprocess
import os
from pathlib import Path
# 配置参数
TEST_DIR = Path(".")
CC_PATH = Path("../../src/smcc.exe")
VM_PATH = Path("../rv32-vm.exe")
WORKSPACE = Path(".") # 测试工作目录
# 测试用例映射表(示例)
TEST_CASE_MAP = {
"./01_return.c": 65536,
"./02_decl_expr.c": 1,
"./03_decl_init.c": 11,
"./04_if.c": 1,
"./05_else.c": 2,
"./06_fcall.c": 3,
"./07_while.c": 10,
"./08_do_while.c": 128,
"./09_for.c": 10,
"./10_main.c": 3,
"./11_recursive.c": 120,
}
def run_command(cmd, capture_stderr=True):
"""执行命令并捕获stderr"""
result = subprocess.run(
cmd,
cwd=WORKSPACE,
stderr=subprocess.PIPE if capture_stderr else None,
text=True,
timeout=1,
)
return result.stderr.strip() if capture_stderr else None
def run_test(test_file, expected):
print(f"\nTesting {test_file}...")
# 1. 编译生成flat.bin
compile_cmd = [str(CC_PATH), str(test_file)]
compile_err = run_command(compile_cmd)
if not (WORKSPACE / "flat.bin").exists():
print(f" Compilation failed: {compile_err}")
return False
# 2. 执行虚拟机
vm_cmd = [str(VM_PATH), "flat.bin"]
# 3. 解析返回值(假设最后一行是返回值)
try:
vm_err = run_command(vm_cmd)
actual = int(vm_err.split()[-1])
except (ValueError, IndexError) as e:
print(f" Invalid VM output: {vm_err}")
return False
except subprocess.TimeoutExpired:
print(" Timeout expired")
return False
# 4. 验证结果
if actual == expected:
print(f" PASSED {test_file}")
return True
else:
print(f" FAILED: Expected {expected}, got {actual}")
return False
def main():
passed = 0
total = 0
for test_file, expected in TEST_CASE_MAP.items():
total += 1
if run_test(TEST_DIR / test_file, expected):
passed += 1
# 清理中间文件
if (WORKSPACE / "flat.bin").exists():
os.remove(WORKSPACE / "flat.bin")
print(f"\nTest Summary: {passed}/{total} passed")
if __name__ == "__main__":
main()