mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
Merge c8134f3c63 into d3e20e71be
This commit is contained in:
commit
a3ba70bc58
2 changed files with 156 additions and 0 deletions
|
|
@ -13,6 +13,7 @@ const Allocator = mem.Allocator;
|
|||
const Target = std.Target;
|
||||
const process = std.process;
|
||||
const EnvMap = std.process.EnvMap;
|
||||
const Thread = std.Thread;
|
||||
const File = fs.File;
|
||||
const Sha256 = std.crypto.hash.sha2.Sha256;
|
||||
const Build = @This();
|
||||
|
|
@ -97,6 +98,8 @@ pkg_hash: []const u8,
|
|||
/// A mapping from dependency names to package hashes.
|
||||
available_deps: AvailableDeps,
|
||||
|
||||
compile_commands: ?*CompileCommands = null,
|
||||
|
||||
release_mode: ReleaseMode,
|
||||
|
||||
build_id: ?std.zig.BuildId = null,
|
||||
|
|
@ -109,6 +112,132 @@ pub const ReleaseMode = enum {
|
|||
small,
|
||||
};
|
||||
|
||||
pub const CompileCommands = struct {
|
||||
step: Step,
|
||||
entries: ArrayList(CompileCommandsEntry),
|
||||
mutex: Thread.Mutex,
|
||||
output_file: LazyPath,
|
||||
generated_file: GeneratedFile,
|
||||
|
||||
pub const base_id: Step.Id = .custom;
|
||||
|
||||
pub fn create(owner: *Build, output_file: LazyPath) *CompileCommands {
|
||||
const self = owner.allocator.create(CompileCommands) catch @panic("OOM");
|
||||
self.* = .{
|
||||
.step = Step.init(.{
|
||||
.id = base_id,
|
||||
.name = owner.fmt("compile_commands.json -> {s}", .{output_file.getDisplayName()}),
|
||||
.owner = owner,
|
||||
.makeFn = make,
|
||||
}),
|
||||
.entries = ArrayList(CompileCommandsEntry).init(owner.allocator),
|
||||
.mutex = .{},
|
||||
.output_file = output_file.dupe(owner),
|
||||
.generated_file = .{ .step = undefined },
|
||||
};
|
||||
self.generated_file.step = &self.step;
|
||||
|
||||
// Set this as the global compile commands database
|
||||
owner.compile_commands = self;
|
||||
|
||||
// Add dependencies from the output file's LazyPath
|
||||
output_file.addStepDependencies(&self.step);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn append(self: *CompileCommands, entry: CompileCommandsEntry) !void {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
try self.entries.append(entry);
|
||||
}
|
||||
|
||||
pub fn getEntries(self: *CompileCommands) []CompileCommandsEntry {
|
||||
self.mutex.lock();
|
||||
defer self.mutex.unlock();
|
||||
return self.entries.items;
|
||||
}
|
||||
|
||||
/// Returns a LazyPath representing the generated compile_commands.json file
|
||||
pub fn getOutput(self: *CompileCommands) LazyPath {
|
||||
return .{ .generated = .{ .file = &self.generated_file } };
|
||||
}
|
||||
|
||||
fn make(build_step: *Step, options: Step.MakeOptions) anyerror!void {
|
||||
_ = options;
|
||||
const self: *CompileCommands = @fieldParentPtr("step", build_step);
|
||||
const b = build_step.owner;
|
||||
const gpa = b.allocator;
|
||||
|
||||
// Create a temporary buffer for the JSON content
|
||||
var buffer = std.ArrayList(u8).init(gpa);
|
||||
defer buffer.deinit();
|
||||
|
||||
var writer = buffer.writer();
|
||||
|
||||
try writer.writeAll("[");
|
||||
|
||||
const entries = self.getEntries();
|
||||
|
||||
var temp = std.ArrayList(u8).init(gpa);
|
||||
defer temp.deinit();
|
||||
|
||||
for (entries, 0..) |entry, i| {
|
||||
if (i != 0) try writer.writeAll(",");
|
||||
try writer.writeAll("\n {\n");
|
||||
|
||||
try writer.writeAll(" \"directory\": \"");
|
||||
try std.json.encodeJsonStringChars(entry.working_directory, .{}, writer);
|
||||
try writer.writeAll("\",\n");
|
||||
|
||||
try writer.writeAll(" \"file\": \"");
|
||||
const full_path = b.pathJoin(&.{ entry.working_directory, entry.relative_path });
|
||||
try std.json.encodeJsonStringChars(full_path, .{}, writer);
|
||||
try writer.writeAll("\",\n");
|
||||
|
||||
try writer.writeAll(" \"command\": \"");
|
||||
|
||||
temp.clearRetainingCapacity();
|
||||
var temp_writer = temp.writer();
|
||||
|
||||
// Write the compiler command
|
||||
try temp_writer.writeAll("zig cc");
|
||||
for (entry.flags) |flag| {
|
||||
try temp_writer.writeAll(" ");
|
||||
try temp_writer.writeAll(flag);
|
||||
}
|
||||
try temp_writer.writeAll(" ");
|
||||
try temp_writer.writeAll(entry.relative_path);
|
||||
|
||||
try std.json.encodeJsonStringChars(temp.items, .{}, writer);
|
||||
try writer.writeAll("\"\n }");
|
||||
}
|
||||
|
||||
try writer.writeAll("\n]\n");
|
||||
|
||||
// Now write the content to the output file based on its type
|
||||
const output_path = self.output_file.getPath2(b, build_step);
|
||||
|
||||
// Ensure directory exists
|
||||
if (std.fs.path.dirname(output_path)) |dirname| {
|
||||
try b.build_root.handle.makePath(dirname);
|
||||
}
|
||||
|
||||
// Write the file
|
||||
try b.build_root.handle.writeFile(.{ .sub_path = output_path, .data = buffer.items });
|
||||
|
||||
// Set the generated file path for LazyPath access
|
||||
self.generated_file.path = try b.build_root.join(gpa, &.{output_path});
|
||||
}
|
||||
};
|
||||
|
||||
pub const CompileCommandsEntry = struct {
|
||||
module: *Module,
|
||||
working_directory: []const u8,
|
||||
relative_path: []const u8,
|
||||
flags: []const []const u8,
|
||||
};
|
||||
|
||||
/// Shared state among all Build instances.
|
||||
/// Settings that are here rather than in Build are not configurable per-package.
|
||||
pub const Graph = struct {
|
||||
|
|
@ -405,6 +534,7 @@ fn createChildOnly(
|
|||
.named_lazy_paths = .init(allocator),
|
||||
.pkg_hash = pkg_hash,
|
||||
.available_deps = pkg_deps,
|
||||
.compile_commands = parent.compile_commands,
|
||||
.release_mode = parent.release_mode,
|
||||
};
|
||||
try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
|
||||
|
|
@ -2237,6 +2367,10 @@ pub fn runBuild(b: *Build, build_zig: anytype) anyerror!void {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn addCompileCommands(b: *Build, output_file: LazyPath) *CompileCommands {
|
||||
return CompileCommands.create(b, output_file);
|
||||
}
|
||||
|
||||
/// A file that is generated by a build step.
|
||||
/// This struct is an interface that is meant to be used with `@fieldParentPtr` to implement the actual path logic.
|
||||
pub const GeneratedFile = struct {
|
||||
|
|
|
|||
|
|
@ -1327,6 +1327,16 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||
try zig_args.append(lang.internalIdentifier());
|
||||
}
|
||||
|
||||
if (b.compile_commands) |compdb| {
|
||||
const path = c_source_file.file.getPath3(mod.owner, step);
|
||||
try compdb.append(.{
|
||||
.module = compile.root_module,
|
||||
.working_directory = b.pathResolve(&.{path.root_dir.path orelse "."}),
|
||||
.relative_path = path.sub_path,
|
||||
.flags = c_source_file.flags,
|
||||
});
|
||||
}
|
||||
|
||||
try zig_args.append(c_source_file.file.getPath2(mod.owner, step));
|
||||
|
||||
if (c_source_file.language != null) {
|
||||
|
|
@ -1354,6 +1364,18 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
|
|||
}
|
||||
|
||||
const root_path = c_source_files.root.getPath2(mod.owner, step);
|
||||
|
||||
if (b.compile_commands) |compdb| {
|
||||
for (c_source_files.files) |file| {
|
||||
try compdb.append(.{
|
||||
.module = compile.root_module,
|
||||
.working_directory = root_path,
|
||||
.relative_path = file,
|
||||
.flags = c_source_files.flags,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (c_source_files.files) |file| {
|
||||
try zig_args.append(b.pathJoin(&.{ root_path, file }));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue