Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 78 additions & 9 deletions src/AutoBuild.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import LibGit2
import PkgLicenses

const DEFAULT_JULIA_VERSION_SPEC = "1.0"
const DEFAULT_JLLWRAPPERS_VERSION_SPEC = "1.2.0"
const PKG_VERSIONS = Base.VERSION >= v"1.7-" ? Pkg.Versions : Pkg.Types

mutable struct BuildTimer
Expand Down Expand Up @@ -140,10 +141,19 @@ supported ones. A few additional keyword arguments are accept:
package. This can for example be used to invoke an initialization API of a
shared library.

* `augment_platform_block` may be set to a string containing Julia code; if
present, this code will be inserted into the top-level of the
generated JLL package. It must define a function `augment_platform!` that
takes as a single argument, the target platform and returns the target
platform, with amended tags. This augmented platform will then be used by the
JLL wrapper to select the artifact. Note that this option requires the Julia
compatibility `julia_compat` to be 1.6 or higher.

!!! note

The `init_block` keyword argument is experimental and may be removed
in a future version of this package. Please use it sparingly.
The `init_block` and `augment_platform_block` keyword arguments are experimental
and may be removed in a future version of this package. Please use them sparingly.

"""
function build_tarballs(ARGS, src_name, src_version, sources, script,
platforms, products, dependencies;
Expand Down Expand Up @@ -304,7 +314,7 @@ function build_tarballs(ARGS, src_name, src_version, sources, script,
# Dependencies that must be downloaded
dependencies,
)
extra_kwargs = extract_kwargs(kwargs, (:lazy_artifacts, :init_block))
extra_kwargs = extract_kwargs(kwargs, (:lazy_artifacts, :init_block, :augment_platform_block))

if meta_json_stream !== nothing
# If they've asked for the JSON metadata, by all means, give it to them!
Expand Down Expand Up @@ -523,7 +533,13 @@ function register_jll(name, build_version, dependencies, julia_compat;
gh_auth=Wizard.github_auth(;allow_anonymous=false),
gh_username=gh_get_json(DEFAULT_API, "/user"; auth=gh_auth)["login"],
lazy_artifacts::Bool=false,
augment_platform_block="",
kwargs...)
if !isempty(augment_platform_block) &&
minimum(VersionNumber(rng.lower.t) for rng in PKG_VERSIONS.semver_spec(julia_compat).ranges) < v"1.6"
error("Augmentation blocks cannot be used with Julia v1.5-.\nChange `julia_compat` to require at least Julia v1.6")
end

# Calculate tree hash of wrapper code
wrapper_tree_hash = bytes2hex(Pkg.GitTools.tree_hash(code_dir))
wrapper_commit_hash = LibGit2.head(code_dir)
Expand All @@ -533,7 +549,8 @@ function register_jll(name, build_version, dependencies, julia_compat;
cache = RegistryTools.RegistryCache(joinpath(Pkg.depots1(), "registries_binarybuilder"))
registry_url = "https://$(gh_username):$(gh_auth.token)@github.com/JuliaRegistries/General"
cache.registries[registry_url] = Base.UUID("23338594-aafe-5451-b93e-139f81909106")
project = Pkg.Types.Project(build_project_dict(name, build_version, dependencies, julia_compat; lazy_artifacts=lazy_artifacts))
jllwrappers_compat = isempty(augment_platform_block) ? DEFAULT_JLLWRAPPERS_VERSION_SPEC : "1.4.0"
project = Pkg.Types.Project(build_project_dict(name, build_version, dependencies, julia_compat; jllwrappers_compat, lazy_artifacts=lazy_artifacts))
errors = setdiff(RegistryTools.registrator_errors, [:version_less_than_all_existing])
reg_branch = RegistryTools.register(
"https://github.com/$(deploy_repo).git",
Expand Down Expand Up @@ -596,7 +613,8 @@ function get_meta_json(
dependencies::Vector{<:AbstractDependency};
julia_compat::String = DEFAULT_JULIA_VERSION_SPEC,
lazy_artifacts::Bool = false,
init_block::String = "")
init_block::String = "",
augment_platform_block::String = "")

dict = Dict(
"name" => src_name,
Expand All @@ -608,6 +626,7 @@ function get_meta_json(
"julia_compat" => julia_compat,
"lazy_artifacts" => lazy_artifacts,
"init_block" => init_block,
"augment_platform_block" => augment_platform_block,
)
# Do not write the list of platforms when building only for `AnyPlatform`
if platforms != [AnyPlatform()]
Expand Down Expand Up @@ -1063,6 +1082,7 @@ function rebuild_jll_package(obj::Dict;
lazy_artifacts = lazy_artifacts,
julia_compat = get(obj, "julia_compat", DEFAULT_JULIA_VERSION_SPEC),
init_block = get(obj, "init_block", ""),
augment_platform_block = get(obj, "augment_platform_block", ""),
from_scratch = from_scratch,
)
end
Expand Down Expand Up @@ -1167,7 +1187,8 @@ function build_jll_package(src_name::String,
verbose::Bool = false,
julia_compat::String = DEFAULT_JULIA_VERSION_SPEC,
lazy_artifacts::Bool = false,
init_block = "")
init_block = "",
augment_platform_block = "",)
# Make way, for prince artifacti
mkpath(joinpath(code_dir, "src", "wrappers"))

Expand Down Expand Up @@ -1290,6 +1311,38 @@ function build_jll_package(src_name::String,
end
end

if !isempty(augment_platform_block)
pkg_dir = joinpath(code_dir, ".pkg")
!ispath(pkg_dir) && mkdir(pkg_dir)
open(joinpath(pkg_dir, "platform_augmentation.jl"), "w") do io
println(io, """
$(augment_platform_block)
""")
end

open(joinpath(pkg_dir, "select_artifacts.jl"), "w") do io
println(io, """
push!(Base.LOAD_PATH, dirname(@__DIR__))

using TOML, Artifacts, Base.BinaryPlatforms
include("./platform_augmentation.jl")
artifacts_toml = joinpath(dirname(@__DIR__), "Artifacts.toml")

# Get "target triplet" from ARGS, if given (defaulting to the host triplet otherwise)
target_triplet = get(ARGS, 1, Base.BinaryPlatforms.host_triplet())

# Augment this platform object with any special tags we require
platform = augment_platform!(HostPlatform(parse(Platform, target_triplet)))

# Select all downloadable artifacts that match that platform
artifacts = select_downloadable_artifacts(artifacts_toml; platform, include_lazy=true)

#Output the result to `stdout` as a TOML dictionary
TOML.print(stdout, artifacts)
""")
end
end

# Generate target-demuxing main source file.
open(joinpath(code_dir, "src", "$(src_name)_jll.jl"), "w") do io
print(io, """
Expand All @@ -1301,6 +1354,13 @@ function build_jll_package(src_name::String,
if lazy_artifacts
println(io, "using LazyArtifacts")
end

if !isempty(augment_platform_block)
print(io, """
Base.include(@__MODULE__, joinpath("..", ".pkg", "platform_augmentation.jl"))
""")
end

print(io, """
import JLLWrappers

Expand Down Expand Up @@ -1429,7 +1489,8 @@ function build_jll_package(src_name::String,

# Add a Project.toml. Note: here we list _all_ runtime dependencies, including those
# that may be required only for some platforms.
project = build_project_dict(src_name, build_version, dependencies, julia_compat; lazy_artifacts=lazy_artifacts)
jllwrappers_compat = isempty(augment_platform_block) ? "1.2.0" : "1.4.0"
project = build_project_dict(src_name, build_version, dependencies, julia_compat; lazy_artifacts=lazy_artifacts, jllwrappers_compat)
open(joinpath(code_dir, "Project.toml"), "w") do io
Pkg.TOML.print(io, project)
end
Expand Down Expand Up @@ -1502,7 +1563,12 @@ function find_uuid(ctx, pkg)
""")
end

function build_project_dict(name, version, dependencies::Array{Dependency}, julia_compat::String=DEFAULT_JULIA_VERSION_SPEC; lazy_artifacts::Bool=false, kwargs...)
function build_project_dict(name, version, dependencies::Array{Dependency},
julia_compat::String=DEFAULT_JULIA_VERSION_SPEC;
jllwrappers_compat::String=DEFAULT_JLLWRAPPERS_VERSION_SPEC,
lazy_artifacts::Bool=false,
augment_platform_block="",
kwargs...)
Pkg.Types.semver_spec(julia_compat) # verify julia_compat is valid
project = Dict(
"name" => "$(name)_jll",
Expand All @@ -1511,7 +1577,7 @@ function build_project_dict(name, version, dependencies::Array{Dependency}, juli
"deps" => Dict{String,Any}(),
# We require at least Julia 1.3+, for Pkg.Artifacts support, but we only claim
# Julia 1.0+ by default so that empty JLLs can be installed on older versions.
"compat" => Dict{String,Any}("JLLWrappers" => "1.2.0",
"compat" => Dict{String,Any}("JLLWrappers" => "$(jllwrappers_compat)",
"julia" => "$(julia_compat)")
)

Expand All @@ -1538,6 +1604,9 @@ function build_project_dict(name, version, dependencies::Array{Dependency}, juli
if lazy_artifacts
project["deps"]["LazyArtifacts"] = "4af54fe1-eca0-43a8-85a7-787d91b784e3"
end
if !isempty(augment_platform_block)
project["deps"]["TOML"] = "fa267f1f-6049-4f14-aa54-33bafae1ed76"
end

return project
end
4 changes: 4 additions & 0 deletions test/basic.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ end

@test_throws ErrorException build_project_dict(name, version, dependencies, "nonsense")

# Ensure passing a JLLWrappers dependency bound works
dict = build_project_dict(name, version, dependencies; jllwrappers_compat="1.4.0")
@test dict["compat"] == Dict{String,Any}("julia" => "1.0", "JLLWrappers" => "1.4.0")

# Ensure passing compat bounds works
dependencies = [
Dependency(PackageSpec(name="libLLVM_jll"), compat="=9.0.0"),
Expand Down