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

How to exclude second main while linking test exe with gradle?

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

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

项目结构

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\mainTestCpp1ezc0ay5ubap2l962cnectq\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.

options.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 是一个 unit-testing 框架。这意味着它用于测试 libraries - 这里的 library 表示 一堆函数 and/or 类 不包括 main 函数。它不是用于测试应用程序, 具有 main 功能。您通过 运行ning 来测试应用程序 应用和进行可控的——可能是自动化的——观察 其公开行为。这种测试有不同的名称,但是 不是 unit-testing,unit-testing 排在第一位。

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

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

有人拥有包含以下内容的应用程序很常见 一堆特定于应用程序的功能 and/or 类 他们会 喜欢 unit-test 与 googletest。这样做的方法是:-

  • 将应用程序重构为:

    • 一个库 - 称之为 app 库 - 包含你想要的函数 and/or 类 unit-test,不包括 main 函数。
    • 余数,包括 main 函数。
  • 通过 link使用应用程序库构建应用程序。

  • 创建一个 test-runner 应用程序,包含您的 googletest 测试用例 和一个 googletest main 函数。当然,测试用例,#include 应用程序库的headers。

  • 通过 link 使用应用程序库构建测试用例和主要功能来构建 test-runner。

  • Unit-test 应用程序库 运行 宁 test-runner.

最简单快捷的方法就是将所有应用程序, main 函数除外,进入应用程序库。但这可能更明智 仅在开发过程中 将内容从应用程序移动到应用程序库 单元测试覆盖它,所以你随时知道应用程序库中的任何内容 有单元测试,其余的没有。以这种方式进行,直到除了 main 函数在应用程序库中,并且有单元测试。

你几乎肯定会发现分解出 app-library 的过程 这样你就可以 link 它与应用程序和测试 运行ner exposes 应用程序中的设计缺陷并迫使您做得更好。这可以启动一个 应用程序库正在成熟为 multi-app 库,一个稳定的 high-quality 软件资产。

所以你从一个项目开始,应用程序项目,你最终 三个项目:

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

无论哪种方式,您拥有的任何构建系统都可以让您自动创建 这些项目之间的依赖关系。显然,您想要:

  • 构建应用程序需要构建应用程序库
  • 构建 test-runner 需要构建应用程序库

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

对于下一个应用程序,您可以开始 这个 3 项目模式, 并仅在您可以从 app库,单元测试必须覆盖,必须通过 在 test-runner。那么你就是在以正确的方式使用 googletest。