Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: If using Xcode CLT >= 15, add -Wl,-ld_classic in create_sysimg_from_object_file() #972

Draft
wants to merge 9 commits into
base: master
Choose a base branch
from
16 changes: 14 additions & 2 deletions src/PackageCompiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@

export create_sysimage, create_app, create_library

include("juliaconfig.jl")
# Vendored:
include("../ext/TerminalSpinners.jl")

# Source code for this package:
include("juliaconfig.jl")
include("library_selection.jl")
include("xcode.jl")


##############
Expand Down Expand Up @@ -711,7 +715,15 @@
end
mkpath(dirname(sysimage_path))
# Prevent compiler from stripping all symbols from the shared lib.
o_file_flags = Sys.isapple() ? `-Wl,-all_load $object_files` : `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`
if Sys.isapple()
if _is_xcode_clt_and_is_gte_xcode_15()
o_file_flags = `-Wl,-all_load $object_files -Wl,-ld_classic`

Check warning on line 720 in src/PackageCompiler.jl

View check run for this annotation

Codecov / codecov/patch

src/PackageCompiler.jl#L720

Added line #L720 was not covered by tests
else
o_file_flags = `-Wl,-all_load $object_files`
end
else
o_file_flags = `-Wl,--whole-archive $object_files -Wl,--no-whole-archive`
end
extra = get_extra_linker_flags(version, compat_level, soname)
cmd = `$(bitflag()) $(march()) -shared -L$(julia_libdir()) -L$(julia_private_libdir()) -o $sysimage_path $o_file_flags $(Base.shell_split(ldlibs())) $extra`
run_compiler(cmd; cplusplus=true)
Expand Down
61 changes: 61 additions & 0 deletions src/xcode.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Get the compiler command from `get_compiler_cmd()`, and run `cc --version`, and parse the
# output to determine whether or not the compiler is an Xcode Clang.
#
# The return value is a NamedTuple of the form (; b, ver)
# b = a Bool that is true iff the compiler is an Xcode Clang.
# ver = the version number of the Xcode Clang. If it's not Xcode Clang, ver is nothing.
function _is_xcode_clt()
cmd = `$(get_compiler_cmd()) --version`
@debug "_active_compiler_is_xcode_clt(): Attempting to run command" cmd
# The `ignorestatus` allows us to proceed if the command does not run successfully.
output = "\n" * strip(read(ignorestatus(cmd), String)) * "\n"

# If this is an Xcode Clang compiler, example output would be:
# > Apple clang version 16.0.0 (clang-1600.0.26.3)
# > Target: arm64-apple-darwin23.6.0
# > Thread model: posix
# > InstalledDir: /Library/Developer/CommandLineTools/usr/bin

installed_dir_m = match(r"\nInstalledDir: ([\w\/]*?)\n", output)
if isnothing(installed_dir_m)
return (; b=false, ver=nothing)
end
installed_dir_str = strip(installed_dir_m[1])
is_xcode_app = startswith(installed_dir_str, "/Applications/Xcode.app")
is_xcode_clt = startswith(installed_dir_str, "/Library/Developer/CommandLineTools")
if is_xcode_app || is_xcode_clt
m = match(r"\nApple clang version ([0-9\.]*?) ", output)
if isnothing(m)
@warn "Could not determine the version of the Xcode Command Line Tools"
(; b=false, ver=nothing)

Check warning on line 30 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L23-L30

Added lines #L23 - L30 were not covered by tests
end
ver_str = strip(m[1])
ver = tryparse(VersionNumber, ver_str)
if isnothing(ver)
@warn "Could not determine the version of the Xcode Command Line Tools" ver_str
(; b=false, ver=nothing)

Check warning on line 36 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L32-L36

Added lines #L32 - L36 were not covered by tests
end
b = true

Check warning on line 38 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L38

Added line #L38 was not covered by tests
else
b = false
ver = nothing

Check warning on line 41 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L40-L41

Added lines #L40 - L41 were not covered by tests
end
return (; b, ver)

Check warning on line 43 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L43

Added line #L43 was not covered by tests
end

# Return true iff the compiler is Xcode Clang AND the Xcode CLT version is >= 15.
#
# If the user sets the JULIA_PACKAGECOMPILER_XCODE_CLT_MAJOR_VERSION environment variable,
# we skip our attempt at auto-detection, and instead use whatever value the user gave us.
function _is_xcode_clt_and_is_gte_xcode_15()
str = strip(get(ENV, "JULIA_PACKAGECOMPILER_XCODE_CLT_MAJOR_VERSION", ""))
ver_int = tryparse(Int, str)
(ver_int isa Int) && return (ver_int >= 15)

result = _is_xcode_clt()
if result.b
return result.ver >= v"15"

Check warning on line 57 in src/xcode.jl

View check run for this annotation

Codecov / codecov/patch

src/xcode.jl#L57

Added line #L57 was not covered by tests
else
return false
end
end
Loading