C++ workspaces
Static CMake package discovery, version edits, internal link ordering, and current limits.
The built-in C++ adapter targets CMake projects that can be analyzed statically. It does not run CMake or try to interpret directories and targets that exist only at build time.
Root project requirement
The project root must contain CMakeLists.txt with a numeric version in project(...):
project(my_library VERSION 1.4.0 LANGUAGES CXX)A root project without VERSION cannot serve as the current C++ workspace entry point. The project name is the manifest name used for matching packages within the C++ workspace.
Subproject discovery
Semifold recursively follows literal calls such as:
add_subdirectory(libs/core)An intermediate directory may only group other directories. Every reachable directory whose own CMakeLists.txt contains project(... VERSION ...) is discovered as a package.
To keep discovery deterministic and safe, the adapter does not interpret:
- subdirectories assembled from variables;
- generator expressions;
- paths downloaded or generated by scripts or the configure phase;
- relative paths that escape the project root.
A resolved path outside the project root fails discovery instead of reading an external project.
Internal dependencies
The adapter recognizes a static call whose first argument is the current project name:
target_link_libraries(my_library PRIVATE support_library)When support_library is another discovered project name in the same workspace, an internal edge is created. PUBLIC, PRIVATE, and INTERFACE all affect dependency order only and do not automatically propagate versions.
The adapter does not guess relationships from variables, alias targets, generator expressions, or other indirect links. Add depends-on to Semifold configuration when a release must propagate.
Version edits
Semifold edits project(... VERSION ...) in the corresponding CMakeLists.txt. When the package directory also contains vcpkg.json, it synchronizes the root version field so the two public version sources do not drift.
The current CMake adapter accepts stable numeric versions only. Named channels such as alpha, beta, and rc are unsupported. Setting a named channel for a C++ package fails version planning; for custom prerelease formats, first evaluate whether a plugin and custom publish workflow can represent the complete format.
Publishing
CMake describes a build graph but does not define one registry, so built-in discovery treats C++ packages as publishable by default. Set publish = false explicitly for a package that should not enter the registry flow. Semifold keeps checks, builds, uploads, and publish behavior in [resolver.cpp] command configuration and runs it in dependency order through the unified publish plan.
Use smif publish --dry-run to inspect preflight and command behavior. Commands run in the package directory. Put compound CMake configuration, packaging, or registry-client logic in a repository script instead of placing shell operators in args.
When to use a plugin
The following cases are generally outside the built-in static rules:
- the version is not in
project(... VERSION ...); - workspace members come from custom metadata or runtime scripts;
- internal dependencies use CMake logic that cannot be expanded statically;
- versions require non-numeric or custom prerelease formats.
A plugin can define discovery, inspection, and candidate version edits for these repositories. Publish commands remain in resolver configuration.