使用include!引入生成的mod文件时触发E0583文件未找到错误
我的Advent of Code项目文件结构如下:
days.rs days/ day01.rs day02.rs ...
我通过build.rs生成了days.in文件,内容为:
pub mod day01; pub mod day02; ...
随后在days.rs中用include!(concat!(env!("OUT_DIR"), "/days.in"));引入该文件。但执行cargo run或cargo build时,每个day模块都触发错误:
error[E0583]: file not found for module `day01` --> D:\Projects\advent-of-code-2024\target\debug\build\advent-of-code-2024-59c0dcca155b0f0e\out\days.in:1:1 | 1 | pub mod day01; | ^^^^^^^^^^^^^^ | = help: to create the module `day01`, create file "D:\Projects\advent-of-code-2024\target\debug\build\advent-of-code-2024-59c0dcca155b0f0e\out\day01.rs" or "D:\Projects\advent-of-code-2024\target\debug\build\advent-of-code-2024-59c0dcca155b0f0e\out\day01\mod.rs" = note: if there is a `mod day01` elsewhere in the crate already, import it with `use crate::...` instead
我发现错误定位在days.in而非days.rs,怀疑include!不是单纯把文件内容复制粘贴到宏位置。而手动将days.in内容替换include!语句后,程序能正常运行。
include!宏确实会将目标文件内容插入到调用位置,但编译器解析模块时,路径是相对于被插入文件的实际位置,而非调用include!的文件位置。
你生成的days.in位于OUT_DIR目录下,当编译器解析其中的pub mod day01;时,会默认在OUT_DIR目录下寻找day01.rs或day01/mod.rs,而非项目根目录下的days/day01.rs。但手动复制内容到days.rs时,pub mod day01;是在days.rs所在目录(项目根)下解析,自然能找到days/子目录里的模块文件。
修改build.rs生成的days.in内容,通过以下方式规避路径问题:
方案1:用绝对路径引入模块
将days.in内容改为绝对路径的use语句:
pub use crate::days::day01; pub use crate::days::day02; // ... 其他day模块
这种方式会从crate根目录定位模块,不受days.in所在位置影响。
方案2:给模块声明指定路径属性
保留mod声明的同时,用path属性指定模块文件的实际位置:
#[path = "../../../days/day01.rs"] pub mod day01; #[path = "../../../days/day02.rs"] pub mod day02; // ... 其他day模块
注意这里的相对路径是从OUT_DIR指向项目中days/文件夹的实际路径,需要根据你的项目结构调整层级。
方案3:直接修改days.rs生成模块声明
如果build.rs仅用于自动生成模块列表,可让它直接修改days.rs(比如在文件末尾追加模块声明),完全替代include!,从根源避免路径问题。
内容的提问来源于stack exchange,提问作者Koen

