Motivation
A build program can link a prebuilt library (link_flag, link_search) and place a file beside the program (deploy), but it cannot say where the program's shared libraries are found at run time. The manifest key [runtime] library_dirs does exactly that — it reaches mcpp run's loader path and mcpp pack's closure search — but it is a fixed TOML array, and the directories in question are known only to the build program: a vcpkg prefix's bin/, a Qt SDK's bin/ resolved through mcpp::xpkg_dir.
Measured against the engine: mcpp pack's PE closure searches plan.runtimeLibraryDirs only (src/pack/pipeline.cppm), which is fed from [runtime] library_dirs and never from link_search/link_flag (src/build/plan.cppm). A plugin that installs a vcpkg prefix therefore has no way to make its DLLs reach mcpp run or the packed tree except one mcpp::deploy per file — and on a project's first build the files do not exist yet when the build program runs.
Found while implementing the same plugins: a role = "check" action whose command writes no stamp (the engine writes it, 2026.8.29.1+) re-runs on every build after one of its inputs changes. __action-stamp only creates a missing stamp and leaves an existing one alone, so after the input changes and the check passes again, the stamp stays older than the input forever.
Design
mcpp::runtime_library_dir(const char* dir), wire mcpp:runtime-library-dir=<dir>, protocol 12: the build-program form of [runtime] library_dirs. Transform::AbsPath, Scope::LinkGlobal, persisted in the build-program cache. apply() folds it into RuntimeConfig::libraryDirs — the field the manifest key fills — so run, pack and the ELF/Mach-O rpath rendering treat it as they treat the manifest key. The root package's own directive is mirrored into the plan snapshot the way deploy already is.
__action-stamp records each stamp's modification time before the command runs; on success it creates a missing stamp and moves an existing stamp it did not write to the present. A stamp the command created or rewrote is left alone, so wrapper scripts keep working.
Scope
src/build/hostprogram.cppm, modules/buildmcpp/src/{directives,program_protocol}.cppm, src/build/prepare.cppm, src/cli.cppm, docs/04 and docs/30 (en, zh), unit tests, e2e 779 and 780.
Consumer: mcpp-community/mcpp-plugins 0.13.0 (deps-vcpkg, deps-cmake, rules-qt).
Motivation
A build program can link a prebuilt library (
link_flag,link_search) and place a file beside the program (deploy), but it cannot say where the program's shared libraries are found at run time. The manifest key[runtime] library_dirsdoes exactly that — it reachesmcpp run's loader path andmcpp pack's closure search — but it is a fixed TOML array, and the directories in question are known only to the build program: a vcpkg prefix'sbin/, a Qt SDK'sbin/resolved throughmcpp::xpkg_dir.Measured against the engine:
mcpp pack's PE closure searchesplan.runtimeLibraryDirsonly (src/pack/pipeline.cppm), which is fed from[runtime] library_dirsand never fromlink_search/link_flag(src/build/plan.cppm). A plugin that installs a vcpkg prefix therefore has no way to make its DLLs reachmcpp runor the packed tree except onemcpp::deployper file — and on a project's first build the files do not exist yet when the build program runs.Found while implementing the same plugins: a
role = "check"action whose command writes no stamp (the engine writes it, 2026.8.29.1+) re-runs on every build after one of its inputs changes.__action-stamponly creates a missing stamp and leaves an existing one alone, so after the input changes and the check passes again, the stamp stays older than the input forever.Design
mcpp::runtime_library_dir(const char* dir), wiremcpp:runtime-library-dir=<dir>, protocol 12: the build-program form of[runtime] library_dirs.Transform::AbsPath,Scope::LinkGlobal, persisted in the build-program cache.apply()folds it intoRuntimeConfig::libraryDirs— the field the manifest key fills — so run, pack and the ELF/Mach-O rpath rendering treat it as they treat the manifest key. The root package's own directive is mirrored into the plan snapshot the waydeployalready is.__action-stamprecords each stamp's modification time before the command runs; on success it creates a missing stamp and moves an existing stamp it did not write to the present. A stamp the command created or rewrote is left alone, so wrapper scripts keep working.Scope
src/build/hostprogram.cppm,modules/buildmcpp/src/{directives,program_protocol}.cppm,src/build/prepare.cppm,src/cli.cppm, docs/04 and docs/30 (en, zh), unit tests, e2e 779 and 780.Consumer: mcpp-community/mcpp-plugins 0.13.0 (
deps-vcpkg,deps-cmake,rules-qt).