Skip to content

Commit 2d68c43

Browse files
authored
Move part of autobuild() into new get_meta_json() helper (#872)
The two new functions have similar but not identical signature; this change means that we don't have to pass things to autobuild() which are not needed for building, but rather just for the meta JSON; and vice versa.
1 parent 056dc62 commit 2d68c43

File tree

3 files changed

+166
-156
lines changed

3 files changed

+166
-156
lines changed

src/AutoBuild.jl

Lines changed: 64 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export build_tarballs, autobuild, print_artifacts_toml, build
1+
export build_tarballs, autobuild, print_artifacts_toml, build, get_meta_json
22
import GitHub: gh_get_json, DEFAULT_API
33
import SHA: sha256, sha1
44
using Pkg.TOML, Dates, UUIDs
@@ -83,10 +83,14 @@ see what it can do, you can call it with `--help` in the `ARGS` or see the
8383
[Command Line](@ref) section in the manual.
8484
8585
The `kwargs` are passed on to [`autobuild`](@ref), see there for a list of
86-
supported ones. In addition, the keyword argument `init_block` may be set to
87-
a string containing Julia code; if present, this code will be inserted into
88-
the initialization path of the generated JLL package. This can for example be
89-
used to invoke an initialization API of a shared library.
86+
supported ones. A few additional keyword arguments are accept:
87+
88+
* `lazy_artifacts` sets whether the artifacts should be lazy.
89+
90+
* `init_block` may be set to a string containing Julia code; if present, this
91+
code will be inserted into the initialization path of the generated JLL
92+
package. This can for example be used to invoke an initialization API of a
93+
shared library.
9094
9195
!!! note
9296
@@ -202,11 +206,7 @@ function build_tarballs(ARGS, src_name, src_version, sources, script,
202206
end
203207
end
204208

205-
# Build the given platforms using the given sources
206-
build_output_meta = autobuild(
207-
# Controls output product placement, mount directory placement, etc...
208-
pwd(),
209-
209+
args = (
210210
# Source information
211211
src_name,
212212
src_version,
@@ -222,17 +222,34 @@ function build_tarballs(ARGS, src_name, src_version, sources, script,
222222
products,
223223

224224
# Dependencies that must be downloaded
225-
dependencies;
226-
227-
# Flags
228-
verbose=verbose,
229-
debug=debug,
230-
meta_json_stream=meta_json_stream,
231-
kwargs...,
225+
dependencies,
232226
)
233227

234-
if meta_json_stream !== nothing && meta_json_stream !== stdout
235-
close(meta_json_stream)
228+
if meta_json_stream !== nothing
229+
# If they've asked for the JSON metadata, by all means, give it to them!
230+
dict = get_meta_json(args...;
231+
lazy_artifacts = lazy_artifacts,
232+
init_block = init_block)
233+
println(meta_json_stream, JSON.json(dict))
234+
235+
if meta_json_stream !== stdout
236+
close(meta_json_stream)
237+
end
238+
239+
build_output_meta = Dict()
240+
else
241+
# Build the given platforms using the given sources
242+
build_output_meta = autobuild(
243+
# Controls output product placement, mount directory placement, etc...
244+
pwd(),
245+
246+
args...;
247+
248+
# Flags
249+
verbose=verbose,
250+
debug=debug,
251+
kwargs...,
252+
)
236253
end
237254

238255
if deploy_jll
@@ -468,6 +485,34 @@ function register_jll(name, build_version, dependencies;
468485
end
469486
end
470487

488+
function get_meta_json(
489+
src_name::AbstractString,
490+
src_version::VersionNumber,
491+
sources::Vector{<:AbstractSource},
492+
script::AbstractString,
493+
platforms::Vector,
494+
products::Vector{<:Product},
495+
dependencies::Vector{<:AbstractDependency};
496+
lazy_artifacts::Bool = false,
497+
init_block::String = "")
498+
499+
dict = Dict(
500+
"name" => src_name,
501+
"version" => "v$(src_version)",
502+
"sources" => sources,
503+
"script" => script,
504+
"products" => products,
505+
"dependencies" => dependencies,
506+
"lazy_artifacts" => lazy_artifacts,
507+
"init_block" => init_block,
508+
)
509+
# Do not write the list of platforms when building only for `AnyPlatform`
510+
if platforms != [AnyPlatform()]
511+
dict["platforms"] = triplet.(platforms)
512+
end
513+
return dict
514+
end
515+
471516
"""
472517
autobuild(dir::AbstractString, src_name::AbstractString,
473518
src_version::VersionNumber, sources::Vector,
@@ -518,11 +563,6 @@ here are the relevant actors, broken down in brief:
518563
519564
* `require_license` enables a special audit pass that requires licenses to be
520565
installed by all packages.
521-
522-
* `lazy_artifacts` sets whether the artifacts should be lazy.
523-
524-
* `meta_json_stream`: If this is set to an IOStream, do not actually build, just
525-
output a JSON representation of all the metadata about this build to the stream.
526566
"""
527567
function autobuild(dir::AbstractString,
528568
src_name::AbstractString,
@@ -539,30 +579,8 @@ function autobuild(dir::AbstractString,
539579
autofix::Bool = true,
540580
code_dir::Union{String,Nothing} = nothing,
541581
require_license::Bool = true,
542-
lazy_artifacts::Bool = false,
543-
init_block::String = "",
544-
meta_json_stream = nothing,
545582
kwargs...)
546583
@nospecialize
547-
# If they've asked for the JSON metadata, by all means, give it to them!
548-
if meta_json_stream !== nothing
549-
dict = Dict(
550-
"name" => src_name,
551-
"version" => "v$(src_version)",
552-
"sources" => sources,
553-
"script" => script,
554-
"products" => products,
555-
"dependencies" => dependencies,
556-
"lazy_artifacts" => lazy_artifacts,
557-
"init_block" => init_block,
558-
)
559-
# Do not write the list of platforms when building only for `AnyPlatform`
560-
if platforms != [AnyPlatform()]
561-
dict["platforms"] = triplet.(platforms)
562-
end
563-
println(meta_json_stream, JSON.json(dict))
564-
return Dict()
565-
end
566584

567585
# If we're on CI and we're not verbose, schedule a task to output a "." every few seconds
568586
if (haskey(ENV, "TRAVIS") || haskey(ENV, "CI")) && !verbose

test/declarative.jl

Lines changed: 96 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,122 +3,114 @@ using JSON, BinaryBuilder, Test
33
import BinaryBuilder.BinaryBuilderBase: sourcify, dependencify, major, minor, patch, version
44

55
@testset "Meta JSON" begin
6-
mktempdir() do tmpdir
6+
meta_json_buff = IOBuffer()
7+
8+
# Run autobuild() a few times to generate a moderately complex `meta.json`:
9+
dict = get_meta_json(
10+
"libfoo",
11+
v"1.0.0",
12+
[FileSource("https://julialang.org", "123123"), DirectorySource("./bundled")],
13+
"exit 1",
14+
[Linux(:x86_64)],
15+
Product[LibraryProduct("libfoo", :libfoo), FrameworkProduct("fooFramework", :libfooFramework)],
16+
[Dependency("Zlib_jll")];
17+
)
18+
println(meta_json_buff, JSON.json(dict))
19+
20+
dict = get_meta_json(
21+
"libfoo",
22+
v"1.0.0",
23+
[GitSource("https://github.com/JuliaLang/julia.git", "5d4eaca0c9fa3d555c79dbacdccb9169fdf64b65")],
24+
"exit 0",
25+
[Linux(:x86_64), Windows(:x86_64)],
26+
Product[ExecutableProduct("julia", :julia), LibraryProduct("libfoo2", :libfoo2; dlopen_flags=[:RTLD_GLOBAL])],
27+
Dependency[];
28+
)
29+
println(meta_json_buff, JSON.json(dict))
30+
31+
# Now, deserialize the info:
32+
seek(meta_json_buff, 0)
33+
34+
# Strip out ending newlines as that makes our while loop below sad
35+
meta_json_buff = IOBuffer(strip(String(take!(meta_json_buff))))
36+
objs = []
37+
while !eof(meta_json_buff)
38+
push!(objs, JSON.parse(meta_json_buff))
39+
end
40+
41+
# Ensure that we get two JSON objects
42+
@test length(objs) == 2
43+
44+
# Merge them, then test that the merged object contains everything we expect
45+
meta = BinaryBuilder.cleanup_merged_object!(BinaryBuilder.merge_json_objects(objs))
46+
47+
@test all(haskey.(Ref(meta), ("name", "version", "script", "platforms", "products", "dependencies")))
48+
@test meta["name"] == "libfoo"
49+
@test meta["version"] == v"1.0.0"
50+
@test Set(meta["platforms"]) == Set([Linux(:x86_64, libc=:glibc), Windows(:x86_64)])
51+
@test length(meta["sources"]) == 3
52+
@test all(in.(
53+
(
54+
FileSource("https://julialang.org", "123123"),
55+
GitSource("https://github.com/JuliaLang/julia.git", "5d4eaca0c9fa3d555c79dbacdccb9169fdf64b65"),
56+
DirectorySource("./bundled"),
57+
), Ref(meta["sources"])))
58+
@test sourcify(Dict("type" => "directory", "path" => "foo")) == DirectorySource("foo")
59+
@test sourcify(Dict("type" => "git", "url" => "https://github.com/JuliaLang/julia.git", "hash" => "12345")) == GitSource("https://github.com/JuliaLang/julia.git", "12345")
60+
@test sourcify(Dict("type" => "file", "url" => "https://julialang.org", "hash" => "98765")) == FileSource("https://julialang.org", "98765")
61+
@test_throws ErrorException sourcify(Dict("type" => "qux"))
62+
# `PackageSpec(; name = "Foo") != PackageSpec(; name = "Foo")`, so we
63+
# need to manually compare the fields we care about
64+
d = dependencify(Dict("type" => "dependency", "name" => "Foo_jll", "uuid" => nothing,
65+
"version-major" => 0, "version-minor" => 0, "version-patch" => 0))
66+
ref_d = Dependency(PackageSpec(; name = "Foo_jll"))
67+
@test d.pkg.name == ref_d.pkg.name
68+
@test d.pkg.uuid == ref_d.pkg.uuid
69+
v = version(d)
70+
ref_v = version(ref_d)
71+
@test (major(v), minor(v), patch(v)) == (major(ref_v), minor(ref_v), patch(ref_v))
72+
d = dependencify(Dict("type" => "builddependency", "name" => "Qux_jll", "uuid" => nothing,
73+
"version-major" => 1, "version-minor" => 2, "version-patch" => 3))
74+
ref_d = Dependency(PackageSpec(; name = "Qux_jll", version = v"1.2.3"))
75+
@test d.pkg.name == ref_d.pkg.name
76+
@test d.pkg.uuid == ref_d.pkg.uuid
77+
v = version(d)
78+
ref_v = version(ref_d)
79+
@test (major(v), minor(v), patch(v)) == (major(ref_v), minor(ref_v), patch(ref_v))
80+
@test_throws ErrorException dependencify(Dict("type" => "bar"))
81+
@test length(meta["products"]) == 4
82+
@test all(in.((LibraryProduct("libfoo", :libfoo), ExecutableProduct("julia", :julia), LibraryProduct("libfoo2", :libfoo2; dlopen_flags=[:RTLD_GLOBAL]), FrameworkProduct("fooFramework", :libfooFramework)), Ref(meta["products"])))
83+
@test length(meta["script"]) == 2
84+
@test all(in.(("exit 0", "exit 1"), Ref(meta["script"])))
85+
86+
@testset "AnyPlatform" begin
787
meta_json_buff = IOBuffer()
8-
# Run autobuild() a few times to generate a moderately complex `meta.json`:
9-
build_output_meta = autobuild(
10-
tmpdir,
11-
"libfoo",
88+
dict = get_meta_json(
89+
"any_file",
1290
v"1.0.0",
13-
[FileSource("https://julialang.org", "123123"), DirectorySource("./bundled")],
91+
FileSource[],
1492
"exit 1",
15-
[Linux(:x86_64)],
16-
Product[LibraryProduct("libfoo", :libfoo), FrameworkProduct("fooFramework", :libfooFramework)],
17-
[Dependency("Zlib_jll")];
18-
meta_json_stream=meta_json_buff,
93+
[AnyPlatform()],
94+
Product[FileProduct("file", :file)],
95+
BuildDependency[];
1996
)
20-
@test build_output_meta == Dict()
21-
22-
build_output_meta = autobuild(
23-
tmpdir,
24-
"libfoo",
25-
v"1.0.0",
26-
[GitSource("https://github.com/JuliaLang/julia.git", "5d4eaca0c9fa3d555c79dbacdccb9169fdf64b65")],
27-
"exit 0",
28-
[Linux(:x86_64), Windows(:x86_64)],
29-
Product[ExecutableProduct("julia", :julia), LibraryProduct("libfoo2", :libfoo2; dlopen_flags=[:RTLD_GLOBAL])],
30-
Dependency[];
31-
meta_json_stream=meta_json_buff,
32-
)
33-
@test build_output_meta == Dict()
34-
35-
# Now, deserialize the info:
36-
seek(meta_json_buff, 0)
97+
println(meta_json_buff, JSON.json(dict))
3798

99+
# Deserialize the info:
100+
seekstart(meta_json_buff)
38101
# Strip out ending newlines as that makes our while loop below sad
39102
meta_json_buff = IOBuffer(strip(String(take!(meta_json_buff))))
40103
objs = []
41104
while !eof(meta_json_buff)
42105
push!(objs, JSON.parse(meta_json_buff))
43106
end
44-
45-
# Ensure that we get two JSON objects
46-
@test length(objs) == 2
47-
107+
# Ensure that we get one JSON object
108+
@test length(objs) == 1
109+
# Platform-independent build: the JSON file doesn't have a "platforms" key
110+
@test !haskey(objs[1], "platforms")
48111
# Merge them, then test that the merged object contains everything we expect
49112
meta = BinaryBuilder.cleanup_merged_object!(BinaryBuilder.merge_json_objects(objs))
50-
51-
@test all(haskey.(Ref(meta), ("name", "version", "script", "platforms", "products", "dependencies")))
52-
@test meta["name"] == "libfoo"
53-
@test meta["version"] == v"1.0.0"
54-
@test Set(meta["platforms"]) == Set([Linux(:x86_64, libc=:glibc), Windows(:x86_64)])
55-
@test length(meta["sources"]) == 3
56-
@test all(in.(
57-
(
58-
FileSource("https://julialang.org", "123123"),
59-
GitSource("https://github.com/JuliaLang/julia.git", "5d4eaca0c9fa3d555c79dbacdccb9169fdf64b65"),
60-
DirectorySource("./bundled"),
61-
), Ref(meta["sources"])))
62-
@test sourcify(Dict("type" => "directory", "path" => "foo")) == DirectorySource("foo")
63-
@test sourcify(Dict("type" => "git", "url" => "https://github.com/JuliaLang/julia.git", "hash" => "12345")) == GitSource("https://github.com/JuliaLang/julia.git", "12345")
64-
@test sourcify(Dict("type" => "file", "url" => "https://julialang.org", "hash" => "98765")) == FileSource("https://julialang.org", "98765")
65-
@test_throws ErrorException sourcify(Dict("type" => "qux"))
66-
# `PackageSpec(; name = "Foo") != PackageSpec(; name = "Foo")`, so we
67-
# need to manually compare the fields we care about
68-
d = dependencify(Dict("type" => "dependency", "name" => "Foo_jll", "uuid" => nothing,
69-
"version-major" => 0, "version-minor" => 0, "version-patch" => 0))
70-
ref_d = Dependency(PackageSpec(; name = "Foo_jll"))
71-
@test d.pkg.name == ref_d.pkg.name
72-
@test d.pkg.uuid == ref_d.pkg.uuid
73-
v = version(d)
74-
ref_v = version(ref_d)
75-
@test (major(v), minor(v), patch(v)) == (major(ref_v), minor(ref_v), patch(ref_v))
76-
d = dependencify(Dict("type" => "builddependency", "name" => "Qux_jll", "uuid" => nothing,
77-
"version-major" => 1, "version-minor" => 2, "version-patch" => 3))
78-
ref_d = Dependency(PackageSpec(; name = "Qux_jll", version = v"1.2.3"))
79-
@test d.pkg.name == ref_d.pkg.name
80-
@test d.pkg.uuid == ref_d.pkg.uuid
81-
v = version(d)
82-
ref_v = version(ref_d)
83-
@test (major(v), minor(v), patch(v)) == (major(ref_v), minor(ref_v), patch(ref_v))
84-
@test_throws ErrorException dependencify(Dict("type" => "bar"))
85-
@test length(meta["products"]) == 4
86-
@test all(in.((LibraryProduct("libfoo", :libfoo), ExecutableProduct("julia", :julia), LibraryProduct("libfoo2", :libfoo2; dlopen_flags=[:RTLD_GLOBAL]), FrameworkProduct("fooFramework", :libfooFramework)), Ref(meta["products"])))
87-
@test length(meta["script"]) == 2
88-
@test all(in.(("exit 0", "exit 1"), Ref(meta["script"])))
89-
end
90-
91-
@testset "AnyPlatform" begin
92-
mktempdir() do tmpdir
93-
meta_json_buff = IOBuffer()
94-
build_output_meta = autobuild(
95-
tmpdir,
96-
"any_file",
97-
v"1.0.0",
98-
FileSource[],
99-
"exit 1",
100-
[AnyPlatform()],
101-
Product[FileProduct("file", :file)],
102-
BuildDependency[];
103-
meta_json_stream=meta_json_buff,
104-
)
105-
@test build_output_meta == Dict()
106-
# Deserialize the info:
107-
seekstart(meta_json_buff)
108-
# Strip out ending newlines as that makes our while loop below sad
109-
meta_json_buff = IOBuffer(strip(String(take!(meta_json_buff))))
110-
objs = []
111-
while !eof(meta_json_buff)
112-
push!(objs, JSON.parse(meta_json_buff))
113-
end
114-
# Ensure that we get one JSON object
115-
@test length(objs) == 1
116-
# Platform-independent build: the JSON file doesn't have a "platforms" key
117-
@test !haskey(objs[1], "platforms")
118-
# Merge them, then test that the merged object contains everything we expect
119-
meta = BinaryBuilder.cleanup_merged_object!(BinaryBuilder.merge_json_objects(objs))
120-
# The "platforms" key comes back in the cleaned up object
121-
@test meta["platforms"] == [AnyPlatform()]
122-
end
113+
# The "platforms" key comes back in the cleaned up object
114+
@test meta["platforms"] == [AnyPlatform()]
123115
end
124116
end

0 commit comments

Comments
 (0)