Pacmon

Dependency notes for C and C++

A C or C++ library is hard to swap out once code is built around it. vcpkg.json or a conanfile names the library, but not why it was chosen, which build options or linkage it needs, or which builds have to pass before its version moves. vcpkg.json is JSON and cannot hold a comment at all.

Pacmon keeps a note for each package beside its manifest — .pacmon/vcpkg/DEPENDENCY-NOTES.md for vcpkg, .pacmon/conan/DEPENDENCY-NOTES.md for Conan — and shows it on the dependency's line.

What Pacmon reads

vcpkg

Pacmon reads string and object entries in the root dependencies array and in features.<name>.dependencies. Host dependencies keep a separate scope. Overrides, baselines, requested dependency features, configuration files, installed trees and transitive packages are not dependencies.

Conan

Pacmon reads references in the requires, tool_requires, test_requires and legacy build_requires sections of conanfile.txt; literal strings, lists or tuples in matching conanfile.py class fields; and literal first arguments to matching self.* calls. Dynamic expressions, lockfiles and transitive packages are not evaluated.

Pacmon never runs vcpkg or Conan, and it does not execute the Python in a conanfile.py: a requirement that code assembles is not seen.

Example

{
  "name": "telemetry-agent",
  "version": "1.4.0",
  "dependencies": [
    "fmt",
    "openssl",
    "spdlog",
    {
      "name": "vcpkg-cmake",
      "host": true
    }
  ]
}

.pacmon/vcpkg/DEPENDENCY-NOTES.md:

## openssl

TLS for the telemetry uploads. Windows builds link it statically.

### Agent notes

- purpose: TLS for the telemetry upload channel and its certificate checks
- constraint: Windows builds use the x64-windows-static triplet; the installer ships no OpenSSL DLLs
- verify: `ctest --test-dir build -R tls` on Windows and Linux
- verified: 3.4.1

In a Conan project, conanfile.txt lists references:

[requires]
zlib/1.3.1
boost/1.86.0

[tool_requires]
cmake/3.30.1

Its sections in .pacmon/conan/DEPENDENCY-NOTES.md are ## boost, ## cmake and ## zlib: the package name before the /, in lower case. In a conanfile.py, a class field such as requires = "zlib/1.3.1" and a call such as self.requires("boost/1.86.0") are read the same way.

Comments in vcpkg.json and conanfile.txt

{
  "dependencies": [
    "fmt",
    {
      "name": "openssl",
      "$why": "TLS for the telemetry uploads; Windows builds link it statically"
    }
  ]
}

vcpkg.json is strict JSON, with no // comments and no trailing commas. vcpkg stops at a // and says so: vcpkg does not support c-style comments, however most objects allow $-prefixed fields to be used as comments. A field whose name starts with $ holds a comment in any object with a fixed set of keys, a dependency included, but not in one whose keys you choose, such as "features". vcpkg format-manifest keeps those fields, though it reorders the keys and sorts the dependencies.

[requires]
# zlib: the version the firmware build was certified with
zlib/1.3.1
boost/1.86.0

conanfile.txt takes # comments on lines of their own. A # straight after a reference is not a comment: Conan reads zlib/1.3.1#why-pinned as a recipe revision and fails with Unable to find 'zlib/1.3.1#why-pinned' in remotes. A conanfile.py is Python, with Python's # comments.

Pinning a version

vcpkg resolves versions from a baseline. builtin-baseline sets the lowest version of every port, "version>=" raises it for one, and vcpkg takes the lowest version that meets every constraint. To hold a port at one version, overrides names it, and vcpkg ignores every other constraint on that port:

"overrides": [
  { "name": "openssl", "version": "3.4.1" }
]

vcpkg has no lock file for a manifest: the baseline and the overrides are what fix the versions.

In Conan, zlib/1.3.1 requires exactly 1.3.1. A range in brackets, such as zlib/[>=1.2.11 <2], takes the newest match, looking in the local cache before the remotes unless --update is given. conan lock create . writes conan.lock, which fixes every version and recipe revision for the installs that use it.

None of these says why a package is held. That goes in its note as constraint:, like the triplet rule for openssl above.

For AI coding agents

An agent reads a package's section before it adds, upgrades or removes it. constraint: holds what the build depends on — a triplet, an option, a linkage — and verify: the builds and tests to run after a version moves. See the rules agents follow.