【问题标题】:Build/linker error for a C project using GoogleTest使用 GoogleTest 的 C 项目的构建/链接器错误
【发布时间】:2021-07-04 01:36:48
【问题描述】:

所以我有一个用于我创建的 C 项目的简单模板,并用它来实现保龄球游戏 kata 以消除错误。该模板适用于使用 C11 的 C 项目,它使用 GTest 作为测试框架。

当 CMake 尝试构建测试二进制文件时,我遇到了链接器问题。

test目录下的CMakeLists.txt如下

include(AddGoogleTest)

## Added these #########
include_directories("${PROJECT_SOURCE_DIR})/include")
set(FILES ../src/library.c ../include/template_demo/library.h)
##################

set(TEST_FILES test_template_demo.cpp)
add_executable(template-demo-test ${TEST_FILES} ${FILES})
add_gtest(template-demo-test)

如果没有“添加这些”块中的行(因为我最初拥有该文件),我会获得对我试图从源代码调用的所有函数的未定义引用(位于 src/library.c并包含/template_demo/library.h)。

所以我在“添加这些”块中添加了这些行,因为我认为问题是测试二进制文件看不到源代码。加入这些行后,错误将变为无此类文件问题。

/projects/template_bowling/src/library.c:2:10: fatal error: template_demo/library.h: No such file or directory
    2 | #include "template_demo/library.h"
      |          ^~~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [tests/CMakeFiles/template-demo-test.dir/build.make:90: tests/CMakeFiles/template-demo-test.dir/__/src/library.c.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:1023: tests/CMakeFiles/template-demo-test.dir/all] Error 2
make: *** [Makefile:146: all] Error 2

据我所知,生产二进制文件仍然构建并运行良好(这是一个最小的存根)。

test_template_demo.cpp 在 library.h 的包含周围有 extern C。

感谢您的帮助!

编辑:未定义的参考错误(至少第一个)是

/usr/bin/ld: CMakeFiles/template-demo-test.dir/test_template_demo.cpp.o: in function `BowlingTest_test_bowling_gutter_game_Test::TestBody()':
test_template_demo.cpp:(.text+0x42): undefined reference to `score_game'

其他错误基本相同,只是调用文件中的其他函数时。

score_game 函数定义在 src/library.c 中,结构如下(为简洁省略实现)

#include <stdlib.h>
#include "template_demo/library.h"

#define MAX_ROLLS 21

struct bowling
{...};

struct bowling *bowling_init(void)
{...}

void bowling_free(struct bowling *b)
{
    free(b);
}

void roll_ball(struct bowling *b, int n)
{...}

int score_game(struct bowling *b)
{...}

文件的头文件位于 include/template_demo/library.h

#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct bowling;
struct bowling *bowling_init(void);
void bowling_free(struct bowling *b);
void roll_ball(struct bowling *b, int n);
int score_game(struct bowling *b);
#ifdef __cplusplus
}
#endif

编辑:

通过将以下行添加到我的测试/CMakeLists.txt

target_link_libraries(template-demo-test PRIVATE template_library)

它解决了问题并允许运行测试二进制文件。

最终的测试/CMakeLists.txt 现在看起来像

include(AddGoogleTest)

set(TEST_FILES
        test_template_demo.cpp
        )
add_executable(template-demo-test ${TEST_FILES})
target_link_libraries(template-demo-test PRIVATE template_library)
add_gtest(template-demo-test)

这似乎比原来的更可靠和稳定。

【问题讨论】:

  • "我得到一个对我试图调用的所有函数的未定义引用" - 请显示(添加到问题帖子)确切的错误消息(在至少,对于第一个错误)。还显示您的 C/C++ 代码的一部分,它定义给定函数。
  • google 测试二进制文件是一个单独的二进制文件,因此您必须将要测试的主要代码构建为库,并链接到 google 二进制文件。或者您必须将所有源代码放入 google 测试项目中,就像主项目一样。
  • @Devolus 所以我需要在构建我的测试可执行文件后将类似 target_link_libraries(template-demo-test PRIVATE template_library) 添加到我的测试/CMakeLists.txt 中?
  • 测试二进制文件是一个完整的独立项目。所以你需要将你的主项目拆分成主项目、库部分(包含要测试的代码)和测试项目。我认为你不能简单地添加一个 target_link_library,因为你需要先构建它。然后将库项目添加为两个项目的链接依赖项。
  • 所以我想我有那个设置。我的 src 目录中的 cmakelists 构建“template_library”,我的 app 目录中的 cmakelists 使用该库来生成一个名为“app”的可执行文件,而测试 cmakelists 使用该库来创建“template-demo-test”二进制文件。跨度>

标签: c++ c cmake build linker


【解决方案1】:

你的结构基本上是这样的:

project
    main_binary (just the startup code for the main code)
    main_library (code which needs to be tested)
    google_binary

main_library 然后作为target_link_libraries 添加到main_binarygoogle_binary

要么这样,要么您必须将main_binary 源也复制到google_binary 中,但这更容易出错,因为这意味着您必须保持两个独立的项目同步。使用库方法更容易。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2012-10-25
    • 2017-02-14
    • 1970-01-01
    • 2019-09-04
    • 2022-10-24
    • 2012-10-06
    相关资源
    最近更新 更多