Skip to content

Commit a483e67

Browse files
committed
Consider OS version when matching artifacts to platforms
We currently largely ignore OS version, and for most platforms that doesn't really matter. But binaries built for a particular FreeBSD version are forward- but not backward-compatible with other FreeBSD versions, and that isn't accounted for when choosing artifacts. That means that whenever the FreeBSD version used in the RootFS is bumped, entries in Artifacts.toml corresponding to older versions need to be manually deleted so they don't get chosen instead. More care is needed here than I had anticipated, as `platforms_match` has documented but unfortunate behavior when both arguments have `compare_version_cap` set for their `os_version` comparison strategies. The function assumes that this case occurs only when both arguments are host platforms, and it compares their versions using `==`. That strategy is set explicitly for `CompilerShard` targets with a comment about treating the OS version as a bound, except it doesn't act as a bound as such if the comparator is e.g. `HostPlatform()`.
1 parent c925b84 commit a483e67

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

src/Platforms.jl

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,33 @@ nbits(::AnyPlatform) = nbits(default_host_platform)
1919
proc_family(::AnyPlatform) = "any"
2020
Base.show(io::IO, ::AnyPlatform) = print(io, "AnyPlatform")
2121

22+
function _agnostic(p::Platform, keeps)
23+
filtered_tags = (Symbol(k) => convert(String, v) for (k, v) in tags(p) if k keeps)
24+
return Platform(arch(p)::String, os(p)::String; filtered_tags...)
25+
end
26+
_agnostic(p::AnyPlatform, _) = p
27+
2228
"""
2329
abi_agnostic(p::AbstractPlatform)
2430
2531
Strip out any tags that are not the basic annotations like `libc` and `call_abi`.
2632
"""
27-
function abi_agnostic(p::Platform)
28-
keeps = ("libc", "call_abi", "os_version")
29-
filtered_tags = Dict{Symbol,String}(Symbol(k) => v for (k, v) in tags(p) if k keeps)
30-
return Platform(arch(p)::String, os(p)::String; filtered_tags...)
31-
end
32-
abi_agnostic(p::AnyPlatform) = p
33+
abi_agnostic(p::AbstractPlatform) = _agnostic(p, ("libc", "call_abi", "os_version"))
3334

3435
"""
35-
abi_agnostic(p::AbstractPlatform)
36+
libabi_agnostic(p::AbstractPlatform)
3637
3738
Like `abi_agnostic`, but keep the sanitizer ABI tags.
3839
"""
39-
function libabi_agnostic(p::Platform)
40-
keeps = ("libc", "call_abi", "os_version", "sanitize")
41-
filtered_tags = Dict{Symbol,String}(Symbol(k) => v for (k, v) in tags(p) if k keeps)
42-
return Platform(arch(p)::String, os(p)::String; filtered_tags...)
43-
end
40+
libabi_agnostic(p::AbstractPlatform) = _agnostic(p, ("libc", "call_abi", "os_version", "sanitize"))
41+
42+
"""
43+
os_version_agnostic(p::AbstractPlatform)
44+
45+
Strip out an `os_version` tag if it exists.
46+
"""
47+
os_version_agnostic(p::AbstractPlatform) =
48+
_agnostic(p, filter(!in(("arch", "os", "os_version")), keys(tags(p))))
4449

4550
platforms_match_with_sanitize(a::AbstractPlatform, b::AbstractPlatform) =
4651
platforms_match(a, b) && sanitize(a) == sanitize(b)

src/Rootfs.jl

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,28 @@ function Base.:(==)(a::CompilerShard, b::CompilerShard)
5959
a.archive_type == b.archive_type
6060
end
6161

62+
# For a `CompilerShard` to match a `Platform`, the shard's target with OS version stripped
63+
# must match, and the OS version if present must be less than or equal to the platform's.
64+
# This is effectively `platforms_match` with a `compare_version_cap` comparison strategy for
65+
# OS version, except it works "correctly" (IMO) when both arguments have that strategy set.
66+
# It also ignores any strategy that's set.
67+
function Base.BinaryPlatforms.platforms_match(cs::CompilerShard, p::AbstractPlatform)
68+
if cs.target === nothing
69+
return platforms_match(cs.host, p)
70+
elseif !platforms_match(os_version_agnostic(cs.target), os_version_agnostic(p))
71+
return false
72+
else
73+
sv = os_version(cs.target)
74+
pv = os_version(p)
75+
return sv === nothing || pv === nothing || pv >= sv
76+
end
77+
end
78+
79+
Base.BinaryPlatforms.platforms_match(p::AbstractPlatform, cs::CompilerShard) = platforms_match(cs, p)
80+
81+
Base.BinaryPlatforms.platforms_match(a::CompilerShard, b::CompilerShard) =
82+
platforms_match(something(a.target, a.host), something(b.target, b.host))
83+
6284
"""
6385
artifact_name(cs::CompilerShard)
6486
@@ -606,7 +628,7 @@ function choose_shards(p::AbstractPlatform;
606628

607629
for cs in all_compiler_shards()
608630
if cs.name == name && cs.version == version &&
609-
(target === nothing || platforms_match(cs.target, target)) &&
631+
(target === nothing || platforms_match(cs, target)) &&
610632
cs.archive_type == archive_type
611633
return cs
612634
end
@@ -711,7 +733,7 @@ function choose_shards(p::AbstractPlatform;
711733
else
712734
function find_latest_version(name)
713735
versions = [cs.version for cs in all_compiler_shards()
714-
if cs.name == name && cs.archive_type == archive_type && platforms_match(something(cs.target, p), p)
736+
if cs.name == name && cs.archive_type == archive_type && platforms_match(cs, p)
715737
]
716738
isempty(versions) && error("No latest shard found for $name")
717739
return maximum(versions)
@@ -770,8 +792,8 @@ function supported_platforms(;exclude::Union{Vector{<:Platform},Function}=Return
770792
# BSDs
771793
Platform("x86_64", "macos"),
772794
Platform("aarch64", "macos"),
773-
Platform("x86_64", "freebsd"),
774-
Platform("aarch64", "freebsd"),
795+
Platform("x86_64", "freebsd"; os_version="13.2"),
796+
Platform("aarch64", "freebsd"; os_version="13.2"),
775797

776798
# Windows
777799
Platform("i686", "windows"),

0 commit comments

Comments
 (0)