diff --git a/containers/cpp/.devcontainer/Dockerfile b/containers/cpp/.devcontainer/Dockerfile index 39267cd4f2..8018695ed8 100644 --- a/containers/cpp/.devcontainer/Dockerfile +++ b/containers/cpp/.devcontainer/Dockerfile @@ -2,6 +2,20 @@ ARG VARIANT=debian-11 FROM mcr.microsoft.com/vscode/devcontainers/cpp:0-${VARIANT} +# [Optional] Install CMake version different from what base image has already installed. +# CMake reinstall choices: none, 3.21.5, 3.22.2, or versions from https://cmake.org/download/ +ARG REINSTALL_CMAKE_VERSION_FROM_SOURCE="none" + +# Optionally install the cmake for vcpkg +COPY ./reinstall-cmake.sh /tmp/ +RUN if [ "${REINSTALL_CMAKE_VERSION_FROM_SOURCE}" != "none" ]; then \ + /tmp/reinstall-cmake.sh ${REINSTALL_CMAKE_VERSION_FROM_SOURCE}; \ + fi \ + && rm -f /tmp/reinstall-cmake.sh + +# [Optional] Uncomment this section to install additional vcpkg ports. +# RUN su vscode -c "${VCPKG_ROOT}/vcpkg install " + # [Optional] Uncomment this section to install additional packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # && apt-get -y install --no-install-recommends diff --git a/containers/cpp/.devcontainer/base-scripts/install-vcpkg.sh b/containers/cpp/.devcontainer/base-scripts/install-vcpkg.sh new file mode 100755 index 0000000000..821e2b6e15 --- /dev/null +++ b/containers/cpp/.devcontainer/base-scripts/install-vcpkg.sh @@ -0,0 +1,93 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +set -e + +USERNAME=${1:-"vscode"} + +# bionic and stretch pkg repos install cmake version < 3.15 which is required to run bootstrap-vcpkg.sh on ARM64 +VCPKG_UNSUPPORTED_ARM64_VERSION_CODENAMES="stretch bionic" + +. /etc/os-release + +# Exit early if ARM64 OS does not have cmake version required to build Vcpkg +if [ "$(dpkg --print-architecture)" = "arm64" ] && [[ "${VCPKG_UNSUPPORTED_ARM64_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]]; then + echo "OS ${VERSION_CODENAME} ARM64 pkg repo installs cmake version < 3.15, which is required to build Vcpkg." + exit 0 +fi + +# Add to bashrc/zshrc files for all users. +updaterc() { + echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..." + if [[ "$(cat /etc/bash.bashrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/bash.bashrc + fi + if [ -f "/etc/zsh/zshrc" ] && [[ "$(cat /etc/zsh/zshrc)" != *"$1"* ]]; then + echo -e "$1" >> /etc/zsh/zshrc + fi +} + +# Run apt-get if needed. +apt_get_update_if_needed() { + if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then + echo "Running apt-get update..." + apt-get update + else + echo "Skipping apt-get update." + fi +} + +# Check if packages are installed and installs them if not. +check_packages() { + if ! dpkg -s "$@" > /dev/null 2>&1; then + apt_get_update_if_needed + apt-get -y install --no-install-recommends "$@" + fi +} + +export DEBIAN_FRONTEND=noninteractive + +# Install additional packages needed by vcpkg: https://github.com/microsoft/vcpkg/blob/master/README.md#installing-linux-developer-tools +check_packages build-essential tar curl zip unzip pkg-config bash-completion ninja-build git + +# Setup group and add user +umask 0002 +if ! cat /etc/group | grep -e "^vcpkg:" > /dev/null 2>&1; then + groupadd -r "vcpkg" +fi +usermod -a -G "vcpkg" "${USERNAME}" + +# Start Installation +# Clone repository with ports and installer +mkdir -p "${VCPKG_ROOT}" +mkdir -p "${VCPKG_DOWNLOADS}" +git clone --depth=1 \ + -c core.eol=lf \ + -c core.autocrlf=false \ + -c fsck.zeroPaddedFilemode=ignore \ + -c fetch.fsck.zeroPaddedFilemode=ignore \ + -c receive.fsck.zeroPaddedFilemode=ignore \ + https://github.com/microsoft/vcpkg "${VCPKG_ROOT}" + +## Run installer to get latest stable vcpkg binary +## https://github.com/microsoft/vcpkg/blob/7e7dad5fe20cdc085731343e0e197a7ae655555b/scripts/bootstrap.sh#L126-L144 +"${VCPKG_ROOT}"/bootstrap-vcpkg.sh + +# Add vcpkg to PATH +updaterc "$(cat << EOF +export VCPKG_ROOT="${VCPKG_ROOT}" +if [[ "\${PATH}" != *"\${VCPKG_ROOT}"* ]]; then export PATH="\${PATH}:\${VCPKG_ROOT}"; fi +EOF +)" + +# Give read/write permissions to the user group. +chown -R ":vcpkg" "${VCPKG_ROOT}" "${VCPKG_DOWNLOADS}" +chmod g+r+w+s "${VCPKG_ROOT}" "${VCPKG_DOWNLOADS}" +chmod -R g+r+w "${VCPKG_ROOT}" "${VCPKG_DOWNLOADS}" + +# Enable tab completion for bash and zsh +VCPKG_FORCE_SYSTEM_BINARIES=1 su "${USERNAME}" -c "${VCPKG_ROOT}/vcpkg integrate bash" +VCPKG_FORCE_SYSTEM_BINARIES=1 su "${USERNAME}" -c "${VCPKG_ROOT}/vcpkg integrate zsh" \ No newline at end of file diff --git a/containers/cpp/.devcontainer/base.Dockerfile b/containers/cpp/.devcontainer/base.Dockerfile index c86b425a9d..98000767e1 100644 --- a/containers/cpp/.devcontainer/base.Dockerfile +++ b/containers/cpp/.devcontainer/base.Dockerfile @@ -8,6 +8,17 @@ RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ && apt-get -y install build-essential cmake cppcheck valgrind clang lldb llvm gdb \ && apt-get autoremove -y && apt-get clean -y && rm -rf /var/lib/apt/lists/* +# Setup ENV vars for vcpkg +ENV VCPKG_ROOT=/usr/local/vcpkg \ + VCPKG_DOWNLOADS=/usr/local/vcpkg-downloads + +ARG USERNAME=vscode + +# Install vcpkg itself: https://github.com/microsoft/vcpkg/blob/master/README.md#quick-start-unix +COPY base-scripts/install-vcpkg.sh /tmp/ +RUN /tmp/install-vcpkg.sh ${USERNAME} \ + && rm -f /tmp/install-vcpkg.sh + # [Optional] Uncomment this section to install additional OS packages. # RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \ # && apt-get -y install --no-install-recommends diff --git a/containers/cpp/.devcontainer/reinstall-cmake.sh b/containers/cpp/.devcontainer/reinstall-cmake.sh new file mode 100755 index 0000000000..c833253832 --- /dev/null +++ b/containers/cpp/.devcontainer/reinstall-cmake.sh @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +#------------------------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information. +#------------------------------------------------------------------------------------------------------------- +# +set -e + +CMAKE_VERSION=${1:-"none"} + +if [ "${CMAKE_VERSION}" = "none" ]; then + echo "No CMake version specified, skipping CMake reinstallation" + exit 0 +fi + +# Cleanup temporary directory and associated files when exiting the script. +cleanup() { + EXIT_CODE=$? + set +e + if [[ -n "${TMP_DIR}" ]]; then + echo "Executing cleanup of tmp files" + rm -Rf "${TMP_DIR}" + fi + exit $EXIT_CODE +} +trap cleanup EXIT + + +echo "Installing CMake..." +apt-get -y purge --auto-remove cmake +mkdir -p /opt/cmake + +architecture=$(dpkg --print-architecture) +case "${architecture}" in + arm64) + ARCH=aarch64 ;; + amd64) + ARCH=x86_64 ;; + *) + echo "Unsupported architecture ${architecture}." + exit 1 + ;; +esac + +CMAKE_BINARY_NAME="cmake-${CMAKE_VERSION}-linux-${ARCH}.sh" +CMAKE_CHECKSUM_NAME="cmake-${CMAKE_VERSION}-SHA-256.txt" +TMP_DIR=$(mktemp -d -t cmake-XXXXXXXXXX) + +echo "${TMP_DIR}" +cd "${TMP_DIR}" + +curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_BINARY_NAME}" -O +curl -sSL "https://github.com/Kitware/CMake/releases/download/v${CMAKE_VERSION}/${CMAKE_CHECKSUM_NAME}" -O + +sha256sum -c --ignore-missing "${CMAKE_CHECKSUM_NAME}" +sh "${TMP_DIR}/${CMAKE_BINARY_NAME}" --prefix=/opt/cmake --skip-license + +ln -s /opt/cmake/bin/cmake /usr/local/bin/cmake diff --git a/containers/cpp/.npmignore b/containers/cpp/.npmignore index 2b6971d690..c9b1cc1eee 100644 --- a/containers/cpp/.npmignore +++ b/containers/cpp/.npmignore @@ -3,5 +3,6 @@ test-project history definition-manifest.json library-scripts +base-scripts .vscode .npmignore diff --git a/containers/cpp/README.md b/containers/cpp/README.md index f841b9232e..d616904b92 100644 --- a/containers/cpp/README.md +++ b/containers/cpp/README.md @@ -50,7 +50,30 @@ See [history](history) for information on the contents of each version and [here Alternatively, you can use the contents of `base.Dockerfile` to fully customize your container's contents or to build it for a container host architecture not supported by the image. -Beyond `git`, this image / `Dockerfile` includes `zsh`, [Oh My Zsh!](https://ohmyz.sh/), a non-root `vscode` user with `sudo` access, and a set of common dependencies for development. +Beyond `git`, this image / `Dockerfile` includes `zsh`, [Oh My Zsh!](https://ohmyz.sh/), a non-root `vscode` user with `sudo` access, a set of common dependencies for development, and [Vcpkg](https://github.com/microsoft/vcpkg) a cross-platform package manager for C++. + +### Using Vcpkg +This dev container and its associated image includes a clone of the [`Vcpkg`](https://github.com/microsoft/vcpkg) repo for library packages, and a bootstrapped instance of the [Vcpkg-tool](https://github.com/microsoft/vcpkg-tool) itself. + +The minimum version of `cmake` required to install packages is higher than the version available in the main package repositories for Debian (<=11) and Ubuntu (<=21.10). `Vcpkg` will download a compatible version of `cmake` for its own use if that is the case (on x86_64 architectures), however you can opt to reinstall a different version of `cmake` globally by adding `"REINSTALL_CMAKE_VERSION_FROM_SOURCE: ""` to build args in `.devcontainer/devcontainer.json`. This will install `cmake` from its github releases. For example: + +```json +"args": { + "VARIANT": "debian-11", + "REINSTALL_CMAKE_VERSION_FROM_SOURCE": "3.21.5" +} +``` + +Most additional library packages installed using Vcpkg will be downloaded from their [official distribution locations](https://github.com/microsoft/vcpkg#security). To configure Vcpkg in this container to access an alternate registry, more information can be found here: [Registries: Bring your own libraries to vcpkg](https://devblogs.microsoft.com/cppblog/registries-bring-your-own-libraries-to-vcpkg/). + +To update the available library packages, pull the latest from the git repository using the following command in the terminal: + +```sh +cd "${VCPKG_ROOT}" +git pull --ff-only +``` + +> Note: Please review the [Vcpkg license details](https://github.com/microsoft/vcpkg#license) to better understand its own license and additional license information pertaining to library packages and supported ports. ### Adding the definition to a project or codespace diff --git a/containers/cpp/definition-manifest.json b/containers/cpp/definition-manifest.json index 010af571e7..d1cdecb86f 100644 --- a/containers/cpp/definition-manifest.json +++ b/containers/cpp/definition-manifest.json @@ -64,10 +64,18 @@ "clang", "lldb", "llvm", - "gdb" + "gdb", + "tar", + "curl", + "zip", + "unzip", + "pkg-config", + "bash-completion", + "ninja-build" ], "git": { - "Oh My Zsh!": "/home/vscode/.oh-my-zsh" + "Oh My Zsh!": "/home/vscode/.oh-my-zsh", + "vcpkg": "/usr/local/vcpkg" }, "languages": { "GCC": { diff --git a/containers/cpp/test-project/test.sh b/containers/cpp/test-project/test.sh index 3269307857..247cda8db6 100755 --- a/containers/cpp/test-project/test.sh +++ b/containers/cpp/test-project/test.sh @@ -6,9 +6,20 @@ source test-utils.sh vscode # Run common tests checkCommon +# Help determine distro +. /etc/os-release + # Run definition specific tests checkExtension "ms-vscode.cpptools" checkOSPackages "command-line-tools" build-essential cmake cppcheck valgrind clang lldb llvm gdb +checkOSPackages "tools-for-vcpkg" tar curl zip unzip pkg-config bash-completion +VCPKG_UNSUPPORTED_ARM64_VERSION_CODENAMES="stretch bionic" +if [ "$(dpkg --print-architecture)" = "amd64" ] || [[ ! "${VCPKG_UNSUPPORTED_ARM64_VERSION_CODENAMES}" = *"${VERSION_CODENAME}"* ]]; then + check "VCPKG_ROOT" [ -d "${VCPKG_ROOT}" ] + check "VCPKG_DOWNLOAD" [ -d "${VCPKG_DOWNLOADS}" ] + VCPKG_FORCE_SYSTEM_BINARIES=1 check "vcpkg-from-root" ${VCPKG_ROOT}/vcpkg --version + VCPKG_FORCE_SYSTEM_BINARIES=1 check "vcpkg-from-bin" vcpkg --version +fi check "g++" g++ -g main.cpp -o main.out rm main.out mkdir -p build