diff --git a/Library/Homebrew/extend/ENV/super.rb b/Library/Homebrew/extend/ENV/super.rb index f46d88744a..977c30fd45 100644 --- a/Library/Homebrew/extend/ENV/super.rb +++ b/Library/Homebrew/extend/ENV/super.rb @@ -105,6 +105,8 @@ module Superenv # have runtime detection of CPU features. # w - Pass -no_weak_imports to the linker # D - Generate debugging information + # f - Pass `-no_fixup_chains` to `ld` whenever it + # is invoked with `-undefined dynamic_lookup` # # These flags will also be present: # a - apply fix for apr-1-config path diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb b/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb index e2d47c2e76..a13761a8b3 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/shared.rb @@ -23,4 +23,18 @@ module SharedEnvExtension true end + + sig { returns(T::Boolean) } + def no_fixup_chains_support? + return false if MacOS.version <= :catalina + + # NOTE: `-version_details` is supported in Xcode 10.2 at the earliest. + ld_version_details = JSON.parse(Utils.safe_popen_read("/usr/bin/ld", "-version_details")) + ld_version = Version.parse(ld_version_details["version"]) + + # This is supported starting Xcode 13, which ships ld64-711. + # https://developer.apple.com/documentation/xcode-release-notes/xcode-13-release-notes + # https://en.wikipedia.org/wiki/Xcode#Xcode_11.0_-_14.x_(since_SwiftUI_framework)_2 + ld_version >= 711 + end end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb index cb42b054a9..0312bfc5bd 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/std.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/std.rb @@ -101,4 +101,8 @@ module Stdenv def no_weak_imports append "LDFLAGS", "-Wl,-no_weak_imports" if no_weak_imports_support? end + + def no_fixup_chains + append "LDFLAGS", "-Wl,-no_fixup_chains" if no_fixup_chains_support? + end end diff --git a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb index bb032b370e..36aac56489 100644 --- a/Library/Homebrew/extend/os/mac/extend/ENV/super.rb +++ b/Library/Homebrew/extend/os/mac/extend/ENV/super.rb @@ -131,9 +131,18 @@ module Superenv # Notably, Xcode 10.2 fixes issues where ZERO_AR_DATE affected file mtimes. # Xcode 11.0 contains fixes for lldb reading things built with ZERO_AR_DATE. self["ZERO_AR_DATE"] = "1" if MacOS::Xcode.version >= "11.0" || MacOS::CLT.version >= "11.0" + + # Pass `-no_fixup_chains` whenever the linker is invoked with `-undefined dynamic_lookup`. + # See: https://github.com/python/cpython/issues/97524 + # https://github.com/pybind/pybind11/pull/4301 + no_fixup_chains end def no_weak_imports append_to_cccfg "w" if no_weak_imports_support? end + + def no_fixup_chains + append_to_cccfg "f" if no_fixup_chains_support? + end end diff --git a/Library/Homebrew/shims/super/cc b/Library/Homebrew/shims/super/cc index 90b7f0e318..2706649680 100755 --- a/Library/Homebrew/shims/super/cc +++ b/Library/Homebrew/shims/super/cc @@ -221,7 +221,7 @@ class Cmd args << "-Wl,-undefined,dynamic_lookup" when /^-isysroot=/, /^--sysroot=/ if mac? - sdk = arg.split("=")[1..-1].join("=") + sdk = arg.split("=", 2).last # We set the sysroot for macOS SDKs args << arg unless sdk.downcase.include? "osx" else @@ -318,9 +318,11 @@ class Cmd when :ld args << "-headerpad_max_install_names" args << "-no_weak_imports" if no_weak_imports? + args << "-no_fixup_chains" if no_fixup_chains? when :ccld, :cxxld args << "-Wl,-headerpad_max_install_names" args << "-Wl,-no_weak_imports" if no_weak_imports? + args << "-Wl,-no_fixup_chains" if no_fixup_chains? end args end @@ -416,6 +418,32 @@ class Cmd config.include?("D") end + def no_fixup_chains? + return false unless config.include?("f") + return false unless calls_ld? + return true if @args.include?("-Wl,-undefined,dynamic_lookup") + + args_consecutive_pairs = @args.each_cons(2) + return true if args_consecutive_pairs.include?(["-undefined", "dynamic_lookup"]) + return true if args_consecutive_pairs.include?(["-Wl,-undefined", "-Wl,dynamic_lookup"]) + + # The next flag would produce an error, but we fix it in `refurbish_arg`. + @args.include?("-undefineddynamic_lookup") + end + + def calls_ld? + return true if mode == :ld + return false unless [:ccld, :cxxld].include?(mode) + + fuse_ld_flags = @args.find_all { |arg| arg.match?(/^-fuse-ld=/) } + return true if fuse_ld_flags.empty? + + fuse_ld_flag = fuse_ld_flags.last.strip + fuse_ld_arg = fuse_ld_flag.split("=", 2).last + + (fuse_ld_arg == "ld") || fuse_ld_arg.end_with?("/usr/bin/ld") + end + def canonical_path(path) path = Pathname.new(path) path = path.realpath if path.exist?