Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions Make.inc
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,13 @@ BUILD_MACHINE := $(shell $(HOSTCC) -dumpmachine)
# don't recognize that, so canonicalize to mingw32
BUILD_MACHINE := $(subst windows-gnu,mingw32,$(BUILD_MACHINE))

# Detect a request for ucrt libc
ifeq (,$(findstring MINGW,$(RAW_BUILD_OS)))
ifeq (UCRT64,$(MSYSTEM))
BUILD_MACHINE := $(subst mingw32,ucrt-mingw32,$(BUILD_MACHINE))
endif
endif

ifeq ($(ARCH),)
override ARCH := $(shell $(CC) -dumpmachine | sed "s/\([^-]*\).*$$/\1/")
else
Expand Down
45 changes: 37 additions & 8 deletions base/binaryplatforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,22 @@ struct Platform <: AbstractPlatform
continue
end

# For compatibility, libstdcxx_version counts as both cxxlib=libstdcxx and
# cxxlib_version, but don't override an explicit existing cxxlib tag (the
# verifier will check for inconsistencies).
if tag == "libstdcxx_version"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giordano do we have any packages that require building with g++ on macOS? I know we used to, which is why we ship libstdc++ on macOS and open it as part of CSL, but I just loaded WGLMakie and it didn't pick up any libraries that actually use it. If we can actually convince ourselves that we'll never have the situation where most things use libc++ but a few things use libstdc++, then I think we're fine to do this Keno's way. Otherwise, I think we need to have libstdcxx_version and libcxx_version so Julia can express that it is simultaneously loading two different C++ stdlibs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to state it explicitly, mixing C++ implementations is a BAD idea, but one way it can come about and not be fatal is if a library uses C++ internally (and does not take in/give out C++ objects through its API). If you have two such libraries loaded at once, you need to ensure that you're selecting versions of those libraries that agree on the minimum version of libstdc++, despite the fact that 99% of your program is using libc++.

I was under the impression that we did have sub-trees of dependencies running using libstdc++ even on macOS/FreeBSD, but perhaps that is no longer the case and we don't have to fear this anymore.r

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we have any packages that require building with g++ on macOS?

Yes, there are a bunch of packages which do use g++ on macOS.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we assemble a list. Why are they using g++ do they specifically care about libstdc++ or is there an issue with clang? If the latter, can we try rebuilding them with g++ but linking libc++? gcc should support it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what I found with a quick search (CC=gcc and CMAKE_TARGET_TOOLCHAIN.*gcc):

Unclear why gcc is needed (sometimes it may be due to OpenMP runtime, but unclear just by reading the code):

Can probably be fixed by using LLVMOpenMP for OpenMP runtime:

Because of JuliaPackaging/Yggdrasil#7139 (they claim a newer SDK didn't help, without providing more information):

haskey(tags, "cxxlib") || add_tag!(tags, "cxxlib", "libstdcxx")
tag = "cxxlib_version"
elseif tag == "cxxstring_abi"
# Implies cxxlib=libstdcxx++ for compatibility
haskey(tags, "cxxlib") || add_tag!(tags, "cxxlib", "libstdcxx")
end

# Normalize things that are known to be version numbers so that comparisons are easy.
# Note that in our effort to be extremely compatible, we actually allow something that
# doesn't parse nicely into a VersionNumber to persist, but if `validate_strict` is
# set to `true`, it will cause an error later on.
if tag ∈ ("libgfortran_version", "libstdcxx_version", "os_version")
if tag ∈ ("libgfortran_version", "cxxlib_version", "os_version")
if isa(value, VersionNumber)
value = string(value)
elseif isa(value, String)
Expand All @@ -88,6 +99,10 @@ struct Platform <: AbstractPlatform
# Default to `glibc` on Linux
tags["libc"] = "glibc"
end
if os == "windows" && !haskey(tags, libc)
# Default to `msvcrt` on Windows
tags["libc"] = "msvcrt"
end
if os == "linux" && arch ∈ ("armv7l", "armv6l") && "call_abi" ∉ keys(tags)
# default `call_abi` to `eabihf` on 32-bit ARM
tags["call_abi"] = "eabihf"
Expand Down Expand Up @@ -217,6 +232,10 @@ function validate_tags(tags::Dict)
if tags["libc"] ∉ ("glibc", "musl")
throw_libc_mismatch()
end
elseif tags["os"] == "windows"
if tags["libc"] ∉ ("msvcrt", "ucrt")
throw_libc_mismatch()
end
else
# Nothing else is allowed to have a `libc` entry
if haskey(tags, "libc")
Expand Down Expand Up @@ -245,13 +264,13 @@ function validate_tags(tags::Dict)
end

# Validate `cxxstring_abi` is one of the two valid options:
if "cxxstring_abi" in keys(tags) && tags["cxxstring_abi"] ∉ ("cxx03", "cxx11")
if "cxxstring_abi" in keys(tags) && (tags["cxxstring_abi"] ∉ ("cxx03", "cxx11") || !haskey(tags, "cxxlib") || tags["cxxlib"] !== "libstdcxx")
throw_invalid_key("cxxstring_abi")
end

# Validate `libstdcxx_version` is a parsable `VersionNumber`
if "libstdcxx_version" in keys(tags) && tryparse(VersionNumber, tags["libstdcxx_version"]) === nothing
throw_version_number("libstdcxx_version")
if "cxxlib_version" in keys(tags) && tryparse(VersionNumber, tags["cxxlib_version"]) === nothing
throw_version_number("cxxlib_version")
end
end

Expand Down Expand Up @@ -331,8 +350,8 @@ function HostPlatform(p::AbstractPlatform)
if haskey(p, "os_version")
set_compare_strategy!(p, "os_version", compare_version_cap)
end
if haskey(p, "libstdcxx_version")
set_compare_strategy!(p, "libstdcxx_version", compare_version_cap)
if haskey(p, "cxxlib") && p["cxxlib"] == "libstdcxx" && haskey(p, "cxxlib_version")
set_compare_strategy!(p, "cxxlib_version", compare_version_cap)
end
return p
end
Expand Down Expand Up @@ -535,6 +554,10 @@ function triplet(p::AbstractPlatform)
if tag ∈ ("os", "arch", "libc", "call_abi", "libgfortran_version", "libstdcxx_version", "cxxstring_abi", "os_version")
continue
end
if tag == "cxxlib" && (cxxstring_abi(p) !== nothing || libstdcxx_version(p) !== nothing)
# Implied by above
continue
end
str = string(str, "-", tag, "+", val)
end
return str
Expand All @@ -551,7 +574,7 @@ function os_str(p::AbstractPlatform)
return "-apple-darwin"
end
elseif os(p) == "windows"
return "-w64-mingw32"
return "-w64"
elseif os(p) == "freebsd"
osvn = os_version(p)
if osvn !== nothing
Expand All @@ -573,6 +596,10 @@ function libc_str(p::AbstractPlatform)
return ""
elseif lc === "glibc"
return "-gnu"
elseif lc === "msvcrt"
return "-mingw32"
elseif lc === "ucrt"
return "-ucrt-mingw32"
else
return string("-", lc)
end
Expand Down Expand Up @@ -643,11 +670,13 @@ const os_mapping = Dict(
"macos" => "-apple-darwin[\\d\\.]*",
"freebsd" => "-(.*-)?freebsd[\\d\\.]*",
"openbsd" => "-(.*-)?openbsd[\\d\\.]*",
"windows" => "-w64-mingw32",
"windows" => "-w64",
"linux" => "-(.*-)?linux",
)
const libc_mapping = Dict(
"libc_nothing" => "",
"ucrt" => "-ucrt-mingw32",
"msvcrt" => "-mingw32", # We default to msvcrt for plain -mingw32 on Windows
"glibc" => "-gnu",
"musl" => "-musl",
)
Expand Down
11 changes: 8 additions & 3 deletions contrib/normalize_triplet.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@
'darwin': "-apple-darwin[\\d\\.]*",
'freebsd': "-(.*-)?freebsd[\\d\\.]*",
'openbsd': "-(.*-)?openbsd[\\d\\.]*",
'windows': "-w64-mingw32",
'windows': "-w64",
'linux': "-(.*-)?linux",
}
libc_mapping = {
'blank_libc': "",
'gnu': "-gnu",
'musl': "-musl",
'ucrt': "-ucrt-mingw32",
}
call_abi_mapping = {
'blank_call_abi': "",
Expand Down Expand Up @@ -88,14 +89,18 @@ def r(x):
x = x.replace("blank_call_abi", "")
x = x.replace("blank_libgfortran", "")
x = x.replace("blank_cxx_abi", "")
x = x.replace("blank_libc", "")
# We combine platform and libc below, since the windows mapping
# needs to know the platform for the correct default libc, so
# replace this one with `-` included.
x = x.replace("-blank_libc", "")
return x

def p(x):
# These contain characters that can't be easily represented as
# capture group names, unfortunately:
os_remapping = {
'darwin': 'apple-darwin',
'windows-ucrt': 'w64-ucrt-mingw32',
'windows': 'w64-mingw32',
'freebsd': 'unknown-freebsd',
'openbsd': 'unknown-openbsd',
Expand Down Expand Up @@ -141,7 +146,7 @@ def p(x):
"": "",
}[sys.argv[3]]

print(arch+p(platform)+p(libc)+r(call_abi)+p(libgfortran_version)+p(cxx_abi))
print(arch+p(platform+"-"+libc)+r(call_abi)+p(libgfortran_version)+p(cxx_abi))

# Testing suite:
# triplets="i686-w64-mingw32 x86_64-pc-linux-musl arm-linux-musleabihf x86_64-linux-gnu arm-linux-gnueabihf x86_64-apple-darwin14 x86_64-unknown-freebsd11.1"
Expand Down
15 changes: 8 additions & 7 deletions stdlib/Artifacts/test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,19 +130,20 @@ end
# Next, fuzz it out! Ensure that we exactly reconstruct our platforms!
platforms = Platform[]
for libgfortran_version in (v"3", v"4", v"5", nothing),
libstdcxx_version in (v"3.4.11", v"3.4.19", nothing),
cxxlib in ("libstdcxx",)
cxxlib_version in (v"3.4.11", v"3.4.19", nothing),
cxxstring_abi in ("cxx03", "cxx11", nothing)

for arch in ("x86_64", "i686", "aarch64", "armv7l"),
libc in ("glibc", "musl")

push!(platforms, Platform(arch, "linux"; libc, libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform(arch, "linux"; libc, libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
end
push!(platforms, Platform("x86_64", "windows"; libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform("i686", "windows"; libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform("x86_64", "macOS"; libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform("aarch64", "macOS"; libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform("x86_64", "FreeBSD"; libgfortran_version, libstdcxx_version, cxxstring_abi))
push!(platforms, Platform("x86_64", "windows"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
push!(platforms, Platform("i686", "windows"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
push!(platforms, Platform("x86_64", "macOS"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
push!(platforms, Platform("aarch64", "macOS"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
push!(platforms, Platform("x86_64", "FreeBSD"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi))
end

for p in platforms
Expand Down
9 changes: 5 additions & 4 deletions test/binaryplatforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ P(args...; kwargs...) = Platform(args...; validate_strict=true, kwargs...)
@test_throws ArgumentError P("armv6l", "linux"; call_abi="kekeke")
@test_throws ArgumentError P("armv6l", "linux"; libgfortran_version="lel")
@test_throws ArgumentError P("x86_64", "linux"; cxxstring_abi="lel")
@test_throws ArgumentError P("x86_64", "windows"; libstdcxx_version="lel")
@test_throws ArgumentError P("x86_64", "windows"; cxxlib_version="lel")
@test_throws ArgumentError P("i686", "macos")
@test_throws ArgumentError P("x86_64", "macos"; libc="glibc")
@test_throws ArgumentError P("x86_64", "macos"; call_abi="eabihf")
Expand Down Expand Up @@ -183,7 +183,7 @@ end
@test R("x86_64-linux-gnu-gcc4-cxx11") == P("x86_64", "linux"; libgfortran_version=v"3", cxxstring_abi="cxx11")
@test R("x86_64-linux-gnu-cxx11") == P("x86_64", "linux"; cxxstring_abi="cxx11")
@test R("x86_64-linux-gnu-libgfortran3-cxx03") == P("x86_64", "linux"; libgfortran_version=v"3", cxxstring_abi="cxx03")
@test R("x86_64-linux-gnu-libstdcxx26") == P("x86_64", "linux"; libstdcxx_version=v"3.4.26")
@test R("x86_64-linux-gnu-libstdcxx26") == P("x86_64", "linux"; cxxlib="libstdcxx", cxxlib_version=v"3.4.26")

@test_throws ArgumentError R("totally FREEFORM text!!1!!!1!")
@test_throws ArgumentError R("invalid-triplet-here")
Expand All @@ -210,10 +210,11 @@ end
# Just do a quick combinatorial sweep for completeness' sake for platform matching
linux = P("x86_64", "linux")
for libgfortran_version in (nothing, v"3", v"5"),
libstdcxx_version in (nothing, v"3.4.18", v"3.4.26"),
cxxlib in ("libstdcxx",),
cxxlib_version in (nothing, v"3.4.18", v"3.4.26"),
cxxstring_abi in (nothing, :cxx03, :cxx11)

p = P("x86_64", "linux"; libgfortran_version, libstdcxx_version, cxxstring_abi)
p = P("x86_64", "linux"; libgfortran_version, cxxlib, cxxlib_version, cxxstring_abi)
@test platforms_match(linux, p)
@test platforms_match(p, linux)

Expand Down