实验代码框架讲解
本节目录
项目结构
.
├── exercises //所有习题都在此文件夹下
├── LICENSE
├── Makefile
├── README.en.md
├── README.md
└── test //所有测例都在此文件夹下
- exercises:这个文件夹包含了所有的习题代码。每个习题可以作为一个子文件夹,其中包含习题的源代码、数据文件和任何相关的资源。
- LICENSE:项目的许可证文件,定义了项目的使用、修改和分发的法律条款。
- Makefile:一个自动化构建脚本,用于编译、测试和清理项目。通过运行
make命令,可以执行 Makefile 中定义的任务。 - test:这个文件夹包含了所有的测试用例。每个测试用例可以作为一个子文件夹或文件,用于验证习题代码的正确性。
Makefile 内容
实验框架的 Makefile:
# Makefile variables for directory structure and tools
AUX_DIR := aux # Auxiliary directory
BUILD_DIR := build # Build output directory
SRC_DIR := src # Source code directory
RESULT_DIR := result # Test result directory
TEST_DIR := test # Directory containing test scripts
# Compiler settings
CC ?= gcc # Default compiler
# Compiler flags
CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -Werror -g # C compiler flags
LDFLAGS = -Wl,--as-needed -Wl,--no-undefined # Linker flags
# Find all exercise directories under SRC_DIR
EXERCISES := $(shell find $(SRC_DIR) -type d -name 'exercise-*' -exec basename {} \;)
# Default target: build all exercises
all: $(EXERCISES)
# Build each exercise directory
$(EXERCISES):
@mkdir -p $(abspath $(BUILD_DIR))/$(notdir $@)
$(MAKE) -C $(SRC_DIR)/$@ OUTPUT_DIR=$(abspath $(BUILD_DIR))/$(notdir $@) || true
# Test target: run tests for all exercises
test: $(RESULT_DIR) $(EXERCISES:%=test-%) report generate_json_report
# Test each exercise
test-%: $(BUILD_DIR)/%
@mkdir -p $(RESULT_DIR)/$*
@echo "Running tests for $*"
@$(TEST_DIR)/$*/test.sh $(BUILD_DIR)/$*/$* && touch $(RESULT_DIR)/$*/$*.pass || touch $(RESULT_DIR)/$*/$*.fail
# Create build directory if it doesn't exist
$(BUILD_DIR):
@mkdir -p $(BUILD_DIR)
# Create result directory if it doesn't exist
$(RESULT_DIR):
@mkdir -p $(RESULT_DIR)
# Generate a human-readable test report
report:
@echo "Generating test report..."
@total=$$(find $(RESULT_DIR) -type f -name '*.pass' -o -name '*.fail' | wc -l); \
success=$$(find $(RESULT_DIR) -type f -name '*.pass' | wc -l); \
failed=$$(find $(RESULT_DIR) -type f -name '*.fail' | wc -l); \
echo "Total tests: $$total"; \
echo "Success: $$success"; \
echo "Failed: $$failed"; \
echo "Success tests:"; \
find $(RESULT_DIR) -type f -name '*.pass' -exec basename {} .pass \; | sed 's/^/ /'; \
echo "Failed tests:"; \
find $(RESULT_DIR) -type f -name '*.fail' -exec basename {} .fail \; | sed 's/^/ /'
# Generate a JSON test report
generate_json_report:
@echo "Generating JSON report..."
@success=$$(find $(RESULT_DIR) -type f -name '*.pass' | wc -l); \
score=$$((success * 5)); \
total_score=100; \
channel="gitee"; \
course_id=1546; \
ext="aaa"; \
name=""; \
echo '{' > $(RESULT_DIR)/report.json; \
echo ' "channel": "'$$channel'"'',' >> $(RESULT_DIR)/report.json; \
echo ' "courseId": ' $$course_id',' >> $(RESULT_DIR)/report.json; \
echo ' "ext": "'$$ext'"'',' >> $(RESULT_DIR)/report.json; \
echo ' "name": "'$$name'"'',' >> $(RESULT_DIR)/report.json; \
echo ' "score": ' $$score',' >> $(RESULT_DIR)/report.json; \
echo ' "totalScore": ' $$total_score >> $(RESULT_DIR)/report.json; \
echo '}' >> $(RESULT_DIR)/report.json;
# Clean target: remove all generated files and directories
clean:
for dir in $(EXERCISES); do \
$(MAKE) -C $$dir clean; \
done
rm -rf $(BUILD_DIR) $(RESULT_DIR)
# Declare phony targets to prevent conflicts with file names
.PHONY: all clean $(EXERCISES) report generate_json_report
- 目录定义:
EXERCISE_DIR:存放练习文件的目录。TEST_DIR:存放测试文件的目录。BUILD_DIR:存放构建产物的目录。
- 文件和目录操作:
mkdir -p $(TEST_DIR) $(BUILD_DIR):确保测试和构建目录存在。
- 编译和链接:
CC = gcc:定义编译器为 gcc。CFLAGS = -Wall -Wextra -std=c99:编译选项,包括警告和 C99 标准。LDFLAGS = -lm:链接选项,链接数学库。
- 构建规则:
$(BUILD_DIR)/%: $(EXERCISE_DIR)/%.c:为每个练习文件生成对应的执行文件。
- 清理规则:
clean:删除所有执行文件和构建目录下的对象文件。
- 测试规则:
generate-test-cases:生成测试用例。test-output:运行测试并比较输出结果。save-test-results:保存测试结果和通过率到 JSON 文件。
使用 makefile 进行实验
在实验过程中,Makefile 提供了自动化构建和测试的便利。以下是如何使用这个 Makefile 进行实验的步骤:
-
编译所有练习:
make这个命令会编译所有练习文件,并在
BUILD_DIR目录下生成对应的执行文件。 -
生成测试用例:
make generate-test-cases这个命令会运行所有执行文件,并将输出保存为测试用例。
-
运行测试:
make test-output这个命令会比较每个执行文件的输出与预期结果,并显示测试结果。
-
保存测试结果:
make save-test-results这个命令会计算测试的通过率,并将结果保存到
test_results.json文件中。 -
清理:
make clean这个命令会删除所有构建产物和对象文件,保持环境整洁。