feat(build): 引入新的 Python 构建系统并移除旧 Makefile
新增基于 Python 的构建脚本 `cbuild.py`,支持包管理、依赖解析和模块化编译。 同时添加 `.gitignore` 忽略 `build` 目录,并在 `justfile` 中更新构建命令。 移除了原有的 `lib/Makefile` 和主目录下的相关 make 规则,统一使用新构建系统。
This commit is contained in:
2
tests/cbuild/cbuild.toml
Normal file
2
tests/cbuild/cbuild.toml
Normal file
@@ -0,0 +1,2 @@
|
||||
[package]
|
||||
name = "test_cbuild"
|
||||
6
tests/cbuild/include/add.h
Normal file
6
tests/cbuild/include/add.h
Normal 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
3
tests/cbuild/src/add.c
Normal file
@@ -0,0 +1,3 @@
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
8
tests/cbuild/src/main.c
Normal file
8
tests/cbuild/src/main.c
Normal 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;
|
||||
}
|
||||
10
tests/cbuild/tests/test_main.c
Normal file
10
tests/cbuild/tests/test_main.c
Normal 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
3
tests/simple/01_return.c
Normal file
@@ -0,0 +1,3 @@
|
||||
int main() {
|
||||
return 65536;
|
||||
}
|
||||
8
tests/simple/02_decl_expr.c
Normal file
8
tests/simple/02_decl_expr.c
Normal file
@@ -0,0 +1,8 @@
|
||||
int main() {
|
||||
int a;
|
||||
int b;
|
||||
a = 1 + 2 * 3;
|
||||
b = 7;
|
||||
a = a - b + 1;
|
||||
return a;
|
||||
}
|
||||
6
tests/simple/03_decl_init.c
Normal file
6
tests/simple/03_decl_init.c
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
int main() {
|
||||
int x = 10;
|
||||
x = x + 1;
|
||||
return x;
|
||||
}
|
||||
10
tests/simple/04_if.c
Normal file
10
tests/simple/04_if.c
Normal 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
10
tests/simple/05_else.c
Normal 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
9
tests/simple/06_fcall.c
Normal 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
5
tests/simple/07_while.c
Normal file
@@ -0,0 +1,5 @@
|
||||
int main() {
|
||||
int i = 0;
|
||||
while (i < 10) i = i + 1;
|
||||
return i;
|
||||
}
|
||||
12
tests/simple/08_do_while.c
Normal file
12
tests/simple/08_do_while.c
Normal 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
7
tests/simple/09_for.c
Normal 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
7
tests/simple/10_main.c
Normal file
@@ -0,0 +1,7 @@
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
return add(1, 2);
|
||||
}
|
||||
18
tests/simple/11_recursive.c
Normal file
18
tests/simple/11_recursive.c
Normal 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
30
tests/simple/Makefile
Normal 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
6
tests/simple/hard_01.c
Normal file
@@ -0,0 +1,6 @@
|
||||
int main() {
|
||||
int a, b;
|
||||
a = 1;
|
||||
b = 2;
|
||||
return a + b;
|
||||
}
|
||||
86
tests/simple/test.py
Normal file
86
tests/simple/test.py
Normal 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()
|
||||
Reference in New Issue
Block a user