< /ul>
Серия событий заставила меня хотеть попробовать Создайте приложение C ++ в контейнере Docker, при использовании VCPKG .
Вот серия операторов, которые должны помочь обеспечить контекст:
[*] Я использую сервер Debian для разработки приложения C ++ < /li>
Приложение записано с использованием C ++ 23. Это относительно недавняя версия стандарта C ++, и как таковой, это только относительно недавние выбросы компиляторов, которые поддерживают эту версию стандарта
[*] Я использую GCC /
Код: Выделить всё
g++[*] Система Debian, которую я использую, имеет более старую версию GCC . Это что -то вроде версии 12. Он не поддерживает (по крайней мере, некоторые из) функций C ++ 23, которые мне нужны < /li>
Я не хочу заменять компилятор системы по умолчанию другим. Как правило, не очень хорошая идея, чтобы поменять компилятор, который поставляется с вашей ОС. Это один из способов, которым вы можете сломать Debian. (См. не сломайте Debian )
[*] I мог бы установить вторую версию GCC , но Я не решаюсь сделать это, потому что это включает либо временное изменение компилятора по умолчанию с помощью альтернатив обновления apt или настройки версии компилятора для выбранной системы сборки вручную . Это не кажется хорошим подходом, и у меня не было хорошего опыта с этим в прошлом. Я бы посоветовал использовать контейнер Docker - это более простой подход. < /p>
У меня есть одно решение, которое работает, но это не хорошее решение. Следующие шаги описаны ниже.
сначала установить vcpkg на хосте
Код: Выделить всё
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg && ./bootstrap-vcpkg.sh -disableMetrics
export VCPKG_ROOT=/path/to/vcpkg
export PATH=$VCPKG_ROOT:$PATH
Код: Выделить всё
mkdir myproject && cd myproject
vcpkg new --application
# created `vcpkg-configuration.json` and `vcpkg.json`
# example: add dependencies using vcpkg
vcpkg add port fmt
Существуют другие доступные системы сборки. Насколько я понимаю, VCPKG совместима с диапазоном систем сборки. Я использую cmake по умолчанию, а не по какой -либо конкретной причине.
Код: Выделить всё
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(myproject)
find_package(fmt CONFIG REQUIRED)
add_executable(myproject main.cpp)
target_link_libraries(myproject PRIVATE fmt::fmt)
Код: Выделить всё
main.cppКод: Выделить всё
# CMakePresets.json
{
"version": 2,
"configurePresets": [
{
"name": "vcpkg",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
}
}
]
}
< /code>
# CMakeUserPresets.json
{
"version": 2,
"configurePresets": [
{
"name": "default",
"inherits": "vcpkg"
}
]
}
< /code>
Note that this file (CMakeUserPresets.jsonКод: Выделить всё
# CMakeUserPresets.json (example from documentation)
{
"version": 2,
"configurePresets": [
{
"name": "default",
"inherits": "vcpkg",
"environment": {
"VCPKG_ROOT": "
"
}
}
]
}
< /code>
I tried changing
"VCPKG_ROOT": "
"
< /code>
to
"VCPKG_ROOT": "$env{VCPKG_ROOT}"
< /code>
however, this resulted in an error when trying to run
$ cmake --preset=default
CMake Error: Could not read presets from /home/user/myproject: Invalid macro expansion
< /code>
Therefore I removed "environment"Код: Выделить всё
CMake was unable to find a build program corresponding to "Ninja".
< /code>
Therefore I changed
"generator": "Ninja"
< /code>
to
"generator": "Unix Makefiles"
< /code>
in CMakePresets.jsonТогда команда выполняется OK: cmake - -preset = default .
Наконец, для создания: < /p>
Код: Выделить всё
cmake --build build
< /code>
Note that if we were to repeat these steps inside a Docker container, the first step would be required, but none of the remaining steps are required.
In the first step, we installed vcpkgОднако оставшиеся шаги не нужны повторять. Мы просто копируем необходимые файлы в изображение контейнера. < /P>
Есть две проблемы с этим подходом: < /p>
Процесс занимает много времени и очень неэффективен. Каждый раз, когда исходный код меняется, VCPKG идет и загружает файл из GitHub. Это вызвано командой cmake - -preset = default .
[*] Процесс сборки работает только, выполняя некоторые работы извне.
< /ul>
, чтобы объяснить вторую точку в более подробном детеальном: сборка изображения контейнера Docker зависит от некоторых команд vcpkg < /code>, которые были выполнены до того, как контейнер будет построен. Это связано с тем, что контейнер зависит от файлов vcpkg-configuration.json и vcpkg.json . Они генерируются путем запуска некоторых команд vcpkg . Чтобы их генерировать, хост -система требует установки vcpkg .
она чувствует себя немного "курицей и яйцом".
это Было бы возможно запустить эти команды внутри контейнера как часть процесса сборки, однако тогда vcpkg-configuration.json и vcpkg.json будет сгенерирован, а не файлы, хранящиеся под управлением источника. /p>
Вот копия Dockerfile < /code>. < /p>
Код: Выделить всё
FROM gcc:latest
WORKDIR /root
RUN apt update && apt install curl zip unzip tar cmake -y
RUN git clone https://github.com/microsoft/vcpkg.git
RUN cd vcpkg && ./bootstrap-vcpkg.sh -disableMetrics
ENV VCPKG_ROOT=/root/vcpkg
ENV PATH=$VCPKG_ROOT:$PATH
RUN mkdir /app
WORKDIR /app
COPY ./myproject ./myproject
WORKDIR /app/myproject
RUN cmake --preset=default
RUN cmake --build build
< /code>
A .dockerignore#.dockerignore
**/build
< /code>
To run it
$ docker build -t myproject/myprojectbuild .
$ docker run --rm myproject/myprojectbuild
< /code>
There is one final problem: How to get the build artifact out of the (temporary) container, and copy it to the host.
Подробнее здесь: https://stackoverflow.com/questions/793 ... sing-vcpkg
Мобильная версия