有没有一种方法可以确定使用哪个版本的Visual Studio编译了一个静态库?

40

我有一组静态库(.lib)文件,其中可能有一个是使用了不同版本的Visual Studio进行编译的。这导致了一个链接了所有静态库的项目的代码生成失败。有没有办法确定哪个版本的Visual Studio被用于编译一个静态库?


4
更好的问题是要问哪个版本的编译器。可以在不使用Visual Studio的情况下编译C++静态库。 - JaredPar
好的。在我的情况下,它们都是使用某个版本的Visual Studio进行编译的。然而,还有一个更一般性的问题潜藏其中。 - Bill Carey
一个更好的问题应该是关于Visual C++,因为Visual Studio只是一个集成开发环境。 - rustyx
5个回答

31

对于发布库,你很难确定其版本。

对于调试库,你可以使用dumpbin

dumpbin /rawdata:1 library.lib

汇编清单应该在转储文件的开头,并包含库所需的 CRT 版本以及用于构建库的编译器的完整路径。

对于可执行文件和 DLL,您可以使用 dumpbin 获取链接器版本;它在“OPTIONAL HEADER VALUES”下面。

dumpbin /headers program.exe

也许还有人知道如何获取发布库的版本号;如果他们知道,我也很感兴趣。


1
你能分享一些关于在哪里找到这个工具的细节吗?如果它不是默认随 Visual Studio 安装提供的,那么我们应该从哪里获取它呢? - SUMIT KUMAR SINGH
“dumpbin /headers program.exe”方法对于发布版本的二进制文件也适用吗?我尝试过了,它可以工作。 - langlauf.io
关于dumpbin:只能从Visual Studio命令提示符启动此工具。您无法从系统命令提示符或文件资源管理器中启动它。详见Microsoft Docs DUMPBIN Reference - Giovanni Faglia

14

我一直使用类似下面的命令(在cygwin窗口中):

strings -f *.lib | grep 'Visual Studio'

编译器将编译器路径插入调试版本的库中,而Visual Studio的编译器默认位置位于包含文本“Visual Studio”的路径下。

因此,与James McNellis的答案一样,这仅适用于调试版本,并且进一步限制为实际使用路径中带有“Visual Studio #”的编译器的构建。

我多年前通过偶然发现了这种方法,并且迄今为止它从未失败过。

如果您熟悉Unix命令行工具,这样做的好处是易于记忆。


我知道“+1”式的评论并不被鼓励,但在我的看法中,这应该是答案列表的首选 - 因为它适用于发布库。谢谢。 - kabdulla
实际上,这甚至对发布库也起作用了 :) - Joerg S

11
如果您有相应的.PDB文件,那么可以使用类似于Pdb Inspector这样的工具从中查看编译器的版本。
或者在十六进制查看器中打开PDB文件并搜索字符串“Microsoft (R) Optimizing Compiler”。版本将在该字符串之前的四个2字节十六进制值中,就像这个例子中所示:
000000A060: .. .. .. .. .. .. . ...  .. .. .. .. .. .. 13 00                ..
000000A070: 00 00 6E 5D 00 00 4D 69  63 72 6F 73 6F 66 74 20  ......Microsoft
000000A080: 28 52 29 20 4F 70 74 69  6D 69 7A 69 6E 67 20 43  (R) Optimizing C
000000A090: 6F 6D 70 69 6C 65 72 00  .. .. .. .. .. .. .. ..  ompiler ........

因此版本为HEX 13 00, 00 00, 6E 5D, 00 00,或19.0.23918.0。


5
也适用于非调试静态库(.lib)文件。 - durasm

0
如果静态库是用C++编写的,并且使用MSVC 2010或更新版本进行构建,则编译器可能已经将FAILIFMISMATCH指令放入了目标文件中。
我无法从Microsoft找到关于FAILIFMISMATCH指令的官方文档,但似乎链接器使用它来检测C++标准库版本之间的不兼容性。
您可以使用以下命令从静态库中打印出这些指令:
find "FAILIFMISMATCH" xyz.lib

(或者如果您喜欢使用Cygwin或MSYS,则可以使用mheyman提到的方法)

结果可能类似于这样:

0@   /FAILIFMISMATCH:"_MSC_VER=1900" /FAILIFMISMATCH:"_ITERATOR_DEBUG_LEVEL=0" /FAILIFMISMATCH:"RuntimeLibrary=MD_DynamicRelease" /DEFAULTLIB:"msvcprt" /FAILIFMISMATCH:"_CRT_STDIO_ISO_WIDE_SPECIFIERS=0" /DEFAULTLIB:"uuid.lib" /DEFAULTLIB:"uuid.lib" /DEFAULTLIB:"MSVCRT" /DEFAULTLIB:"OLDNAMES"

请注意第一个指令:“_MSC_VER=NNNN”。据我观察,NNNN 总是与用于创建对象文件的编译器版本匹配。在我的情况下,xyz.lib 是使用 MSVC 2015 update 3 创建的,其 C++ 编译器版本为 19.00.24215,因此将 /FAILIFMISMATCH:“_MSC_VER=1900” 放入对象文件中。
Visual Studio 版本和 Microsoft C/C++ 编译器版本之间的详细映射可以在这里找到。

针对VS2017,测试了一些使用v15.9.5和v15.9.6构建的库,但它一直报告/FAILIFMISMATCH:“_MSC_VER=1900”,而不是1916(v15.9的四位代码)。无论如何,您的答案在许多情况下都可能非常有用。 - Giovanni Faglia

-5

您没有指定语言,但在C#中,在运行时了解操作系统和.NET版本(在您的代码中)的答案是:

System.Version osVersion = System.Environment.OSVersion;
System.Version cliVersion = System.Environment.Version;

在Managed C++/CLI中会有一个等效的版本

这不会告诉您编译器或IDE的版本,但会告诉您.NET运行时的版本。您可能需要知道操作系统的版本。

-Jesse


1
这与所提出的问题毫不相关。虽然问题中没有指定语言(这是正确的),但它涉及静态库。静态库意味着本地代码。问题本质上在询问编译到二进制代码中的运行时版本。操作系统版本在这里并不重要。 - IInspectable

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接