diff --git a/Make.inc b/Make.inc index a3543a5e276f0..0baac4c8d8da6 100644 --- a/Make.inc +++ b/Make.inc @@ -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 diff --git a/base/binaryplatforms.jl b/base/binaryplatforms.jl index c2f019c4d4eea..6c4c4cfb362e3 100644 --- a/base/binaryplatforms.jl +++ b/base/binaryplatforms.jl @@ -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" + 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) @@ -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" @@ -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") @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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", ) diff --git a/contrib/normalize_triplet.py b/contrib/normalize_triplet.py index 833b725480996..17fc5dab55657 100755 --- a/contrib/normalize_triplet.py +++ b/contrib/normalize_triplet.py @@ -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': "", @@ -88,7 +89,10 @@ 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): @@ -96,6 +100,7 @@ def p(x): # capture group names, unfortunately: os_remapping = { 'darwin': 'apple-darwin', + 'windows-ucrt': 'w64-ucrt-mingw32', 'windows': 'w64-mingw32', 'freebsd': 'unknown-freebsd', 'openbsd': 'unknown-openbsd', @@ -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" diff --git a/stdlib/Artifacts/test/runtests.jl b/stdlib/Artifacts/test/runtests.jl index cb81c16347abf..5cdf6ed9ebd31 100644 --- a/stdlib/Artifacts/test/runtests.jl +++ b/stdlib/Artifacts/test/runtests.jl @@ -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 diff --git a/test/binaryplatforms.jl b/test/binaryplatforms.jl index 8de522e9c6c8b..501abf5eec0a2 100644 --- a/test/binaryplatforms.jl +++ b/test/binaryplatforms.jl @@ -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") @@ -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") @@ -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)