我在尝试链接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路径设置为Debug路径)并且由于_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一起使用?
由于
答案 0 :(得分:2)
您需要两个不同的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})
请注意,这仍然不完全正确,因为它没有正确区分所有四种默认配置(Debug,Release,MinSizeRel和RelWithDebInfo),但它对大多数用例来说已经足够了。
在现代CMake中,查找脚本通常创建导入的目标,而不是通过变量公开查找结果,如果需要,理论上它提供与config-file packages相同的灵活性。看一下较新的CMake版本附带的脚本,以了解它的外观(FindZlib.cmake
是一个很好的例子,因为它很小)。
永远不要依赖CMAKE_BUILD_TYPE
查找脚本,因为它is only supported by single-config generators(如Makefile)!
答案 1 :(得分:0)
我想详细说明ComicSansMS的答案。他为我指明了正确的方向。
我来这里是因为我一直在寻找一种解决方案来在 Linux 和 MS Windows 上找到 GoogleTest 安装的库。首先,我查看了 cmake 模块 FindGTest 但这有点问题(不提供正确的目录)并且也不提供 gmock 的路径我也需要。所以我决定自己使用 cmake find_library()
查找目录。
安装 GoogleTest 在这里不是问题。我在 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})
如果两个版本都可用,此顺序将仅匹配发布版本。如果您更喜欢先匹配 Debug,则只需重新排序库名称即可。使用 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 初始化。