From feaf31764d1e3ee63a692196a333c55063dc5797 Mon Sep 17 00:00:00 2001 From: Bart Beumer Date: Mon, 9 Mar 2026 21:50:49 +0100 Subject: [PATCH] Initial version of a C++ development environment for training purposes. --- CMakeLists.txt | 8 +++++ README.md | 10 ++++++ cpp-code-server-devenv.Dockerfile | 52 +++++++++++++++++++++++++++++++ docker-helper/config.yaml | 4 +++ docker-helper/entrypoint.py | 40 ++++++++++++++++++++++++ docker-helper/entrypoint.sh | 3 ++ example-executable/CMakeLists.txt | 13 ++++++++ example-executable/main.cpp | 7 +++++ example-library/CMakeLists.txt | 19 +++++++++++ example-library/include/sum.h | 6 ++++ example-library/src/sum.cpp | 11 +++++++ example-unittest/CMakeLists.txt | 26 ++++++++++++++++ example-unittest/test.cpp | 8 +++++ 13 files changed, 207 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 README.md create mode 100644 cpp-code-server-devenv.Dockerfile create mode 100644 docker-helper/config.yaml create mode 100644 docker-helper/entrypoint.py create mode 100644 docker-helper/entrypoint.sh create mode 100644 example-executable/CMakeLists.txt create mode 100644 example-executable/main.cpp create mode 100644 example-library/CMakeLists.txt create mode 100644 example-library/include/sum.h create mode 100644 example-library/src/sum.cpp create mode 100644 example-unittest/CMakeLists.txt create mode 100644 example-unittest/test.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..36a464a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.20) + +project(all) +enable_testing() + +add_subdirectory(example-unittest) +add_subdirectory(example-library) +add_subdirectory(example-executable) diff --git a/README.md b/README.md new file mode 100644 index 0000000..7f34cdc --- /dev/null +++ b/README.md @@ -0,0 +1,10 @@ + +# Building the docker image + +The following command can be used to create the docker container image: +``docker build -t cpp-devenv-in-docker -f cpp-code-server-devenv.Dockerfile .`` + +To run the container there is only 2 things it really needs. A password, and a port on which +code server will be reachable. The port that the image exposes is 8080, we map it to 7501 +``docker run -t -p 7501:8080 -e CODE_SERVER_PASSWD=YourPasswordHere cpp-devenv-in-docker`` + diff --git a/cpp-code-server-devenv.Dockerfile b/cpp-code-server-devenv.Dockerfile new file mode 100644 index 0000000..606df2c --- /dev/null +++ b/cpp-code-server-devenv.Dockerfile @@ -0,0 +1,52 @@ +# A Ubuntu based playground for C++ development in a training context. + +FROM ubuntu:latest + +# Install: +# - some useful tools. +# - a debugger. +# - some compilers. +# - some C++ libraries (boost, google test) +# +RUN apt-get update && apt-get install -y \ + curl \ + wget \ + sudo \ + python3 \ + build-essential \ + gdb \ + git \ + cmake \ + ninja-build \ + gcc-14 \ + clang \ + clangd \ + libboost-all-dev \ + libgtest-dev \ + libgmock-dev + +# Install Code-Server (VS Code in the browser) +# TODO: Fix that we are not running random scripts from the web. +RUN curl -fsSL https://code-server.dev/install.sh | sh + +# Install some extensions we are going to use +RUN code-server --install-extension ms-python.python && \ + code-server --install-extension ms-vscode.cmake-tools && \ + code-server --install-extension kylinideteam.cppdebug + +WORKDIR /workspace +ADD CMakeLists.txt . +ADD example-executable example-executable +ADD example-library example-library +ADD example-unittest example-unittest + +WORKDIR /root +ADD --chmod=544 docker-helper/entrypoint.py . +ADD --chmod=544 docker-helper/entrypoint.sh . +ADD --chmod=444 docker-helper/config.yaml .config/code-server/config.yaml + +# Expose port for Code-Server +EXPOSE 8080 + +# Start Code-Server on container launch +CMD ["/root/entrypoint.sh"] diff --git a/docker-helper/config.yaml b/docker-helper/config.yaml new file mode 100644 index 0000000..ff7b03b --- /dev/null +++ b/docker-helper/config.yaml @@ -0,0 +1,4 @@ +bind-addr: 0.0.0.0:8080 +auth: password +password: 0a520bf60575a012f41bf571 +cert: false diff --git a/docker-helper/entrypoint.py b/docker-helper/entrypoint.py new file mode 100644 index 0000000..18516a4 --- /dev/null +++ b/docker-helper/entrypoint.py @@ -0,0 +1,40 @@ +#! /usr/bin/python3 +import argparse +import yaml +import os +import subprocess +import sys + +def runcmd(command): + print('RUN ' + command) + process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True) + for line in iter(process.stdout.readline, b''): # b'' indicates EOF + print(line.decode('utf-8'), end='') + +# Read environment variable +parser = argparse.ArgumentParser() +parser.add_argument('--password') +args = parser.parse_args() + + +new_password = args.password +if not isinstance(new_password , str): + print('ERROR: expect the password to be a string') + sys.exit(1) + + +# Read code-server configuration and adjust the password according to ENV +code_server_config_path = '.config/code-server/config.yaml'; + +code_server_config = None +with open(code_server_config_path, 'r') as file: + code_server_config = yaml.safe_load(file) + +if code_server_config is not None: + code_server_config['password'] = new_password + with open(code_server_config_path, 'w') as file: + yaml.dump(code_server_config, file) + +runcmd('code-server /workspace') + +sys.exit(0) diff --git a/docker-helper/entrypoint.sh b/docker-helper/entrypoint.sh new file mode 100644 index 0000000..55a052a --- /dev/null +++ b/docker-helper/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./entrypoint.py --password=$CODE_SERVER_PASSWD diff --git a/example-executable/CMakeLists.txt b/example-executable/CMakeLists.txt new file mode 100644 index 0000000..9b5db4b --- /dev/null +++ b/example-executable/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required(VERSION 3.20) + +project(empty-executable) + +add_executable( + ${PROJECT_NAME} + main.cpp +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 23 +) diff --git a/example-executable/main.cpp b/example-executable/main.cpp new file mode 100644 index 0000000..cf49085 --- /dev/null +++ b/example-executable/main.cpp @@ -0,0 +1,7 @@ +#include + +int main(int argc, char** argv) +{ + std::cout << "Hello World" << std::endl; + return 1; +} diff --git a/example-library/CMakeLists.txt b/example-library/CMakeLists.txt new file mode 100644 index 0000000..4b1c378 --- /dev/null +++ b/example-library/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.20) + +project(example-library) + +add_library( + ${PROJECT_NAME} + ./src/sum.cpp + ./include/sum.h +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 23 +) + +target_include_directories( + ${PROJECT_NAME} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include +) diff --git a/example-library/include/sum.h b/example-library/include/sum.h new file mode 100644 index 0000000..82a3231 --- /dev/null +++ b/example-library/include/sum.h @@ -0,0 +1,6 @@ +#pragma once + +namespace example_library +{ + int sum(int a, int b); +} diff --git a/example-library/src/sum.cpp b/example-library/src/sum.cpp new file mode 100644 index 0000000..3d6e950 --- /dev/null +++ b/example-library/src/sum.cpp @@ -0,0 +1,11 @@ +#include "sum.h" + +namespace example_library +{ + +int sum(int a, int b) +{ + return a + b; +} + +} diff --git a/example-unittest/CMakeLists.txt b/example-unittest/CMakeLists.txt new file mode 100644 index 0000000..535ea9b --- /dev/null +++ b/example-unittest/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.20) + +find_package(GTest REQUIRED) +include(GoogleTest) + +project(empty-unittest) +add_test(NAME ${PROJECT_NAME} COMMAND ${PROJECT_NAME}) + +add_executable( + ${PROJECT_NAME} + test.cpp +) + +set_property( + TARGET ${PROJECT_NAME} + PROPERTY CXX_STANDARD 23 +) + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC + example-library + GTest::gtest_main + GTest::gmock + +) diff --git a/example-unittest/test.cpp b/example-unittest/test.cpp new file mode 100644 index 0000000..bbbf36f --- /dev/null +++ b/example-unittest/test.cpp @@ -0,0 +1,8 @@ +#include +#include +#include "sum.h" + +TEST(Example, OK) +{ + EXPECT_EQ(42, example_library::sum(2, 40)); +}