Настроить и установить необходимые пакеты для проекта - PullRequest
0 голосов
/ 19 июня 2020

Исходя из других менеджеров пакетов, я ожидаю, что смогу сделать следующее в проекте:

  • настроить необходимые библиотеки (в файле конфигурации, например CMakelists.txt или nuget * packages.config)

  • установить / обновить все необходимые библиотеки

Это невозможно с vcpkg и CMake:

Мне удалось настроить vcpkg и CMakefile (linux):

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

target_link_libraries(<app> <package>)

Однако для этого необходимо вручную установить все необходимые библиотеки (vcpkg install <package>).

Как Могу ли я перечислить необходимые пакеты и управлять ими с помощью vcpkg или CMake (например, автоматически установить их, если они отсутствуют)?

Ответы [ 2 ]

0 голосов
/ 28 июня 2020

Недавно я потратил некоторое время на работу с CMake и vcpkg. Мне не нравится типичный подход к управлению vcpkg и его установленными пакетами отдельно от моих проектов CMake, поэтому я написал несколько сценариев CMake для обработки vcpkg в процессе сборки CMake.

Сценарий CMake для установки vcpkg в первую очередь является обращением к 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()

Сценарий для установки пакета vcpkg требует настраиваемой команды и цели.

# ./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()

Для правильной привязки основного проекта к 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
)

Используя эту структуру, CMake будет управлять установкой как vcpkg, так и пакетов, поддерживаемых им.

Обратите внимание, что это точечное решение. У меня есть более общий шаблон для этого в моем Github , который охватывает Windows и Linux и позволяет использовать отдельно поддерживаемый экземпляр vcpkg.

0 голосов
/ 19 июня 2020

Я сделал нечто подобное в своих проектах, используя ExternalProject_Add .

Код будет аналогичен приведенному ниже шаблону (я заменил свою зависимость на вашу)

  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()

Другой вариант - использовать FetchContent , но я еще не пробовал.

...