【问题标题】:Force library linking with Qt and google test强制库与 Qt 和 google 测试链接
【发布时间】:2009-11-23 13:44:34
【问题描述】:

我正在尝试使用谷歌测试为我的 Qt(c++) 应用程序编写一个测试套件,主要问题是我的应用程序由一个主程序和各种共享库组成。一切正常,直到我尝试使用 gcov/lcov(它不能在动态库上运行)进行一些代码覆盖,所以我修改了所有 .pro 文件以使用静态库编译:


CONFIG += staticlib create_prl
QMAKE_LFLAGS += -static
LIBS += ../../Libs/lib*.a

问题是谷歌测试测试应用程序是这样的:



int main(int argc, char **argv) {

  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

所以它在运行时检测到链接,这意味着当我在这里编译测试应用程序时没有警告或任何表明问题的东西,并且在运行测试应用程序时它执行 0 test 因为它没有找到任何东西。

我的解决方案(摆脱烦人的解决方案)是在每个类中定义将用于测试虚假公共静态成员并在其上为主要测试应用程序执行操作:

class SETTINGS_TESTS_SHARED_EXPORT SettingsTests: public testing::Test { public: SettingsTests(); virtual ~SettingsTests(); static bool dummy; protected: virtual void SetUp(); virtual void TearDown(); private: Settings* _setting0; Settings* _setting1; Settings* _setting2; };


using namespace MBI::SETTINGS;
using namespace MBI::TESTS;

int main(int argc, char **argv) {

  SettingsTests::dummy = true;
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

所以我可以在我的应用程序上强制链接该库。

我还发现选项 -u 可以在 gcc 中执行类似的操作,但似乎不起作用。如果在编译时无法检测到符号,有没有人可以强制静态库链接?

【问题讨论】:

    标签: qt static linker googletest


    【解决方案1】:

    我没有完全理解这个问题,它没有解释::testing::InitGoogleTestRUN_ALL_TESTS 的实际作用,以及它们与动态链接的关系。

    但是:您可以使用选项 --unresolved-symbols=ignore-all 使 GNU 链接器在链接时忽略未解析的符号,或者如果您需要将选项传递给 gcc,-Wl,--unresolved-symbols=ignore-all

    【讨论】:

    • "::testing::InitGoogleTest() 函数解析命令行以查找 Google 测试标志,并删除所有可识别的标志。这允许用户通过各种标志控制测试程序的行为。您必须在调用 RUN_ALL_TESTS() 之前调用此函数,否则标志将无法正确初始化。" GoogleTest doc 这个函数将解析你传递给测试程序的命令行选项,在我的例子中:
        ./TestsApp --gtest_color yes --gtest_output="xml:../"  pre>  所以我可以得到 Junit like xml 报告。
    • 这并没有解释它与链接的关系。
    【解决方案2】:

    在 google 测试文档中提到了 Visual c++ dll 的链接问题:

    Visual C++ 用户的重要说明 如果您将测试放入库中并且您的 main() 函数位于不同的库或 .exe 文件中,则这些测试将不会运行。原因是 Visual C++ 中的一个错误。当您定义测试时,Google Test 会创建某些静态对象来注册它们。这些对象没有从其他地方引用,但它们的构造函数仍然应该运行。当 Visual C++ 链接器发现库中的任何内容都没有从其他地方引用时,它会将库抛出。您必须使用主程序中的测试来引用您的库,以防止链接器丢弃它。这是如何做到的。在您的库代码中的某处声明一个函数: __declspec(dllimport) int PullInMyLibrary() { return 0; } 如果您将测试放在静态库(而不是 DLL)中,则不需要 __declspec(dllexport)。现在,在您的主程序中,编写一个调用该函数的代码: int PullInMyLibrary(); 静态 int 虚拟 = PullInMyLibrary(); 这将使您的测试保持引用,并使它们在启动时注册自己。 此外,如果您在静态库中定义测试,请将 /OPT:NOREF 添加到主程序链接器选项中。如果您使用 MSVC++ IDE,请转到您的 .exe 项目属性/配置属性/链接器/优化并将引用设置设置为保留未引用的数据 (/OPT:NOREF)。这将防止 Visual C++ 链接器从最终可执行文件中丢弃测试生成的单个符号。 不过,还有一个陷阱。如果您将 Google Test 用作静态库(这就是它在 gtest.vcproj 中的定义方式),您的测试也必须驻留在静态库中。如果您必须将它们放在 DLL 中,则必须将 Google Test 也更改为构建到 DLL 中。否则,您的测试将无法正确运行或根本不会运行。这里的一般结论是:让您的生活更轻松 - 不要在库中编写测试!

    采用的解决方案与我使用 g++ 所做的差不多。我怀疑 qmake 产生中间文件 moc_* 并且我的代码与之相关联的事实。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 2010-11-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多