Skip to content

feat: compile_commands.json generation - #14185

Merged
Alizter merged 1 commit into
ocaml:mainfrom
Alizter:push-zrvtnvoxttow
Apr 18, 2026
Merged

feat: compile_commands.json generation#14185
Alizter merged 1 commit into
ocaml:mainfrom
Alizter:push-zrvtnvoxttow

Conversation

@Alizter

@Alizter Alizter commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator

We generate compile_commonds.json and promote it to the workspace root when dune lang is 3.23. This is a compilation database containing the flags and compiler invocations for foreign stubs and archives, used by C/C++ editor support.

Comment thread src/dune_rules/gen_rules.ml
@rgrinberg

Copy link
Copy Markdown
Member

Is the alias really necessary? It's producing a single target, might as well just use that target instead of the alias.

It would be fine to add this target to the check alias however.

Comment thread src/dune_rules/compile_commands.ml Outdated
@Alizter

Alizter commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

Is the alias really necessary? It's producing a single target, might as well just use that target instead of the alias.

It would be fine to add this target to the check alias however.

I'm using an alias so that generating the target is a bit more intentional since it also promotes. Putting it in check would promote to source which is likely to be annoying unless its warranted.

I considered introducing a configuration option, however because it is a workspace wide thing it would have to go in a config or workspace file. Having it in a dune-project file seems more natural but then that opens the question of how to compose the option which I don't know how to solve.

I'm wondering if there is an easy thing we can do here. Promoting is obviously useful for clangd and ccls but I don't know if it will be something people want all the time.

@rgrinberg

Copy link
Copy Markdown
Member

When do you think somebody might want to build @check and not want compile_commands?

@Alizter

Alizter commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

When do you think somebody might want to build @check and not want compile_commands?

It's the promoting part that's making me think here.

@rgrinberg

Copy link
Copy Markdown
Member

If the file isn't promoted, it's completely useless as the lsp servers will never find it.

@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch from acb2293 to 7782ade Compare April 15, 2026 17:32
@Alizter

Alizter commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

@rgrinberg Should we be guarding this behind dune lang. Will that work well with workspaces?

@Alizter

Alizter commented Apr 15, 2026

Copy link
Copy Markdown
Collaborator Author

I'm going to add it to @check conditionally based on dune lang. Otherwise older builds that use check will have this file promoted.

@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch 5 times, most recently from ec384dc to ac58711 Compare April 15, 2026 20:02
@rgrinberg

Copy link
Copy Markdown
Member

If you do it with the workspace, people will be able to take advantage of this feature in composed dune builds as well as packages where they haven't upgraded the dune version. On the other hand, doing it in the package is simpler for most users.

Comment thread src/dune_rules/foreign_rules.ml Outdated
Comment thread test/blackbox-tests/test-cases/foreign-stubs/compile-commands/cxx-stubs.t Outdated
@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch 2 times, most recently from 4e8c9b1 to eec17c4 Compare April 17, 2026 21:54
@Alizter
Alizter marked this pull request as ready for review April 17, 2026 21:54
@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch from eec17c4 to 0925d20 Compare April 17, 2026 23:04
@Alizter
Alizter requested a review from rgrinberg April 18, 2026 14:43
Comment thread src/dune_rules/compile_commands.ml Outdated
Comment thread src/dune_rules/compile_commands.ml Outdated
Comment thread src/dune_rules/compile_commands.ml Outdated
@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch from 0925d20 to 1915667 Compare April 18, 2026 20:27
@Alizter
Alizter requested a review from rgrinberg April 18, 2026 20:36
@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch from 1915667 to ea5ae16 Compare April 18, 2026 20:49
Generate a compilation database (compile_commands.json) for C and C++
foreign stubs. This enables language servers like clangd and ccls to
provide code navigation, completion, and diagnostics for C stubs in
OCaml projects.

The file is generated and promoted to the workspace root when building
`@check`, gated behind (lang dune 3.23). It is only produced for the
merlin context and removed by dune clean.

The implementation refactors foreign_rules.ml to extract shared
helpers (c_compile_args, build_include_flags, compilation_flags) that
are reused by both the existing C compilation rules and the new
compile_commands generation.

Signed-off-by: Ali Caglayan <alizter@gmail.com>
@Alizter
Alizter force-pushed the push-zrvtnvoxttow branch from ea5ae16 to fa06913 Compare April 18, 2026 20:50
@Alizter

Alizter commented Apr 18, 2026

Copy link
Copy Markdown
Collaborator Author

I've rechecked locally that all is working and ccls is happy with the generated database (after clearing its cache).

@Alizter
Alizter merged commit f6f4d55 into ocaml:main Apr 18, 2026
29 of 30 checks passed
@Alizter
Alizter deleted the push-zrvtnvoxttow branch April 18, 2026 21:03
avsm pushed a commit to ocaml/opam-repository that referenced this pull request May 5, 2026
CHANGES:

### Fixed

- Auto-inject `"menhir" {>= "20180523"}` into generated opam files when the
  menhir extension is used. Dune's menhir rules rely on `--infer-write-query`
  and `--infer-read-reply`, which require at least this version; without the
  lower bound, builds fail with older menhir installations.
  (ocaml/dune#10707, @robinbb)

- Fix `--display=quiet` not suppressing "Entering directory" and "Leaving
  directory" messages when using `--root`. These messages are now deferred
  until there is actual output, so silent builds produce no noise.
  (ocaml/dune#12974, fixes ocaml/dune#12854, @Alizter)

- Fix an internal error when a module is shared between a `rocq.theory` and
  `rocq.extraction` stanza. The error now includes a hint pointing to the
  conflicting stanza. (ocaml/dune#13733, @Durbatuluk1701)

- Fix cookies defined on `ppx_rewriter` being lost when that rewriter was used
  as a dependency of another `ppx_rewriter`. (ocaml/dune#13737, fixes ocaml/dune#3426, @Alizter)

- Improve opam file generation for packages that set `(dir ..)`. Such packages
  will now have a test target that is limited to this directory. (ocaml/dune#13778, @rgrinberg)

- Stop duplicating dune diagnostics to subscribers over RPC (ocaml/dune#13816,
  @rgrinberg)

- Fix dependency cycle when using the `package` with a library
  conditionally enabled via `enabled_if`. (ocaml/dune#13833, @toots)

- Fix underspecification of dependencies in the sandbox for modules with
  interfaces. (ocaml/dune#13842, @anmonteiro)

- Honor sandbox settings specified inside `(:include ..)` expressions in the `deps` field
  (ocaml/dune#13898, @rgrinberg)

- Fix `dune pkg lock` failing when a `pin` stanza contains a `file://` URL with
  a relative path outside the workspace (ocaml/dune#13915, fixes ocaml/dune#10254, @shunueda)

- Use all stat attributes to detect patch back source tree changes (ocaml/dune#13986, @rgrinberg)

- Use device and inode number for invalidating cached digests (ocaml/dune#13991, @rgrinberg)

- Stop trying to set SO_REUSEADDR on unix sockets when setting up dune rpc
  (ocaml/dune#14056, @rgrinberg)

- Fix autolocking to correctly detect changes to `(depends)` in watch mode
  (ocaml/dune#14066, fixes ocaml/dune#13234, @Alizter)

- Fix incremental builds for libraries using `(wrapped (transition ...))`.
  The compat shim modules were never recompiled when the inner module's
  interface changed, causing "inconsistent assumptions" errors.
  (ocaml/dune#14090, fixes ocaml/dune#14089, @Alizter)

- Fix Rocq configuration detection to use `rocq c --config` subcommand
  instead of `rocq --config` (ocaml/dune#14093, fixes ocaml/dune#13774, @Durbatuluk1701)

- Bump dune rpc's request pending request limit 10 to 100 (ocaml/dune#14094, @rginberg)

- Invalidate stale cached digests in all build commands (ocaml/dune#14126, @rgrinberg)

- Fix `root_module` generating duplicate module definitions when a
  findlib sub-package shares a directory with its parent (e.g.,
  `logs.lwt` alongside `logs`). (ocaml/dune#14135, fixes ocaml/dune#6148, @robinbb)

- Fix `dune subst` prepending a duplicate `version:` field to opam
  files that already contain one, instead of replacing it in place.
  (ocaml/dune#14136, fixes ocaml/dune#878, @robinbb)

- Fix `@ocaml-index` alias being generated for all contexts, causing build
  errors in multi-context workspaces where some libraries are disabled in
  non-default contexts. The alias is now only generated for the merlin context.
  (ocaml/dune#14137, fixes ocaml/dune#12007, @robinbb)

- Remove the warning about the deprecation of the coq stanza for
  dune lang before 3.21 since it has been introduced in this
  version (ocaml/dune#14187, @bobot)

- `$ dune init` now generates projects with correct .opam files (ocaml/dune#14192, @rgrinberg)

- Send SIGTERM before SIGKILL when cancelling child processes in watch
  mode, giving cleanup handlers a chance to run before escalating.
  (ocaml/dune#14224, ocaml/dune#14170, fixes ocaml/dune#2445, @robinbb)

- Correctly specify dependencies for `generate_runner` in inline tests (ocaml/dune#14276, @rgrinberg)

- Fix duplicate dune version bounds in generated opam files. When users
  declare `(dune (>= X.Y))` matching or exceeding the `(lang dune X.Y)`
  version, the generated opam `depends` no longer contains redundant
  constraints like `{>= "2.7" & >= "2.7"}`. (ocaml/dune#3916, ocaml/dune#11106, @robinbb)

- Fix inline tests not being executed for byte-only libraries. When a library
  has `(modes byte)`, the inline test runner is now linked in byte mode so the
  library's test code is included. (ocaml/dune#9757, @robinbb)

### Added

- Add support for `c_library_flags` in foreign_stubs (ocaml/dune#13484, @madroach)

- Move the management of Jsoo config details out of dune (ocaml/dune#13613, @vouillon)

- Js_of_ocaml: share standalone runtimes (ocaml/dune#13621, @vouillon)

- Allow multiple `(dirs ..)` stanzas in the same Dune file. Starting with
  `(lang dune 3.23)`, Dune takes the union of the specified directories
  (ocaml/dune#13734, fixes ocaml/dune#6249, @anmonteiro)

- Sandboxed rules are now allowed to produce diff promotions when `(corrections
  produce)` is set on the rules. Whenever such an action produces `foo.corrected`, it will
  be automatically registered as a promotion for `foo` (ocaml/dune#13813, @rgrinberg)

- `$ dune clean` now accepts arguments to only remove certain targets from the
  _build directory (ocaml/dune#13875, @rgrinberg)

- `$ dune promote` now promotes all paths that are a prefix of the path provided.
  For example, `$ dune promote foo` will promote `foo`, `foo/bar`, `foo/bar/baz`
  (but not `foobar`). (ocaml/dune#13876, @rgrinberg)

- Allow for the `diff` action to diff entire directories (ocaml/dune#13880, fixes ocaml/dune#3567, @rgrinberg)

- A hint is now emitted when trying to build a target inside a directory that
  was excluded by a `(dirs ...)` stanza (ocaml/dune#13919, @mefyl).

- Add --debug-backtraces to `$ dune {promote,trace,cache}` (ocaml/dune#13933, @rgrinberg)

- Actions are now able to observe their project directory via
  `DUNE_PROJECT_ROOT` (ocaml/dune#13934, @rgrinberg)

- Support hardlink sandboxing on Windows. (ocaml/dune#13987, addresses part of ocaml/dune#4362, @Alizter)

- `rocq.extraction`: Add `extracted_files` field in `(rocq 0.13)`, replacing
  `extracted_modules`, supporting extraction to languages other than OCaml
  (ocaml/dune#13997, @Durbatuluk1701).

- Infer source directories as dependencies when they're as reference
  directories in `diff` actions.

- Add trace events for build start/stop/restarts (ocaml/dune#14163, ocaml/dune#14166, @rgrinberg)

- Generate `compile_commands.json` for C/C++ foreign stubs when building
  `@check` with `(lang dune 3.23)`. This enables `clangd`, `ccls`, and other
  tools that consume compilation databases. (ocaml/dune#14185, fixes ocaml/dune#3531, @Alizter)

- Add trace events for accepting clients and shutting down RPC (ocaml/dune#14232, @rgrinberg)

- Back up the default trace file as `trace.csexp.old` before each build,
  preserving the previous trace for comparison. This does not apply when
  `--trace-file` is used. (ocaml/dune#14269, @Alizter)

### Changed

- Dune digests target files and directories in background threads (ocaml/dune#13341,
  @rgrinbreg)

- `Dyn.pp` now prints valid OCaml literals for more constructors:
  - `Char` is quoted (e.g., `'a'`)
  - `Int32`/`Int64`/`Nativeint` include literal suffixes (`l`/`L`/`n`)
  - `Float` handles `infinity`, `neg_infinity`, and `nan`
  (ocaml/dune#13394, grants ocaml/dune#13378, @Alizter)

- Bump the minimal OCaml version required to build Dune from 4.08 to 4.14.
  (ocaml/dune#13533, @Alizter)

- Starting from 3.23, user rules are sandboxed by default (ocaml/dune#13805, @rgrinberg)

- Dune will no longer stat paths in the _build directory. This was done as protection
  from user rules accidentally touching things in the _build directory. This is forbidden,
  and dune offers rule sandboxing to prevent this (ocaml/dune#13875, @rgrinberg)

- Improve mtime precision by no longer approximating them with floats (ocaml/dune#13962,
  @rgrinberg).

- Remove `--makefile` (or `-m`) in `$ dune rules`. The sexp output is the only
  supported way of reflecting dune rules (ocaml/dune#14069, @rgrinberg)

- Do not automatically promote files. Now, opam files must be manually
  promoted with `$ dune promote`. Their generation is triggered by `@install`,
  `@runtest`, and `@opam`. In release mode, .opam files aren't generated at all
  and whatever is in the source is used (ocaml/dune#14108, @rgrinberg)

- Inline test runner generation is now sandboxed (ocaml/dune#14257, @rgrinberg)
@Alizter Alizter added this to the 3.23.0 milestone Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Generate JSON Compilation Database

2 participants