【问题标题】:force visual studio to link all symbols in a lib file强制 Visual Studio 链接 lib 文件中的所有符号
【发布时间】:2010-10-10 14:04:46
【问题描述】:

有什么方法可以强制 Visual Studio 将 lib 文件中的所有符号链接到 dll 中,因为 atm 它正在优化程序在运行时使用 dll 所需的“未使用”函数。

我尝试使用 /OPT:NOREF 和 /OPT:NOICF 但它们似乎不起作用。

我需要它们的原因是因为它们是全局类,它们向控制器注册它们自己,并且它们没有在 dll 中链接。

【问题讨论】:

  • 你能列出你用来编译和链接的完整命令行吗?

标签: c++ visual-studio linker


【解决方案1】:

我不知道在 Visual Studio 中是否有更优雅的方式,但我们使用它的跨平台解决方案有两个宏来强制链接有问题的目标文件。

一个放在要排除的函数的源文件中,另一个放在链接器知道将被调用的函数中。

类似的东西;

#define FORCE_LINK_THIS(x) int force_link_##x = 0;

#define FORCE_LINK_THAT(x) { extern int force_link_##x; force_link_##x = 1; }

这不是很优雅,但我们还没有找到一个更好的跨平台工作的解决方案。

【讨论】:

  • __declspec(dllexport)__declspec(dllimport) 是不够的,因为它们(向编译器)声明代码在 DLL 中。这使得 thunk 函数和 .DEF 文件变得不必要。只是一个小的优化:#define FORCE_LINK_THAT(x) void force_link_function_##x(void) { extern int force_link_##x; force_link_##x = 1; } 允许将宏放置在您知道它将被链接的文件的顶部。顺便说一句,从不调用虚拟函数没有任何区别。
  • 似乎也适用于具有空主体的函数。只需在将 lib 链接到的可执行文件或 dll 中的某个位置调用它即可。
【解决方案2】:

其实有一个半官方的解决方案,还有here it is

TL;DR:

'使用库依赖输入'

在 VS 术语中,“库依赖输入”是构成库的 obj 文件的名称。您实际上可以在两个范围内控制此行为:

  1. 根据参考:通过“使用库依赖项输入” 参考属性中的组合。这是我使用的解决方案 就个人而言,提到的那个in the post

  2. 按整个可执行文件:在 exe 项目中 属性 /C++/Linker/General/ 使用库依赖输入 -> 是

这些神秘设置的历史动机是 enabling incremental linking in places it wasn't available before,但它具有直接链接到打包在 lib 中的 obj 文件的有用副作用,从而也构造未引用的全局对象。

【讨论】:

    【解决方案3】:

    我在插件系统中遇到了同样的问题,其中各种 DLL 中的工厂都使用一个通用的主工厂,所有内容在加载库时在启动时注册,而无需硬编译要使用的插件列表。这在 Linux 下运行良好,但在 Windows 下有两个问题:

    1. DLL 之间的工厂并不常见。这不是你的问题,但它是相关的。我在这里找到了解决方案:Ensuring to use common fatories。看看 James 用 set_the_global 函数给出的答案。
    2. 如果在主程序中没有使用 DLL 的符号,则不会在启动时设置它们。我认为这是你的问题。我发现的唯一解决方案是使用配置文件(一个子项目)列出可用插件(DLL)的名称,并在我的例子中强制使用 QLibrary 进行链接。使用 cmake,每个子项目的配置文件的默认版本在构建时使用以下宏生成,而不是在每个插件目录中调用 add_library:

      file(WRITE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "")
      macro (DECLARE_AMOSE_PLUGIN _plugin)
        file (APPEND ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}-plugins "${_plugin}\n")
        add_library(${_plugin} SHARED ${${_plugin}_LIB_SRCS})
      endmacro (DECLARE_AMOSE_PLUGIN)
      

    【讨论】:

      【解决方案4】:

      我使用了编译指示,它似乎有效,但如果你不包含该行,它不会窒息。

      #include "library1.h"
      #include <QApplication>
      #pragma comment(lib, "C:\\Qt\\5.5\\msvc2013_64\\lib\\Qt5Guid.lib")
      PHI_STATUS PHI_EXP_CONV PHI_ShowGUI(size_t reserved)
      {
          QApplication app(none, nullptr);
          ...
      }
      

      您还可以通过Librarian 选项卡中的Additional Dependencies 字段链接它们。

      【讨论】:

        【解决方案5】:

        DLL 将如何在运行时从您的库中调用函数?这听起来有点难以置信。

        现在,如果 DLL 的用户 将调用您的库函数,那么您的问题是有道理的。 Windows 编译器(与 Unix 编译器不同)仅在明确请求时才从 DLL 导出函数。最常见的方法是声明函数“dllexport”,但您也可以在 .DEF 文件中命名函数,并将其传递给链接器。请注意,您需要在 .DEF 文件中列出 C++ 错位名称。

        【讨论】:

        • 因为它们是全局类,它们通过控制器自行注册,并且没有在 dll 中链接。
        • 那么,将其放在问题中会很有用。这是一个很好的问题,有这个补充,但与你现在问的不同。
        【解决方案6】:

        在 MSVC2k17 中测试...

        __pragma(comment(linker,"/export:REGISTERfunc"));
        void REGISTERfunc() { printf("I'm linked!\n" ); }
        

        完全有效。这甚至可以在静态链接的 .lib 中,并且会一直传递到输出可执行文件甚至更远!

        编辑:您甚至可以将其放入宏中以获得超棒积分!

        编辑:另一个注意事项:您必须启用链接时代码生成。 /LTCG ...一些东西

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-07-11
          • 1970-01-01
          • 2014-11-15
          • 1970-01-01
          • 2010-12-22
          • 1970-01-01
          • 2020-02-18
          • 2020-11-06
          相关资源
          最近更新 更多