04-13-2023, 04:19 PM
SCons构建C/C++文件的时候不使用类似-MF之类的选项,那么它是怎么知道一个目标文件依赖什么文件的?
首先SCons是支持在修改了一个目标文件依赖的头文件之后,重新构建目标文件的。SCons把依赖信息放到了 .sconsign.dblite 文件里面,用 sconsign 工具就可以看到依赖。之后我发现了一个问题,SCons记录的目标文件的依赖里面,只有通过 #include 用引号包含的文件,而用尖括号包含的文件,例如 "#include <stdio.h>" 包含的 stdio.h 是不在依赖列表里面的。简单地测试一下也能看出来,改了 stdio.h 之后不会触发 SCons 重新构建。这个倒不是什么大问题,因为工程内的文件用尖括号包含是不能通过编译的,但是如果系统的头文件更新了,不重新构建就可能会出现不同目标文件引用头文件不一致的问题。
然后我找了关于SCons和sconsign相关的代码,看到了SCons有个SCanner模块,简略地看了下代码,发现它是实现了一个简单的预处理器。在SCanner模块下还能看到一些其他语言的Scanner. 在 Tool/__init__.py 下,SCons 根据文件后缀选择调用哪种 Scanner,从而知道一个源文件编译出的文件依赖哪些文件。
首先SCons是支持在修改了一个目标文件依赖的头文件之后,重新构建目标文件的。SCons把依赖信息放到了 .sconsign.dblite 文件里面,用 sconsign 工具就可以看到依赖。之后我发现了一个问题,SCons记录的目标文件的依赖里面,只有通过 #include 用引号包含的文件,而用尖括号包含的文件,例如 "#include <stdio.h>" 包含的 stdio.h 是不在依赖列表里面的。简单地测试一下也能看出来,改了 stdio.h 之后不会触发 SCons 重新构建。这个倒不是什么大问题,因为工程内的文件用尖括号包含是不能通过编译的,但是如果系统的头文件更新了,不重新构建就可能会出现不同目标文件引用头文件不一致的问题。
然后我找了关于SCons和sconsign相关的代码,看到了SCons有个SCanner模块,简略地看了下代码,发现它是实现了一个简单的预处理器。在SCanner模块下还能看到一些其他语言的Scanner. 在 Tool/__init__.py 下,SCons 根据文件后缀选择调用哪种 Scanner,从而知道一个源文件编译出的文件依赖哪些文件。