C测试-使用Unity和CMake的未定义参考

C测试-使用Unity和CMake的未定义参考,c,unit-testing,cmake,ctest,unity-test-framework,C,Unit Testing,Cmake,Ctest,Unity Test Framework,我目前正试图获得一个项目设置,其中代码覆盖率和测试采用C语言。我当前的堆栈是CLion(用于IDE)、Clang(用于编译器)、gcov和lcov(用于覆盖率)、Unity(用于测试框架)和CMock(用于测试期间的模拟/存根) 我目前拥有以下包结构: app/root | build | *.* |- cmake |- modules |- CodeCoverage.cmake |- coverage |- coverage.inf

我目前正试图获得一个项目设置,其中代码覆盖率和测试采用C语言。我当前的堆栈是CLion(用于IDE)、Clang(用于编译器)、gcov和lcov(用于覆盖率)、Unity(用于测试框架)和CMock(用于测试期间的模拟/存根)

我目前拥有以下包结构:

app/root
  | build
      | *.*
  |- cmake
     |- modules
        |- CodeCoverage.cmake
  |- coverage
      |- coverage.info
  |- external
      |- Unity
      |- CMock
      |- CMakeLists.txt
  |- src
      |- *.c
      |- *.h
      |- CMakeLists.txt
  |- tests
      |- *.c
      |- *.h
      |- CMakeLists.txt
  |- CMakeLists.txt
我的更高级别的CMakeLists.txt如下所示:

cmake_minimum_required(VERSION 3.6)

project(my_c_app)

set(CMAKE_C_COMPILER "/usr/bin/clang")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)


set(CMAKE_VERBOSE_MAKEFILE ON)

add_subdirectory(external)
add_subdirectory(src)
add_subdirectory(tests)
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99")

set(SOURCE_FILES
        util.c
        util.h)

add_executable(my_c_app ${SOURCE_FILES})

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_c_app Threads::Threads)

target_include_directories(my_c_app PUBLIC ${PROJECT_SOURCE_DIR}/include)
enable_testing()

include(CodeCoverage)
include(CTest)

SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99 -g -fprofile-arcs -ftest-coverage")

SETUP_TARGET_FOR_COVERAGE(coverage tests ${PROJECT_SOURCE_DIR}/coverage/coverage "'/usr/*';'tests/*';'external/*'")

add_executable(tests util_test.c)

target_link_libraries(tests Unity CMock)

add_test(tests util_test.c)
我的应用程序级别CMakeLists.txt如下所示:

cmake_minimum_required(VERSION 3.6)

project(my_c_app)

set(CMAKE_C_COMPILER "/usr/bin/clang")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)


set(CMAKE_VERBOSE_MAKEFILE ON)

add_subdirectory(external)
add_subdirectory(src)
add_subdirectory(tests)
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99")

set(SOURCE_FILES
        util.c
        util.h)

add_executable(my_c_app ${SOURCE_FILES})

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_c_app Threads::Threads)

target_include_directories(my_c_app PUBLIC ${PROJECT_SOURCE_DIR}/include)
enable_testing()

include(CodeCoverage)
include(CTest)

SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99 -g -fprofile-arcs -ftest-coverage")

SETUP_TARGET_FOR_COVERAGE(coverage tests ${PROJECT_SOURCE_DIR}/coverage/coverage "'/usr/*';'tests/*';'external/*'")

add_executable(tests util_test.c)

target_link_libraries(tests Unity CMock)

add_test(tests util_test.c)
我的测试级别CMakeLists.txt如下所示:

cmake_minimum_required(VERSION 3.6)

project(my_c_app)

set(CMAKE_C_COMPILER "/usr/bin/clang")

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake/modules)


set(CMAKE_VERBOSE_MAKEFILE ON)

add_subdirectory(external)
add_subdirectory(src)
add_subdirectory(tests)
SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99")

set(SOURCE_FILES
        util.c
        util.h)

add_executable(my_c_app ${SOURCE_FILES})

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_c_app Threads::Threads)

target_include_directories(my_c_app PUBLIC ${PROJECT_SOURCE_DIR}/include)
enable_testing()

include(CodeCoverage)
include(CTest)

SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99 -g -fprofile-arcs -ftest-coverage")

SETUP_TARGET_FOR_COVERAGE(coverage tests ${PROJECT_SOURCE_DIR}/coverage/coverage "'/usr/*';'tests/*';'external/*'")

add_executable(tests util_test.c)

target_link_libraries(tests Unity CMock)

add_test(tests util_test.c)
目前我的问题是我做的事情不正确。在尝试测试util.c中的函数时,我得到了一个未定义的引用:

CMakeFiles/tests.dir/util_test.c.o: In function `test_my_method':
/home/patches/my_c_app/tests/util_test.c:6: undefined reference to `my_method'
我的util_test.c当前是:

#include <unity.h>
#include "../src/util.h"

void test_my_method(void) {
    uchar result = my_method();
    // assertion and other logic would go here
}

int main(void) {
    UNITY_BEGIN();
    RUN_TEST(test_my_method);
    return UNITY_END();
}

所以我觉得我100%被某种类型的链接器问题困住了。

util.c
不是
tests
源代码的一部分,也不是在链接到
tests
的库中编译的。因此,对于
my_方法
,您没有为
测试
提供任何定义,因此是未定义的引用

您的可执行文件
my_c_app
的源代码中没有
main.c
文件。我猜您的主要函数是在
util.c
中定义的。如果我是对的,请将其放入
main.c
文件中,并将应用程序级别的CMakeLists.txt更改为:

SET(CMAKE_CXX_FLAGS "-O0")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99")

set(SOURCE_FILES
        util.c
        util.h)

add_library(my_c_lib STATIC ${SOURCE_FILES})

set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(my_c_app Threads::Threads)

target_include_directories(my_c_app PUBLIC ${PROJECT_SOURCE_DIR}/include)

add_executable(my_c_app main.c)
target_link_libraries(my_c_app my_c_lib)
现在,您的源代码被编译在一个静态库
my_c_lib
中,您可以对其进行链接。您的应用程序已链接到它,您也可以在测试级别CMakeLists.txt中将您的测试链接到它:

enable_testing()

include(CodeCoverage)
include(CTest)

SET(CMAKE_CXX_FLAGS "-g -O0 -fprofile-arcs -ftest-coverage")
SET(CMAKE_C_FLAGS "-DLINUX -O0 -Wall -std=c99 -g -fprofile-arcs -ftest-coverage")

SETUP_TARGET_FOR_COVERAGE(coverage tests ${PROJECT_SOURCE_DIR}/coverage/coverage "'/usr/*';'tests/*';'external/*'")

add_executable(tests util_test.c)

target_link_libraries(tests Unity CMock my_c_lib)
                                        ^^^^^^^^

add_test(tests util_test.c)
关于这一行:

add_test(tests util_test.c)
我在拍摄目标及其来源时看不到签名。你想用这个达到什么目的

请注意,您可以使用而不是
CMAKE\u C\u标志指定C版本:

SET(CMAKE_C_STANDARD 99)

为避免全球污染,还可以使用声明编译定义。

非常感谢您提供详细信息。你刚才说的很清楚。为了增加复杂性,src dir被包装成一个*.so,但我的情况中唯一没有提到的是,我将*.so放入rails应用程序中,并使用FFI将调用放入其中,因此不需要main。我觉得补充一句会使问题变得太复杂。我可以通过添加
add_executable(tests${TEST_SOURCES})
来解决这个问题,其中TEST_源是用src中的必要文件定义的。但是是的,你所说的很受欢迎。