由于问题是关于 CMake,让我从 CMake 的角度提出一个替代方案。使用 CMake,您可以构建测试来编译要测试的源文件 (SUT) 以及您的测试,而不是与正在测试的目标链接。
这会增加一些额外的编译时间,因为源文件需要在测试中重新编译。如果这是一个问题,请停止阅读。
假设这对您来说不是问题,那么您可以简单地拉入 PUBLIC 标头依赖项,而无需拉入它们的实现。然后,您可以为测试文件中使用的依赖项实现模拟/伪造。
这是一个示例源文件 include/foo.h、foo.c 和 CMakeLists.txt。
#include <ext_decl.h> //Declares struct ext_lib_struct_t in a CMake target ext_decl_lib
int foo(struct ext_lib_struct_t a);
#include <foo.h> //Declares void* foo();
#include <ext_impl.h> //This is the header declaring extlibcall in a CMake target ext_impl_lib
int foo(struct ext_lib_struct_t a) {
return extlibcall(a); //A mock will be used for this call.
}
add_library(foo_lib)
target_sources(foo_lib
PRIVATE
foo.c
)
target_link_libraries(foo_lib
PUBLIC
ext_decl_lib
PRIVATE
ext_impl_lib
)
target_include_directories(foo_lib
PUBLIC
include # Where foo.h is.
)
这是您的测试文件 testfoo.c。使用您最喜欢的单元测试框架对其进行自定义。
#include <foo.h>
#include <assert.h>
int test_data;
int extlibcall() {
return test_data;
}
void testA() { //Replace this with test cases from your favorite unit testing platform.
test_data = 2;
int tr = foo();
ASSERT(test_data == tr); //Use your favorite assert utility.
}
int main(void)
{
testA();
return 0;
}
最后是你的测试的 CMake 指令,它可以进入你的测试目录中的 CMakeLists.txt 文件。
add_executable(testlibfoo)
target_sources(testlibfoo
PRIVATE
testfoo.c
$<TARGET_PROPERTY:foo_lib,SOURCE_DIR>/foo.c
)
target_include_directories(test_unity_sall_mgm_join
PRIVATE
include
$<TARGET_PROPERTY:foo_lib,INCLUDE_DIRECTORIES>
)
target_link_libraries(test_unity_sall_mgm_join
PRIVATE
assert_lib
#Add your favorite unit test framework and/or other libraries used in the test
)
测试代码只编译一次 foo.c,因为 foo_lib 没有链接。但是,当其他一些库链接到 foo_lib 时,它可能会在稍后为您的生产代码重新编译。