新人编译报错,指着 fatal error: config.h: No such file or directory 问:源文件明明就在目录里,为什么找不到?过去一看,config.h 在上一级 include 目录,编译命令没带 -I。

源文件是程序员写给人看的文本,编译器读它,再翻译成机器能跑的东西。C 里的 .c 和 .h、Java 的 .java、Go 的 .go、前端 src 下的 .ts 和 .scss,都算源文件。和它相对的叫目标文件,.o、.obj、.class、.pyc,还有最终的可执行文件和库。

编译链路上谁读谁

预处理把 include 的头文件内容原样展开,编译生成汇编,汇编变成 .o,链接器再把多个 .o 和库拼成可执行文件。整个过程只认源文件,产物随时可以删掉重来。所以源文件丢了才是真丢了,.o 丢了执行一次 make 就有。

找不到头文件是搜索路径问题,gcc 加 -I./include,或者把路径写进 Makefile 的 CFLAGS。链接阶段报 undefined reference 则是另一回事,说明函数声明有了、实现没链上,检查 -l 和 -L 参数。

改了头文件不生效的老问题

Makefile 只写了 .c 到 .o 的依赖,没写 .h,改完头文件 make 认为无事可做,跑的还是旧目标文件。gcc -MM 能自动生成依赖文件,把它 include 进来就行。这也是很多人代码改了没生效的真正原因。

还有一层容易混的用法:前端项目里说源文件,指的是 src 下未压缩的 ts 和 scss,产物在 dist;后端说源文件,指的是进版本库的那部分。判断标准其实一致,能被重新加工出产物的是源文件,产物本身不进 git。

编译报错时先分清是找不到源文件、找不到头文件,还是链接不到实现,这三类错误的修法完全不同。