有没有办法比较Visual Studio中的obj文件?

时间:2011-10-25 20:47:31

标签: c++ visual-studio build

我有一个C ++项目,它构建了多个配置(不仅仅是Debug / Release),而且它是一个相当庞大的项目。我们称之为KitchenSink.vcproj

我怀疑这个项目的许多部分都是相同的,无论配置如何。例如。对于不使用字符串的源文件,使用/不支持Unicode的构建无关紧要。

这将导致在多个配置中编译相同的源文件,但生成(有效)相同的.obj文件。它不会生成相同的文件,因为时间戳等嵌入在文件中,但目标文件的所有功能部分都是相同的。

有没有办法检查这个?我想将KitchenSink的部分提取到他们自己的,更简单的项目中,他们只需要构建一次。这将加快构建时间,并简化我们的代码库。但我需要一种方法来自动查找构建相同代码的部分,无论配置如何。有没有一种简单的方法可以做到这一点?

编辑:澄清我的观点。想象一下以下文件:

// Some header file
int calculate_something(int a, int b);

// The source file
int calculate_something(int a, int b) {
    return a * b;
}

现在,该源文件与Unicode无关。因此,如果我们在U​​nicode配置中构建它,然后使用MultiByte配置再次构建它,我们只是在浪费时间。我们可以把它放到它自己的静态库中,它是在没有Unicode支持的情况下构建的,然后我的其他项目可以使用新的lib。这没有任何风险。

我只需找到可以安全移动到单独项目的这些文件。

编辑:进一步澄清:

KitchenSink.vcproj has the following files (among others)
    StringUtils.h
    StringUtils.cpp
    MathStuff.h
    MathStuff.cpp

现在,如果你用Unicode构建KitchenSink,再用MultiByte构建,你将构建两次StringUtils.obj,两次构建MathStuff.obj。显然,这对于StringUtils.obj是必要的,因为它在Unicode和MultiByte中会有所不同。但MathStuff.obj应该构建完全相同的。

所以,我想重新安排/重构/重构以下内容:

KitchenSink.vcproj has the following files (among others)
    StringUtils.h
    StringUtils.cpp

NewProject.vcproj has the following files
    MathStuff.h
    MathStuff.cpp

现在,可以使用多种配置构建KitchenSink,而只需使用一个Debug / Release选项即可构建NewProject。

同样,我不是在谈论共享obj文件。我正在谈论从一个项目中删除cpp / h文件,并将它们放在另一个项目中。

另请注意,Unicode / Multibyte是具有多个配置的项目的示例。我的项目中的实际情况实际上更复杂,因此每个源文件编译4次,而不是Unicode / Multibyte会发生的2次。

4 个答案:

答案 0 :(得分:2)

在linux和Cygwin / MINGW上有ccache可以帮助实现这一点(检测具有相同编译标志的相同预处理源)。 SCons(使用python进行make替换)可以做同样的事情。

对于Visual Studio,我担心你会看IncrediBuild

那就是说,这个答案列出了对其他候选人(正在进行的项目)的一些参考: Is there a Ccache for Visual Studio?

答案 1 :(得分:0)

好吧,您可以使用diff -b来比较.obj文件,但我认为沿着这条路走下去是愚蠢的。所需要的只是对源代码进行一次小的更改,以使优化的构建过程无效。我不会考虑做这样的事情。

答案 2 :(得分:0)

在Visual Studio中,检查编译器/链接器生成的二进制文件的主要工具是dumpbin.exe。查看How to compare binary images of the same project builds

请注意,事实转换单元不使用字符串,并不意味着Unicode和非Unicode构建将是相同的。 Unicode构建会影响Windows API的使用,因此目标文件最终将链接到系统库中的不同符号。

旁注,我们的想法是在构建之间重用.obj文件,特别是在构建稍有不同的构建之间,非常弱。有许多微妙的问题可能。 例如,考虑到完全相同的构建配置,理论上,静态库等同于.obj文件的集合。但是,我遇到了非常奇怪的差异和问题,将我的应用程序与静态库链接到与此库的* .obj文件的链接。以下是我在MSDN论坛中的主题,您可以在其中找到与.obj files as drop-in replacement for static library相关的一些详细信息。

答案 3 :(得分:0)

要查看项目是否在不同的配置中构建相同的文件,但毫无意义,最好比较预处理器的输出。比较目标文件很容易失败,而且不是必需的。

基本思路是:在多个配置的文件上运行预处理器,并比较输出文件。如果它们是相同的,那么在不同的配置中构建该文件并没有多大意义,并且它是一个很好的候选者,可以用更少的配置重构到不同的项目。

在Visual Studio中:

  1. 右键单击项目,然后转到“属性”
  2. 在配置属性下 - > C / C ++ - >预处理器,编辑“生成预处理文件”
  3. 将其设为Without Line Numbers (/EP /P)
  4. 在ConfigurationA中进行构建
  5. 预处理文件生成在与源文件相同的目录中,而不是在配置子目录中生成,因此请将所有*.i文件移至ConfigurationA子目录以便安全保存。
  6. 对ConfigurationB(以及任何其他配置)重复步骤45
  7. 比较每个Configuration子目录中的各个*.i文件。如果源文件在所有配置中生成相同的.i文件,则可以将其提取到不同的(单一配置)库中。
  8. Generate Preprocessed File设置回原始设置。
  9. 然而,如果您使用预编译的标头,那么可能会搞砸了。预编译头可能包含给定文件根本不需要的东西,但会导致预处理器输出不必要地更改。

    E.g。 SimpleFile.cppSimpleFile.h仅使用基本类型,因此根本不需要包含任何内容。但是,SimpleFile.cpp包含stdafx.h,因为VisualStudio要求项目中的每个文件都包含预编译的标头。 stdafx.h包含多个文件,包括HighlyConfigurable.h - 其中包含多个#ifdef语句,并且行为非常不同,具体取决于配置。因此,由于SimpleFile.cpp包含stdafx.h,其中包含HighlyConfigurable.h,因此每个配置的预处理器输出SimpleFile.i将完全不同。然而,如果未使用stdafx.h,则SimpleFile.i在所有配置中都是相同的。

    这里的简单解决方法是注释掉stdafx.h的全部内容。这可能听起来很激烈,但你不打算以这种方式保存文件 - 你只需按照上面的步骤生成预处理器文件进行比较,然后将stdafx.h恢复到以前的荣耀。