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

Is there a way to compare obj files from Visual Studio?

本文关键字:中的 obj 文件 Studio Visual 比较 有没有      更新时间:2023-10-16

我有一个C++项目,它构建了多种配置(不仅仅是调试/发布(,这是一个相当大的项目。 让我们称之为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 无关。 因此,如果我们在 Unicode 配置中构建它,然后使用 MultiByte 配置再次构建它,我们只是在浪费时间。 我们可以把它放到它自己的静态库中,它是在没有Unicode支持的情况下构建的,然后这个新的库可以被我的其他项目使用。 这没有什么风险。

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

编辑:进一步澄清:

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可以在其多种配置中构建,而NewProject只需一个调试/发布选项即可构建。

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

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

在 Linux 和 Cygwin/MINGW 上,有 ccache 可以帮助解决这个问题(检测具有相同编译标志的相同预处理源(。SCons(使用python的make替代品(也可以做同样的事情。

对于Visual Studio,恐怕你会关注IncrediBuild。

也就是说,这个答案列出了一些对其他候选人(正在进行的项目(的引用:有Visual Studio的Ccache吗?

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

在Visual Studio中,检查编译器/链接器生成的二进制文件的主要工具是dumpbin.exe。检查如何比较同一项目生成的二进制映像

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

旁注,在构建之间重用 .obj 文件的想法非常弱,尤其是在配置略有不同的构建之间。可能有许多微妙的问题。例如,考虑到完全相同的构建配置,理论上,静态库等效于 .obj 文件的集合。但是,我遇到了非常奇怪的差异和问题,将我的应用程序链接到静态库与链接到该库的 *.obj 文件。这是我在 MSDN 论坛中的帖子,您可以在其中找到与 .obj 文件相关的一些详细信息,作为静态库的直接替代品。

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

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

在 Visual Studio 中:

  1. 右键单击项目,然后转到"属性">
  2. 在"配置属性"-> C/C++ -> 预处理器下,编辑"生成预处理的文件">
  3. 将其设置为Without Line Numbers (/EP /P)
  4. 在配置 A 中执行构建
  5. 预处理的文件在与源文件相同的目录中生成,而不是在配置子目录中生成,因此请将所有*.i文件移动到ConfigurationA子目录中以便安全保存。
  6. 对配置 B(和任何其他配置(重复步骤 45
  7. 比较每个配置子目录中的各个*.i文件。 如果源文件在所有配置中生成相同的.i文件,则最好将其提取到不同的(单配置(库中。
  8. Generate Preprocessed File设置回其原始设置。

但是,如果您使用的是预编译标头,则可能会搞砸它。 预编译标头可能包含给定文件根本不需要的内容,但会导致预处理器输出发生不必要的更改。

例如 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恢复到以前的辉煌。