Skip to content

emit build-database rewrites the build program's host mcpp.lock on every run and lists it in data.watch, so a watcher re-runs emit forever #807

Closed

Description

@speak-agent

Summary

mcpp emit build-database --format json lists a file in data.watch that the same command rewrites on every run. The file is the mcpp.lock of the build program's synthesized host package:

~/.mcpp/cache/build-database/<h>/target/.build-mcpp/host/<h>/mcpp.lock

The content stays the same; only the mtime changes. A tool that watches data.watch and runs emit again when a watched file changes never settles: each emit "changes" the file that triggers the next one.

Seen in mcpp-language-server 0.0.15 on a project with a build.mcpp and [build-dependencies] (a Qt Widgets demo using mcpp:plugins rules-qt). It runs mcpp emit every 2 seconds for as long as the project is open. The log repeats project model loaded again: unchanged, each run preceded by a didChangeWatchedFiles for this mcpp.lock (type 2, changed).

Reproduce (mcpp 2026.10.11.1, Linux x86_64)

Any project whose build.mcpp has build dependencies, for example:

[build-dependencies.mcpp]
plugins = { version = "0.15.2", features = ["rules-qt"], host-module = true }
mcpp emit build-database --format json > /tmp/emit.json
python3 -c "import json; print([w for w in json.load(open('/tmp/emit.json'))['data']['watch'] if w.endswith('mcpp.lock')])"
# ['…/.mcpp/cache/build-database/5042b60d2f765ba8/target/.build-mcpp/host/e50cbbe8641b/mcpp.lock', 'mcpp.lock']

f=~/.mcpp/cache/build-database/5042b60d2f765ba8/target/.build-mcpp/host/e50cbbe8641b/mcpp.lock
stat -c %Y "$f"; md5sum < "$f"     # 1791919945  0c27208d1dd09132234081d90d03aa3e
sleep 1; mcpp emit build-database --format json > /dev/null
stat -c %Y "$f"; md5sum < "$f"     # 1791919946  0c27208d1dd09132234081d90d03aa3e   <- rewritten, same bytes

Where

  • src/build/prepare/records.cpp:314: (void)mcpp::lockfile::write(lock, lockPath); runs unconditionally, so a resolution that did not change still rewrites the lock.
  • src/build/build_database.cppm:591: watch_file(ctx.projectRoot / "mcpp.lock");. For the build-program member, projectRoot is the synthesized host package under the build-database cache, so a file mcpp itself writes is reported as an input.

Suggested fix

  1. Write the lock only when its bytes differ from what is on disk (write-if-changed). This also helps anything else that watches a project's own mcpp.lock: editors, cargo watch-style tools, file sync.
  2. Optionally, leave the synthesized host package's mcpp.lock out of data.watch. It is an output of the plan, not something a person edits. The inputs that decide it (the root mcpp.toml, build.mcpp, the root mcpp.lock) are already listed.

mcpp-language-server will also stop reacting to a watched file whose content did not change, so it no longer depends on this. Other consumers of data.watch still would.

Activity

  1. added a commit that references this issue on Oct 21, 2026
    f5a7742
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions