使用 CMake 在 Windows(MSVC) 中查找库
Find libraries in Windows(MSVC) with CMake
im 在尝试链接 MSVC 中的库时遇到问题。我有一些外部依赖项,我已经编译用于发布和调试,并将它们设置在不同的文件夹中(${PROJECT_SOURCE_DIR}/External/Debug/lib 和 ${PROJECT_SOURCE_DIR}/External/Release/lib)。我编写了一些 FindFoo.cmake 模块,这些模块作为find_library命令的提示 ${EXTERNAL_LIB_DIR},该命令根据 ${CMAKE_BUILD_TYPE} 设置。
这项工作在 Linux 上完善,但在 Windows 中失败(它总是将EXTERNAL_LIB_DIR路径设置为调试路径),并且由于_ITERATOR_DEBUG_LEVEL而无法链接。
这是我正在使用的FindFoo.cmake的示例。
FIND_PATH(SOIL_INCLUDE_DIR
NAMES SOIL/SOIL.h
PATHS
${EXTERNAL_DIR}/soil/inc
NO_DEFAULT_PATH
)
find_library(
SOIL_LIBRARY
NAMES SOIL soil soil_debug
PATHS
${EXTERNAL_LIB_DIR}
NO_DEFAULT_PATH
)
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(SOIL DEFAULT_MSG SOIL_LIBRARY S
SOIL_INCLUDE_DIR)
if (${SOIL_FOUND})
SET(SOIL_INCLUDE_DIRS ${SOIL_INCLUDE_DIR})
SET(SOIL_LIBRARIES ${SOIL_LIBRARY})
endif()
MARK_AS_ADVANCED( SOIL_LIBRARY SOIL_INCLUDE_DIR )
在这里创造了EXTERNAL_LIB_DIR # 设置外部库
set(EXTERNAL_DIR ${PROJECT_SOURCE_DIR}/External)
if (${CMAKE_BUILD_TYPE} MATCHES Debug)
set(EXTERNAL_LIB_DIR ${PROJECT_SOURCE_DIR}/External/lib/Debug)
else()
set(EXTERNAL_LIB_DIR ${PROJECT_SOURCE_DIR}/External/lib/Release)
endif()
message(STATUS "Using libraries in ${EXTERNAL_LIB_DIR}")
我应该如何修改创建EXTERNAL_LIB_DIR变量的 FindFoo.cmake 以使其与 MSVC 一起使用?
谢谢
您将需要两个不同的find_library
调用,一个用于调试,一个用于发布。
find_library(SOIL_LIBRARY_DEBUG NAMES soil_debug
PATHS ${PROJECT_SOURCE_DIR}/External/lib/Debug
NO_DEFAULT_PATH)
find_library(SOIL_LIBRARY_RELEASE NAMES SOIL soil
PATHS ${PROJECT_SOURCE_DIR}/External/lib/Release
NO_DEFAULT_PATH)
set(SOIL_LIBRARIES debug ${SOIL_LIBRARY_DEBUG} optimized ${SOIL_LIBRARY_RELEASE})
target_link_libraries(foo ${SOIL_LIBRARIES})
请注意,这仍然不完全正确,因为它不能正确区分所有四种默认配置(调试,发布,MinSizeRel和RelWithDebInfo),但对于大多数用例来说已经足够了。
在现代 CMake 中,查找脚本通常创建导入的目标,而不是通过变量公开查找结果,如果需要,理论上可以提供与配置文件包相同的灵活性。看看较新的CMake版本附带的脚本,以了解它的外观(FindZlib.cmake
是一个很好的例子,因为它相当小)。
永远不要在查找脚本中依赖CMAKE_BUILD_TYPE
,因为它仅受单一配置生成器(如 Makefiles)支持!
我想详细说明ComicSansMS的答案。他为我指出了正确的方向。
我来这里是因为我正在寻找一种解决方案来查找Linux和MS Windows上的GoogleTest安装库。首先,我看了一下cmake模块 FindGTest,但这有点问题(不提供正确的目录),也没有提供我也需要的gmock路径。所以我决定自己使用 cmakefind_library()
查找目录。
安装谷歌测试在这里不是问题。我在build/
目录上使用其默认安装并得到:
# On Linux with build type Debug
tree build/lib/
build/lib/
├── libgmock_maind.a
├── libgmockd.a
├── libgtest_maind.a
└── libgtestd.a
# On Linux with build type Release
tree build/lib/
build/lib/
├── libgmock.a
├── libgmock_main.a
├── libgtest.a
└── libgtest_main.a
请注意,库名称后附加了一个带有Debug的d
。较新的安装将覆盖旧安装。
# On MS Windows with build type Debug and Release
build/lib/
├── Debug
│ ├── gmock_maind.lib
│ ├── gmock_maind.pdb
│ ├── gmockd.lib
│ ├── gmockd.pdb
│ ├── gtest_maind.lib
│ ├── gtest_maind.pdb
│ ├── gtestd.lib
│ └── gtestd.pdb
└── Release
├── gmock.lib
├── gmock_main.lib
├── gtest.lib
└── gtest_main.lib
MS Windows不会覆盖旧的构建类型,但它具有其他子目录。例如,我希望所有四个库gtest[d]
、gtest_main[d]
、gmock[d]
和gmock_main[d]
都添加为两个操作系统上链接目标的库,而无需修改:
message("CMAKE_FIND_LIBRARY_PREFIXES is: ${CMAKE_FIND_LIBRARY_PREFIXES}")
message("CMAKE_FIND_LIBRARY_SUFFIXES is: ${CMAKE_FIND_LIBRARY_SUFFIXES}")
find_library(GTEST_STATIC_LIBRARY gtest gtestd
PATHS ${CMAKE_BINARY_DIR}/lib
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
NO_DEFAULT_PATH)
message("GTEST_STATIC_LIBRARY is: ${GTEST_STATIC_LIBRARY}")
find_library(GMOCK_STATIC_LIBRARY gmock gmockd
PATHS ${CMAKE_BINARY_DIR}/lib
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
NO_DEFAULT_PATH)
message("GMOCK_STATIC_LIBRARY is: ${GMOCK_STATIC_LIBRARY}")
find_library(GTEST_MAIN_STATIC_LIBRARY gtest_main gtest_maind
PATHS ${CMAKE_BINARY_DIR}/lib
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
NO_DEFAULT_PATH)
message("GTEST_MAIN_STATIC_LIBRARY is: ${GTEST_MAIN_STATIC_LIBRARY}")
find_library(GMOCK_MAIN_STATIC_LIBRARY gmock_main gmock_maind
PATHS ${CMAKE_BINARY_DIR}/lib
PATH_SUFFIXES Debug Release MinSizeRel RelWithDebInfo
NO_DEFAULT_PATH)
message("GMOCK_MAIN_STATIC_LIBRARY is: ${GMOCK_MAIN_STATIC_LIBRARY}")
link_libraries(${GTEST_STATIC_LIBRARY} ${GMOCK_STATIC_LIBRARY}
${GTEST_MAIN_STATIC_LIBRARY} ${GMOCK_MAIN_STATIC_LIBRARY})
如果两个版本都可用,则此顺序将仅与发布版本匹配。如果您希望先匹配调试,则只需对库名称重新排序即可。有了PATH_SUFFIXES,查找将匹配所有可能的构建类型。结果我得到发布:
# On Linux:
~$ rm -rf build/ && cmake -S . -B build -D CMAKE_BUILD_TYPE=Release
--- snip ---
CMAKE_FIND_LIBRARY_PREFIXES is: lib
CMAKE_FIND_LIBRARY_SUFFIXES is: .so;.a
GTEST_STATIC_LIBRARY is: /home/ingo/develbuild/lib/libgtest.a
GMOCK_STATIC_LIBRARY is: /home/ingo/develbuild/lib/libgtest.a
GTEST_MAIN_STATIC_LIBRARY is: /home/ingo/develbuild/lib/libgtest_main.a
GMOCK_MAIN_STATIC_LIBRARY is: /home/ingo/develbuild/lib/libgmock_main.a
rem On MS Windows:
~>cmake --build build --config Release
--- snip ---
CMAKE_FIND_LIBRARY_PREFIXES is:
CMAKE_FIND_LIBRARY_SUFFIXES is: .lib
GTEST_STATIC_LIBRARY is: C:/Users/ingo/devel/build/lib/Release/gtest.lib
GMOCK_STATIC_LIBRARY is: C:/Users/ingo/devel/build/lib/Release/gmock.lib
GTEST_MAIN_STATIC_LIBRARY is: C:/Users/ingo/devel/build/lib/Release/gtest_main.lib
GMOCK_MAIN_STATIC_LIBRARY is: C:/Users/ingo/devel/build/lib/Release/gmock_main.lib
CMAKE_FIND_LIBRARY_PREFIXES和MAKE_FIND_LIBRARY_SUFFIXES由cmake正常初始化。
- 正在查找文档以获得PS4平台的C++中的设备信息
- 在C++中查找文件
- MSVC多行宏编译器错误
- 模板元程序查找相似的连续类型名称
- 在UNIX系统中使用DIR查找文件的字节大小
- 查找最接近的大于当前数字的数字的索引
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 查找后更改类变量
- 使用正则表达式regex_search在字符串中查找字符串
- 为什么使用__LINE_的代码在发布模式下在MSVC下编译,而不是在调试模式下
- MSVC是否支持C++11样式的属性而不是__declspec
- 使用gcc从静态链接的文件中查找可选符号
- MSVC将仅移动结构参数解释为指针
- 在C++中查找范围的长度
- C++17中函数模板中的静态数组初始化(MSVC 2019)
- 算法问题:查找从堆栈中弹出的所有序列
- 有与__builtin__FUNCTION()等效的MSVC吗
- 使用 CMake 在 Windows(MSVC) 中查找库
- 查找包含在MSVC中的c++名称空间的位置
- 匹配MSVC符号导出名称到Qt Creator导入查找