| ... | ... | @@ -93,6 +93,32 @@ pub fn make( |
| 93 | 93 | else => |e| return e, |
| 94 | 94 | }; |
| 95 | 95 | }, |
| 96 | .meson => { |
| 97 | const tf = template_file.?; |
| 98 | const contents = tf.root_dir.handle.readFileAlloc( |
| 99 | io, |
| 100 | tf.sub_path, |
| 101 | arena, |
| 102 | input_size_limit, |
| 103 | ) catch |err| return step.fail( |
| 104 | maker, |
| 105 | "unable to read meson input file {f}: {t}", |
| 106 | .{ tf, err }, |
| 107 | ); |
| 108 | |
| 109 | renderMeson( |
| 110 | maker, |
| 111 | step, |
| 112 | contents, |
| 113 | &aw, |
| 114 | value_pairs, |
| 115 | &value_map, |
| 116 | tf, |
| 117 | ) catch |err| switch (err) { |
| 118 | error.WriteFailed => return error.OutOfMemory, |
| 119 | else => |e| return e, |
| 120 | }; |
| 121 | }, |
| 96 | 122 | .blank => { |
| 97 | 123 | renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) { |
| 98 | 124 | error.WriteFailed => return error.OutOfMemory, |
| ... | ... | @@ -370,6 +396,62 @@ fn renderCmake( |
| 370 | 396 | if (any_errors) return error.MakeFailed; |
| 371 | 397 | } |
| 372 | 398 | |
| 399 | fn renderMeson( |
| 400 | maker: *Maker, |
| 401 | step: *Step, |
| 402 | contents: []const u8, |
| 403 | aw: *Writer.Allocating, |
| 404 | value_pairs: []const Value.Pair, |
| 405 | value_map: *const ValueMap, |
| 406 | src_path: Path, |
| 407 | ) !void { |
| 408 | const w = &aw.writer; |
| 409 | const conf = &maker.scanned_config.configuration; |
| 410 | const newline = detectNewline(contents); |
| 411 | |
| 412 | try w.writeAll(c_generated_line); |
| 413 | try w.writeAll(newline); |
| 414 | |
| 415 | var any_errors = false; |
| 416 | var line_index: u32 = 0; |
| 417 | var line_it = std.mem.splitScalar(u8, contents, '\n'); |
| 418 | // https://mesonbuild.com/Configuration.html |
| 419 | while (line_it.next()) |raw_line| : (line_index += 1) { |
| 420 | const last_line = line_it.index == line_it.buffer.len; |
| 421 | const line = std.mem.trimEnd(u8, raw_line, "\r"); |
| 422 | |
| 423 | const old_len = aw.written().len; |
| 424 | expandVariablesMeson(w, conf, line, value_pairs, value_map) catch |err| switch (err) { |
| 425 | error.MissingToken => { |
| 426 | try step.addError(maker, "{f}:{d}: error: missing define name", .{ src_path, line_index + 1 }); |
| 427 | any_errors = true; |
| 428 | continue; |
| 429 | }, |
| 430 | error.MissingValue => { |
| 431 | const name = aw.written()[old_len..]; |
| 432 | defer aw.shrinkRetainingCapacity(old_len); |
| 433 | |
| 434 | try step.addError(maker, "{f}:{d}: error: unspecified config header value: {q}", .{ |
| 435 | src_path, line_index + 1, name, |
| 436 | }); |
| 437 | any_errors = true; |
| 438 | continue; |
| 439 | }, |
| 440 | else => { |
| 441 | try step.addError(maker, "{f}:{d}: unable to substitute variable: error: {t}", .{ |
| 442 | src_path, line_index + 1, err, |
| 443 | }); |
| 444 | any_errors = true; |
| 445 | continue; |
| 446 | }, |
| 447 | }; |
| 448 | if (!last_line) try w.writeAll(newline); |
| 449 | } |
| 450 | |
| 451 | try ensureAllValuesUsed(maker, step, value_map, src_path); |
| 452 | if (any_errors) return error.MakeFailed; |
| 453 | } |
| 454 | |
| 373 | 455 | fn renderBlank( |
| 374 | 456 | conf: *const Configuration, |
| 375 | 457 | w: *Writer, |
| ... | ... | @@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam |
| 432 | 514 | } |
| 433 | 515 | } |
| 434 | 516 | |
| 517 | fn renderValueMeson( |
| 518 | conf: *const Configuration, |
| 519 | w: *Writer, |
| 520 | name: []const u8, |
| 521 | value: Value.Index, |
| 522 | ) !void { |
| 523 | switch (value.unpack(conf)) { |
| 524 | .undef => try w.print("/* #undef {s} */", .{name}), |
| 525 | .defined => try w.print("#define {s}", .{name}), |
| 526 | .bool => |b| { |
| 527 | if (b) { |
| 528 | try w.print("#define {s}", .{name}); |
| 529 | } else { |
| 530 | try w.print("#undef {s}", .{name}); |
| 531 | } |
| 532 | }, |
| 533 | inline .u64, .i64 => |int| try w.print("#define {s} {d}", .{ name, int }), |
| 534 | .ident => |ident| try w.print("#define {s} {s}", .{ name, ident }), |
| 535 | .string => |string| try w.print("#define {s} \"{f}\"", .{ name, std.zig.fmtString(string) }), |
| 536 | } |
| 537 | } |
| 538 | |
| 435 | 539 | fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void { |
| 436 | 540 | try w.print("#define {s}", .{name}); |
| 437 | 541 | if (ident.len > 0) { |
| ... | ... | @@ -628,3 +732,36 @@ fn expandVariablesCmake( |
| 628 | 732 | |
| 629 | 733 | return result.toOwnedSliceAssert(); |
| 630 | 734 | } |
| 735 | |
| 736 | fn expandVariablesMeson( |
| 737 | w: *Writer, |
| 738 | conf: *const Configuration, |
| 739 | line: []const u8, |
| 740 | value_pairs: []const Value.Pair, |
| 741 | value_map: *const ValueMap, |
| 742 | ) !void { |
| 743 | const mesondefine = "#mesondefine"; |
| 744 | if (std.mem.startsWith(u8, line, mesondefine)) { |
| 745 | const line_offset = mesondefine.len + 1; |
| 746 | if (line_offset > line.len) return error.MissingToken; |
| 747 | |
| 748 | var it = std.mem.tokenizeAny(u8, line[line_offset..], " \t\r"); |
| 749 | const name = it.next() orelse return error.MissingToken; |
| 750 | |
| 751 | const index = value_map.getIndex(name) orelse { |
| 752 | // Report the missing key to the caller. |
| 753 | try w.writeAll(name); |
| 754 | return error.MissingValue; |
| 755 | }; |
| 756 | |
| 757 | const value = value_pairs[index].index; |
| 758 | value_map.values()[index] = true; // Mark as used. |
| 759 | |
| 760 | try renderValueMeson(conf, w, name, value); |
| 761 | |
| 762 | // comments/any other text passthrough unaffected |
| 763 | return try w.writeAll(line[line_offset + name.len ..]); |
| 764 | } |
| 765 | |
| 766 | try expandVariablesAutoconfAt(w, line, conf, value_pairs, value_map); |
| 767 | } |