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.
- Completely specify a C++ development environment in this repository for rapid experimentation with the latest compiler features and libraries.
- Make project (files, dependency) management trivially straightforward.
- Physically co-locate tests with source code for easier development and verification.
- Offer drop-in benchmarking capabilities
- Offer "it just works" linting and formatting.
- Install Docker and ensure the daemon is running by opening the Desktop app.
- Install the extensions listed in
.vscode/extensions.json
. These are requirements, not suggestions.
- When opening this directory in VSCode, you should be prompted to "reopen folder to develop in a container". Select
Reopen in Container
. - Run the command
CMake: Build
either through the Command Palette or by hitting F7. - 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.
- Update
vcpkg.json
per vcpkg's Manifest Mode documentation - In
MyCppApp/CMakeLists.txt
, add a correspondingfind_package
directive, and updatetarget_link_libraries
to link to your new dependency. - Rebuild the project (it should not be necessary to rebuild the environment image).
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.