Repository navigation
Add dedicated C++ devcontainer - #1606
bferanmi806-sketch wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The unsupported CMake Tools preset setting makes the documented default preset behavior incorrect.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Adds a dedicated C++ devcontainer while preserving the existing Python environment.
Changes:
- Adds Ubuntu-based C++ tooling and VS Code integration.
- Documents building, testing, and debugging.
- Enforces LF endings for Dockerfiles.
| File | Description |
|---|---|
.devcontainer/cpp/Dockerfile |
Installs C++ compilers, tools, and dependencies. |
.devcontainer/cpp/devcontainer.json |
Configures the C++ development environment. |
.devcontainer/cpp/devcontainer.json.license |
Adds SPDX licensing metadata. |
.gitattributes |
Enforces Dockerfile LF endings. |
docs/advanced_documentation/build-guide.md |
Links to the C++ container guide. |
docs/advanced_documentation/devcontainer-setup.md |
Documents C++ container workflows. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
mgovers
left a comment
There was a problem hiding this comment.
Thank you very much for the contribution and my apologies for the delay on the review. We have been very occupied recently.
I have a couple open questions - see my comments below.
In addition to that, please also make sure all your commits are marked Verified (see also https://power-grid-model.readthedocs.io/en/stable/contribution/CONTRIBUTING.html#commit-signature-verification ).
| gcc-14 g++-14 \ | ||
| clang-18 lld-18 clang-format-18 clang-tidy-18 \ | ||
| cmake ninja-build gdb \ | ||
| libboost-dev libeigen3-dev nlohmann-json3-dev libmsgpack-cxx-dev doctest-dev \ | ||
| gcovr lcov pkg-config git curl ca-certificates \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # The CMake presets resolve `gcc`/`g++`/`clang`/`clang++` via PATH | ||
| # (same approach as CI, which symlinks the versioned binaries). | ||
| RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-14 100 \ | ||
| && update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-14 100 \ | ||
| && update-alternatives --install /usr/bin/clang clang /usr/bin/clang-18 100 \ | ||
| && update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-18 100 \ | ||
| && update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-18 100 \ | ||
| && update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 100 |
There was a problem hiding this comment.
please bump all compilers etc. in accordance with #1631
It is also a good idea to merge with main before doing so
There was a problem hiding this comment.
Done. I merged the current main and aligned the image with #1631: GCC/G++ 16, Clang/Clang++ 22, clang-tidy 18, and libclang-rt-22-dev, on the Ubuntu 26.04 (resolute) base. I checked each package/version against the 26.04 archive; the compiler versions are also asserted by the postCreateCommand output.
| && update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-18 100 \ | ||
| && update-alternatives --install /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-18 100 | ||
|
|
||
| ENV CC=gcc CXX=g++ |
There was a problem hiding this comment.
does this work combined with the preset? e.g. if i select clang-debug, will it automatically use Clang?
I am getting this CMake Error when I run clang-debug on my machine
[main] Building folder: /power-grid-model/cpp_build/clang-debug
[main] Configuring project: power-grid-model
[proc] Executing command: /usr/bin/cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPGM_ENABLE_DEV_BUILD=ON -DPGM_MSVC_REPRODUCIBLE_BUILD=OFF -DCMAKE_INSTALL_PREFIX=/power-grid-model/install/clang-debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S /power-grid-model -B /power-grid-model/cpp_build/clang-debug -G Ninja
[cmake] CMake Error: The current CMakeCache.txt directory /power-grid-model/cpp_build/clang-debug/CMakeCache.txt is different than the directory <local_path_to_repo>/power-grid-model/cpp_build/clang-debug where CMakeCache.txt was created. This may result in binaries being created in the wrong place. If you are not sure, reedit the CMakeCache.txt
[cmake] CMake Error: The source "/power-grid-model/CMakeLists.txt" does not match the source "<local_path_to_repo>/power-grid-model/CMakeLists.txt" used to generate cache. Re-run cmake with a different source directory.
[proc] The command: /usr/bin/cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DPGM_ENABLE_DEV_BUILD=ON -DPGM_MSVC_REPRODUCIBLE_BUILD=OFF -DCMAKE_INSTALL_PREFIX=/power-grid-model/install/clang-debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -S /power-grid-model -B /power-grid-model/cpp_build/clang-debug -G Ninja exited with code: 1
gcc-debug, on the other hand, works just fine.
There was a problem hiding this comment.
Yes: both presets set the compiler explicitly, so selecting clang-debug uses clang/clang++ (the CC/CXX environment variables only affect ad-hoc CMake invocations and do not override a preset).
The error is a stale cpp_build cache, not the preset. It appears when the same cpp_build/<preset> was configured on the host and then reused at the container path. I changed cpp_build to a per-checkout named volume (power-grid-model-cpp-build-${devcontainerId}), so the container never reuses a host-generated CMakeCache.txt, and parallel worktrees do not share one either.
If you tested the earlier revision, delete the stale cpp_build directory (or its old volume) once and reconfigure; cmake --list-presets is part of postCreateCommand and will confirm both presets are visible.
| "ms-vscode.cpptools", | ||
| "ms-vscode.cmake-tools", | ||
| "matepek.vscode-catch2-test-adapter", | ||
| "jeff-hykin.better-cpp-syntax", | ||
| "tamasfe.even-better-toml" |
There was a problem hiding this comment.
there is no extension for clang-format installed in the devcontainer. please make sure to add + configure it
There was a problem hiding this comment.
Added xaver.clang-format to the container extensions and configured it to use /power-grid-model/.venv/bin/clang-format with -style=file. That is the clang-format 23.1.3 version pinned in uv.lock and used by CI, so editor formatting matches pre-commit/CI rather than a distro clang-format. C and C++ files use it as the default formatter on save.
| ### Debug a C++ test in the IDE | ||
|
|
||
| * Build with a Debug preset as above so binaries carry symbols. | ||
| * Set a breakpoint, then start the preconfigured `Debug validation test [Unix]` launch configuration | ||
| (`.vscode/launch.json`, `gdb`-based), or right-click an individual test in the Test Explorer and debug it. | ||
| * The launch configuration resolves the test binary via `${command:cmake.buildDirectory}` | ||
| (e.g. `cpp_build/gcc-debug/bin/power_grid_model_validation_tests`). |
There was a problem hiding this comment.
how to format, run REUSE, etc. (the stuff usually also provided using pre-commit, which are not available in this container at the moment)?
There was a problem hiding this comment.
Added a "Format, check licences and run pre-commit" section to devcontainer-setup.md. postCreateCommand now creates the uv environment and installs the Git hook, and the docs cover:
uv run --frozen pre-commit run --all-files
uv run --frozen pre-commit run clang-format --files path/to/file.cpp
uv run --frozen pre-commit run reuse --all-files
uv run --frozen clang-format -style=file -i path/to/file.cppIt also lists the hook IDs and how to recreate the environment after a rebuild.
d5566ab to
fbfad01
Compare
Provide a separately selectable C++ development container alongside the default Python container (issue PowerGridModel#1272). The container is based on Ubuntu 26.04 and mirrors the Linux CI toolchain after PowerGridModel#1631: gcc-16/g++-16, clang-22, clang-tidy-18, CMake, Ninja, gdb and the C++ dependencies from the build guide (boost, eigen3, nlohmann-json, msgpack-cxx, doctest). It reuses the gcc-debug/clang-debug CMake presets and the existing VS Code debug configurations. cpp_build is kept in a per-checkout Docker volume. CMake caches contain absolute paths, so sharing that directory with the host made presets fail with a CMakeCache.txt directory mismatch (reported for clang-debug). The clang-format extension uses the version pinned in uv.lock, which is the same version CI runs through pre-commit, and the documentation now covers formatting, REUSE, pre-commit and compiler verification. Signed-off-by: Balogun Feranmi <bferanmi806@gmail.com>
fbfad01 to
2ea60f4
Compare


Add dedicated C++ devcontainer
References #1272 (does not close it — no merge/close performed from this PR).
What
Adds a separately selectable C++ devcontainer while keeping the existing
Python devcontainer untouched as the default:
.devcontainer/cpp/Dockerfile— Ubuntu 26.04 (resolute)-based image with thepinned Linux C++ toolchain (
gcc-14/g++-14,clang-18,CMake,Ninja,gdb,clang-format/clang-tidy) and the C++ dependencies (boost,eigen3,nlohmann-json,msgpack-cxx,doctest). Unversionedgcc/g++/clang/clang++symlinks mirror CI so the existing CMake presetsresolve. No extra privileges or broad security exceptions (runs as
vscode,no
--privileged/cap adds). Only the compiler versions are pinned to CI —the Linux CI jobs still run on Ubuntu 24.04, so the container OS intentionally
differs from CI (stated in the Dockerfile and the docs).
.devcontainer/cpp/devcontainer.json— selectable aspower-grid-model (C++)in VS Code; same/power-grid-modelworkspacemount as the Python container; C++ extensions only (
cpptools,cmake-tools,catch2-test-adapter,better-cpp-syntax). Nocmake.configurePresetentry: that setting does not exist in CMake Tools, sofirst-time users run
CMake: Select Configure Presetand choosegcc-debug(
clang-debugremains an alternative).docs/advanced_documentation/devcontainer-setup.md— new"C++ Development Container" section: select, run
CMake: Select Configure Presetand choosegcc-debug, configure/build via preset, run tests, IDEdebug, return to Python.
build-guide.mdpoints at it..gitattributes—Dockerfile text eol=lfso the Dockerfile keeps LFendings on Windows checkouts.
Out of scope (per thread agreement): combined Python/C++ and docs-building
environments.
Validation (all run for real, nothing invented)
Environment limitation, stated honestly: no Docker daemon on the Windows
host (
docker infofails; Docker Desktop not installed, no devcontainerCLI). Validation used the Docker Engine 29.7.2 inside WSL2 Ubuntu 26.04 plus a
native toolchain install there. VS Code interactive debugging was not
available, so IDE debugging is verified via the identical
gdbpath thecppdbglaunch config uses (same binary layout, samegdbbackend).Ubuntu 26.04 (this update, commit
d5566aba4):docker manifest inspect mcr.microsoft.com/devcontainers/base:resolute—exists (amd64). The
:ubuntu-26.04tag does not exist, so theDockerfile uses
:resolute.docker build -t pgm-cpp-dev-26 .devcontainer/cpp— success (resolutebase). Toolchain/dependency versions inside the image:
g++ 14.3.0,clang++ 18.1.8,cmake 4.2.3,ninja 1.13.2,gdb 17.1boost 1.90.0,eigen3 3.4.0,nlohmann-json 3.12,msgpack-cxx 7.0.0,doctest 2.4.12cmake --preset gcc-debuginside the 26.04 container — configurescleanly, all
find_packagecalls resolve (Boost 1.90, nlohmann_json,Threads). CMake 4.2.3 accepts the project's
cmake_minimum_required(3.23).g++-14under the preset's own flags(
-Werror, ASan+UBSan, C++23): every translation unit attempted compiledwith zero errors — the core C/C++ libraries, all 9
power_grid_model_api_testsTUs and the attempted unit-test TUs (~277 MBof objects). This retires the header/API-compatibility risk for the newer
dependency versions (Boost 1.90, msgpack-cxx 7.0, nlohmann-json 3.12,
doctest 2.4.12).
ctestruns on 26.04. The local box (WSL2, ~6 GB RAM, slow cores) cannot finish an
ASan-instrumented link of these binaries in one uninterrupted run, and
backgrounded builds do not survive between sessions here. No 26.04
incompatibility was found at any stage — every failure observed was the
environment (OOM pressure, WSL service restarts under load), never a
compiler, header, or package error. If reviewers prefer full local
build+test proof before merging, I can revert the base to 24.04 on request.
Ubuntu 24.04 (original validation, commit
50a55450c, superseded by the abovefor the container itself):
docker build -t pgm-cpp-dev .devcontainer/cpp— success (noble base).Toolchain/dependency versions inside the image:
g++ 14.2.0,clang++ 18.1.3,cmake 3.28.3,ninja 1.11.1,gdb 15.1boost 1.83.0,eigen3 3.4.0,nlohmann-json 3.11.3,msgpack-cxx 6.1.0,doctest 2.4.11cmake --preset gcc-debuginside the container asvscodewith/power-grid-modelmounted — configures cleanly, allfind_packagecalls resolve. (This caught a real bug during development:
libmsgpack-devdoes not ship themsgpack-cxxCMake config;fixed to
libmsgpack-cxx-devbefore committing.)gcc-debugbuild + tests on equivalent host toolchain(gcc 14.3, same package set),
ctest --preset gcc-debug:56/66 pass, 0 real failures — the 10 non-passing entries are
NOT_BUILTplaceholders for suites not yet compiled at that point.power_grid_model_api_tests: 49/49 cases, 56608/56608 assertions passpower_grid_model_validation_tests--test-case="Validation test single - power flow":1/1 case, 1282/1282 assertions pass
gdbbreakpoint debugging on both binaries (.vscode/launch.jsonuses the
cppdbg/gdbbackend against the same${command:cmake.buildDirectory}/bin/...layout):break test_api_model.cpp:195→ hit,btshowsdoctest::Context::run → mainbreak test_validation.cpp:672→ hit, same clean backtracewith debug_info, not stripped.devcontainer/devcontainer.jsonbyte-identical (
git diffshows only the newcpp/dir, docs and theone
.gitattributesline); both devcontainer JSON files parse;referenced presets (
gcc-debug,clang-debug) exist.Not yet completed locally:
power_grid_model_unit_testsbinary (buildingat PR time on a slow machine) and interactive VS Code debugging — covered
by CI.
reusecompliance: new JSON config carries a.licensesidecarlike the existing one; Dockerfile carries an inline SPDX header.
Files
.devcontainer/cpp/Dockerfile,.devcontainer/cpp/devcontainer.json,.devcontainer/cpp/devcontainer.json.license,.gitattributes,docs/advanced_documentation/build-guide.md,docs/advanced_documentation/devcontainer-setup.md— commits50a55450c,d5566aba4.