c++ - 如何在 CMake 项目中包含 IntelliSense 的外部库源?
问题描述
我正在使用 Visual Studio 的 CMake 项目模板在 Visual Studio 中开发 C++ 应用程序。要构建我的应用程序,我只需要标头和外部库,我可以像这样链接它:
# CMakeList.txt : CMake project for myapp, include source and define project specific logic here.
cmake_minimum_required (VERSION 3.8)
# Add source to this project's executable.
add_executable (myapp "myapp.cpp" "myapp.h")
# Add TIFF library
set(TIFF_INCLUDE_DIR "C:\\libs\\tiff\\out\\install\\x64-Debug\\include")
set(TIFF_LIBRARY "C:\\libs\\tiff\\out\\install\\x64-Debug\\lib\\tiffd.lib")
find_package(TIFF REQUIRED)
target_link_libraries(myapp PRIVATE TIFF::TIFF)
到目前为止,一切都很好。我可以使用 tiff 库来打开、读取、写入 tiff 文件等,并且 IntelliSense 正在赶上头文件中的声明。但是,我希望 IntelliSense 也能了解 TIFF 库的完整源代码。例如,如果我在 myapp.cpp 并且我ctrl+click
在TIFFOpen
它上面打开了对应的头文件,TIFFOpen
但是当我ctrl+click
TIFFOpen
在头文件中时,它并没有转到对应的源文件,这是myapp
. 这是可以理解的,因为我从未告诉 Visual Studio 在哪里可以找到外部库的源文件。
CMake 不需要知道外部库的源文件在哪里,因为它不会构建外部库,因此我想我不/不应该更改 CMakeLists.txt 中的任何内容
一种选择(我还没有尝试过,但我很确定它会起作用),将整个 tiff 库作为 myapp 的子项目包含在内。我确实对这个解决方案有一些问题:
- 外部库在概念上不是项目的组成部分,我不打算修改外部库。这更像是一个原则问题。
- 简单地将它作为我的项目中的子文件夹会导致更改我不打算更改的内容的风险。
- 当我全部重建时,我不想重建外部库。我知道 Visual Studio / CMake 足够聪明,可以发现没有任何变化并且不会重建,但我宁愿让 Visual Studio / CMake 甚至不尝试。
在我看来,我必须在 Visual Studio 设置中的某处设置包含源文件的目录,但仍与项目相关。我最好的猜测是这.vs/ProjectSettings.json
是我需要以某种方式编辑的文件,但老实说,我不知道。
或者,也许我可以编写一些CMakeLists.txt
不执行任何操作但会触发 IntelliSense 以查看包含源文件的文件夹的命令。再说一次,我不知道该怎么做。
简而言之,我希望 IntelliSense 能够看到外部库的所有源文件,就像它看到 myapp 的源文件一样,而不是将外部库的所有源文件都包含为 myapp 的子项目。如果可能的话,我应该怎么做?
如果相关,我使用 Visual Studio 2019 社区和它附带的 CMake (3.15)。
解决方案
关于您的最后一条评论,在评论部分编写代码很不方便,所以我会在这里发布,尽管不是答案。
libtiff-4.pc
是用于 pkg-config,而不是 cmake,并且find_package()
不能直接在 Windows 上处理它,如果你真的想要的话,需要做一些工作。手动编写所有内容可能更容易。请记住根据您的配置设置tiff.lib
and 。tiffd.lib
您可以使用CMAKE_BUILD_TYPE
变量和if()
命令,例如:
# set build type to release if not specified
if(NOT CMAKE_BUILD_TYPE OR CMAKE_BUILD_TYPE STREQUAL "")
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build Type" FORCE)
endif()
# switch lib to link according to build type
if(CMAKE_BUILD_TYPE STREQUAL "Release")
# for release
set(TIFF_LIBRARY "<your_path_to_installed_lib>/tiff.lib")
else()
# for debug. If you have other configs like relwithdebinfo you can add more
set(TIFF_LIBRARY "<your_path_to_installed_lib>/tiffd.lib")
endif()
此外,删除find_package()
并使用target_link_libraries()
and target_inlude_directories()
:
set(TIFF_INCLUDE_DIR "<your_path_to_installed_headers>/include")
target_link_libraries(myapp PRIVATE ${TIFF_LIBRARY})
target_include_directories(myapp PRIVATE ${TIFF_INCLUDE_DIR})
如果您愿意,您也可以跳过设置TIFF_LIBRARY
并TIFF_INCLUDE_DIR
直接传递字符串。
我经常使用 Visual Studio,它是我最喜欢的 IDE。但是在 Windows 上使用 cmake 进行包管理不如 Linux 流畅。永远记得在编译和安装外部库之后设置环境变量。
通常 find_package() 将查找名为的系统环境变量<libname>_DIR
(例如TIFF_DIR
,在您的情况下未找到),该变量用于存储已安装库的路径,然后在该文件夹中查找<libname>Config.cmake
and <libname>ConfigVersion.cmake
(并且会失败,TIFF
因为它没有没有它们)。
它还会搜索其他地方,详情请查看https://cmake.org/cmake/help/v3.15/command/find_package.html?highlight=find_package。
因此,对于那些带有 cmake 导出文件的库,请添加一个具有正确名称和值的变量。这仅用于编译。
如果您希望您的应用程序在编译后运行,您还需要将已安装 lib 的二进制文件(通常是 *.dll)的路径添加到系统Path
变量中。在您的情况下,您应该找到类似的东西tiff.dll
,tiffd.dll
在编译和安装之后,将该文件夹添加到Path
您就可以开始了。