@@ -238,7 +238,15 @@ pub fn build(b: *Builder) !void {
238238 exe_options .addOption ([:0 ]const u8 , "version" , try b .allocator .dupeZ (u8 , version ));
239239
240240 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+ };
242250
243251 if (is_stage1 ) {
244252 const softfloat = b .addStaticLibrary ("softfloat" , null );
@@ -689,31 +697,53 @@ const CMakeConfig = struct {
689697
690698const max_config_h_bytes = 1 * 1024 * 1024 ;
691699
692- fn findAndParseConfigH (b : * Builder , config_h_path_option : ? []const u8 ) ? CMakeConfig {
693- const config_h_text : []const u8 = if (config_h_path_option ) | config_h_path | blk : {
694- break :blk fs .cwd ().readFileAlloc (b .allocator , config_h_path , max_config_h_bytes ) catch unreachable ;
695- } else blk : {
696- // TODO this should stop looking for config.h once it detects we hit the
697- // zig source root directory.
698- var check_dir = fs .path .dirname (b .zig_exe ).? ;
699- while (true ) {
700- var dir = fs .cwd ().openDir (check_dir , .{}) catch unreachable ;
701- defer dir .close ();
702-
703- break :blk dir .readFileAlloc (b .allocator , "config.h" , max_config_h_bytes ) catch | err | switch (err ) {
704- error .FileNotFound = > {
705- const new_check_dir = fs .path .dirname (check_dir );
706- if (new_check_dir == null or mem .eql (u8 , new_check_dir .? , check_dir )) {
707- return null ;
708- }
709- check_dir = new_check_dir .? ;
710- continue ;
711- },
712- else = > unreachable ,
713- };
714- } else unreachable ; // TODO should not need `else unreachable`.
715- };
700+ fn findConfigH (b : * Builder , config_h_path_option : ? []const u8 ) ? []const u8 {
701+ if (config_h_path_option ) | path | {
702+ var config_h_or_err = fs .cwd ().openFile (path , .{});
703+ if (config_h_or_err ) | * file | {
704+ file .close ();
705+ return path ;
706+ } else | _ | {
707+ std .log .err ("Could not open provided config.h: \" {s}\" " , .{path });
708+ std .os .exit (1 );
709+ }
710+ }
711+
712+ var check_dir = fs .path .dirname (b .zig_exe ).? ;
713+ while (true ) {
714+ var dir = fs .cwd ().openDir (check_dir , .{}) catch unreachable ;
715+ defer dir .close ();
716+
717+ // Check if config.h is present in dir
718+ var config_h_or_err = dir .openFile ("config.h" , .{});
719+ if (config_h_or_err ) | * file | {
720+ file .close ();
721+ return fs .path .join (
722+ b .allocator ,
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+ }
716745
746+ fn parseConfigH (b : * Builder , config_h_text : []const u8 ) ? CMakeConfig {
717747 var ctx : CMakeConfig = .{
718748 .llvm_linkage = undefined ,
719749 .cmake_binary_dir = undefined ,
0 commit comments