Scons如何计算构建签名?

时间:2015-11-18 14:57:11

标签: scons

我将一个项目的不同版本保存在不同的目录中。 (这个确实在这个项目中有意义。可悲的。)由于版本之间只有细微的差别,我希望通过对所有版本使用公共缓存目录,我可以在第一个版本之后加速所有版本。

不幸的是,我必须意识到,当从不同目录中的相同源构建目标文件时,SCons 2.3.3将结果存储在缓存中的不同位置。 (我假设该位置等于构建签名。)为每个目录重新编译相同的源。那么为什么SCons确定不同的构建签名,尽管

  • 编译命令相同且
  • 源文件和包含文件是相同的(预处理器阶段的相同输出,gcc -E ...
  • 我正在使用决策程序“MD5-timestamp”

即使生成的目标文件也相同!

对于一个简单的例子(来自SCons文档的helloworld)重用缓存有效。虽然在我正在开展的大型项目中,但事实并非如此。也许“SCons构建环境”会影响构建签名,即使它对编译命令没有任何影响吗?

除了--cache-debug=-之外,是否有任何可以帮助的调试选项? SCons的哪种方法决定了构建签名?

文件夹看起来像这样:

<basedir1>/
       SConstruct
       src/something.cpp …
       include/header.hpp …
<basedir2>/
       SConstruct
       src/something.cpp …
       include/header.hpp …
/SharedCache/
       0/ 1/ 2/ … F/

我在 basedir1 basedir2 中检查项目,并在两者中调用scons --build-cache-dir=/SharedCache。 (编辑:--build-cache-dir是一个自定义选项,在此项目的SConstruct文件中实现。它映射到env.CacheDir('/SharedCache')

EDIT2:在我意识到这个问题之前,我做了一些测试来评估使用--cache-implicit或SCons 2.4.0的效果。

1 个答案:

答案 0 :(得分:1)

这是文件src/engine/SCons/Node/FS.py中方法def get_cachedir_bsig(self): """ Return the signature for a cached file, including its children. It adds the path of the cached file to the cache signature, because multiple targets built by the same action will all have the same build signature, and we have to differentiate them somehow. """ try: return self.cachesig except AttributeError: pass # Collect signatures for all children children = self.children() sigs = [n.get_cachedir_csig() for n in children] # Append this node's signature... sigs.append(self.get_contents_sig()) # ...and it's path sigs.append(self.get_internal_path()) # Merge this all into a single signature result = self.cachesig = SCons.Util.MD5collect(sigs) return result 的代码:

get_cachedir_csig()

它显示了缓存文件的路径如何包含在“缓存构建签名”中,这解释了您看到的行为。为了完整起见,这里还有来自同一FS.py文件的def get_cachedir_csig(self): """ Fetch a Node's content signature for purposes of computing another Node's cachesig. This is a wrapper around the normal get_csig() method that handles the somewhat obscure case of using CacheDir with the -n option. Any files that don't exist would normally be "built" by fetching them from the cache, but the normal get_csig() method will try to open up the local file, which doesn't exist because the -n option meant we didn't actually pull the file from cachedir. But since the file *does* actually exist in the cachedir, we can use its contents for the csig. """ try: return self.cachedir_csig except AttributeError: pass cachedir, cachefile = self.get_build_env().get_CacheDir().cachepath(self) if not self.exists() and cachefile and os.path.exists(cachefile): self.cachedir_csig = SCons.Util.MD5filesignature(cachefile, \ SCons.Node.FS.File.md5_chunksize * 1024) else: self.cachedir_csig = self.get_csig() return self.cachedir_csig 方法的代码:

RunAndRenderTask

将子节点的缓存路径散列到最终构建签名中。

编辑:然后使用上面计算的“缓存构建签名”来构建“缓存路径”。像这样,所有文件/目标都可以映射到一个唯一的“缓存路径”,通过它可以引用它们并在缓存中找到(=从中检索)。正如上面的注释所解释的那样,每个文件的相对路径(从SConstruct的顶级文件夹开始)是这个“缓存路径”的一部分。因此,如果您在不同的目录中具有相同的源/目标(foo.c-&gt; foo.obj),它们将具有不同的“缓存路径”并且彼此独立构建。

如果您真的想在不同项目之间共享源代码,请注意CacheDir功能如何更多地用于在不同开发人员之间共享相同的源,您可能需要查看Repository()方法。它让你将另一个源树挂载(融入)到你当前的项目......