我正在建立一个“框架”库,我试图整合Google测试。它是一个非常小的库,最后给我一个.so
或.dll
文件。
当我开始测试我的库时,我发现一个配置(下面的详细信息)在我的linux环境中的CMakeFile
上工作正常。但是当我尝试使用MSBuild
MSVC14
运行同一项目时,它会给我一个链接错误
LINK : fatal error LNK1104: cannot open file '..\src\Debug\foobar.lib'
我认为我的cmake猜测lib名称错误(foobar.lib
而不是foobar.dll
),但我找不到原因,也找不到解决方法。
另外,我不知道这是否真的是我测试它的最佳方式。我想要的是一种在没有main.cpp
文件的情况下测试整个框架(初始化,创建东西,检查返回等等)的方法,同时开始创建单元测试。
所以,我的问题是..我做错了,在Windows环境中,链接器找不到由foobar
构建的src/CMakeLists.txt
lib? (我检查过,lib是在“src / Debug / foobar.dll”中创建的,出现在错误中的同一目录,并且工作正常)
另外,我的方法是如此错误,以至于Windows不想处理?大声笑我的意思是,做我想做的事情是错误的?这不是我不想进行单元测试,我将很快做,但我真的想在开始这样做之前不使用任何外部exec二进制文件来构建和尝试我的lib。
谢谢!
OBS:
我的谷歌测试在linux和windows中都运行良好;
如果我删除了链接到foobar
lib的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)
答案 0 :(得分:1)
重新制定并加强我之前的评论:
您需要在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)