c++ - 如何在将测试 exe 与 gradle 链接时排除第二个主程序?

标签 c++ gradle linker googletest

我正在尝试将单元测试集成到 native (C++)gradle 项目中,但我似乎找不到可行的解决方案。链接测试可执行文件时会出现问题,因为有两个可用的 wmain(一个用于主应用程序,一个用于单元测试)。有谁知道如何在链接步骤中排除其中之一?

这是我的设置的一个最小示例:

项目结构

build.gradle
src
    -> main
        -> cpp
            -> main.cpp
            -> registry.cpp
        -> headers
            -> registry.hpp
    -> test
        -> cpp
            -> main_test.cpp
            -> test_registry.cpp
libs
    -> googletest
        -> 1.7.0
            -> include
                -> ...
            -> lib
                -> libgtest.a

build.gradle

apply plugin: 'cpp'
apply plugin: 'google-test-test-suite'

model {
    platforms {
        x86 {
            architecture "x86"
        }
        x64 {
            architecture "x86_64"
        }
    }

    components {
        main(NativeExecutableSpec) {
            baseName "Registry"
            targetPlatform "x86"
            binaries.all {
                cppCompiler.args "-std=c++11", "-municode", "-mwindows"
                linker.args "-municode", "-mwindows"
            }
        }
    }

    testSuites {
        mainTest(GoogleTestTestSuiteSpec) {
            testing $.components.main

            sources {
                cpp.source.srcDir 'src/test/cpp'
            }
        }
    }

    repositories {
        libs(PrebuiltLibraries) {
            googleTest {
                headers.srcDir "libs/googletest/1.7.0/include"
                binaries.withType(StaticLibraryBinary) {
                    staticLibraryFile =
                        file("libs/googletest/1.7.0/lib/libgtest.a")
                }
            }
        }
    }
}

model {
    binaries {
        withType(GoogleTestTestSuiteBinarySpec) {
            lib library: "googleTest", linkage: "static"

            cppCompiler.args "-std=c++11", "-municode"
            linker.args "-municode"
        }
    }
}

错误消息

:compileMainExecutableMainCpp
:linkMainExecutable
:mainExecutable
:assemble
:compileMainTestGoogleTestExeMainCpp
:compileMainTestGoogleTestExeMainTestCpp
:linkMainTestGoogleTestExe
C:\Users\minimal\build\objs\mainTest\mainCpp\e7f4uxujatdodel7e7qw5uhsp\main.obj:main.cpp:(.text+0x0): multiple definition of `wmain'
C:\Users\minimal\build\objs\mainTest\mainTestCpp\271ezc0ay5ubap2l962cnectq\main_test.obj:main_test.cpp:(.text+0x0): first defined here
collect2.exe: error: ld returned 1 exit status

:linkMainTestGoogleTestExe FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':linkMainTestGoogleTestExe'.
> A build operation failed.
      Linker failed while linking mainTest.exe.

选项.txt

-o
C:\\Users\\minimal\\build\\exe\\mainTest\\mainTest.exe
C:\\Users\\minimal\\build\\objs\\mainTest\\mainTestCpp\\271ezc0ay5ubap2l962cnectq\\main_test.obj
C:\\Users\\minimal\\build\\objs\\mainTest\\mainTestCpp\\dp6ieaohq04qqqa31sdfwrsxj\\test_registry.obj
C:\\Users\\minimal\\build\\objs\\mainTest\\mainCpp\\68sxcjmhakj69ha7wqtijofs3\\Registry.obj
C:\\Users\\minimal\\build\\objs\\mainTest\\mainCpp\\e7f4uxujatdodel7e7qw5uhsp\\main.obj
C:\\Users\\minimal\\libs\\googletest\`.7.0\\lib\\libgtest.a
-municode
-m32

非常感谢任何帮助!

最佳答案

您的问题是由于尝试使用 googletest 做错误的事情而产生的。

Googletest 是一个单元测试框架。这意味着它是为了测试 - 其中在这里表示一堆函数和/或类 不包含 main 函数。它不是用于测试应用程序, 具有 main 功能。您可以通过运行以下命令来测试应用程序 应用并进行受控(可能是自动化)观察 其公开的行为。这种测试有多种名称,但都是 不是单元测试,单元测试是第一位的。

要使用 googletest 测试库,您需要创建一个应用程序 运行你的 googletest 测试用例。该应用程序(测试运行程序)需要 它自己的 main 函数,除了运行测试用例之外什么也不做:

int main(int argc, char **argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}

某人拥有一个包含以下内容的应用程序是很常见的 一堆特定于应用程序的函数和/或类 喜欢用 googletest 进行单元测试。这样做的方法是:-

  • 将应用程序重构为:

    • 一个库 - 称之为应用程序库 - 包含您想要的函数和/或类 单元测试,不包括 main 函数。
    • 其余部分,包括 main 函数。
  • 通过将其余部分与应用程序库链接来构建应用程序。

  • 创建一个测试运行应用程序,其中包含您的 googletest 测试用例 和 googletest main 函数。当然,测试用例,#include 应用程序库的标题。

  • 通过将测试用例和主函数与应用程序库链接来构建测试运行程序。

  • 通过运行测试运行程序对应用库进行单元测试。

最简单、最快的方法就是将所有应用程序, 除了 main 函数之外,都进入应用程序库。但这可能更明智 仅在开发时将内容从应用程序移至应用程序库 单元测试来覆盖它,这样你就可以随时知道应用程序库中的内容 有单元测试,其余没有。以此类推,直到除了 main 函数位于应用程序库中,并且具有单元测试。

你几乎肯定会发现分解应用程序库的过程 这样您就可以将其与应用程序和测试运行器公开 应用程序中的设计缺陷并迫使您做得更好。这可以启动一个 应用程序库正在走向成熟,成为一个多应用程序库,一个稳定的高质量 软件 Assets 。

因此,您从一个项目(应用程序项目)开始,最终得到 三个项目:

  • 构建应用库的项目
  • 构建应用程序的项目
  • 构建测试运行程序的项目

无论怎样,您拥有的任何构建系统都将允许您自动进行 这些项目之间的依赖关系。显然,您想要:

  • 构建应用程序需要构建应用程序库
  • 构建测试运行程序需要构建应用程序库

但是您可以更进一步,使构建应用程序需要 构建测试运行程序 - 它将构建应用程序库 - 并成功 运行测试运行程序。这样,您将永远不会构建应用程序 除非单元测试成功。这对你来说可能有点过分了 桌面开发周期,但不适用于 CI 构建。

对于下一个应用程序,您可以从这个 3 项目模式开始, 仅当您可以从应用程序获取功能时才向应用程序添加功能 应用程序库,必须由单元测试覆盖,并且必须通过 在测试运行程序中。那么你就以正确的方式使用 googletest 了。

关于c++ - 如何在将测试 exe 与 gradle 链接时排除第二个主程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42713190/

相关文章:

c++ - 如何用模板参数或 std::function 替换函数指针?

c++ - 不能声明为抽象类型

osgi - 使用 Gradle 创建具有依赖 Jas 的 Osgi Bundle

c++ - 通过函数指针定义 "main"

c - 当我在 c 中使用 strlcpy 函数时,编译器给我一个错误

c - LNK1120、LNK2001、LNK2019 - 无法追踪原因

c++ - 在 C++ 中使用多重函数合并两个链表

c++ - 将字符串转换为整数然后找到连续对整数 C++ 的最大总和

android - 无法应用插件 'com.android.internal.application' Android Gradle 插件需要 Java 11 才能运行。您当前使用的是 Java 1.8

gradle - 在所有项目文件上使用 Gradle 运行 Checkstyle