c++ - 将 C++ 和 C/C++ 静态库与 CMake 混合
问题描述
我搜索了各种论坛,但找不到解决问题的方法。
我正在尝试在 C 文件中编写函数的单元测试。我正在使用谷歌测试库。
尽管我按照指南进行操作,但该项目无法正确编译。
用 C++ 编写的测试看不到 C 文件中的函数。(未定义参考)
下面我附上我的文件,也许有人会注意到我在哪里犯了错误。我没主意了。
pir_driver.h
#ifndef PIR_DRIVER_H_
#define PIR_DRIVER_H_
#ifdef __cplusplus
extern "C"
{
#endif
#include <stdint.h>
uint32_t xTaskGetTickCount();
#ifdef __cplusplus
} /* extern "C" */
#endif
pir_driver.c
#include "pir_driver.h"
uint32_t xTaskGetTickCount()
{
return 1000;
}
pir_test.cpp
#include <gtest/gtest.h>
#include "../pir_driver.h"
TEST(PIR_Timer_Test, Start)
{
uint32_t test = xTaskGetTickCount() * 2;
EXPECT_EQ(test, test);
}
项目根 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
set(This pir_driver)
project(${This} C CXX)
include(Dart)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
enable_testing()
add_subdirectory(googletest)
set(Headers
pir_driver.h
)
set(Source
pir_driver.c
)
add_library(${This} STATIC ${Sources} ${Headers})
set_target_properties(${This} PROPERTIES LINKER_LANGUAGE C)
add_subdirectory(test)
测试 CMakeLists.txt
cmake_minimum_required(VERSION 3.8)
set(This pir_test)
set(Sources pir_test.cpp )
add_executable(${This} ${Sources})
set_target_properties(${This} PROPERTIES LINKER_LANGUAGE CXX)
target_link_libraries(${This} PUBLIC pir_driver gtest_main )
add_test( NAME ${This} COMMAND ${This})
编译日志:
[proc] Wykonywanie polecenia: "C:\Program Files\CMake\bin\cmake.EXE" --build c:/Users/xxx/ansi_c_projects/pir_test/build --config Debug --target all -- -j 10
[build] [ 14%] Linking C static library libpir_driver.a
[build] [ 28%] Building CXX object googletest/CMakeFiles/gtest.dir/src/gtest-all.cc.obj
[build] [ 28%] Built target pir_driver
[build] [ 42%] Linking CXX static library ..\lib\libgtestd.a
[build] [ 42%] Built target gtest
[build] [ 57%] Building CXX object googletest/CMakeFiles/gtest_main.dir/src/gtest_main.cc.obj
[build] [ 71%] Linking CXX static library ..\lib\libgtest_maind.a
[build] [ 71%] Built target gtest_main
[build] [ 85%] Building CXX object test/CMakeFiles/pir_test.dir/pir_test.cpp.obj
[build] [100%] Linking CXX executable pir_test.exe
[build] CMakeFiles\pir_test.dir/objects.a(pir_test.cpp.obj): In function `PIR_Timer_Test_Start_Test::TestBody()':
[build] C:/Users/xxx/ansi_c_projects/pir_test/test/pir_test.cpp:13: undefined reference to `xTaskGetTickCount'
[build] collect2.exe: error: ld returned 1 exit status
[build] mingw32-make.exe[2]: *** [test\CMakeFiles\pir_test.dir\build.make:108: test/pir_test.exe] Error 1
[build] mingw32-make.exe[1]: *** [CMakeFiles\Makefile2:1004: test/CMakeFiles/pir_test.dir/all] Error 2
[build] mingw32-make.exe: *** [Makefile:113: all] Error 2
解决方案
它不起作用的原因是您在 main 中有一个错字CMakeLists.txt
:您定义了变量Source
,但Sources
在填充pir_driver
目标源时使用了变量。因此 .c 文件未编译,链接器无法找到其中定义的符号。
缺少的 .c 文件也是您首先需要手动设置链接器语言的原因。添加源文件后,您可以删除该set_target_properties(${This} PROPERTIES LINKER_LANGUAGE C)
行,因为 CMake 将根据源文件的扩展名自行确定。
为避免将来出现此类问题,您可以使用
add_library(pir_driver STATIC)
target_sources(pir_driver
PRIVATE
pir_driver.h
pir_driver.c
)
而不是 CMake 变量来收集 CMake 3.11 及更高版本中的源和标头。
推荐阅读
- javascript - 禁用除母亲节以外的所有星期日
- spring - Spring JPA 存储库多对多映射在添加记录时创建重复项
- javascript - 为什么控制台记录html没有行结束
- python - Python Pandas 中的嵌套循环 - 将子循环结果组合成连接的 df,并在文件名中使用组名保存
- docker - Docker Swarm 中的优雅容器关闭超时
- c++ - 根据满足哪个概念来决定要实例化哪个模板
- javascript - NodeJS 脚本更新特定标签的 JSON 文件
- email - 从我自己的域发送请求时电子邮件被触发为垃圾邮件,但适用于 Heroku
- node.js - 使用 Web3.js HttpProvider 调用 API 时如何向 Ankr 提供凭据?
- angular - 订阅者返回订阅者不是信息