This PR closes issue #17365 from Github.
I was wanting this functionality, and got the general idea of how to implement it from the following stale PR:
The general idea is the same, JSON fragments are generated using Clang's -MJ[path] flag, and then merged into a single JSON file. However, I integrated this deeper into Zig's build system using a new Step.CompileCommands step type. The positive to this is that all generated JSON files are LazyPaths now, so if they aren't installed/depended upon by something, they don't get generated. The fragments themselves always get generated (when enabled) into a temporary directory since they're an artifact of the compilation itself.
New functionality:
- When creating a
Step.Compile in build.zig (addExecutable(), addObject(), addLibrary(), addTest()), you now have an option .enable_compdb.
- When
true, this allows you to access a generated compile_commands.json via LazyPath with a new function Step.Compile.getCompileCommandsJson().
- This is the
compile_commands.json ONLY for that Step.Compile
- There is a new flag
-fcompdb for zig build
- When used, this will default ALL
Step.Compile to generate compile_commands.json
- For both cases, you can get a
LazyPath to the merged compile_commands.json for ALL Step.Compile that had it enabled via Build.getMergedCompileCommandsJson()
- This gives an easy way to get a
compile_commands.json for ALL C file compilations in a project, even across dependencies
Testing:
- I added two standalone tests at
test/standalone/compdb_single and test/standalone/compdb_merged
- Check the source code for details (+ a good example of using the new API), but the general idea is I generate a bunch of compile commands files and check them against my rough expectation for how they should look
Areas for Review:
- I didn't mess with any kind of caching for the fragment files, so in theory the case where only a single C file out of many is recompiled might lead to inaccurate
compile_commands.json. In practice I could never get this to happen, so I'm a little afraid enabling this feature always forces ALL C files to recompile. I don't know why that would be the case with how I've set up the step dependencies, but it's something I'd like a sanity check on.
- In the
make function in CompileCommands.zig, I took the logic for writing a file to tmp that might be installed by the user later from WriteFile.zig. Specifically the code:
varrand_int:u64=undefined;io.random(@ptrCast(&rand_int));consttmp_dir_path="tmp"++Dir.path.sep_str++std.fmt.hex(rand_int);
I think this is fine, and it works in practice, but wanted to double check this is the correct way to get what I'm after.
This PR closes issue [#17365](https://github.com/ziglang/zig/issues/17365) from Github.
I was wanting this functionality, and got the general idea of how to implement it from the following stale PR:
- https://github.com/ziglang/zig/pull/18391
The general idea is the same, JSON fragments are generated using Clang's `-MJ[path]` flag, and then merged into a single JSON file. However, I integrated this deeper into Zig's build system using a new `Step.CompileCommands` step type. The positive to this is that all generated JSON files are `LazyPath`s now, so if they aren't installed/depended upon by something, they don't get generated. The fragments themselves always get generated (when enabled) into a temporary directory since they're an artifact of the compilation itself.
New functionality:
- When creating a `Step.Compile` in `build.zig` (`addExecutable(), addObject(), addLibrary(), addTest()`), you now have an option `.enable_compdb`.
- When `true`, this allows you to access a generated `compile_commands.json` via `LazyPath` with a new function `Step.Compile.getCompileCommandsJson()`.
- This is the `compile_commands.json` ONLY for that `Step.Compile`
- There is a new flag `-fcompdb` for `zig build`
- When used, this will default ALL `Step.Compile` to generate `compile_commands.json`
- For both cases, you can get a `LazyPath` to the merged `compile_commands.json` for ALL `Step.Compile` that had it enabled via `Build.getMergedCompileCommandsJson()`
- This gives an easy way to get a `compile_commands.json` for ALL C file compilations in a project, even across dependencies
Testing:
- I added two standalone tests at `test/standalone/compdb_single` and `test/standalone/compdb_merged`
- Check the source code for details (+ a good example of using the new API), but the general idea is I generate a bunch of compile commands files and check them against my rough expectation for how they should look
Areas for Review:
- I didn't mess with any kind of caching for the fragment files, so in theory the case where only a single C file out of many is recompiled might lead to inaccurate `compile_commands.json`. In practice I could never get this to happen, so I'm a little afraid enabling this feature always forces ALL C files to recompile. I don't know why that would be the case with how I've set up the step dependencies, but it's something I'd like a sanity check on.
- In the `make` function in `CompileCommands.zig`, I took the logic for writing a file to `tmp` that might be installed by the user later from `WriteFile.zig`. Specifically the code:
``` zig
var rand_int: u64 = undefined;
io.random(@ptrCast(&rand_int));
const tmp_dir_path = "tmp" ++ Dir.path.sep_str ++ std.fmt.hex(rand_int);
```
I think this is fine, and it works in practice, but wanted to double check this is the correct way to get what I'm after.