Skip to content

About

A dependency-free C++17 CLI that diagnoses broken compilation databases, missing compilers, stale paths, and include directories—with actionable fixes and JSON reports.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

C++ Environment Doctor

Find stale paths and missing tools in your C++ compilation database.

cpp-doctor is a small, dependency-free C++17 command-line tool for the moment when your editor, checkout, and build configuration stop agreeing. It reads compile_commands.json, checks the local environment, and explains actionable problems. It never runs commands from the database or modifies your project.

Version 0.1.0 is an initial POSIX release focused on Linux and GCC/Clang-style commands. macOS is included in the CI configuration; Windows is not yet supported.

Quick start

Build with a C++17 compiler and Make:

make
./build/cpp-doctor --help
make test  # Python 3 required for tests only

Or use CMake 3.16+:

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
cmake --build build --parallel
ctest --test-dir build --output-on-failure
./build/cpp-doctor check --build-dir build

Use -DBUILD_TESTING=OFF to configure without Python. Installation is optional:

cmake --install build --prefix "$HOME/.local"

To inspect another CMake project, generate its database using a Makefiles or Ninja generator, then point the doctor at it:

cmake -S /path/to/project -B /path/to/project/build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
./build/cpp-doctor check --build-dir /path/to/project/build

Example output (paths and entry counts depend on the project):

C++ Environment Doctor 0.1.0
Database: "/workspace/app/build/compile_commands.json"

FAIL [compiler.missing] entry 1 "Compiler is missing or not executable: /opt/toolchain/bin/clang++"
     "Install the toolchain, update PATH, or regenerate the database for this machine."
WARN [include.missing] entry 1 "Include directory is missing or inaccessible: /workspace/app/build/generated"
     "Check the include flag or build the target that generates this directory."

1 entries checked; 1 errors, 1 warnings.

What it checks

Check Result
JSON syntax, root shape, required entry fields Error
Missing/inaccessible working directories Error; dependent checks skipped
Missing source files, including generated sources Error
Compiler or supported launcher absent/not executable Error
Missing explicit sysroot Error
Missing value for a supported directory flag Error
Missing explicit include directories Warning; may be optional or not generated yet
Relative working directories Warning; resolved against the database directory
Response files, shell expressions, unsupported wrappers Warning; affected checks skipped
Empty database Warning

Supported include flags: -I, -isystem, -iquote, and -idirafter, with joined or separate values. Explicit sysroots support --sysroot=PATH, --sysroot PATH, and -isysroot PATH/-isysrootPATH. Include paths starting with = or $SYSROOT are resolved when an explicit sysroot is known and no response files are present.

Relative source, compiler, and include paths resolve against each entry's directory, not the process's current directory. Compiler lookup uses the current PATH; relative PATH entries resolve against the compilation working directory. Simple ccache, sccache, and distcc launcher chains are recognized.

The arguments field takes precedence over command. An invalid arguments field is reported rather than silently falling back to command. Multiple commands for the same source file are valid and are checked independently.

CLI and CI

cpp-doctor check                              # ./compile_commands.json
cpp-doctor check --build-dir build
cpp-doctor check --database out/compile_commands.json
cpp-doctor check --build-dir build --json
cpp-doctor check --build-dir build --strict    # Fail on warnings too
Exit code Meaning
0 No errors; warnings allowed unless --strict is set
1 Diagnostic errors, or warnings with --strict
2 Usage, database loading, or JSON/root-format error

--json emits one JSON object to standard output, including input errors. It has schema_version, database, entries, errors, warnings, exit_code, and a findings array. Findings contain severity, code, entry, message, and hint. Entry numbers are one-based; zero denotes a database-level finding. Consumers should use diagnostic codes rather than match English text.

Example healthy report:

{"schema_version":1,"database":"/workspace/app/build/compile_commands.json","entries":1,"errors":0,"warnings":0,"exit_code":0,"findings":[]}

Once installed in a CI job, use:

cpp-doctor check --build-dir build --strict --json > doctor-report.json

Run after configuration, or after code generation if the project generates sources and include directories. The included GitHub Actions workflow builds, tests, and inspects this project's own compilation database.

Scope and limitations

A clean report means the supported environment checks passed, not that code compiles or that clangd is configured correctly.

  • Does not invoke compilers, discover implicit/system include paths, validate compiler flags generally, or inspect clangd configuration and logs.
  • Does not identify toolchain versions, ABI compatibility, or whether a found executable is actually a compiler.
  • Supports ordinary POSIX command quoting. Shell expansion, operators, environment assignments, and shell wrappers produce warnings instead of being evaluated.
  • Does not expand @response files. Launcher-specific options and MSVC-style commands are outside the first release's scope.
  • Does not interpret every GCC/Clang path-affecting option, such as -iprefix, -iwithprefix, framework search flags, or driver configuration files.
  • Relative working directories are an explicit fallback convention; generate absolute working directories for reliable portability.
  • Checks current local filesystem state and PATH; remote/container toolchains must be checked inside their own environment.
  • Limits database input to 64 MiB and JSON nesting to 128 levels. Duplicate JSON object keys are rejected. Terminal control characters are escaped in output.
  • Reports per entry; large databases can produce repeated diagnostics.

Development

make test
# Optional, with a supporting GCC/Clang toolchain:
g++ -std=c++17 -g -fsanitize=address,undefined -fno-omit-frame-pointer src/main.cpp -o build/cpp-doctor-sanitized
python3 tests/test_cli.py build/cpp-doctor-sanitized

The integration tests use isolated temporary projects and fake compiler executables. They check path resolution, diagnostics, quoting, Unicode, malformed input, strict exit codes, and that database commands are never executed.

See CONTRIBUTING.md for contribution guidelines and ROADMAP.md for the next milestones.

Compilation database format reference: Clang's specification.

License

Copyright 2026 Ali Naqvi and cpp-doctor contributors. Licensed under the Apache License, Version 2.0; see LICENSE and NOTICE. See AUTHORS.md for attribution.

About

A dependency-free C++17 CLI that diagnoses broken compilation databases, missing compilers, stale paths, and include directories—with actionable fixes and JSON reports.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages