Skip to content

stlab/sandbox

Repository files navigation

C++ Devcontainer Sandbox

This project specifies a fully self-contained C++ development environment by combining VSCode Devcontainers, vcpkg, and cmake.

This is alpha-quality software. Suggestions and issues are welcome.

Goals

  1. Completely specify a C++ development environment in this repository for rapid experimentation with the latest compiler features and libraries.
  2. Make project (files, dependency) management trivially straightforward.
  3. Physically co-locate tests with source code for easier development and verification.
  4. Offer drop-in benchmarking capabilities
  5. Offer "it just works" linting and formatting.

Requirements

  1. Install Docker and ensure the daemon is running by opening the Desktop app.
  2. Install the extensions listed in .vscode/extensions.json. These are requirements, not suggestions.

Building

  1. When opening this directory in VSCode, you should be prompted to "reopen folder to develop in a container". Select Reopen in Container.
  2. Run the command CMake: Build either through the Command Palette or by hitting F7.
  3. From the "Run and Debug" menu (CMD SHIFT D), press the play button for the configuration (gdb) Launch. Breakpoints in project files are supported.

Note: CMake configuration will be re-run when a CMakeLists.txt is modified and saved.

Recipes

Adding a Dependency

  1. Update vcpkg.json per vcpkg's Manifest Mode documentation
  2. In MyCppApp/CMakeLists.txt, add a corresponding find_package directive, and update target_link_libraries to link to your new dependency.
  3. Rebuild the project (it should not be necessary to rebuild the environment image).

Room for Improvement

Install dependencies in one step (like npm)

You'll see above that Adding a Dependency is a multi-step process. Contrast this with npm install <foo>, which not only syncs the dependency, but adds it to your project to be used immediately. Here, we need to both specify the dependency in vcpkg.json and in Sandbox/CMakeLists.txt. While one could argue that this separation of concerns is useful (e.g., perhaps vcpkg is syncing mutually-exclusive dependencies for multiple subprojects), it makes this simpler case more complicated.

You'll notice during vcpkg install that certain usage messages are printed:

[cmake] doctest provides CMake targets:
[cmake]
[cmake]     # this is heuristically generated, and may not be correct
[cmake]     find_package(doctest CONFIG REQUIRED)
[cmake]     target_link_libraries(main PRIVATE doctest::doctest)
[cmake]
[cmake] The package fmt provides CMake targets:
[cmake]
[cmake]     find_package(fmt CONFIG REQUIRED)
[cmake]     target_link_libraries(main PRIVATE fmt::fmt)
[cmake]
[cmake]     # Or use the header-only version
[cmake]     target_link_libraries(main PRIVATE fmt::fmt-header-only)
[cmake]
[cmake] The package zlib is compatible with built-in CMake targets:
[cmake]
[cmake]     find_package(ZLIB REQUIRED)
[cmake]     target_link_libraries(main PRIVATE ZLIB::ZLIB)

These are generated by usage files. For example, out/build/linux-debug/vcpkg_installed/PLATFORM-linux/share/DEPENDENCY/usage, where:

  • PLATFORM is either arm64 or x86_64, and
  • DEPENDENCY is the name of the dependency, e.g. fmt.

One might think we could parse these usage files to (albeit, hackily) compose cmake commands for linking our synced dependencies. However, vcpkg does not require these files exist, nor do they standardize their format. Package maintainers may add them at their discretion. Incidentally, vcpkg will add the caveat, # this is heuristically generated, and may not be correct if a usage file is not supplied, and vcpkg must make a best-guess at the cmake configuration. As far as I can tell, this precludes any programmatic generation of cmake configuration by querying vcpkg.

This issue has been pointed out here, but there's no noticeable activity.

About

C++ devcontainer with modern tooling

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published