diff --git a/src/Compilation.zig b/src/Compilation.zig index c80352d35a..65ab739ecd 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -6228,6 +6228,9 @@ pub fn addCCArgs( } if (target_util.supports_fpic(target)) { + // PIE needs to go before PIC because Clang interprets `-fno-PIE` to imply `-fno-PIC`, which + // we don't necessarily want. + try argv.append(if (comp.config.pie) "-fPIE" else "-fno-PIE"); try argv.append(if (mod.pic) "-fPIC" else "-fno-PIC"); } diff --git a/src/Compilation/Config.zig b/src/Compilation/Config.zig index 1251552086..e2dea2b93f 100644 --- a/src/Compilation/Config.zig +++ b/src/Compilation/Config.zig @@ -135,6 +135,7 @@ pub const ResolveError = error{ LibCppRequiresLibC, LibUnwindRequiresLibC, TargetCannotDynamicLink, + TargetCannotStaticLinkExecutables, LibCRequiresDynamicLinking, SharedLibrariesRequireDynamicLinking, ExportMemoryAndDynamicIncompatible, @@ -360,6 +361,10 @@ pub fn resolve(options: Options) ResolveError!Config { if (options.link_mode == .dynamic) return error.TargetCannotDynamicLink; break :b .static; } + if (target.os.tag == .fuchsia and options.output_mode == .Exe) { + if (options.link_mode == .static) return error.TargetCannotStaticLinkExecutables; + break :b .dynamic; + } if (explicitly_exe_or_dyn_lib and link_libc and (target_util.osRequiresLibC(target) or // For these libcs, Zig can only provide dynamic libc when cross-compiling. @@ -416,22 +421,29 @@ pub fn resolve(options: Options) ResolveError!Config { const pie: bool = b: { switch (options.output_mode) { - .Obj, .Exe => {}, + .Exe => if (target.os.tag == .fuchsia or + (target.abi.isAndroid() and link_mode == .dynamic)) + { + if (options.pie == false) return error.TargetRequiresPie; + break :b true; + }, .Lib => if (link_mode == .dynamic) { if (options.pie == true) return error.DynamicLibraryPrecludesPie; break :b false; }, - } - if (target_util.requiresPIE(target)) { - if (options.pie == false) return error.TargetRequiresPie; - break :b true; + .Obj => {}, } if (options.any_sanitize_thread) { if (options.pie == false) return error.SanitizeThreadRequiresPie; break :b true; } if (options.pie) |pie| break :b pie; - break :b false; + break :b if (options.output_mode == .Exe) switch (target.os.tag) { + .fuchsia, + .openbsd, + => true, + else => target.os.tag.isDarwin(), + } else false; }; const root_strip = b: { diff --git a/src/main.zig b/src/main.zig index 73ba082e65..ade23312b7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -4118,6 +4118,7 @@ fn createModule( error.LibCppRequiresLibC => fatal("libc++ requires linking libc", .{}), error.LibUnwindRequiresLibC => fatal("libunwind requires linking libc", .{}), error.TargetCannotDynamicLink => fatal("dynamic linking unavailable on the specified target", .{}), + error.TargetCannotStaticLinkExecutables => fatal("static linking of executables unavailable on the specified target", .{}), error.LibCRequiresDynamicLinking => fatal("libc of the specified target requires dynamic linking", .{}), error.SharedLibrariesRequireDynamicLinking => fatal("using shared libraries requires dynamic linking", .{}), error.ExportMemoryAndDynamicIncompatible => fatal("exporting memory is incompatible with dynamic linking", .{}), diff --git a/src/target.zig b/src/target.zig index 71a58369fc..23c915ddd3 100644 --- a/src/target.zig +++ b/src/target.zig @@ -43,10 +43,6 @@ pub fn libCxxNeedsLibUnwind(target: std.Target) bool { }; } -pub fn requiresPIE(target: std.Target) bool { - return target.abi.isAndroid() or target.os.tag.isDarwin() or target.os.tag == .openbsd; -} - /// This function returns whether non-pic code is completely invalid on the given target. pub fn requiresPIC(target: std.Target, linking_libc: bool) bool { return target.abi.isAndroid() or @@ -64,7 +60,12 @@ pub fn picLevel(target: std.Target) u32 { /// This is not whether the target supports Position Independent Code, but whether the -fPIC /// C compiler argument is valid to Clang. pub fn supports_fpic(target: std.Target) bool { - return target.os.tag != .windows and target.os.tag != .uefi; + return switch (target.os.tag) { + .windows, + .uefi, + => target.abi == .gnu or target.abi == .cygnus, + else => true, + }; } pub fn alwaysSingleThreaded(target: std.Target) bool {