使用Dune从批量纯文本文件生成可执行.ml测试用例
解决Dune自动生成OCaml测试用例的问题
问题分析
你在为词法/解析模块搭建测试套件时,希望Dune自动处理目录中的.ll测试文件并生成OCaml测试用例,遇到两个核心问题:
- 使用
%{input-file}在别名规则中报错,因为这类规则的动作是一次性执行,无法针对每个依赖文件单独触发 - 无法通过通配符自动匹配所有源/目标文件,需要手动逐个列出
解决方案
1. 针对每个.ll文件单独执行脚本
Dune的(foreach)语法可以遍历所有依赖文件,为每个文件单独执行处理脚本,替换报错的%{input-file}:
(tests (names lexer) (libraries llvmlexer llvmparser ounit2)) (rule (alias runtest) (deps (glob_files **/*.ll)) ; 递归匹配所有.ll文件,可根据目录结构调整路径 (action (foreach %{deps} (run ./preprocess-lexer.sh %{item}))))
这里%{item}会遍历每个匹配到的.ll文件,作为脚本的输入参数,解决了单个动作无法处理多文件的问题。
2. 自动关联源文件与生成的测试目标
如果你的脚本需要生成对应的OCaml测试文件(比如从test.ll生成test_test.ml),可以用Dune的动态目标命名规则,无需手动列出每个文件:
; 为每个.ll文件生成对应的测试用例.ml文件 (rule (targets %{basename}_test.ml) (deps %{input-file}) (action (run ./preprocess-lexer.sh %{input-file} %{target}))) ; 将生成的测试文件纳入测试套件 (tests (names lexer) (modules lexer %{glob:*_test.ml}) ; 自动包含所有生成的_test.ml文件 (libraries llvmlexer llvmparser ounit2))
%{basename}会提取.ll文件的文件名(不含后缀),自动生成对应的测试目标文件;%{glob:*_test.ml}则会匹配所有生成的测试文件,无需手动逐个添加。
关键说明
(glob_files **/*.ll):递归匹配项目中所有.ll文件,若只需匹配特定目录,可改为(glob_files test/*.ll)这类路径(foreach):仅适用于(action)块,用于遍历依赖列表执行重复动作- 动态目标命名:利用
%{basename}、%{target}等变量,让Dune自动关联源文件与生成目标,避免手动维护文件列表
内容的提问来源于stack exchange,提问作者s1gtrap
相关产品推荐
相关产品推荐

