使用CMake在Windows(MSVC)中查找库

时间:2018-01-17 01:17:37

标签: c++ windows visual-studio cmake

我在尝试链接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一起使用?

由于

2 个答案:

答案 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 初始化。

相关问题