| ... | @@ -238,7 +238,15 @@ pub fn build(b: *Builder) !void { | ... | @@ -238,7 +238,15 @@ pub fn build(b: *Builder) !void { |
| 238 | exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); | 238 | exe_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version)); |
| 239 | | 239 | |
| 240 | if (enable_llvm) { | 240 | if (enable_llvm) { |
| 241 | const cmake_cfg = if (static_llvm) null else findAndParseConfigH(b, config_h_path_option); | 241 | const cmake_cfg = if (static_llvm) null else blk: { |
| | 242 | if (findConfigH(b, config_h_path_option)) |config_h_path| { |
| | 243 | const file_contents = fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable; |
| | 244 | break :blk parseConfigH(b, file_contents); |
| | 245 | } else { |
| | 246 | std.log.warn("config.h could not be located automatically. Consider providing it explicitly via \"-Dconfig_h\"", .{}); |
| | 247 | break :blk null; |
| | 248 | } |
| | 249 | }; |
| 242 | | 250 | |
| 243 | if (is_stage1) { | 251 | if (is_stage1) { |
| 244 | const softfloat = b.addStaticLibrary("softfloat", null); | 252 | const softfloat = b.addStaticLibrary("softfloat", null); |
| ... | @@ -689,31 +697,53 @@ const CMakeConfig = struct { | ... | @@ -689,31 +697,53 @@ const CMakeConfig = struct { |
| 689 | | 697 | |
| 690 | const max_config_h_bytes = 1 * 1024 * 1024; | 698 | const max_config_h_bytes = 1 * 1024 * 1024; |
| 691 | | 699 | |
| 692 | fn findAndParseConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?CMakeConfig { | 700 | fn findConfigH(b: *Builder, config_h_path_option: ?[]const u8) ?[]const u8 { |
| 693 | const config_h_text: []const u8 = if (config_h_path_option) |config_h_path| blk: { | 701 | if (config_h_path_option) |path| { |
| 694 | break :blk fs.cwd().readFileAlloc(b.allocator, config_h_path, max_config_h_bytes) catch unreachable; | 702 | var config_h_or_err = fs.cwd().openFile(path, .{}); |
| 695 | } else blk: { | 703 | if (config_h_or_err) |*file| { |
| 696 | // TODO this should stop looking for config.h once it detects we hit the | 704 | file.close(); |
| 697 | // zig source root directory. | 705 | return path; |
| 698 | var check_dir = fs.path.dirname(b.zig_exe).?; | 706 | } else |_| { |
| 699 | while (true) { | 707 | std.log.err("Could not open provided config.h: \"{s}\"", .{path}); |
| 700 | var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; | 708 | std.os.exit(1); |
| 701 | defer dir.close(); | 709 | } |
| 702 | | 710 | } |
| 703 | break :blk dir.readFileAlloc(b.allocator, "config.h", max_config_h_bytes) catch |err| switch (err) { | 711 | |
| 704 | error.FileNotFound => { | 712 | var check_dir = fs.path.dirname(b.zig_exe).?; |
| 705 | const new_check_dir = fs.path.dirname(check_dir); | 713 | while (true) { |
| 706 | if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { | 714 | var dir = fs.cwd().openDir(check_dir, .{}) catch unreachable; |
| 707 | return null; | 715 | defer dir.close(); |
| 708 | } | 716 | |
| 709 | check_dir = new_check_dir.?; | 717 | // Check if config.h is present in dir |
| 710 | continue; | 718 | var config_h_or_err = dir.openFile("config.h", .{}); |
| 711 | }, | 719 | if (config_h_or_err) |*file| { |
| 712 | else => unreachable, | 720 | file.close(); |
| 713 | }; | 721 | return fs.path.join( |
| 714 | } else unreachable; // TODO should not need `else unreachable`. | 722 | b.allocator, |
| 715 | }; | 723 | &[_][]const u8{ check_dir, "config.h" }, |
| | 724 | ) catch unreachable; |
| | 725 | } else |e| switch (e) { |
| | 726 | error.FileNotFound => {}, |
| | 727 | else => unreachable, |
| | 728 | } |
| | 729 | |
| | 730 | // Check if we reached the source root by looking for .git, and bail if so |
| | 731 | var git_dir_or_err = dir.openDir(".git", .{}); |
| | 732 | if (git_dir_or_err) |*git_dir| { |
| | 733 | git_dir.close(); |
| | 734 | return null; |
| | 735 | } else |_| {} |
| | 736 | |
| | 737 | // Otherwise, continue search in the parent directory |
| | 738 | const new_check_dir = fs.path.dirname(check_dir); |
| | 739 | if (new_check_dir == null or mem.eql(u8, new_check_dir.?, check_dir)) { |
| | 740 | return null; |
| | 741 | } |
| | 742 | check_dir = new_check_dir.?; |
| | 743 | } else unreachable; // TODO should not need `else unreachable`. |
| | 744 | } |
| 716 | | 745 | |
| | 746 | fn parseConfigH(b: *Builder, config_h_text: []const u8) ?CMakeConfig { |
| 717 | var ctx: CMakeConfig = .{ | 747 | var ctx: CMakeConfig = .{ |
| 718 | .llvm_linkage = undefined, | 748 | .llvm_linkage = undefined, |
| 719 | .cmake_binary_dir = undefined, | 749 | .cmake_binary_dir = undefined, |