authorgravatar for michael.dusan@gmail.comMichael Dusan <michael.dusan@gmail.com> 2022-09-19 19:11:10-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-10-12 13:50:25-04:00
log0b47e69b7c0aedbc142400305cda86ef58b41656
tree69ddb125e0d0cabc888045697f26da92b5c10f06
parentc23b3e6fd924725d21ecbbc85ef086d330dd4322

improve header searchlist handling in build, main

build.zig: - use "-I" instead of "-isystem" for `b.addSearchPrefix()` main.zig: - silently ignore superfluous search dirs - warn when a dir is added to multiple searchlists - consolidate "expected paramter after {s}" fatal error messages - rename command-line switch `-dirafter` → `-idirafter` closes #12888

2 files changed, 129 insertions(+), 135 deletions(-)

lib/std/build.zig+1-1
...@@ -3123,7 +3123,7 @@ pub const LibExeObjStep = struct {...@@ -3123,7 +3123,7 @@ pub const LibExeObjStep = struct {
3123 try zig_args.append(builder.pathJoin(&.{3123 try zig_args.append(builder.pathJoin(&.{
3124 search_prefix, "lib",3124 search_prefix, "lib",
3125 }));3125 }));
3126 try zig_args.append("-isystem");3126 try zig_args.append("-I");
3127 try zig_args.append(builder.pathJoin(&.{3127 try zig_args.append(builder.pathJoin(&.{
3128 search_prefix, "include",3128 search_prefix, "include",
3129 }));3129 }));
src/main.zig+128-134
...@@ -416,7 +416,7 @@ const usage_build_generic =...@@ -416,7 +416,7 @@ const usage_build_generic =
416 \\ plan9 Plan 9 from Bell Labs object format416 \\ plan9 Plan 9 from Bell Labs object format
417 \\ hex (planned feature) Intel IHEX417 \\ hex (planned feature) Intel IHEX
418 \\ raw (planned feature) Dump machine code directly418 \\ raw (planned feature) Dump machine code directly
419 \\ -dirafter [dir] Add directory to AFTER include search path419 \\ -idirafter [dir] Add directory to AFTER include search path
420 \\ -isystem [dir] Add directory to SYSTEM include search path420 \\ -isystem [dir] Add directory to SYSTEM include search path
421 \\ -I[dir] Add directory to include search path421 \\ -I[dir] Add directory to include search path
422 \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted)422 \\ -D[macro]=[value] Define C [macro] to [value] (1 if [value] omitted)
...@@ -845,11 +845,22 @@ fn buildOutputType(...@@ -845,11 +845,22 @@ fn buildOutputType(
845 defer it.i += 1;845 defer it.i += 1;
846 return it.args[it.i];846 return it.args[it.i];
847 }847 }
848 fn nextOrFatal(it: *@This()) []const u8 {
849 if (it.i >= it.args.len) {
850 if (it.resp_file) |*resp| if (resp.next()) |sentinel| return std.mem.span(sentinel);
851 fatal("expected parameter after {s}", .{it.args[it.i - 1]});
852 }
853 defer it.i += 1;
854 return it.args[it.i];
855 }
848 };856 };
849 var args_iter = Iterator{857 var args_iter = Iterator{
850 .args = all_args[2..],858 .args = all_args[2..],
851 };859 };
852860
861 var cssan = ClangSearchSanitizer.init(gpa, &clang_argv);
862 defer cssan.map.deinit();
863
853 args_loop: while (args_iter.next()) |arg| {864 args_loop: while (args_iter.next()) |arg| {
854 if (mem.startsWith(u8, arg, "@")) {865 if (mem.startsWith(u8, arg, "@")) {
855 // This is a "compiler response file". We must parse the file and treat its866 // This is a "compiler response file". We must parse the file and treat its
...@@ -895,9 +906,7 @@ fn buildOutputType(...@@ -895,9 +906,7 @@ fn buildOutputType(
895 cur_pkg = cur_pkg.parent orelse906 cur_pkg = cur_pkg.parent orelse
896 fatal("encountered --pkg-end with no matching --pkg-begin", .{});907 fatal("encountered --pkg-end with no matching --pkg-begin", .{});
897 } else if (mem.eql(u8, arg, "--main-pkg-path")) {908 } else if (mem.eql(u8, arg, "--main-pkg-path")) {
898 main_pkg_path = args_iter.next() orelse {909 main_pkg_path = args_iter.nextOrFatal();
899 fatal("expected parameter after {s}", .{arg});
900 };
901 } else if (mem.eql(u8, arg, "-cflags")) {910 } else if (mem.eql(u8, arg, "-cflags")) {
902 extra_cflags.shrinkRetainingCapacity(0);911 extra_cflags.shrinkRetainingCapacity(0);
903 while (true) {912 while (true) {
...@@ -915,67 +924,37 @@ fn buildOutputType(...@@ -915,67 +924,37 @@ fn buildOutputType(
915 fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg});924 fatal("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
916 };925 };
917 } else if (mem.eql(u8, arg, "--subsystem")) {926 } else if (mem.eql(u8, arg, "--subsystem")) {
918 const next_arg = args_iter.next() orelse {927 subsystem = try parseSubSystem(args_iter.nextOrFatal());
919 fatal("expected parameter after {s}", .{arg});
920 };
921 subsystem = try parseSubSystem(next_arg);
922 } else if (mem.eql(u8, arg, "-O")) {928 } else if (mem.eql(u8, arg, "-O")) {
923 optimize_mode_string = args_iter.next() orelse {929 optimize_mode_string = args_iter.nextOrFatal();
924 fatal("expected parameter after {s}", .{arg});
925 };
926 } else if (mem.eql(u8, arg, "--entry")) {930 } else if (mem.eql(u8, arg, "--entry")) {
927 entry = args_iter.next() orelse {931 entry = args_iter.nextOrFatal();
928 fatal("expected parameter after {s}", .{arg});
929 };
930 } else if (mem.eql(u8, arg, "--stack")) {932 } else if (mem.eql(u8, arg, "--stack")) {
931 const next_arg = args_iter.next() orelse {933 const next_arg = args_iter.nextOrFatal();
932 fatal("expected parameter after {s}", .{arg});
933 };
934 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {934 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
935 fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) });935 fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) });
936 };936 };
937 } else if (mem.eql(u8, arg, "--image-base")) {937 } else if (mem.eql(u8, arg, "--image-base")) {
938 const next_arg = args_iter.next() orelse {938 const next_arg = args_iter.nextOrFatal();
939 fatal("expected parameter after {s}", .{arg});
940 };
941 image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {939 image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
942 fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) });940 fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) });
943 };941 };
944 } else if (mem.eql(u8, arg, "--name")) {942 } else if (mem.eql(u8, arg, "--name")) {
945 provided_name = args_iter.next() orelse {943 provided_name = args_iter.nextOrFatal();
946 fatal("expected parameter after {s}", .{arg});
947 };
948 } else if (mem.eql(u8, arg, "-rpath")) {944 } else if (mem.eql(u8, arg, "-rpath")) {
949 try rpath_list.append(args_iter.next() orelse {945 try rpath_list.append(args_iter.nextOrFatal());
950 fatal("expected parameter after {s}", .{arg});
951 });
952 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {946 } else if (mem.eql(u8, arg, "--library-directory") or mem.eql(u8, arg, "-L")) {
953 try lib_dirs.append(args_iter.next() orelse {947 try lib_dirs.append(args_iter.nextOrFatal());
954 fatal("expected parameter after {s}", .{arg});
955 });
956 } else if (mem.eql(u8, arg, "-F")) {948 } else if (mem.eql(u8, arg, "-F")) {
957 try framework_dirs.append(args_iter.next() orelse {949 try framework_dirs.append(args_iter.nextOrFatal());
958 fatal("expected parameter after {s}", .{arg});
959 });
960 } else if (mem.eql(u8, arg, "-framework")) {950 } else if (mem.eql(u8, arg, "-framework")) {
961 const path = args_iter.next() orelse {951 try frameworks.put(gpa, args_iter.nextOrFatal(), .{});
962 fatal("expected parameter after {s}", .{arg});
963 };
964 try frameworks.put(gpa, path, .{});
965 } else if (mem.eql(u8, arg, "-weak_framework")) {952 } else if (mem.eql(u8, arg, "-weak_framework")) {
966 const path = args_iter.next() orelse {953 try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .weak = true });
967 fatal("expected parameter after {s}", .{arg});
968 };
969 try frameworks.put(gpa, path, .{ .weak = true });
970 } else if (mem.eql(u8, arg, "-needed_framework")) {954 } else if (mem.eql(u8, arg, "-needed_framework")) {
971 const path = args_iter.next() orelse {955 try frameworks.put(gpa, args_iter.nextOrFatal(), .{ .needed = true });
972 fatal("expected parameter after {s}", .{arg});
973 };
974 try frameworks.put(gpa, path, .{ .needed = true });
975 } else if (mem.eql(u8, arg, "-install_name")) {956 } else if (mem.eql(u8, arg, "-install_name")) {
976 install_name = args_iter.next() orelse {957 install_name = args_iter.nextOrFatal();
977 fatal("expected parameter after {s}", .{arg});
978 };
979 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {958 } else if (mem.startsWith(u8, arg, "--compress-debug-sections=")) {
980 const param = arg["--compress-debug-sections=".len..];959 const param = arg["--compress-debug-sections=".len..];
981 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, param) orelse {960 linker_compress_debug_sections = std.meta.stringToEnum(link.CompressDebugSections, param) orelse {
...@@ -984,9 +963,7 @@ fn buildOutputType(...@@ -984,9 +963,7 @@ fn buildOutputType(
984 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {963 } else if (mem.eql(u8, arg, "--compress-debug-sections")) {
985 linker_compress_debug_sections = link.CompressDebugSections.zlib;964 linker_compress_debug_sections = link.CompressDebugSections.zlib;
986 } else if (mem.eql(u8, arg, "-pagezero_size")) {965 } else if (mem.eql(u8, arg, "-pagezero_size")) {
987 const next_arg = args_iter.next() orelse {966 const next_arg = args_iter.nextOrFatal();
988 fatal("expected parameter after {s}", .{arg});
989 };
990 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {967 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
991 fatal("unable to parse pagezero size'{s}': {s}", .{ next_arg, @errorName(err) });968 fatal("unable to parse pagezero size'{s}': {s}", .{ next_arg, @errorName(err) });
992 };969 };
...@@ -995,9 +972,7 @@ fn buildOutputType(...@@ -995,9 +972,7 @@ fn buildOutputType(
995 } else if (mem.eql(u8, arg, "-search_dylibs_first")) {972 } else if (mem.eql(u8, arg, "-search_dylibs_first")) {
996 search_strategy = .dylibs_first;973 search_strategy = .dylibs_first;
997 } else if (mem.eql(u8, arg, "-headerpad")) {974 } else if (mem.eql(u8, arg, "-headerpad")) {
998 const next_arg = args_iter.next() orelse {975 const next_arg = args_iter.nextOrFatal();
999 fatal("expected parameter after {s}", .{arg});
1000 };
1001 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {976 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
1002 fatal("unable to parse headerpat size '{s}': {s}", .{ next_arg, @errorName(err) });977 fatal("unable to parse headerpat size '{s}': {s}", .{ next_arg, @errorName(err) });
1003 };978 };
...@@ -1008,65 +983,44 @@ fn buildOutputType(...@@ -1008,65 +983,44 @@ fn buildOutputType(
1008 } else if (mem.eql(u8, arg, "-dead_strip_dylibs")) {983 } else if (mem.eql(u8, arg, "-dead_strip_dylibs")) {
1009 dead_strip_dylibs = true;984 dead_strip_dylibs = true;
1010 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {985 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
1011 linker_script = args_iter.next() orelse {986 linker_script = args_iter.nextOrFatal();
1012 fatal("expected parameter after {s}", .{arg});
1013 };
1014 } else if (mem.eql(u8, arg, "--version-script")) {987 } else if (mem.eql(u8, arg, "--version-script")) {
1015 version_script = args_iter.next() orelse {988 version_script = args_iter.nextOrFatal();
1016 fatal("expected parameter after {s}", .{arg});
1017 };
1018 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {989 } else if (mem.eql(u8, arg, "--library") or mem.eql(u8, arg, "-l")) {
1019 const next_arg = args_iter.next() orelse {
1020 fatal("expected parameter after {s}", .{arg});
1021 };
1022 // We don't know whether this library is part of libc or libc++ until990 // We don't know whether this library is part of libc or libc++ until
1023 // we resolve the target, so we simply append to the list for now.991 // we resolve the target, so we simply append to the list for now.
1024 try system_libs.put(next_arg, .{});992 try system_libs.put(args_iter.nextOrFatal(), .{});
1025 } else if (mem.eql(u8, arg, "--needed-library") or993 } else if (mem.eql(u8, arg, "--needed-library") or
1026 mem.eql(u8, arg, "-needed-l") or994 mem.eql(u8, arg, "-needed-l") or
1027 mem.eql(u8, arg, "-needed_library"))995 mem.eql(u8, arg, "-needed_library"))
1028 {996 {
1029 const next_arg = args_iter.next() orelse {997 const next_arg = args_iter.nextOrFatal();
1030 fatal("expected parameter after {s}", .{arg});
1031 };
1032 try system_libs.put(next_arg, .{ .needed = true });998 try system_libs.put(next_arg, .{ .needed = true });
1033 } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) {999 } else if (mem.eql(u8, arg, "-weak_library") or mem.eql(u8, arg, "-weak-l")) {
1034 const next_arg = args_iter.next() orelse {1000 try system_libs.put(args_iter.nextOrFatal(), .{ .weak = true });
1035 fatal("expected parameter after {s}", .{arg});1001 } else if (mem.eql(u8, arg, "-D")) {
1036 };
1037 try system_libs.put(next_arg, .{ .weak = true });
1038 } else if (mem.eql(u8, arg, "-D") or
1039 mem.eql(u8, arg, "-isystem") or
1040 mem.eql(u8, arg, "-I") or
1041 mem.eql(u8, arg, "-dirafter") or
1042 mem.eql(u8, arg, "-iwithsysroot") or
1043 mem.eql(u8, arg, "-iframework") or
1044 mem.eql(u8, arg, "-iframeworkwithsysroot"))
1045 {
1046 try clang_argv.append(arg);1002 try clang_argv.append(arg);
1047 try clang_argv.append(args_iter.next() orelse {1003 try clang_argv.append(args_iter.nextOrFatal());
1048 fatal("expected parameter after {s}", .{arg});1004 } else if (mem.eql(u8, arg, "-I")) {
1049 });1005 try cssan.addIncludePath(.I, arg, args_iter.nextOrFatal(), false);
1006 } else if (mem.eql(u8, arg, "-isystem") or mem.eql(u8, arg, "-iwithsysroot")) {
1007 try cssan.addIncludePath(.isystem, arg, args_iter.nextOrFatal(), false);
1008 } else if (mem.eql(u8, arg, "-idirafter")) {
1009 try cssan.addIncludePath(.idirafter, arg, args_iter.nextOrFatal(), false);
1010 } else if (mem.eql(u8, arg, "-iframework") or mem.eql(u8, arg, "-iframeworkwithsysroot")) {
1011 try cssan.addIncludePath(.iframework, arg, args_iter.nextOrFatal(), false);
1050 } else if (mem.eql(u8, arg, "--version")) {1012 } else if (mem.eql(u8, arg, "--version")) {
1051 const next_arg = args_iter.next() orelse {1013 const next_arg = args_iter.nextOrFatal();
1052 fatal("expected parameter after {s}", .{arg});
1053 };
1054 version = std.builtin.Version.parse(next_arg) catch |err| {1014 version = std.builtin.Version.parse(next_arg) catch |err| {
1055 fatal("unable to parse --version '{s}': {s}", .{ next_arg, @errorName(err) });1015 fatal("unable to parse --version '{s}': {s}", .{ next_arg, @errorName(err) });
1056 };1016 };
1057 have_version = true;1017 have_version = true;
1058 } else if (mem.eql(u8, arg, "-target")) {1018 } else if (mem.eql(u8, arg, "-target")) {
1059 target_arch_os_abi = args_iter.next() orelse {1019 target_arch_os_abi = args_iter.nextOrFatal();
1060 fatal("expected parameter after {s}", .{arg});
1061 };
1062 } else if (mem.eql(u8, arg, "-mcpu")) {1020 } else if (mem.eql(u8, arg, "-mcpu")) {
1063 target_mcpu = args_iter.next() orelse {1021 target_mcpu = args_iter.nextOrFatal();
1064 fatal("expected parameter after {s}", .{arg});
1065 };
1066 } else if (mem.eql(u8, arg, "-mcmodel")) {1022 } else if (mem.eql(u8, arg, "-mcmodel")) {
1067 machine_code_model = parseCodeModel(args_iter.next() orelse {1023 machine_code_model = parseCodeModel(args_iter.nextOrFatal());
1068 fatal("expected parameter after {s}", .{arg});
1069 });
1070 } else if (mem.startsWith(u8, arg, "-ofmt=")) {1024 } else if (mem.startsWith(u8, arg, "-ofmt=")) {
1071 target_ofmt = arg["-ofmt=".len..];1025 target_ofmt = arg["-ofmt=".len..];
1072 } else if (mem.startsWith(u8, arg, "-mcpu=")) {1026 } else if (mem.startsWith(u8, arg, "-mcpu=")) {
...@@ -1076,51 +1030,29 @@ fn buildOutputType(...@@ -1076,51 +1030,29 @@ fn buildOutputType(
1076 } else if (mem.startsWith(u8, arg, "-O")) {1030 } else if (mem.startsWith(u8, arg, "-O")) {
1077 optimize_mode_string = arg["-O".len..];1031 optimize_mode_string = arg["-O".len..];
1078 } else if (mem.eql(u8, arg, "--dynamic-linker")) {1032 } else if (mem.eql(u8, arg, "--dynamic-linker")) {
1079 target_dynamic_linker = args_iter.next() orelse {1033 target_dynamic_linker = args_iter.nextOrFatal();
1080 fatal("expected parameter after {s}", .{arg});
1081 };
1082 } else if (mem.eql(u8, arg, "--sysroot")) {1034 } else if (mem.eql(u8, arg, "--sysroot")) {
1083 sysroot = args_iter.next() orelse {
1084 fatal("expected parameter after {s}", .{arg});
1085 };
1086 try clang_argv.append("-isysroot");1035 try clang_argv.append("-isysroot");
1087 try clang_argv.append(sysroot.?);1036 try clang_argv.append(args_iter.nextOrFatal());
1088 } else if (mem.eql(u8, arg, "--libc")) {1037 } else if (mem.eql(u8, arg, "--libc")) {
1089 libc_paths_file = args_iter.next() orelse {1038 libc_paths_file = args_iter.nextOrFatal();
1090 fatal("expected parameter after {s}", .{arg});
1091 };
1092 } else if (mem.eql(u8, arg, "--test-filter")) {1039 } else if (mem.eql(u8, arg, "--test-filter")) {
1093 test_filter = args_iter.next() orelse {1040 test_filter = args_iter.nextOrFatal();
1094 fatal("expected parameter after {s}", .{arg});
1095 };
1096 } else if (mem.eql(u8, arg, "--test-name-prefix")) {1041 } else if (mem.eql(u8, arg, "--test-name-prefix")) {
1097 test_name_prefix = args_iter.next() orelse {1042 test_name_prefix = args_iter.nextOrFatal();
1098 fatal("expected parameter after {s}", .{arg});
1099 };
1100 } else if (mem.eql(u8, arg, "--test-cmd")) {1043 } else if (mem.eql(u8, arg, "--test-cmd")) {
1101 try test_exec_args.append(args_iter.next() orelse {1044 try test_exec_args.append(args_iter.nextOrFatal());
1102 fatal("expected parameter after {s}", .{arg});
1103 });
1104 } else if (mem.eql(u8, arg, "--cache-dir")) {1045 } else if (mem.eql(u8, arg, "--cache-dir")) {
1105 override_local_cache_dir = args_iter.next() orelse {1046 override_local_cache_dir = args_iter.nextOrFatal();
1106 fatal("expected parameter after {s}", .{arg});
1107 };
1108 } else if (mem.eql(u8, arg, "--global-cache-dir")) {1047 } else if (mem.eql(u8, arg, "--global-cache-dir")) {
1109 override_global_cache_dir = args_iter.next() orelse {1048 override_global_cache_dir = args_iter.nextOrFatal();
1110 fatal("expected parameter after {s}", .{arg});
1111 };
1112 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {1049 } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
1113 override_lib_dir = args_iter.next() orelse {1050 override_lib_dir = args_iter.nextOrFatal();
1114 fatal("expected parameter after {s}", .{arg});
1115 };
1116 } else if (mem.eql(u8, arg, "--debug-log")) {1051 } else if (mem.eql(u8, arg, "--debug-log")) {
1117 const next_arg = args_iter.next() orelse {
1118 fatal("expected parameter after {s}", .{arg});
1119 };
1120 if (!build_options.enable_logging) {1052 if (!build_options.enable_logging) {
1121 std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});1053 std.log.warn("Zig was compiled without logging enabled (-Dlog). --debug-log has no effect.", .{});
1122 } else {1054 } else {
1123 try log_scopes.append(gpa, next_arg);1055 try log_scopes.append(gpa, args_iter.nextOrFatal());
1124 }1056 }
1125 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {1057 } else if (mem.eql(u8, arg, "--debug-link-snapshot")) {
1126 if (!build_options.enable_link_snapshots) {1058 if (!build_options.enable_link_snapshots) {
...@@ -1129,9 +1061,7 @@ fn buildOutputType(...@@ -1129,9 +1061,7 @@ fn buildOutputType(
1129 enable_link_snapshots = true;1061 enable_link_snapshots = true;
1130 }1062 }
1131 } else if (mem.eql(u8, arg, "--entitlements")) {1063 } else if (mem.eql(u8, arg, "--entitlements")) {
1132 entitlements = args_iter.next() orelse {1064 entitlements = args_iter.nextOrFatal();
1133 fatal("expected parameter after {s}", .{arg});
1134 };
1135 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {1065 } else if (mem.eql(u8, arg, "-fcompiler-rt")) {
1136 want_compiler_rt = true;1066 want_compiler_rt = true;
1137 } else if (mem.eql(u8, arg, "-fno-compiler-rt")) {1067 } else if (mem.eql(u8, arg, "-fno-compiler-rt")) {
...@@ -1322,9 +1252,7 @@ fn buildOutputType(...@@ -1322,9 +1252,7 @@ fn buildOutputType(
1322 } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) {1252 } else if (mem.eql(u8, arg, "-fno-allow-shlib-undefined")) {
1323 linker_allow_shlib_undefined = false;1253 linker_allow_shlib_undefined = false;
1324 } else if (mem.eql(u8, arg, "-z")) {1254 } else if (mem.eql(u8, arg, "-z")) {
1325 const z_arg = args_iter.next() orelse {1255 const z_arg = args_iter.nextOrFatal();
1326 fatal("expected parameter after {s}", .{arg});
1327 };
1328 if (mem.eql(u8, z_arg, "nodelete")) {1256 if (mem.eql(u8, z_arg, "nodelete")) {
1329 linker_z_nodelete = true;1257 linker_z_nodelete = true;
1330 } else if (mem.eql(u8, z_arg, "notext")) {1258 } else if (mem.eql(u8, z_arg, "notext")) {
...@@ -1394,10 +1322,10 @@ fn buildOutputType(...@@ -1394,10 +1322,10 @@ fn buildOutputType(
1394 try system_libs.put(arg["-needed-l".len..], .{ .needed = true });1322 try system_libs.put(arg["-needed-l".len..], .{ .needed = true });
1395 } else if (mem.startsWith(u8, arg, "-weak-l")) {1323 } else if (mem.startsWith(u8, arg, "-weak-l")) {
1396 try system_libs.put(arg["-weak-l".len..], .{ .weak = true });1324 try system_libs.put(arg["-weak-l".len..], .{ .weak = true });
1397 } else if (mem.startsWith(u8, arg, "-D") or1325 } else if (mem.startsWith(u8, arg, "-D")) {
1398 mem.startsWith(u8, arg, "-I"))
1399 {
1400 try clang_argv.append(arg);1326 try clang_argv.append(arg);
1327 } else if (mem.startsWith(u8, arg, "-I")) {
1328 try cssan.addIncludePath(.I, arg, arg[2..], true);
1401 } else if (mem.startsWith(u8, arg, "-mexec-model=")) {1329 } else if (mem.startsWith(u8, arg, "-mexec-model=")) {
1402 wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, arg["-mexec-model=".len..]) orelse {1330 wasi_exec_model = std.meta.stringToEnum(std.builtin.WasiExecModel, arg["-mexec-model=".len..]) orelse {
1403 fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{arg["-mexec-model=".len..]});1331 fatal("expected [command|reactor] for -mexec-mode=[value], found '{s}'", .{arg["-mexec-model=".len..]});
...@@ -5497,3 +5425,69 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {...@@ -5497,3 +5425,69 @@ fn parseSubSystem(next_arg: []const u8) !std.Target.SubSystem {
5497 });5425 });
5498 }5426 }
5499}5427}
5428
5429/// Model a header searchlist as a group.
5430/// Silently ignore superfluous search dirs.
5431/// Warn when a dir is added to multiple searchlists.
5432const ClangSearchSanitizer = struct {
5433 argv: *std.ArrayList([]const u8),
5434 map: std.StringHashMap(Membership),
5435
5436 fn init(gpa: Allocator, argv: *std.ArrayList([]const u8)) @This() {
5437 return .{
5438 .argv = argv,
5439 .map = std.StringHashMap(Membership).init(gpa),
5440 };
5441 }
5442
5443 fn addIncludePath(self: *@This(), group: Group, arg: []const u8, dir: []const u8, joined: bool) !void {
5444 const gopr = try self.map.getOrPut(dir);
5445 const m = gopr.value_ptr;
5446 if (!gopr.found_existing) {
5447 // init empty membership
5448 m.* = .{};
5449 }
5450 const wtxt = "add '{s}' to header searchlist '-{s}' conflicts with '-{s}'";
5451 switch (group) {
5452 .I => {
5453 if (m.I) return;
5454 m.I = true;
5455 if (m.isystem) std.log.warn(wtxt, .{ dir, "I", "isystem" });
5456 if (m.idirafter) std.log.warn(wtxt, .{ dir, "I", "idirafter" });
5457 if (m.iframework) std.log.warn(wtxt, .{ dir, "I", "iframework" });
5458 },
5459 .isystem => {
5460 if (m.isystem) return;
5461 m.isystem = true;
5462 if (m.I) std.log.warn(wtxt, .{ dir, "isystem", "I" });
5463 if (m.idirafter) std.log.warn(wtxt, .{ dir, "isystem", "idirafter" });
5464 if (m.iframework) std.log.warn(wtxt, .{ dir, "isystem", "iframework" });
5465 },
5466 .idirafter => {
5467 if (m.idirafter) return;
5468 m.idirafter = true;
5469 if (m.I) std.log.warn(wtxt, .{ dir, "idirafter", "I" });
5470 if (m.isystem) std.log.warn(wtxt, .{ dir, "idirafter", "isystem" });
5471 if (m.iframework) std.log.warn(wtxt, .{ dir, "idirafter", "iframework" });
5472 },
5473 .iframework => {
5474 if (m.iframework) return;
5475 m.iframework = true;
5476 if (m.I) std.log.warn(wtxt, .{ dir, "iframework", "I" });
5477 if (m.isystem) std.log.warn(wtxt, .{ dir, "iframework", "isystem" });
5478 if (m.idirafter) std.log.warn(wtxt, .{ dir, "iframework", "idirafter" });
5479 },
5480 }
5481 try self.argv.append(arg);
5482 if (!joined) try self.argv.append(dir);
5483 }
5484
5485 const Group = enum { I, isystem, idirafter, iframework };
5486
5487 const Membership = packed struct {
5488 I: bool = false,
5489 isystem: bool = false,
5490 idirafter: bool = false,
5491 iframework: bool = false,
5492 };
5493};