Skip to content

Commit 0396263

Browse files
committed
Add the concept of a top-level dependency
1 parent 6b66193 commit 0396263

File tree

2 files changed

+55
-12
lines changed

2 files changed

+55
-12
lines changed

src/Dependencies.jl

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using UUIDs
22

33
export Dependency, RuntimeDependency, BuildDependency, HostBuildDependency,
4-
is_host_dependency, is_target_dependency, is_build_dependency, is_runtime_dependency,
4+
is_host_dependency, is_target_dependency, is_build_dependency, is_runtime_dependency, is_top_level_dependency,
55
filter_platforms
66

77

@@ -32,6 +32,7 @@ Subtypes of `AbstractDependency` should define the following traits:
3232
* [`is_target_dependency`](@ref)
3333
* [`is_build_dependency`](@ref)
3434
* [`is_runtime_dependency`](@ref)
35+
* [`is_top_level_dependency`][@ref]
3536
"""
3637
abstract type AbstractDependency end
3738

@@ -63,6 +64,13 @@ Return whether `dep` is a runtime dependency or not.
6364
"""
6465
is_runtime_dependency
6566

67+
"""
68+
is_top_level_dependency(dep::AbstractDependency) ->
69+
70+
Return wheter `dep` is a top-level dependency or not.
71+
"""
72+
is_top_level_dependency(dep::AbstractDependency) = false
73+
6674
"""
6775
Dependency(dep::Union{PackageSpec,String}, build_version::VersionNumber;
6876
compat::String, platforms::Vector{<:AbstractPlatform})
@@ -86,14 +94,24 @@ The optional keyword argument `platforms` is a vector of `AbstractPlatform`s
8694
which indicates for which platforms the dependency should be used. By default
8795
`platforms=[AnyPlatform()]`, to mean that the dependency is compatible with all
8896
platforms.
97+
98+
The optional keyword argument `top_level` denotates that this dependency is
99+
platform independent. It implies that the `platforms` keyword argument is set
100+
to `[AnyPlatform()]`. The primary use-case is for packages that hold information
101+
about the platform selection using `Preferences`. Platform selection is cached
102+
and in the case that no platform is available we need to be able to invalidate
103+
said cache. Invalidation occurs through the package that owns the `Preferences`
104+
data.
89105
"""
90106
struct Dependency <: AbstractDependency
91107
pkg::PkgSpec
92108
build_version::Union{VersionNumber,Nothing}
93109
compat::String # semver string for use in Project.toml of the JLL
94110
platforms::Vector{<:AbstractPlatform}
111+
top_level::Bool
95112
function Dependency(pkg::PkgSpec, build_version = nothing; compat::String = "",
96-
platforms::Vector{<:AbstractPlatform}=[AnyPlatform()])
113+
platforms::Vector{<:AbstractPlatform}=[AnyPlatform()],
114+
top_level=false)
97115
if !isempty(compat)
98116
spec = PKG_VERSIONS.semver_spec(compat) # verify compat is valid
99117
if build_version === nothing
@@ -109,16 +127,24 @@ struct Dependency <: AbstractDependency
109127
throw(ArgumentError("PackageSpec version and compat for $(pkg) are incompatible"))
110128
end
111129
end
112-
new(pkg, build_version, compat, platforms)
130+
if top_level
131+
if !(isempty(platforms) || all(p->p==AnyPlatform(), platforms))
132+
throw(ArgumentError("A top-level dependency can't be restricted to platforms."))
133+
end
134+
end
135+
new(pkg, build_version, compat, platforms, top_level)
113136
end
114137
end
115138
function Dependency(dep::AbstractString, build_version = nothing;
116-
compat::String = "", platforms::Vector{<:AbstractPlatform}=[AnyPlatform()])
117-
return Dependency(PackageSpec(; name = dep), build_version; compat, platforms)
139+
compat::String = "",
140+
platforms::Vector{<:AbstractPlatform} = [AnyPlatform()],
141+
top_level = false)
142+
return Dependency(PackageSpec(; name = dep), build_version; compat, platforms, top_level)
118143
end
119144
is_host_dependency(::Dependency) = false
120145
is_build_dependency(::Dependency) = true
121146
is_runtime_dependency(::Dependency) = true
147+
is_top_level_dependency(dep::Dependency) = dep.top_level
122148

123149
"""
124150
RuntimeDependency(dep::Union{PackageSpec,String}; compat::String, platforms::Vector{<:AbstractPlatform})
@@ -310,6 +336,7 @@ for (type, type_descr) in ((Dependency, "dependency"), (RuntimeDependency, "runt
310336
"version-minor" => minor(version(d)),
311337
"version-patch" => patch(version(d)),
312338
"platforms" => triplet.(d.platforms),
339+
"top_level" => is_top_level_dependency(d),
313340
)
314341
end
315342

@@ -324,8 +351,9 @@ function dependencify(d::Dict)
324351
version = version == PKG_VERSIONS.VersionSpec(v"0") ? PKG_VERSIONS.VersionSpec() : version
325352
spec = PackageSpec(; name = d["name"], uuid = uuid, version = version)
326353
platforms = parse_platform.(d["platforms"])
354+
top_level = d["top_level"]::Bool
327355
if d["type"] == "dependency"
328-
return Dependency(spec; compat, platforms)
356+
return Dependency(spec; compat, platforms, top_level)
329357
elseif d["type"] == "runtimedependency"
330358
return RuntimeDependency(spec; compat, platforms)
331359
elseif d["type"] == "builddependency"

test/dependencies.jl

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ end
2525
@test is_target_dependency(dep)
2626
@test is_build_dependency(dep)
2727
@test is_runtime_dependency(dep)
28+
@test !is_top_level_dependency(dep)
2829
@test getname(dep) == name
2930
@test getname(PackageSpec(; name = name)) == name
3031
@test getpkg(dep) == PackageSpec(; name = name)
@@ -60,6 +61,7 @@ end
6061
@test is_target_dependency(run_dep)
6162
@test !is_build_dependency(run_dep)
6263
@test is_runtime_dependency(run_dep)
64+
@test !is_top_level_dependency(run_dep)
6365
@test getname(run_dep) == name
6466
@test getname(PackageSpec(; name)) == name
6567
@test getpkg(run_dep) == PackageSpec(; name)
@@ -76,6 +78,7 @@ end
7678
@test is_target_dependency(build_dep)
7779
@test is_build_dependency(build_dep)
7880
@test !is_runtime_dependency(build_dep)
81+
@test !is_top_level_dependency(build_dep)
7982
@test getname(build_dep) == build_name
8083
@test getname(PackageSpec(; name = build_name)) == build_name
8184
@test getpkg(build_dep) == PackageSpec(; name = build_name)
@@ -87,42 +90,54 @@ end
8790
@test !is_target_dependency(host_dep)
8891
@test is_build_dependency(host_dep)
8992
@test !is_runtime_dependency(host_dep)
93+
@test !is_top_level_dependency(host_dep)
9094
@test getname(host_dep) == host_name
9195
@test getname(PackageSpec(; name = host_name)) == host_name
9296
@test getpkg(host_dep) == PackageSpec(; name = host_name)
9397

98+
top_level_name = "MPIPreferences"
99+
@test_throws ArgumentError Dependency(PackageSpec(; name = top_level_name); platforms=supported_platforms(; experimental=true, exclude=!Sys.isapple),
100+
top_level=true)
101+
102+
top_level_dep = Dependency(PackageSpec(; name = top_level_name); top_level=true)
103+
@test is_top_level_dependency(top_level_dep)
104+
94105
@testset "Filter dependencies by platform" begin
95106
@test filter_platforms([dep, dep_buildver, dep_compat], Platform("x86_64", "linux"; cxxstring_abi="cxx03")) == [dep_compat]
96107
@test filter_platforms([dep, dep_buildver, dep_compat], Platform("x86_64", "macos")) == [dep, dep_compat]
97108
end
98109

99110
@testset "JSON (de)serialization" begin
100111
jdep = JSON.lower(dep)
101-
@test jdep == Dict("type" => "dependency", "name" => name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["x86_64-apple-darwin", "aarch64-apple-darwin"])
112+
@test jdep == Dict("type" => "dependency", "name" => name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["x86_64-apple-darwin", "aarch64-apple-darwin"], "top_level" => false)
102113
@test dependencify(jdep) == dep
103114

104115
jrun_dep = JSON.lower(run_dep)
105-
@test jrun_dep == Dict("type" => "runtimedependency", "name" => name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"])
116+
@test jrun_dep == Dict("type" => "runtimedependency", "name" => name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"], "top_level" => false)
106117
@test dependencify(jrun_dep) == run_dep
107118

108119
jdep_buildver = JSON.lower(dep_buildver)
109-
@test jdep_buildver == Dict("type" => "dependency", "name" => name, "uuid" => nothing, "compat" => "~1.2", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["x86_64-linux-gnu-cxx11"])
120+
@test jdep_buildver == Dict("type" => "dependency", "name" => name, "uuid" => nothing, "compat" => "~1.2", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["x86_64-linux-gnu-cxx11"], "top_level" => false)
110121
# the build_version is currently not serialized, so the following test fails
111122
@test dependencify(jdep_buildver) == dep_buildver broken=true
112123

113124
jbuild_dep = JSON.lower(build_dep)
114-
@test jbuild_dep == Dict("type" => "builddependency", "name" => build_name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"])
125+
@test jbuild_dep == Dict("type" => "builddependency", "name" => build_name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"], "top_level" => false)
115126
@test dependencify(jbuild_dep) == build_dep
116127

117128
jhost_dep = JSON.lower(host_dep)
118-
@test jhost_dep == Dict("type" => "hostdependency", "name" => host_name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"])
129+
@test jhost_dep == Dict("type" => "hostdependency", "name" => host_name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"], "top_level" => false)
119130
@test dependencify(jhost_dep) == host_dep
120131

121132
full_dep = Dependency(PackageSpec(; name = "Baz_jll", uuid = "00000000-1111-2222-3333-444444444444", version = PKG_VERSIONS.VersionSpec("3.1.4")))
122133
jfull_dep = JSON.lower(full_dep)
123-
@test jfull_dep == Dict("type" => "dependency", "name" => "Baz_jll", "uuid" => "00000000-1111-2222-3333-444444444444", "compat" => "", "version-major" => 0x3, "version-minor" => 0x1, "version-patch" => 0x4, "platforms" => ["any"])
134+
@test jfull_dep == Dict("type" => "dependency", "name" => "Baz_jll", "uuid" => "00000000-1111-2222-3333-444444444444", "compat" => "", "version-major" => 0x3, "version-minor" => 0x1, "version-patch" => 0x4, "platforms" => ["any"], "top_level" => false)
124135
@test dependencify(jfull_dep) == full_dep
125136
@test_throws ErrorException dependencify(Dict("type" => "git"))
137+
138+
jtop_level_dep = JSON.lower(top_level_dep)
139+
@test jtop_level_dep == Dict("type" => "dependency", "name" => "MPIPreferences", "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"], "top_level" => true)
140+
@test dependencify(jtop_level_dep) == top_level_dep
126141
end
127142

128143
@testset "Setup" begin

0 commit comments

Comments
 (0)