微软Visual Studio中相当于GCC ld选项--whole-archive的是什么?

27
当将静态库链接到可执行文件时,未使用的符号通常会被丢弃。在我的情况下,一些否则不使用的对象用于将它们各自的类注册到工厂中,如果这些对象被丢弃,此注册将失败。在使用gcc的Unix系统下,可以向链接器ld传递--whole-archive标志(请参见以下内容从ld文档中摘录的说明),使ld不丢弃任何对象。对于Visual C ++是否有类似的功能呢?

--whole-archive

    在命令行上使用--whole-archive选项指定的每个存档文件中,都包含存档文件中的每个对象文件,而不是在存档文件中搜索所需的对象文件。这通常用于将存档文件转换为共享库,强制将每个对象包含在生成的共享库中。此选项可以使用多次。


感谢对 --whole-archive 的解释,我正好在搜索何时使用它的场景。 - Deqing
7个回答

30
Visual Studio 2015 Update 2 中的 Visual C++ 版本引入了一个名为 /WHOLEARCHIVE 的新标记,该标记有类似于 ld 命令中的 --whole-archive 选项的功能。根据文档所述:

/WHOLEARCHIVE 选项强制链接器包含指定静态库中的所有目标文件, 如果没有指定库,则从 LINK 命令指定的所有静态库。


1
哇,这太棒了。谢谢你提供的信息。 - fschmitt

9
据我所知,没有任何一种选项能可靠地保证这一点。有一些优化选项的组合(悄悄地)禁用了它,所以没有办法……/INCLUDE是有效的,但你需要提取和硬编码符号的变形名称。你有两个选择:(1)确保所有注册器都包含在包含main的翻译单元中并强制使用它们。(2)放弃这种“习惯用法”,使用显式注册。
注意:这个答案现在已经近7年了,关于MSVC++工具链中选项的可用性的说法已经过时。尽管如此,我仍建议不要依赖注册器模式,而要看看其他替代方案。

谢谢。我选择了创建一个小程序的方式,从静态库中提取所有符号名称,并将它们包含在主程序中。 - fschmitt
1
看起来这个问题在两年后默默地被投了两次反对票。您能否请留言说明原因? - Paul Michalik
@fschmitt,你有没有找到更好的解决方案来解决这个问题? - rr-
1
我从静态库转向了动态链接库,这解决了问题,因为动态链接库中没有符号被丢弃。 - fschmitt

6
您可以通过CMake使用,例如:
add_executable(hello ${SOURCE_FILES})
target_link_libraries(hello libA libB libC)     # Not need /wholearchive libC 
set_target_properties(hello PROPERTIES LINK_FLAGS "/WHOLEARCHIVE:libA /WHOLEARCHIVE:libB")

注意:只有在Visual Studio 2015更新2及以上版本中才可使用“/WHOLEARCHIVE”。

6
我认为最接近的等效物应该是 /OPT:NOREF

2
似乎没有任何效果,特别是考虑到它在调试构建中是隐含的。 - rr-
那应该可以工作,但实际上完全不行,而且不仅仅是我遇到这个问题。非常不幸。 - Piyush Soni

4
我使用 /INCLUDE: 强制包含未使用的符号。

1
我采用了另一种方法 - 不是将所有内容编译成一个 .lib 文件,然后将该 .lib 文件链接到可执行文件上,而是直接将可执行文件与 .obj 文件进行链接。
在 CMake 中,可以这样实现:
add_library(common OBJECT ${common_sources})
add_executable(executable1 "main1.cc" $<TARGET_OBJECTS:common>
add_executable(executable2 "main2.cc" $<TARGET_OBJECTS:common>

修改任何位于${common_sources})中的文件只会重新编译它们相应的目标文件和可执行文件,这样做可以获得与通过中间.lib链接相同的好处。同时,所有静态构造函数仍然存在,从而解决了问题。
请注意,只有在静态链接时才有用。
此方法已在gcc 5.2.0、MinGW-w64 5.2.0和MSVC 15上进行了测试。

0
在可执行文件的属性页面中,查看Common Properties/References/Use Library Dependency Inputs,将其设置为true。这基本上是MS版本的--whole-archive。

编辑:但是所涉及的库需要是解决方案的一部分。


不,它会将所有的obj文件添加到链接器命令中,而不是库文件。 - colin lamarre

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