将我的主输出库与测试可执行文件链接时出现问题
Problems when linking my main output library with my test executable
我正在构建一个"框架"库,我正在尝试集成Google测试。这是一个非常小的库,最后给了我一个.so
或.dll
的文件。
当我开始测试我的库时,我发现了一个配置(详细信息如下(,可以在我的 linux 环境中CMakeFile
上运行良好。但是当我尝试使用MSBuild
forMSVC14
运行同一个项目时,它会给我一个链接错误
LINK : fatal error LNK1104: cannot open file '..srcDebugfoobar.lib'
我认为我的 cmake 猜错了库名称(foobar.lib
而不是foobar.dll
(,但我找不到原因以及如何解决它。
另外,我不知道这是否真的是我测试它的最佳方式。我想要的是一种在没有main.cpp
文件的情况下测试整个框架(初始化、创建东西、检查返回等(的方法,同时开始创建单元测试。
所以,我的问题是..在 Windows 环境中链接器找不到src/CMakeLists.txt
构建的foobar
库,我做错了什么?(我检查了一下,库是在"src/Debug/foobar.dll"中创建的,与错误时出现的目录相同,并且工作正常(
另外,我的方法是否如此错误,以至于Windows不想处理? 哈哈,我的意思是,像我想做的那样做某事是错误的?这并不是说我不想进行单元测试,我很快就会这样做,但我真的很喜欢在开始之前构建和尝试我的 lib,而无需使用任何外部 exec 二进制文件。
谢谢!
观察:
-
我的谷歌测试在 Linux 和 Windows 中都运行良好;
-
如果我删除链接到
foobar
库的 FooBar 测试,我可以运行测试 FooA。 -
使用我的 linux 环境,此配置可以完美运行。
更新:
正如@vre建议的那样,我找到了宏__declspec(dllexport)
并将其放在我的FooBar
类名之前,编译通过了,但是当我运行时它崩溃并在编译时抛出此警告:
warning C4251: 'FooBar::_impl': class 'std::unique_ptr<FooBar::FooBarImpl,
std::default_delete<_Ty>>' needs to have dll-interface to be used by clients of class 'FooBar'
那是因为我有一个FooBar
类的 PImp 实现。所以,我有这个:
class __declspec(dllexport) FooBar
{
...
private:
class FooBarImpl;
std::unique_ptr<FooBarImpl> _impl;
}
我还不知道这是什么意思。试图找出它崩溃的原因。
我的项目有这个文件树:
├── CMakeLists.txt
├── include
| ├── FooBar.hpp
├── src
│ ├── CMakeLists.txt
│ ├── FooBar.cpp
│ ├── FooA
│ │ └── CMakeLists.txt
│ ├── FooB
│ │ └── CMakeLists.txt
│ └── FooC
│ └── CMakeLists.txt
└── test
├── CMakeLists.txt
├── FooBar
│ └── FooBarTest.hpp
├── FooA
│ ├── FakeBar.hpp
│ ├── FooATest.hpp
│ └── mockObj.hpp
我的主要CMakeLists.txt
是这样的:
...
set(FOOBAR_INCLUDE "${PROJECT_SOURCE_DIR}/include/FooBar.hpp")
# Include src main CMakeLists
add_subdirectory("${PROJECT_SOURCE_DIR}/src")
# Include tests if enabled
if (test)
add_subdirectory("${PROJECT_SOURCE_DIR}/test")
endif ()
我的src/CMakeLists.txt
:
...
set(FOOBAR_SOURCES "FooBar.cpp")
# Build
add_library(foobar SHARED ${FOOBAR_SOURCES} ${FOOBAR_INCLUDE})
# Links the library with components.
target_link_libraries(foobar FooA FooB FooC)
我的test/CMakeLists.txt
是这样的:
enable_testing()
# Include directories used for testing.
include_directories("${CMAKE_SOURCE_DIR}/src"
"${CMAKE_SOURCE_DIR}/include"
"FooA/"
"FooBar/")
# Include the files for testing.
set(INCLUDE_TESTS "${CMAKE_SOURCE_DIR}/src/FooA/FooA.cpp"
"${CMAKE_SOURCE_DIR}/src/FooA/Bar.cpp")
# Include the test source files.
set(TEST_SOURCES "main.cpp"
"FooBar/JepluTest.hpp"
"FooA/FakeBar.hpp"
"FooA/FooATest.hpp")
# Build
add_executable(foobar-test ${TEST_SOURCES} ${INCLUDE_TESTS})
# Links the library with components. (HERE IS WHERE OCCURS THE PROBLEM)
target_link_libraries(foobar-test gtest foobar)
# Not really important right now
add_test(NAME foobar-test COMMAND foobar-test)
重新表述和增强我之前的评论:
您需要从Windows上的DLL导出符号,否则不会创建导入库,这就是MSBuild抱怨的。
首先,您应该将以下构造添加到 FooBar.hpp 标头中:
#ifdef WIN32
#ifdef FOOBARLIB_EXPORTS
#define FOOBARLIB_API __declspec(dllexport)
#else
#define FOOBARLIB_API __declspec(dllimport)
#endif
#else
#define FOOBARLIB_API
#endif
稍后标记要导出的类、函数和符号,如下所示:
void FOOBARLIB_API foobar(char*)
{
}
在创建共享库目标后的CMakeLists.txt
foobar
添加以下行:
target_compile_definitions(foobar PRIVATE FOOBARLIB_EXPORTS)
编辑: 正如@vre所评论的那样,还需要这些CMake
属性,因为Windows不会加载位于另一个文件夹中的DLL
,从而导致在尝试运行可执行文件时崩溃。因此,当生成DLL
并设置CMAKE_RUNTIME_OUTPUT_DIRECTORY
变量时,输出库将转到与测试.exe
文件相同的目录。
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
- 使用jsoncpp库时出现链接问题
- Cmake 链接问题:未定义对 Button::mousePressEvent(QGraphicsSceneMouseE
- 如何将GTest与CMake一起使用?遵循谷歌指南时的链接问题
- 未解决的外部链接问题
- 'make check' GLIBC 运行时的链接问题
- 在树莓派上用libtorch构建程序时的链接问题
- 野牛弹性链接问题
- 与 AWS 开发工具包的链接问题
- Qt & Firebase C++ SDK 在 iOS 上的链接问题
- 链接问题 boost::p ython::numpy.
- 与 32 位共享对象的链接问题
- 在单元测试项目中包括 .c 文件,并从多个 cpp 文件访问它而不会出现链接问题
- 安卓链接问题
- LLVM 传递链接问题:未定义的符号
- Cmake Mac OSX库链接问题:在Linux上进行编译,但在Mac上进行了编译
- 用libclang解析源文件 - 链接问题包括文件
- C / C++链接问题与非常简单的设置
- Zbar 在 vs2015 链接问题
- Vulkan + GLFW + Cmake在Linux环境下的链接问题
- TFS构建由于链接问题而失败