使用支持所有vcpkg/apt get/brew的cmake添加FreeType依赖项

使用支持所有vcpkg/apt get/brew的cmake添加FreeType依赖项,cmake,freetype,vcpkg,Cmake,Freetype,Vcpkg,我有一个项目,它依赖于FreeType,并使用CMake作为构建系统。CMake有一个内置模块,应该像这样使用,例如,请参见: 自CMake 3.10以来,还存在导入的目标,因此我们可以避免使用目标\u include\u目录: 这在Ubuntu18.04上非常有效,FreeType通过apt安装libfreetype6-dev安装。我假设它也可以在macOS上使用,因为它是通过我还没有测试过的自制软件安装的 但是,在Windows上,我希望允许开发人员依赖安装了vcpkg的FreeType:

我有一个项目,它依赖于FreeType,并使用CMake作为构建系统。CMake有一个内置模块,应该像这样使用,例如,请参见:

自CMake 3.10以来,还存在导入的目标,因此我们可以避免使用目标\u include\u目录:

这在Ubuntu18.04上非常有效,FreeType通过apt安装libfreetype6-dev安装。我假设它也可以在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中的任何一个一起使用,因为通过vcpkg安装FreeType时,查找并链接到FreeType的正确方法如下:

find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype)  # Here, all-lowercase is required
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
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
特别是,vcpkg提供的freetype-config.cmake config文件定义了与内置查找模块类似的目标freetype not freetype::freetype,并且没有定义任何freetype_库或freetype_INCLUDE_DIRS变量

怎样才能使我的CMakeLists.txt既与查找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,它开始变得更加丑陋

这似乎是一种好的做法吗?还有更好的主意吗

不,对可能的包管理器不可知

请执行以下操作:

find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype)  # Here, all-lowercase is required
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
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
然后测试目标Freetype::Freetype或Freetype是否存在

如果不想为目标设置别名,还可以定义一个名为FREETYPE_target的变量,并将其设置为正确的目标以进行链接

这似乎是一种好的做法吗?还有更好的主意吗

不,对可能的包管理器不可知

请执行以下操作:

find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype)  # Here, all-lowercase is required
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
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
然后测试目标Freetype::Freetype或Freetype是否存在


如果不想为目标设置别名,还可以定义一个名为FREETYPE_target的变量,并将其设置为正确的目标以进行链接。

在较旧版本的vcpkg<2020年1月,请参阅,安装FREETYPE时通常会出现以下消息:

The package freetype is compatible with built-in CMake targets:

    find_package(Freetype REQUIRED)
    target_link_libraries(main PRIVATE Freetype::Freetype)
在当前版本中,他们建议find_packagefreetype CONFIG REQUIRED,这确保配置包vcpkg//freetype-CONFIG.cmake优先于cmake的内置模块包FindFreetype.cmake

但是,使用内置模块包仍然可以正常工作:它将找到vcpkg安装的库,如果CMake>=3.10而不是Freetype目标,它将定义Freetype::Freetype目标

请注意,默认情况下,find_packageFreetype REQUIRED首先搜索模块包,然后搜索配置包。但是,用户可以设置CMAKE\u FIND\u PACKAGE\u preference\u CONFIG,这将使用CONFIG包。因此,确保定义Freetype::Freetype的健壮方法是执行以下操作:

find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype)  # Here, all-lowercase is required
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
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
但是,如果CMake<3.10,这仍然不能定义Freetype::Freetype目标。在这种情况下,一种选择是在您的CMAKE_模块_路径中提供较新版本的的副本


为了更加健壮,您甚至可以将其命名为FindFreetype.cmake,在不太可能的情况下,您的CMakeLists.txt被用作另一个项目的子目录,该项目还修改了cmake_MODULE_路径,并提供了不兼容的FindFreetype.cmake。

在较旧版本的vcpkg<2020年1月,请参阅,安装Freetype时,通常会显示以下消息:

The package freetype is compatible with built-in CMake targets:

    find_package(Freetype REQUIRED)
    target_link_libraries(main PRIVATE Freetype::Freetype)
在当前版本中,他们建议find_packagefreetype CONFIG REQUIRED,这确保配置包vcpkg//freetype-CONFIG.cmake优先于cmake的内置模块包FindFreetype.cmake

但是,使用内置模块包仍然可以正常工作:它将找到vcpkg安装的库,如果CMake>=3.10而不是Freetype目标,它将定义Freetype::Freetype目标

请注意,默认情况下,find_packageFreetype REQUIRED首先搜索模块包,然后搜索配置包。但是,用户可以设置CMAKE\u FIND\u PACKAGE\u preference\u CONFIG,这将使用CONFIG包。因此,确保定义Freetype::Freetype的健壮方法是执行以下操作:

find_package(freetype CONFIG REQUIRED) # `Freetype` works too, but vcpkg doc recommends `freetype`
target_link_libraries(mylib freetype)  # Here, all-lowercase is required
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
find_package(Freetype MODULE REQUIRED)
target_link_libraries(mylib Freetype::Freetype)
但是,如果CMake<3.10,这仍然不能定义Freetype::Freetype目标。在这种情况下,一种选择是在您的CMAKE_模块_路径中提供较新版本的的副本

为了更加健壮,您甚至可以将其称为FindFreetype。
cmake,在不太可能的情况下,您的CMakeLists.txt被用作另一个项目的子目录,该项目还修改了cmake_MODULE_路径,并提供了不兼容的FindFreetype.cmake。

这是一个好主意!感谢并欢迎使用Stack Overflow:-我还没有尝试过,但我已经接受了答案,因为它看起来确实应该有效,否则我可能会忘记回来接受答案。我终于有时间了。有一些小问题:我们需要安静,而不是在第一次调用中需要,并且设置别名并不顺利:我们需要CMake 3.11+为导入的目标定义别名,需要CMake 3.18+为非全局导入的目标定义别名,尽管这很有帮助。有效的解决方案是通过add_libraryFreetype::Freetype SHARED导入并设置其所有属性来重新定义新目标。但后来,我意识到这些事实上都不是必要的:我发布了一个新的答案。无论如何,非常感谢你的帮助!这是个好主意!感谢并欢迎使用Stack Overflow:-我还没有尝试过,但我已经接受了答案,因为它看起来确实应该有效,否则我可能会忘记回来接受答案。我终于有时间了。有一些小问题:我们需要安静,而不是在第一次调用中需要,并且设置别名并不顺利:我们需要CMake 3.11+为导入的目标定义别名,需要CMake 3.18+为非全局导入的目标定义别名,尽管这很有帮助。有效的解决方案是通过add_libraryFreetype::Freetype SHARED导入并设置其所有属性来重新定义新目标。但后来,我意识到这些事实上都不是必要的:我发布了一个新的答案。无论如何,非常感谢你的帮助!请不要。。。。。导入的_位置${FREETYPE_LIBRARIES}错误_LIBRARIES变量可以包含以下内容:优化;somelib.lib;调试;someother.lib会破坏您的代码。@AlexanderNeumann您是对的,谢谢您提供的信息。我仍然在学习这些东西。我已经用一个更健壮的解决方案更新了答案。我仍然觉得这个解决方案很难看,但不幸的是,你的答案似乎不适用于CMake<3.10:真的没有任何有效的理由被困在一个三岁的CMake中。。。。确保CMake模块在CMake版本中稳定的唯一方法是自己提供它们,这是您描述的CMake_模块_路径解决方案。这也是由例如VTK完成的。绝对最佳的解决方案是为您的项目重定向方法提供具有唯一名称空间目标的自定义FindFreetype.CMake。这样可以避免目标碰撞。但是您的解决方案仍然失败,因为用户可能会设置CMAKE\u FIND\u PACKAGE\u preference\u CONFIG,而net会设置库vars@AlexanderNeumannUbuntu 16.04 LTS于2021年4月30日到期。它随cmake 3.5.1一起发布。我希望Ubuntu 16.04上的用户能够轻松地编译我的应用程序,而不必获得他们系统上官方不支持的较新版本的CMake。当存在解决方法时,没有理由强迫人们使用尖端的CMake。@AlexanderNeumann您关于CMake\u FIND\u PACKAGE\u preference\u CONFIG的观点是正确的。我想我们可以通过使用find_packageFreetype模块REQUIRED来解决这个问题,或者按照您的建议,使用更健壮的find_packageFreetype REQUIRED。请不要。。。。。导入的_位置${FREETYPE_LIBRARIES}错误_LIBRARIES变量可以包含以下内容:优化;somelib.lib;调试;someother.lib会破坏您的代码。@AlexanderNeumann您是对的,谢谢您提供的信息。我仍然在学习这些东西。我已经用一个更健壮的解决方案更新了答案。我仍然觉得这个解决方案很难看,但不幸的是,你的答案似乎不适用于CMake<3.10:真的没有任何有效的理由被困在一个三岁的CMake中。。。。确保CMake模块在CMake版本中稳定的唯一方法是自己提供它们,这是您描述的CMake_模块_路径解决方案。这也是由例如VTK完成的。绝对最佳的解决方案是为您的项目重定向方法提供具有唯一名称空间目标的自定义FindFreetype.CMake。这样可以避免目标碰撞。但是您的解决方案仍然失败,因为用户可能会设置CMAKE\u FIND\u PACKAGE\u preference\u CONFIG,而net会设置库vars@AlexanderNeumannUbuntu 16.04 LTS于2021年4月30日到期。它随cmake 3.5.1一起发布。我希望Ubuntu 16.04上的用户能够轻松地编译我的应用程序,而不必获得他们系统上官方不支持的较新版本的CMake。当存在解决方法时,没有理由强迫人们使用尖端的CMake。@AlexanderNeumann您关于CMake\u FIND\u PACKAGE\u preference\u CONFIG的观点是正确的。我想我们可以通过使用find_packageFreetype模块REQUIRED来解决这个问题,或者按照您的建议,使用更健壮的find_packageFreetype REQUIRED。