Observation
mcpp emit build-database builds the host tools the planned packages request, as mcpp build does. The tool is resolved into a sub-build, and a ninja build of its link unit runs under plan_only (src/build/prepare.cppm, the host-tool branch). Only a failed tool build is softened, to MCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT (#699 E2). A tool that builds is built in full, including every prepare action its own package declares.
Measured on 2026.9.26.2 with Sunrisepeak/GalTranslPP#2. The GUI member requests its sibling application as a tool ("gpp.updater" = { path = "../Updater", tools = ["Updater"] }) so that its release layout carries the executable. On a fresh Windows checkout, emit build-database spent over 38 minutes inside that tool's sub-build before the run was cancelled: vcpkg manifest installation (22 ports, binary cache restored), Qt code generation and compilation. An earlier state of the same project, whose tool build failed quickly, planned the workspace in about 3 minutes.
Why it matters
emit build-database is what an editor runs to answer "where are the includes" on a machine that never built. SPEC-007 §5 states the obligation for build programs (plan without constructing); this is the engine performing construction during planning on the program's behalf. A tool can be arbitrarily expensive, since it is an ordinary package.
Proposed behaviour
Under plan_only, do not build a host tool that is not already in the tool store. Hand the build program the path the tool will be published at (binOut, already computed before the build), as the unbuilt case does today, and record a note that the tool is not yet built. A build program that runs a tool while planning is the exception, and it already has to handle the unbuilt path, because a failed tool build produces the same state.
Observation
mcpp emit build-databasebuilds the host tools the planned packages request, asmcpp builddoes. The tool is resolved into a sub-build, and a ninja build of its link unit runs underplan_only(src/build/prepare.cppm, the host-tool branch). Only a failed tool build is softened, toMCPP_BUILD_DATABASE_HOST_TOOL_UNBUILT(#699 E2). A tool that builds is built in full, including everyprepareaction its own package declares.Measured on 2026.9.26.2 with Sunrisepeak/GalTranslPP#2. The GUI member requests its sibling application as a tool (
"gpp.updater" = { path = "../Updater", tools = ["Updater"] }) so that its release layout carries the executable. On a fresh Windows checkout,emit build-databasespent over 38 minutes inside that tool's sub-build before the run was cancelled: vcpkg manifest installation (22 ports, binary cache restored), Qt code generation and compilation. An earlier state of the same project, whose tool build failed quickly, planned the workspace in about 3 minutes.Why it matters
emit build-databaseis what an editor runs to answer "where are the includes" on a machine that never built. SPEC-007 §5 states the obligation for build programs (plan without constructing); this is the engine performing construction during planning on the program's behalf. A tool can be arbitrarily expensive, since it is an ordinary package.Proposed behaviour
Under
plan_only, do not build a host tool that is not already in the tool store. Hand the build program the path the tool will be published at (binOut, already computed before the build), as the unbuilt case does today, and record a note that the tool is not yet built. A build program that runs a tool while planning is the exception, and it already has to handle the unbuilt path, because a failed tool build produces the same state.