简体   繁体   English

为项目配置和安装所需的包

[英]Configure and Install required packages for a project

Coming from other package managers I expect to be able to do the following on a project:来自其他 package 经理,我希望能够在项目中执行以下操作:

  • configure the required libraries (in a config file, eg CMakelists.txt or nuget's packages.config )配置所需的库(在配置文件中,例如CMakelists.txt或 nuget 的packages.config

  • install/upgrade all the required libraries安装/升级所有必需的库

This seems to not be possible with vcpkg and CMake:对于 vcpkg 和 CMake,这似乎是不可能的:

I managed to set up vcpkg and CMakefile (linux):我设法设置了 vcpkg 和 CMakefile (linux):

# in ternimal
vcpkg install <package>
# CMakeLists.txt
find_package(nlohmann_json CONFIG REQUIRED)

target_link_libraries(<app> <package>)

This however requires to manually install all the required libraries ( vcpkg install <package> ).然而,这需要手动安装所有必需的库( vcpkg install <package> )。

How can I list the required packages and have vcpkg or CMake managed them as required (eg automatically install them if they are missing)?我如何列出所需的软件包并让 vcpkg 或 CMake 根据需要管理它们(例如,如果它们丢失,自动安装它们)?

I've recently spent some time working with CMake and vcpkg.我最近花了一些时间使用 CMake 和 vcpkg。 I dislike the typical approach of managing vcpkg and its installed packages separately from my CMake projects, so I wrote some CMake scripts to handle vcpkg during the CMake build process.我不喜欢将 vcpkg 及其安装包与我的 CMake 项目分开管理的典型方法,因此我在 CMake 构建过程中编写了一些 CMake 脚本来处理 vcpkg。

The CMake script to install vcpkg is primarily a call to ExternalProject_Add.安装 vcpkg 的 CMake 脚本主要是调用 ExternalProject_Add。

# ./vcpkg_utilities.cmake (part 1)
include(ExternalProject)
function(get_vcpkg)
    ExternalProject_Add(vcpkg
        GIT_REPOSITORY https://github.com/microsoft/vcpkg.git
        CONFIGURE_COMMAND ""
        INSTALL_COMMAND ""
        UPDATE_COMMAND ""
        BUILD_COMMAND "<SOURCE_DIR>/bootstrap-vcpkg.sh"
    )
    ExternalProject_Get_Property(vcpkg SOURCE_DIR)
    set(VCPKG_DIR ${SOURCE_DIR} PARENT_SCOPE)
    set(VCPKG_DEPENDENCIES "vcpkg" PARENT_SCOPE)
endfunction()

The script to have vcpkg install a package requires a custom command and target.让 vcpkg 安装 package 的脚本需要自定义命令和目标。

# ./vcpkg_utilities.cmake (part 2)
function(vcpkg_install PACKAGE_NAME)
    add_custom_command(
        OUTPUT ${VCPKG_DIR}/packages/${PACKAGE_NAME}_x64-linux/BUILD_INFO
        COMMAND ${VCPKG_DIR}/vcpkg install ${PACKAGE_NAME}:x64-linux
        WORKING_DIRECTORY ${VCPKG_DIR}
        DEPENDS vcpkg
    )
    add_custom_target(get${PACKAGE_NAME}
        ALL
        DEPENDS ${VCPKG_DIR}/packages/${PACKAGE_NAME}_x64-linux/BUILD_INFO
    )
    list(APPEND VCPKG_DEPENDENCIES "get${PACKAGE_NAME}")
    set(VCPKG_DEPENDENCIES ${VCPKG_DEPENDENCIES} PARENT_SCOPE)
endfunction()

Getting the main project linked to vcpkg appropriately (via toolchain file) requires vcpkg to be available when the main project is configured, so the main project is configured as an ExternalProject.将主项目适当地链接到 vcpkg(通过工具链文件)要求在配置主项目时 vcpkg 可用,因此主项目配置为 ExternalProject。

# /CMakeLists.txt
cmake_minimum_required(VERSION 3.17)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
project(top LANGUAGES CXX)
include(vcpkg_utilities)
get_vcpkg()
vcpkg_install(nlohmann_json)

include(ExternalProject)
set_property(DIRECTORY PROPERTY EP_BASE main_projectname)
ExternalProject_Add(main_projectname
    DEPENDS ${VCPKG_DEPENDENCIES}
    SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/src
    INSTALL_COMMAND ""
    CMAKE_ARGS --no-warn-unused-cli;
               -DCMAKE_TOOLCHAIN_FILE=${VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake
)

Using this structure, CMake will manage the installation of both vcpkg and packages maintained by it.使用此结构,CMake 将管理 vcpkg 及其维护的软件包的安装。

Note that this is a point solution.请注意,这是一个点解决方案。 I have a more generalized template for this in my Github that covers Windows and Linux, and allows the use of a separately-maintained vcpkg instance.我的Github中有一个更通用的模板,涵盖 Windows 和 Linux,并允许使用单独维护的 vcpkg 实例。

I've done something similar in my projects usingExternalProject_Add .我在我的项目中使用ExternalProject_Add做了类似的事情。

Code will be similar to the below pattern (I've replaced my dependency with your)代码将类似于以下模式(我已将我的依赖项替换为您的)

  find_package(nlohmann_json CONFIG) # make package not REQUIRED to avoid error...

  if(NOT NLOHMANN_JSON_FOUND)  # or whatever variable indicating _FOUND
    ...
    # here ExternalProject_Add from https://github.com/nlohmann/json.git
    # using specific tag...
    ...
    ExternalProject_Get_Property(... INSTALL_DIR)

    # create imported target here similar to nlohmann_json, as if we found it
    ...

  else()
    # We've found lib already installed... will use it...
    ...

  endif()

Another option can be using FetchContent , but I haven't tried it yet.另一种选择是使用FetchContent ,但我还没有尝试过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM