mirror of
https://gitlab.kitware.com/cmake/cmake.git
synced 2026-09-25 04:09:36 +03:00
devcontainer: Add a Dev Container definition for CMake development
Provide a `.devcontainer` definition, following the Dev Container Specification, to give contributors a ready-made Linux environment with the tools needed to build CMake, run its test suite, build its documentation, and satisfy its style rules. Base the container on Ubuntu, which offers the broadest ecosystem of packages and tooling for development, including a recent `cmake` and the `clang-format` version our style rules require, exactly. Mirror the package lists of the Debian image our CI infrastructure uses, section by section, so that the dependencies available closely match the ones against which merge requests are tested. Build the image the way the images under `.gitlab/ci/docker/` are built: bind mount the package lists and the installation script rather than copying them in, and cache the package lists and downloaded archives so that a rebuild fetches only what has changed. Run optional `.devcontainer/hooks/root.sh` and `.devcontainer/hooks/user.sh` scripts, both ignored by Git, so that developers may customize the container without modifying tracked files. Document usage in a new `Help/dev/devcontainer.rst`. Fixes: #28043
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
|
||||||
|
# Base image for the CMake development container.
|
||||||
|
#
|
||||||
|
# The images our CI infrastructure uses, described under `.gitlab/ci/docker/`,
|
||||||
|
# are built on the distributions we test CMake against and are minimized for
|
||||||
|
# CI use. Prepare the environment from scratch on Ubuntu instead: it offers
|
||||||
|
# the broadest ecosystem of packages and tooling for development, including a
|
||||||
|
# recent `cmake` and the `clang-format` version our style rules require.
|
||||||
|
ARG BASE_IMAGE=ubuntu:26.04
|
||||||
|
|
||||||
|
FROM ${BASE_IMAGE}
|
||||||
|
|
||||||
|
ARG USERNAME=cmake-dev
|
||||||
|
ARG USER_UID=1000
|
||||||
|
ARG USER_GID=${USER_UID}
|
||||||
|
|
||||||
|
# Install the packages needed to build CMake, run its test suite, build its
|
||||||
|
# documentation, and satisfy its style rules, along with a few more that make
|
||||||
|
# the container a comfortable place to work.
|
||||||
|
#
|
||||||
|
# Cache the package lists and the downloaded archives, and hide the
|
||||||
|
# `docker-clean` configuration the base image provides so that it does not
|
||||||
|
# discard them, so that rebuilding the container downloads only what has
|
||||||
|
# changed since the last build.
|
||||||
|
RUN --mount=type=bind,source=install_deps.sh,target=/root/install_deps.sh \
|
||||||
|
--mount=type=bind,source=deps_packages.lst,target=/root/deps_packages.lst \
|
||||||
|
--mount=type=bind,source=dev_packages.lst,target=/root/dev_packages.lst \
|
||||||
|
--mount=type=bind,source=docker-clean,target=/etc/apt/apt.conf.d/docker-clean \
|
||||||
|
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
|
||||||
|
--mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||||
|
sh /root/install_deps.sh
|
||||||
|
|
||||||
|
# Create an unprivileged user matching the typical host account so that files
|
||||||
|
# created in the mounted source tree are not owned by `root`.
|
||||||
|
RUN --mount=type=bind,source=create_user.sh,target=/root/create_user.sh \
|
||||||
|
sh /root/create_user.sh ${USERNAME} ${USER_UID} ${USER_GID}
|
||||||
|
|
||||||
|
# Run the optional local customization scripts. They are ignored by Git so
|
||||||
|
# that developers may customize the container without modifying tracked files
|
||||||
|
# or risking that the customizations end up in a commit. See
|
||||||
|
# `Help/dev/devcontainer.rst`.
|
||||||
|
#
|
||||||
|
# `USER` sets neither the working directory nor `HOME`, and BuildKit passes a
|
||||||
|
# `RUN` only the environment the image records, which names just `PATH`. Say
|
||||||
|
# where each hook runs and whose home it writes to, so that a hook may spell a
|
||||||
|
# path relative to either.
|
||||||
|
WORKDIR /root
|
||||||
|
RUN --mount=type=bind,source=hooks,target=/opt/cmake-dev-hooks \
|
||||||
|
if test -f /opt/cmake-dev-hooks/root.sh; then \
|
||||||
|
HOME=/root sh -e /opt/cmake-dev-hooks/root.sh; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
USER ${USERNAME}
|
||||||
|
WORKDIR /home/${USERNAME}
|
||||||
|
RUN --mount=type=bind,source=hooks,target=/opt/cmake-dev-hooks \
|
||||||
|
if test -f /opt/cmake-dev-hooks/user.sh; then \
|
||||||
|
HOME=/home/${USERNAME} sh -e /opt/cmake-dev-hooks/user.sh; \
|
||||||
|
fi
|
||||||
Executable
+38
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Create the unprivileged user that the container runs as, given its name,
|
||||||
|
# uid, and gid. See `Help/dev/devcontainer.rst`.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly username="$1"
|
||||||
|
readonly uid="$2"
|
||||||
|
readonly gid="$3"
|
||||||
|
|
||||||
|
# The base image already ships an unprivileged user, which usually occupies
|
||||||
|
# the uid we want. Remove whoever holds it, and the group holding our gid,
|
||||||
|
# before creating ours.
|
||||||
|
if getent passwd "$uid" > /dev/null; then
|
||||||
|
userdel --remove "$(getent passwd "$uid" | cut -d: -f1)"
|
||||||
|
fi
|
||||||
|
if getent group "$gid" > /dev/null; then
|
||||||
|
groupdel "$(getent group "$gid" | cut -d: -f1)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
groupadd --gid "$gid" "$username"
|
||||||
|
useradd --uid "$uid" --gid "$gid" --create-home --shell /bin/bash "$username"
|
||||||
|
|
||||||
|
# Let the user administer the container, e.g. to install more packages.
|
||||||
|
echo "$username ALL=(ALL) NOPASSWD:ALL" > "/etc/sudoers.d/$username"
|
||||||
|
chmod 0440 "/etc/sudoers.d/$username"
|
||||||
|
|
||||||
|
# Pre-create the directories that `devcontainer.json` mounts volumes over so
|
||||||
|
# that the volumes inherit the ownership recorded here. Name the parents too:
|
||||||
|
# `install -d` records the ownership only of the directories it is given, and
|
||||||
|
# tools that write elsewhere under them need to own them as well.
|
||||||
|
install -d -o "$username" -g "$username" \
|
||||||
|
"/home/$username/.cache" \
|
||||||
|
"/home/$username/.cache/ccache" \
|
||||||
|
"/home/$username/.config" \
|
||||||
|
"/home/$username/.config/glab-cli" \
|
||||||
|
"/home/$username/workspace"
|
||||||
@@ -0,0 +1,126 @@
|
|||||||
|
# Packages needed to build CMake, run its test suite, and build its
|
||||||
|
# documentation.
|
||||||
|
#
|
||||||
|
# This list mirrors `.gitlab/ci/docker/debian13-x86_64/deps_packages.lst`,
|
||||||
|
# section by section, so that the two are easy to compare as our
|
||||||
|
# dependencies evolve. Package names differ where Ubuntu names them
|
||||||
|
# differently, and entries needed only by our CI infrastructure are left out
|
||||||
|
# with a note saying so.
|
||||||
|
#
|
||||||
|
# Additions for personal use belong in `.devcontainer/hooks/root.sh`.
|
||||||
|
# See `Help/dev/devcontainer.rst`.
|
||||||
|
|
||||||
|
locales
|
||||||
|
|
||||||
|
# Install build requirements.
|
||||||
|
libssl-dev
|
||||||
|
|
||||||
|
# Install development tools.
|
||||||
|
g++
|
||||||
|
curl
|
||||||
|
git
|
||||||
|
|
||||||
|
# The base image carries no certificate store, which `curl` and `apt` need
|
||||||
|
# to reach anything over HTTPS.
|
||||||
|
ca-certificates
|
||||||
|
|
||||||
|
# Install optional external build dependencies.
|
||||||
|
libarchive-dev
|
||||||
|
libbz2-dev
|
||||||
|
libcurl4-gnutls-dev
|
||||||
|
libexpat1-dev
|
||||||
|
libjsoncpp-dev
|
||||||
|
liblzma-dev
|
||||||
|
libncurses-dev
|
||||||
|
librhash-dev
|
||||||
|
libuv1-dev
|
||||||
|
libzstd-dev
|
||||||
|
zlib1g-dev
|
||||||
|
|
||||||
|
# NOTE `include-what-you-use` is not provided here. CI builds it from
|
||||||
|
# source, which is more than a development container needs.
|
||||||
|
|
||||||
|
# Tools needed for the test suite.
|
||||||
|
jq
|
||||||
|
|
||||||
|
# Packages needed to test CTest.
|
||||||
|
brz
|
||||||
|
cvs
|
||||||
|
subversion
|
||||||
|
mercurial
|
||||||
|
|
||||||
|
# Install ASM_NASM language toolchain.
|
||||||
|
nasm
|
||||||
|
|
||||||
|
# NOTE The HIP language toolchain, `hipcc`, is not provided here. It is
|
||||||
|
# large and rarely needed while working on CMake itself.
|
||||||
|
|
||||||
|
# NOTE The IAR compiler is not provided here, so neither are the packages it
|
||||||
|
# depends on.
|
||||||
|
|
||||||
|
# Packages needed to test find modules.
|
||||||
|
alsa-utils
|
||||||
|
aspell
|
||||||
|
aspell-en
|
||||||
|
doxygen graphviz
|
||||||
|
freeglut3-dev
|
||||||
|
libgnutls28-dev
|
||||||
|
libarchive-dev
|
||||||
|
libaspell-dev
|
||||||
|
libblas-dev
|
||||||
|
libboost-dev
|
||||||
|
libboost-filesystem-dev
|
||||||
|
libboost-program-options-dev
|
||||||
|
libboost-python-dev
|
||||||
|
libboost-thread-dev
|
||||||
|
libbz2-dev
|
||||||
|
libcups2-dev
|
||||||
|
libcurl4-gnutls-dev
|
||||||
|
libdevil-dev
|
||||||
|
libfontconfig1-dev
|
||||||
|
libfreetype-dev
|
||||||
|
libgdal-dev
|
||||||
|
libgif-dev
|
||||||
|
libgl1-mesa-dev
|
||||||
|
libglew-dev
|
||||||
|
libgmock-dev
|
||||||
|
libgrpc++-dev libgrpc-dev
|
||||||
|
libgsl-dev
|
||||||
|
libgtest-dev
|
||||||
|
libgtk2.0-dev
|
||||||
|
libhdf5-dev
|
||||||
|
libhdf5-mpich-dev
|
||||||
|
libhdf5-openmpi-dev
|
||||||
|
libicu-dev
|
||||||
|
libinput-dev
|
||||||
|
libjpeg-dev
|
||||||
|
libjsoncpp-dev
|
||||||
|
liblapack-dev
|
||||||
|
liblzma-dev
|
||||||
|
libmagick++-dev
|
||||||
|
libopenal-dev
|
||||||
|
libopenmpi-dev openmpi-bin
|
||||||
|
libosp-dev
|
||||||
|
libpng-dev
|
||||||
|
libpq-dev postgresql-server-dev-18
|
||||||
|
libprotobuf-dev libprotobuf-c-dev libprotoc-dev protobuf-compiler protobuf-compiler-grpc
|
||||||
|
libsdl1.2-dev
|
||||||
|
libsqlite3-dev
|
||||||
|
libtiff-dev
|
||||||
|
libuv1-dev
|
||||||
|
libwxgtk3.2-dev
|
||||||
|
libx11-dev
|
||||||
|
libxalan-c-dev
|
||||||
|
libxerces-c-dev
|
||||||
|
libxml2-dev libxml2-utils
|
||||||
|
libxslt1-dev xsltproc
|
||||||
|
openjdk-25-jdk
|
||||||
|
python3 python3-dev python3-numpy pypy3 pypy3-dev python3-venv
|
||||||
|
qtbase5-dev qtbase5-dev-tools
|
||||||
|
rbenv ruby-build
|
||||||
|
ruby ruby-dev
|
||||||
|
swig
|
||||||
|
unixodbc-dev
|
||||||
|
|
||||||
|
# NOTE The packages needed to test ironpython are not provided here. Ubuntu
|
||||||
|
# no longer carries `libmono-system-windows-forms4.0-cil`.
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# Packages that make the container a comfortable place to work in, but that
|
||||||
|
# building CMake, running its test suite, and building its documentation do
|
||||||
|
# not need, and so are not part of `deps_packages.lst`.
|
||||||
|
#
|
||||||
|
# Additions for personal use belong in `.devcontainer/hooks/root.sh`.
|
||||||
|
# See `Help/dev/devcontainer.rst`.
|
||||||
|
|
||||||
|
# Make the shell pleasant to work in interactively. `unminimize` restores
|
||||||
|
# the documentation of the packages the base image provides, which it ships
|
||||||
|
# without; see `Help/dev/devcontainer.rst`.
|
||||||
|
bash-completion
|
||||||
|
less
|
||||||
|
man-db
|
||||||
|
manpages
|
||||||
|
manpages-dev
|
||||||
|
nano
|
||||||
|
unminimize
|
||||||
|
vim
|
||||||
|
|
||||||
|
# Build CMake.
|
||||||
|
ccache
|
||||||
|
cmake
|
||||||
|
ninja-build
|
||||||
|
|
||||||
|
# Debug CMake.
|
||||||
|
gdb
|
||||||
|
|
||||||
|
# Build the documentation.
|
||||||
|
python3-sphinx
|
||||||
|
|
||||||
|
# Satisfy our style rules. Our `.clang-format` requires `clang-format`
|
||||||
|
# version 18, exactly, so install that version by name. Do not install the
|
||||||
|
# unversioned `clang-format` package: it provides a much newer version.
|
||||||
|
clang-format-18
|
||||||
|
pre-commit
|
||||||
|
|
||||||
|
# Run `glab` and `glab-axi`, and reach GitLab over SSH. `nodejs` and `npm`
|
||||||
|
# are needed both to install `glab-axi` and to run it.
|
||||||
|
nodejs
|
||||||
|
npm
|
||||||
|
openssh-client
|
||||||
|
|
||||||
|
# Let the unprivileged container user install more packages.
|
||||||
|
sudo
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "CMake",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"remoteUser": "cmake-dev",
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"type": "volume",
|
||||||
|
"source": "cmake-dev-ccache",
|
||||||
|
"target": "/home/cmake-dev/.cache/ccache"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"postAttachCommand": "${containerWorkspaceFolder}/.devcontainer/setup-status.sh",
|
||||||
|
"customizations": {
|
||||||
|
"vscode": {
|
||||||
|
"extensions": [
|
||||||
|
"EditorConfig.EditorConfig",
|
||||||
|
"ms-vscode.cmake-tools",
|
||||||
|
"ms-vscode.cpptools",
|
||||||
|
"lextudio.restructuredtext",
|
||||||
|
"llvm-vs-code-extensions.vscode-clangd"
|
||||||
|
],
|
||||||
|
"settings": {
|
||||||
|
"C_Cpp.clang_format_path": "/usr/bin/clang-format-18",
|
||||||
|
"cmake.configureOnOpen": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
# Local customizations applied while building the development container.
|
||||||
|
# Everything here is ignored, except this file, so that customizations may
|
||||||
|
# bring along whatever files they need. See `Help/dev/devcontainer.rst`.
|
||||||
|
/*
|
||||||
|
!/.gitignore
|
||||||
Executable
+27
@@ -0,0 +1,27 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Install the packages listed in `deps_packages.lst` and `dev_packages.lst`.
|
||||||
|
# See `Help/dev/devcontainer.rst`.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Install without asking questions, e.g. the time zone `tzdata` wants.
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# Unlike our CI images, keep the documentation that packages carry: the base
|
||||||
|
# image excludes man pages and the like, which is not what one wants in a
|
||||||
|
# development environment. Packages already installed in the base image
|
||||||
|
# remain without their documentation; `unminimize` restores that.
|
||||||
|
rm -f /etc/dpkg/dpkg.cfg.d/excludes
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y $(grep -h '^[^#]\+$' /root/deps_packages.lst /root/dev_packages.lst)
|
||||||
|
|
||||||
|
# Add locales, the way our CI images do, for the tests that need them.
|
||||||
|
sed -i -E '/^# en_US[ .](ISO-8859-1|UTF-8)( |$)/ s/^# //' /etc/locale.gen
|
||||||
|
dpkg-reconfigure --frontend=noninteractive locales
|
||||||
|
|
||||||
|
# `Utilities/Scripts/clang-format.bash` finds `clang-format-18` by name, but
|
||||||
|
# make the unversioned name resolve to version 18 as well so that tools
|
||||||
|
# looking for it get the version our style rules require.
|
||||||
|
ln -s "$(command -v clang-format-18)" /usr/local/bin/clang-format
|
||||||
Executable
+25
@@ -0,0 +1,25 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# Report whether this clone and its development container are ready to use
|
||||||
|
# and, if they are not, print what remains to be set up. Run each time a
|
||||||
|
# tool attaches to the container. See `Help/dev/devcontainer.rst`.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
# Check that development setup is up-to-date, the way our `pre-commit` hook
|
||||||
|
# does. `Utilities/SetupForDevelopment.sh` is interactive, so the container
|
||||||
|
# cannot run it on the developer's behalf.
|
||||||
|
eval "$(grep '^SetupForDevelopment_VERSION=' Utilities/SetupForDevelopment.sh)"
|
||||||
|
setup_done=$(git config --get hooks.SetupForDevelopment || echo 0)
|
||||||
|
if test "$setup_done" -lt "${SetupForDevelopment_VERSION:-0}"; then
|
||||||
|
cat <<MESSAGE
|
||||||
|
git: this work tree is not set up for development.
|
||||||
|
Run 'Utilities/SetupForDevelopment.sh' to configure your Git identity and
|
||||||
|
install the project's commit hooks. The work tree is shared with the host,
|
||||||
|
so running it here sets up both.
|
||||||
|
MESSAGE
|
||||||
|
else
|
||||||
|
echo "git: this work tree is set up for development."
|
||||||
|
fi
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
.clang-format export-ignore
|
.clang-format export-ignore
|
||||||
.clang-tidy export-ignore
|
.clang-tidy export-ignore
|
||||||
.codespellrc export-ignore
|
.codespellrc export-ignore
|
||||||
|
.devcontainer export-ignore
|
||||||
.editorconfig export-ignore
|
.editorconfig export-ignore
|
||||||
.pre-commit-config.yaml export-ignore
|
.pre-commit-config.yaml export-ignore
|
||||||
.typos.toml export-ignore
|
.typos.toml export-ignore
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ To contribute patches:
|
|||||||
#. Fork the upstream `CMake Repository`_ into a personal account.
|
#. Fork the upstream `CMake Repository`_ into a personal account.
|
||||||
#. Run `Utilities/SetupForDevelopment.sh`_ for local git configuration.
|
#. Run `Utilities/SetupForDevelopment.sh`_ for local git configuration.
|
||||||
#. See `Building CMake`_ for building CMake locally.
|
#. See `Building CMake`_ for building CMake locally.
|
||||||
|
Optionally, see the `CMake Dev Container Guide`_ for a ready-made
|
||||||
|
development environment.
|
||||||
#. See the `CMake Source Code Guide`_ for coding guidelines
|
#. See the `CMake Source Code Guide`_ for coding guidelines
|
||||||
and the `CMake Testing Guide`_ for testing instructions.
|
and the `CMake Testing Guide`_ for testing instructions.
|
||||||
#. Create a topic branch named suitably for your work.
|
#. Create a topic branch named suitably for your work.
|
||||||
@@ -52,6 +54,7 @@ preparing or submitting a change.
|
|||||||
.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
|
.. _`CMake Repository`: https://gitlab.kitware.com/cmake/cmake
|
||||||
.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh
|
.. _`Utilities/SetupForDevelopment.sh`: Utilities/SetupForDevelopment.sh
|
||||||
.. _`Building CMake`: README.rst#building-cmake
|
.. _`Building CMake`: README.rst#building-cmake
|
||||||
|
.. _`CMake Dev Container Guide`: Help/dev/devcontainer.rst
|
||||||
.. _`CMake Source Code Guide`: Help/dev/source.rst
|
.. _`CMake Source Code Guide`: Help/dev/source.rst
|
||||||
.. _`CMake Testing Guide`: Help/dev/testing.rst
|
.. _`CMake Testing Guide`: Help/dev/testing.rst
|
||||||
.. _`commit messages`: Help/dev/review.rst#commit-messages
|
.. _`commit messages`: Help/dev/review.rst#commit-messages
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ Developer Documentation
|
|||||||
|
|
||||||
CMake developer documentation is provided by the following documents:
|
CMake developer documentation is provided by the following documents:
|
||||||
|
|
||||||
|
* The `CMake Dev Container Guide`_.
|
||||||
* The `CMake Source Code Guide`_.
|
* The `CMake Source Code Guide`_.
|
||||||
* The `CMake Documentation Guide`_.
|
* The `CMake Documentation Guide`_.
|
||||||
* The `CMake Testing Guide`_.
|
* The `CMake Testing Guide`_.
|
||||||
@@ -43,6 +44,7 @@ CMake developer documentation is provided by the following documents:
|
|||||||
* The `CMake Debugging Guide`_.
|
* The `CMake Debugging Guide`_.
|
||||||
* The `CMake Diagnostics Guide`_.
|
* The `CMake Diagnostics Guide`_.
|
||||||
|
|
||||||
|
.. _`CMake Dev Container Guide`: devcontainer.rst
|
||||||
.. _`CMake Source Code Guide`: source.rst
|
.. _`CMake Source Code Guide`: source.rst
|
||||||
.. _`CMake Documentation Guide`: documentation.rst
|
.. _`CMake Documentation Guide`: documentation.rst
|
||||||
.. _`CMake Testing Guide`: testing.rst
|
.. _`CMake Testing Guide`: testing.rst
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
CMake Dev Container Guide
|
||||||
|
*************************
|
||||||
|
|
||||||
|
The following is a guide to the development container provided for building,
|
||||||
|
testing, and formatting CMake itself. See documentation on `CMake
|
||||||
|
Development`_ for more information.
|
||||||
|
|
||||||
|
.. _`CMake Development`: README.rst
|
||||||
|
|
||||||
|
Overview
|
||||||
|
========
|
||||||
|
|
||||||
|
The `.devcontainer`_ directory at the top of the CMake source tree describes
|
||||||
|
a Linux development environment following the `Dev Container Specification`_.
|
||||||
|
Using it is entirely optional, but it offers a quick way to get a complete
|
||||||
|
environment with all the tools needed to build CMake, run its test suite,
|
||||||
|
build its documentation, and satisfy its style rules.
|
||||||
|
|
||||||
|
The container is built on Ubuntu, which offers the broadest ecosystem of
|
||||||
|
packages and tooling for development. Its package lists mirror those of the
|
||||||
|
Debian image our CI infrastructure uses, described under
|
||||||
|
`.gitlab/ci/docker`_, so the dependencies available closely match the ones
|
||||||
|
against which merge requests are tested. A few pieces of the CI environment
|
||||||
|
are left out because a development container rarely needs them, and each is
|
||||||
|
noted in the list that would otherwise carry it:
|
||||||
|
|
||||||
|
`.devcontainer/deps_packages.lst`_
|
||||||
|
The packages needed to build CMake, run its test suite, and build its
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
`.devcontainer/dev_packages.lst`_
|
||||||
|
The packages that make the container a comfortable place to work in, which
|
||||||
|
building and testing CMake does not itself need.
|
||||||
|
|
||||||
|
.. _`.devcontainer`: ../../.devcontainer
|
||||||
|
.. _`Dev Container Specification`: https://containers.dev
|
||||||
|
.. _`.gitlab/ci/docker`: ../../.gitlab/ci/docker
|
||||||
|
.. _`.devcontainer/deps_packages.lst`: ../../.devcontainer/deps_packages.lst
|
||||||
|
.. _`.devcontainer/dev_packages.lst`: ../../.devcontainer/dev_packages.lst
|
||||||
|
|
||||||
|
Prerequisites
|
||||||
|
=============
|
||||||
|
|
||||||
|
* A container engine such as `Docker`_ or `Podman`_. Building the image uses
|
||||||
|
bind and cache mounts, as the image builds under `.gitlab/ci/docker`_ do, so
|
||||||
|
it needs `BuildKit`_, enabled by default since Docker 23.0, or Podman 4.0 or
|
||||||
|
newer.
|
||||||
|
|
||||||
|
* A tool that understands the specification, such as the `Dev Containers`_
|
||||||
|
extension for Visual Studio Code, the `Dev Container CLI`_, or another
|
||||||
|
`supporting tool`_.
|
||||||
|
|
||||||
|
.. _`Docker`: https://docs.docker.com/get-started/get-docker/
|
||||||
|
.. _`Podman`: https://podman.io
|
||||||
|
.. _`BuildKit`: https://docs.docker.com/build/buildkit/
|
||||||
|
.. _`Dev Containers`: https://code.visualstudio.com/docs/devcontainers/containers
|
||||||
|
.. _`Dev Container CLI`: https://github.com/devcontainers/cli
|
||||||
|
.. _`supporting tool`: https://containers.dev/supporting
|
||||||
|
|
||||||
|
Usage
|
||||||
|
=====
|
||||||
|
|
||||||
|
In Visual Studio Code, open the CMake source tree and run the
|
||||||
|
``Dev Containers: Reopen in Container`` command. With the
|
||||||
|
`Dev Container CLI`_, start the container from the top of the source tree:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ devcontainer up --workspace-folder .
|
||||||
|
$ devcontainer exec --workspace-folder . bash
|
||||||
|
|
||||||
|
The source tree is mounted into the container, so changes made inside it are
|
||||||
|
made to the same working tree. Commits may be created either inside or
|
||||||
|
outside the container. `Utilities/SetupForDevelopment.sh`_ may likewise be
|
||||||
|
run in either place to configure your Git identity and install the project's
|
||||||
|
commit hooks, and takes effect in both. It is interactive, so the container
|
||||||
|
does not run it automatically, but `.devcontainer/setup-status.sh`_ reports
|
||||||
|
whether it still needs to be run each time a tool attaches to the container.
|
||||||
|
|
||||||
|
.. _`Utilities/SetupForDevelopment.sh`: ../../Utilities/SetupForDevelopment.sh
|
||||||
|
.. _`.devcontainer/setup-status.sh`: ../../.devcontainer/setup-status.sh
|
||||||
|
|
||||||
|
Build CMake in the container as one would on any other Linux host, as
|
||||||
|
described in `Building CMake`_:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cmake -G Ninja -B build -S .
|
||||||
|
$ cmake --build build
|
||||||
|
$ ctest --test-dir build
|
||||||
|
|
||||||
|
.. _`Building CMake`: ../../README.rst#building-cmake
|
||||||
|
|
||||||
|
Provided Tools
|
||||||
|
==============
|
||||||
|
|
||||||
|
In addition to the compiler and the external dependencies CMake can build
|
||||||
|
against, the container provides:
|
||||||
|
|
||||||
|
* ``cmake`` and ``ninja``, to build CMake with.
|
||||||
|
|
||||||
|
* ``ccache``, to speed up repeated builds, e.g.:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cmake -G Ninja -B build -S . -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
|
|
||||||
|
Its cache is stored in a named volume so that it survives rebuilds of the
|
||||||
|
container.
|
||||||
|
|
||||||
|
* ``clang-format`` version 18, exactly as required by our `C++ Code Style`_,
|
||||||
|
available as both ``clang-format`` and ``clang-format-18``:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ Utilities/Scripts/clang-format.bash --modified
|
||||||
|
|
||||||
|
* ``pre-commit``, to run the checks configured in
|
||||||
|
`.pre-commit-config.yaml`_:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ pre-commit install
|
||||||
|
$ pre-commit run --all-files
|
||||||
|
|
||||||
|
* ``sphinx-build``, to build the documentation as described in the
|
||||||
|
`CMake Documentation Guide`_.
|
||||||
|
|
||||||
|
* ``gdb``, to debug CMake as described in the `CMake Debugging Guide`_.
|
||||||
|
|
||||||
|
.. _`C++ Code Style`: source.rst#c-code-style
|
||||||
|
.. _`.pre-commit-config.yaml`: ../../.pre-commit-config.yaml
|
||||||
|
.. _`CMake Documentation Guide`: documentation.rst
|
||||||
|
.. _`CMake Debugging Guide`: debug.rst
|
||||||
|
|
||||||
|
The base image ships without documentation, but the container keeps the man
|
||||||
|
pages and other documentation of every package installed on top of it. Run
|
||||||
|
``sudo unminimize`` to restore the documentation of the packages the base
|
||||||
|
image itself provides.
|
||||||
|
|
||||||
|
Local Customization
|
||||||
|
===================
|
||||||
|
|
||||||
|
The container is meant to be an unconstrained space that each developer may
|
||||||
|
adapt. Two optional scripts, if present, run while the container image is
|
||||||
|
built:
|
||||||
|
|
||||||
|
``.devcontainer/hooks/root.sh``
|
||||||
|
Runs as ``root``, e.g. to install additional packages.
|
||||||
|
|
||||||
|
``.devcontainer/hooks/user.sh``
|
||||||
|
Runs as the unprivileged container user, e.g. to populate a shell
|
||||||
|
configuration file.
|
||||||
|
|
||||||
|
Each runs in the home directory of the user it runs as, with ``HOME`` naming
|
||||||
|
that directory.
|
||||||
|
|
||||||
|
The whole ``hooks`` directory is ignored by Git, apart from its
|
||||||
|
``.gitignore``, so customizations never appear in a commit, may bring along
|
||||||
|
whatever other files they need, and are preserved across updates to the
|
||||||
|
tracked container definition. For example, to add a package and a shell
|
||||||
|
alias:
|
||||||
|
|
||||||
|
.. code-block:: console
|
||||||
|
|
||||||
|
$ cat > .devcontainer/hooks/root.sh <<'EOF'
|
||||||
|
apt-get update && apt-get install -y tmux
|
||||||
|
EOF
|
||||||
|
$ cat > .devcontainer/hooks/user.sh <<'EOF'
|
||||||
|
echo "alias b='cmake --build build'" >> ~/.bashrc
|
||||||
|
EOF
|
||||||
|
|
||||||
|
Rebuild the container to apply them, e.g. with the
|
||||||
|
``Dev Containers: Rebuild Container`` command in Visual Studio Code.
|
||||||
|
|
||||||
|
Larger or longer-lived changes may of course be made by editing
|
||||||
|
`.devcontainer/Dockerfile`_ or `.devcontainer/devcontainer.json`_ directly,
|
||||||
|
but take care not to commit them accidentally.
|
||||||
|
|
||||||
|
.. _`.devcontainer/Dockerfile`: ../../.devcontainer/Dockerfile
|
||||||
|
.. _`.devcontainer/devcontainer.json`: ../../.devcontainer/devcontainer.json
|
||||||
Reference in New Issue
Block a user