Skip to content

Commit 871eb95

Browse files
authored
[Dependencies] Define new RuntimeDependency (#249)
1 parent 8f84f3a commit 871eb95

File tree

3 files changed

+74
-6
lines changed

3 files changed

+74
-6
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "BinaryBuilderBase"
22
uuid = "7f725544-6523-48cd-82d1-3fa08ff4056e"
33
authors = ["Elliot Saba <[email protected]>"]
4-
version = "1.11.0"
4+
version = "1.12.0"
55

66
[deps]
77
CodecZlib = "944b1d66-785c-5afd-91f1-9de20f533193"

src/Dependencies.jl

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

3-
export Dependency, BuildDependency, HostBuildDependency,
3+
export Dependency, RuntimeDependency, BuildDependency, HostBuildDependency,
44
is_host_dependency, is_target_dependency, is_build_dependency, is_runtime_dependency,
55
filter_platforms
66

@@ -18,11 +18,20 @@ Concrete subtypes of `AbstractDependency` are
1818
1919
* [`Dependency`](@ref): a JLL package that is necessary for to build the package
2020
and to load the generated JLL package.
21+
* [`RuntimeDependency`](@ref): a JLL package that is necessary only at runtime. Its
22+
artifact will not be installed in the prefix during the build.
2123
* [`BuildDependency`](@ref): a JLL package that is necessary only to build the
2224
package. This will not be a dependency of the generated JLL package.
2325
* [`HostBuildDependency`](@ref): similar to `BuildDependency`, but it will
2426
install the artifact for the host platform, instead of that for the target
2527
platform.
28+
29+
Subtypes of `AbstractDependency` should define the following traits:
30+
31+
* [`is_host_dependency`](@ref)
32+
* [`is_target_dependency`](@ref)
33+
* [`is_build_dependency`](@ref)
34+
* [`is_runtime_dependency`](@ref)
2635
"""
2736
abstract type AbstractDependency end
2837

@@ -81,7 +90,7 @@ struct Dependency <: AbstractDependency
8190
platforms::Vector{<:AbstractPlatform}
8291
function Dependency(pkg::PkgSpec, build_version = nothing; compat::String = "",
8392
platforms::Vector{<:AbstractPlatform}=[AnyPlatform()])
84-
if length(compat) > 0
93+
if !isempty(compat)
8594
spec = PKG_VERSIONS.semver_spec(compat) # verify compat is valid
8695
if build_version === nothing
8796
# Since we usually want to build against the oldest compatible
@@ -107,6 +116,44 @@ is_host_dependency(::Dependency) = false
107116
is_build_dependency(::Dependency) = true
108117
is_runtime_dependency(::Dependency) = true
109118

119+
"""
120+
RuntimeDependency(dep::Union{PackageSpec,String}; compat::String, platforms::Vector{<:AbstractPlatform})
121+
122+
Define a binary dependency that is only listed as dependency of the generated JLL package,
123+
but its artifact is not installed in the prefix during the build. The `dep` argument can be
124+
either a string with the name of the JLL package or a `Pkg.PackageSpec`.
125+
126+
The optional keyword argument `compat` can be used to specify a string for use
127+
in the `Project.toml` of the generated Julia package.
128+
129+
The optional keyword argument `platforms` is a vector of `AbstractPlatform`s which indicates
130+
for which platforms the dependency should be used. By default `platforms=[AnyPlatform()]`,
131+
to mean that the dependency is compatible with all platforms.
132+
"""
133+
struct RuntimeDependency <: AbstractDependency
134+
pkg::PkgSpec
135+
compat::String # semver string for use in Project.toml of the JLL
136+
platforms::Vector{<:AbstractPlatform}
137+
function RuntimeDependency(pkg::PkgSpec; compat::String = "",
138+
platforms::Vector{<:AbstractPlatform}=[AnyPlatform()])
139+
if !isempty(compat)
140+
spec = PKG_VERSIONS.semver_spec(compat) # verify compat is valid
141+
if pkg.version != PKG_VERSIONS.VersionSpec("*") && !(pkg.version in spec)
142+
throw(ArgumentError("PackageSpec version and compat for $(pkg) are incompatible"))
143+
end
144+
end
145+
return new(pkg, compat, platforms)
146+
end
147+
end
148+
RuntimeDependency(name::AbstractString; compat::String = "", platforms::Vector{<:AbstractPlatform}=[AnyPlatform()]) =
149+
RuntimeDependency(PackageSpec(; name); compat, platforms)
150+
is_host_dependency(::RuntimeDependency) = false
151+
is_build_dependency(::RuntimeDependency) = false
152+
is_runtime_dependency(::RuntimeDependency) = true
153+
# In some cases we may want to automatically convert a `RuntimeDependency` to a `Dependency`
154+
Base.convert(::Type{Dependency}, dep::RuntimeDependency) =
155+
Dependency(dep.pkg; compat=dep.compat, platforms=dep.platforms)
156+
110157
"""
111158
BuildDependency(dep::Union{PackageSpec,String}; platforms)
112159
@@ -250,7 +297,7 @@ version(d::Dependency) = __version(d.pkg.version)
250297
getcompat(d::AbstractDependency) = ""
251298
getcompat(d::Dependency) = d.compat
252299

253-
for (type, type_descr) in ((Dependency, "dependency"), (BuildDependency, "builddependency"), (HostBuildDependency, "hostdependency"))
300+
for (type, type_descr) in ((Dependency, "dependency"), (RuntimeDependency, "runtimedependency"), (BuildDependency, "builddependency"), (HostBuildDependency, "hostdependency"))
254301
JSON.lower(d::type) = Dict("type" => type_descr,
255302
"name" => d.pkg.name,
256303
"uuid" => string_or_nothing(d.pkg.uuid),
@@ -266,7 +313,7 @@ end
266313
# dictionaries. This function converts the dictionary back to the appropriate
267314
# AbstractDependency.
268315
function dependencify(d::Dict)
269-
if d["type"] in ("dependency", "builddependency", "hostdependency")
316+
if d["type"] in ("dependency", "runtimedependency", "builddependency", "hostdependency")
270317
uuid = isnothing(d["uuid"]) ? d["uuid"] : UUID(d["uuid"])
271318
compat = d["compat"]
272319
version = PKG_VERSIONS.VersionSpec(VersionNumber(d["version-major"], d["version-minor"], d["version-patch"]))
@@ -275,6 +322,8 @@ function dependencify(d::Dict)
275322
platforms = parse_platform.(d["platforms"])
276323
if d["type"] == "dependency"
277324
return Dependency(spec; compat, platforms)
325+
elseif d["type"] == "runtimedependency"
326+
return RuntimeDependency(spec; compat, platforms)
278327
elseif d["type"] == "builddependency"
279328
return BuildDependency(spec; platforms)
280329
elseif d["type"] == "hostdependency"

test/dependencies.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,22 @@ end
5151
@test getcompat(dep_compat) == "2, ~$(build_version)"
5252

5353
# if build_version and compat don't match, an error should be thrown
54-
@test_throws ArgumentError Dependency(PackageSpec(; name = name), build_version, compat = "2.0")
54+
@test_throws ArgumentError Dependency(PackageSpec(; name = name), build_version; compat = "2.0")
55+
56+
run_dep = RuntimeDependency(PackageSpec(; name))
57+
@test RuntimeDependency(name) == run_dep
58+
@test !is_host_dependency(run_dep)
59+
@test is_target_dependency(run_dep)
60+
@test !is_build_dependency(run_dep)
61+
@test is_runtime_dependency(run_dep)
62+
@test getname(run_dep) == name
63+
@test getname(PackageSpec(; name)) == name
64+
@test getpkg(run_dep) == PackageSpec(; name)
65+
# We should be able to convert a `Vector{RuntimeDependency}` to `Vector{Dependency}`
66+
@test Dependency[RuntimeDependency(name; compat="~1.8", platforms=[Platform("aarch64", "macos"; cxxstring_abi="cxx03")])] ==
67+
[Dependency(name; compat="~1.8", platforms=[Platform("aarch64", "macos"; cxxstring_abi="cxx03")])]
68+
# If the version in the PackageSpec and the compat don't match, an error should be thrown
69+
@test_throws ArgumentError RuntimeDependency(PackageSpec(; name, version=v"1.2.3"); compat = "2.0")
5570

5671
build_name = "Foo_headers_jll"
5772
build_dep = BuildDependency(PackageSpec(; name = build_name))
@@ -85,6 +100,10 @@ end
85100
@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"])
86101
@test dependencify(jdep) == dep
87102

103+
jrun_dep = JSON.lower(run_dep)
104+
@test jrun_dep == Dict("type" => "runtimedependency", "name" => name, "uuid" => nothing, "compat" => "", "version-major" => 0x0, "version-minor" => 0x0, "version-patch" => 0x0, "platforms" => ["any"])
105+
@test dependencify(jrun_dep) == run_dep
106+
88107
jdep_buildver = JSON.lower(dep_buildver)
89108
@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"])
90109
# the build_version is currently not serialized, so the following test fails

0 commit comments

Comments
 (0)