使用支持所有 vcpkg/apt-get/brew 的 cmake 添加 FreeType 依赖项
Add FreeType dependency with cmake supporting all vcpkg/apt-get/brew
我有一个项目依赖于 FreeType,并使用 CMake 作为构建系统。 CMake 有一个 FindFreeType built-in module which is supposed to be used like this, see for example this other SO question:
find_package(Freetype REQUIRED)
target_link_libraries(mylib ${FREETYPE_LIBRARIES})
target_include_directories(mylib PRIVATE ${FREETYPE_INCLUDE_DIRS})
从 CMake 3.10 开始,还有 Freetype::Freetype
导入目标,因此我们可以避免 target_include_directories
:
find_package(Freetype REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
这在 Ubuntu 18.04 上运行良好,通过 apt install libfreetype6-dev
安装了 FreeType。我假设当通过自制程序安装软件包时它也适用于 macOS(我还没有测试过)。
但是,在 Windows,我希望允许开发人员依赖安装了 vcpkg 的 FreeType:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install
.\vcpkg install freetype:x64-windows
他们将通过 运行 以下 CMake 命令定位:
cmake .. -G "Visual Studio 15 2017" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/Users/Boris/vcpkg/scripts/buildsystems/vcpkg.cmake
不幸的是,上面的 CMake 命令对这个问题开头的两个 CMakeLists.txt 中的任何一个都不起作用,因为在安装 FreeType 时找到和 link 的正确方法通过 vcpkg 如下:
find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype) # Here, all-lowercase is required
特别是,vcpkg 提供的 freetype-config.cmake
配置文件定义了目标 freetype
(不像内置查找模块那样 Freetype::Freetype
),并且没有定义任何 FREETYPE_LIBRARIES
或 FREETYPE_INCLUDE_DIRS
个变量。
什么是使我的 CMakeLists.txt
与 "traditional" 查找 FreeType 的方法以及 vcpkg 兼容的正确方法?
假设是 CMake 3.10 之前的版本,我正在考虑以下内容:
if(DEFINED VCPKG_TARGET_TRIPLET)
find_package(freetype CONFIG REQUIRED)
set(FREETYPE_LIBRARIES freetype)
set(FREETYPE_INCLUDE_DIRS "")
else()
find_package(Freetype REQUIRED)
endif()
target_link_libraries(mylib ${FREETYPE_LIBRARIES})
target_include_directories(mylib PRIVATE ${FREETYPE_INCLUDE_DIRS})
这看起来是个好习惯吗?有更好的主意吗?
感觉很难看,此外,开发人员总是有可能希望将 vcpkg 用于某些其他依赖项而不是 FreeType(例如,显式提供 FREETYPE_DIR
),所以这个技巧不会'在所有情况下都不够,我们需要另一个 CMake 选项,如 MYLIB_IGNORE_VCPKG_FREETYPE
,它开始变得更丑陋。
Would that seem like good practice? Any better idea?
不要对可能的包管理器一无所知。
执行以下操作:
find_package(Freetype CONFIG) # should find freetype-config.cmake if available
find_package(Freetype REQUIRED) # Will not be executed if Freetype_FOUND ist already set
# if you do not want two find_package calls consider using CMAKE_FIND_PACKAGE_PREFER_CONFIG
然后测试目标Freetype::Freetype
或freetype
是否存在
if(TARGET freetype AND NOT TARGET Freetype::Freetype)
add_library(Freetype::Freetype ALIAS freetype) # target freetype is defined by freetype-targets.cmake
# might need to add freetype to global scope if cmake errors here
# alternativly if the above does not work for you you can use
# add_library(Freetype::Freetype INTERFACE IMPORTED)
# target_link_libraries(Freetype::Freetype INTERFACE freetype)
endif()
if(NOT TARGET Freetype::Freetype)
# insert error here
# or create the target correctly (see cmakes newer FindFreetype.cmake)
endif()
target_link_libraries(mylib PRIVATE Freetype::Freetype)
如果您不想为目标添加别名,您还可以定义一个名为 FREETYPE_TARGET
的变量,并将其设置为正确的链接目标。
在旧版本的vcpkg中(<2020年1月,参见vcpkg#9311),安装Freetype时曾经有过如下信息:
The package freetype is compatible with built-in CMake targets:
find_package(Freetype REQUIRED)
target_link_libraries(main PRIVATE Freetype::Freetype)
在当前版本中,他们改为推荐 find_package(freetype CONFIG REQUIRED)
,这确保配置包 vcpkg/<...>/freetype-config.cmake
优先于 CMake 的 built-in 模块包 FindFreetype.cmake
.
但是,使用 built-in 模块包仍然可以正常工作:它将找到 vcpkg-installed 库,并定义一个 Freetype::Freetype
目标(如果 CMake >= 3.10)而不是一个 freetype
目标。
请注意,默认情况下,find_package(Freetype REQUIRED)
首先搜索模块包,然后搜索配置包。但是,用户可以设置 CMAKE_FIND_PACKAGE_PREFER_CONFIG
,这将改为使用配置包。因此,确保定义 Freetype::Freetype
的可靠方法是执行以下操作:
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
但是,如果 CMake < 3.10,这仍然没有定义 Freetype::Freetype
目标。在这种情况下,一种选择是在您的 CMAKE_MODULE_PATH
.
中提供一份更新版本的 FindFreetype.cmake
为了更加稳健,您甚至可以将其称为 Find<Mylib>Freetype.cmake
,在不太可能的情况下,您的 CMakeLists.txt 被用作另一个项目的子目录,该项目也修改了 CMAKE_MODULE_PATH
并提供不兼容的 FindFreetype.cmake
.
我有一个项目依赖于 FreeType,并使用 CMake 作为构建系统。 CMake 有一个 FindFreeType built-in module which is supposed to be used like this, see for example this other SO question:
find_package(Freetype REQUIRED)
target_link_libraries(mylib ${FREETYPE_LIBRARIES})
target_include_directories(mylib PRIVATE ${FREETYPE_INCLUDE_DIRS})
从 CMake 3.10 开始,还有 Freetype::Freetype
导入目标,因此我们可以避免 target_include_directories
:
find_package(Freetype REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
这在 Ubuntu 18.04 上运行良好,通过 apt install libfreetype6-dev
安装了 FreeType。我假设当通过自制程序安装软件包时它也适用于 macOS(我还没有测试过)。
但是,在 Windows,我希望允许开发人员依赖安装了 vcpkg 的 FreeType:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
.\vcpkg integrate install
.\vcpkg install freetype:x64-windows
他们将通过 运行 以下 CMake 命令定位:
cmake .. -G "Visual Studio 15 2017" -A x64 -DCMAKE_TOOLCHAIN_FILE=C:/Users/Boris/vcpkg/scripts/buildsystems/vcpkg.cmake
不幸的是,上面的 CMake 命令对这个问题开头的两个 CMakeLists.txt 中的任何一个都不起作用,因为在安装 FreeType 时找到和 link 的正确方法通过 vcpkg 如下:
find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype) # Here, all-lowercase is required
特别是,vcpkg 提供的 freetype-config.cmake
配置文件定义了目标 freetype
(不像内置查找模块那样 Freetype::Freetype
),并且没有定义任何 FREETYPE_LIBRARIES
或 FREETYPE_INCLUDE_DIRS
个变量。
什么是使我的 CMakeLists.txt
与 "traditional" 查找 FreeType 的方法以及 vcpkg 兼容的正确方法?
假设是 CMake 3.10 之前的版本,我正在考虑以下内容:
if(DEFINED VCPKG_TARGET_TRIPLET)
find_package(freetype CONFIG REQUIRED)
set(FREETYPE_LIBRARIES freetype)
set(FREETYPE_INCLUDE_DIRS "")
else()
find_package(Freetype REQUIRED)
endif()
target_link_libraries(mylib ${FREETYPE_LIBRARIES})
target_include_directories(mylib PRIVATE ${FREETYPE_INCLUDE_DIRS})
这看起来是个好习惯吗?有更好的主意吗?
感觉很难看,此外,开发人员总是有可能希望将 vcpkg 用于某些其他依赖项而不是 FreeType(例如,显式提供 FREETYPE_DIR
),所以这个技巧不会'在所有情况下都不够,我们需要另一个 CMake 选项,如 MYLIB_IGNORE_VCPKG_FREETYPE
,它开始变得更丑陋。
Would that seem like good practice? Any better idea?
不要对可能的包管理器一无所知。
执行以下操作:
find_package(Freetype CONFIG) # should find freetype-config.cmake if available
find_package(Freetype REQUIRED) # Will not be executed if Freetype_FOUND ist already set
# if you do not want two find_package calls consider using CMAKE_FIND_PACKAGE_PREFER_CONFIG
然后测试目标Freetype::Freetype
或freetype
是否存在
if(TARGET freetype AND NOT TARGET Freetype::Freetype)
add_library(Freetype::Freetype ALIAS freetype) # target freetype is defined by freetype-targets.cmake
# might need to add freetype to global scope if cmake errors here
# alternativly if the above does not work for you you can use
# add_library(Freetype::Freetype INTERFACE IMPORTED)
# target_link_libraries(Freetype::Freetype INTERFACE freetype)
endif()
if(NOT TARGET Freetype::Freetype)
# insert error here
# or create the target correctly (see cmakes newer FindFreetype.cmake)
endif()
target_link_libraries(mylib PRIVATE Freetype::Freetype)
如果您不想为目标添加别名,您还可以定义一个名为 FREETYPE_TARGET
的变量,并将其设置为正确的链接目标。
在旧版本的vcpkg中(<2020年1月,参见vcpkg#9311),安装Freetype时曾经有过如下信息:
The package freetype is compatible with built-in CMake targets:
find_package(Freetype REQUIRED)
target_link_libraries(main PRIVATE Freetype::Freetype)
在当前版本中,他们改为推荐 find_package(freetype CONFIG REQUIRED)
,这确保配置包 vcpkg/<...>/freetype-config.cmake
优先于 CMake 的 built-in 模块包 FindFreetype.cmake
.
但是,使用 built-in 模块包仍然可以正常工作:它将找到 vcpkg-installed 库,并定义一个 Freetype::Freetype
目标(如果 CMake >= 3.10)而不是一个 freetype
目标。
请注意,默认情况下,find_package(Freetype REQUIRED)
首先搜索模块包,然后搜索配置包。但是,用户可以设置 CMAKE_FIND_PACKAGE_PREFER_CONFIG
,这将改为使用配置包。因此,确保定义 Freetype::Freetype
的可靠方法是执行以下操作:
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
但是,如果 CMake < 3.10,这仍然没有定义 Freetype::Freetype
目标。在这种情况下,一种选择是在您的 CMAKE_MODULE_PATH
.
为了更加稳健,您甚至可以将其称为 Find<Mylib>Freetype.cmake
,在不太可能的情况下,您的 CMakeLists.txt 被用作另一个项目的子目录,该项目也修改了 CMAKE_MODULE_PATH
并提供不兼容的 FindFreetype.cmake
.