From bd693f7260b74d22c5d78ecca214785b59a54bb4 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Wed, 20 Sep 2023 16:07:14 +0000 Subject: [PATCH 1/3] wizard: Support for {Runtime,Build,HostBuild}Dependency Both in the wizard menu and as a `bb` command. --- src/wizard/deploy.jl | 2 +- src/wizard/interactive_build.jl | 34 +++++++++++++++++++++++++++------ src/wizard/obtain_source.jl | 27 ++++++++++++++++++++++++-- src/wizard/state.jl | 2 +- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/wizard/deploy.jl b/src/wizard/deploy.jl index 9675b137c..e5b4c4354 100644 --- a/src/wizard/deploy.jl +++ b/src/wizard/deploy.jl @@ -58,7 +58,7 @@ function print_build_tarballs(io::IO, state::WizardState) if length(state.dependencies) >= 1 function psrepr(ps) - s = "\n Dependency(PackageSpec(name=\"$(getname(ps))\"" + s = "\n $(typeof(ps))(PackageSpec(name=\"$(getname(ps))\"" if !isnothing(getpkg(ps).uuid) s *= ", uuid=\"$(getpkg(ps).uuid)\"" end diff --git a/src/wizard/interactive_build.jl b/src/wizard/interactive_build.jl index c23da85d2..e6fe7d077 100644 --- a/src/wizard/interactive_build.jl +++ b/src/wizard/interactive_build.jl @@ -212,7 +212,10 @@ function diff_srcdir(state::WizardState, prefix::Prefix, ur::Runner) return false end -function bb_add(client, state::WizardState, prefix::Prefix, prefix_artifacts::Union{Dict{Prefix,Vector{String}}, Nothing}, platform::AbstractPlatform, jll::AbstractString) +function bb_add(client, state::WizardState, prefix::Prefix, prefix_artifacts::Union{Dict{Prefix,Vector{String}}, Nothing}, platform::AbstractPlatform, dep_kind::Type, jll::AbstractString) + if !endswith(jll, "_jll") + jll *= "_jll" + end if any(dep->getpkg(dep).name == jll, state.dependencies) println(client, "ERROR: Package was already added") return @@ -221,7 +224,7 @@ function bb_add(client, state::WizardState, prefix::Prefix, prefix_artifacts::Un println(client, "ERROR: `bb add` not available in this context (if you think it should be, file an issue)!") return end - new_dep = Dependency(jll) + new_dep = dep_kind(jll) try # This will redo some work, but that may be ok concrete_platform = get_concrete_platform(platform, state) @@ -231,8 +234,9 @@ function bb_add(client, state::WizardState, prefix::Prefix, prefix_artifacts::Un pkgs = getpkg.([state.dependencies; new_dep]) prefix_artifacts[prefix] = setup_dependencies(prefix, pkgs, concrete_platform) push!(state.dependencies, new_dep) + println(client, "[bb] Added dependency $jll. The dependency is available for use.") catch e - showerror(client, e) + showerror(client, e, catch_backtrace()) end end @@ -247,10 +251,24 @@ function bb_parser() action = :command end + add_arg_group!(s["add"], "dependency kind", exclusive=true) + @add_arg_table! s["add"] begin + "--build" + help = "This is a build-only dependency (e.g. for header-only libraries)" + nargs = 0 + "--runtime" + help = "This is a runtime-only dependency (e.g. for runtime assets)" + nargs = 0 + "--hostbuild" + help = "This is a host build-time dependency (e.g. cross-compile build tools)" + nargs = 0 + end + + add_arg_group!(s["add"], "jll name") @add_arg_table! s["add"] begin "jll" - help = "The jll to add" - required = true + help = "The jll to add" + required = true end s @@ -276,7 +294,11 @@ function setup_bb_service(state::WizardState, prefix, platform, prefix_artifacts parsed = parse_args(ARGS, s) if parsed == nothing elseif parsed["%COMMAND%"] == "add" - bb_add(client, state, prefix, prefix_artifacts, platform, parsed["add"]["jll"]) + dep_kind = parsed["add"]["build"] ? BuildDependency : + parsed["add"]["runtime"] ? RuntimeDependency : + parsed["add"]["hostbuild"] ? HostBuildDependency : + Dependency + bb_add(client, state, prefix, prefix_artifacts, platform, dep_kind, parsed["add"]["jll"]) end close(client) catch e diff --git a/src/wizard/obtain_source.jl b/src/wizard/obtain_source.jl index c464e7475..aa3a227ff 100644 --- a/src/wizard/obtain_source.jl +++ b/src/wizard/obtain_source.jl @@ -231,18 +231,32 @@ function obtain_binary_deps(state::WizardState) terminal = TTYTerminal("xterm", state.ins, state.outs, state.outs) local resolved_deps jll_names = String[] + dependencies = AbstractDependency[] while true jll_name = nonempty_line_prompt("package name", "Enter JLL package name:"; ins=state.ins, outs=state.outs) if !endswith(jll_name, "_jll") jll_name *= "_jll" end + choices = Pair{String, Type}[ + "Build and runtime target dependency (e.g. libraries) [default]" => Dependency, + "Build-only dependency (e.g. header-only libraries)" => BuildDependency, + "Runtime-only dependency (e.g. runtime assets)" => RuntimeDependency, + "Host-build dependency (e.g. cross-compile build tools)" => HostBuildDependency, + ] + + selected_kind = request(terminal, "What kind of dependency is this?", + RadioMenu(map(x->x[1], choices); charset=:ascii)) + + dep_kind = choices[selected_kind][2] + # Check to see if this JLL package name can be resolved: push!(jll_names, jll_name) - all_resolved, resolved_deps = resolve_jlls(Dependency.(jll_names), outs=state.outs) + push!(dependencies, dep_kind(jll_name)) + all_resolved, resolved_deps = resolve_jlls(dependencies, outs=state.outs) if !all_resolved - pop!(jll_names) + pop!(jll_names); pop!(dependencies) if yn_prompt(state, "Unable to resolve \"$(jll_name)\"; enter a new one?", :y) != :y break else @@ -250,6 +264,7 @@ function obtain_binary_deps(state::WizardState) end end + println(state.outs) q = "Would you like to provide additional dependencies? " if yn_prompt(state, q, :n) != :y break @@ -260,6 +275,14 @@ function obtain_binary_deps(state::WizardState) state.dependencies = filter(x -> getname(x) ∈ jll_names, resolved_deps) end println(state.outs) + print(state.outs, """ + Dependency selection complete. + If you discover additional required dependencies during the build process, you + may add them using: + """) + println(state.outs) + printstyled(state.outs, "\tbb add [--build|--runtime|--hostbuild] \n", bold=true) + println(state.outs) end function obtain_source(state::WizardState) diff --git a/src/wizard/state.jl b/src/wizard/state.jl index ce7cb3980..b9df62394 100644 --- a/src/wizard/state.jl +++ b/src/wizard/state.jl @@ -33,7 +33,7 @@ necessary. It also holds all necessary metadata such as input/output streams. workspace::Union{Nothing, String} = nothing source_urls::Union{Nothing, Vector{String}} = nothing source_files::Union{Nothing, Vector{SetupSource}} = nothing - dependencies::Union{Nothing, Vector{Dependency}} = nothing + dependencies::Union{Nothing, Vector{AbstractDependency}} = nothing compilers::Union{Nothing, Vector{Symbol}} = nothing preferred_gcc_version::Union{Nothing, VersionNumber} = nothing preferred_llvm_version::Union{Nothing, VersionNumber} = nothing From 8d3420c8870a254886d468e3c95a40b4c6417d0b Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 21 Sep 2023 12:39:49 +0000 Subject: [PATCH 2/3] Adjust tests --- test/wizard.jl | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/wizard.jl b/test/wizard.jl index 395b969e6..7169c81f1 100644 --- a/test/wizard.jl +++ b/test/wizard.jl @@ -4,6 +4,8 @@ import Pkg: PackageSpec import BinaryBuilder.BinaryBuilderBase: available_gcc_builds, available_llvm_builds, getversion +const DO_DEBUG=false + function with_wizard_output(f::Function, state, step_func::Function) # Create fake terminal to communicate with BinaryBuilder over pty = VT100.create_pty(false) @@ -16,8 +18,7 @@ function with_wizard_output(f::Function, state, step_func::Function) while isopen(pty.master) z = String(readavailable(pty.master)) - # Un-comment this to figure out what on earth is going wrong - # print(z) + DO_DEBUG && print(z) write(out_buff, z) end end @@ -238,13 +239,16 @@ end call_response(ins, outs, "Do you require any (binary) dependencies", "Y") call_response(ins, outs, "Enter JLL package name:", "ghr_jll") + call_response(ins, outs, "What kind of dependency is this?", "\r"; newline=false) call_response(ins, outs, "Would you like to provide additional dependencies?", "Y") # Test auto-JLL suffixing call_response(ins, outs, "Enter JLL package name:", "Zlib") + call_response(ins, outs, "What kind of dependency is this?", "\r"; newline=false) call_response(ins, outs, "Would you like to provide additional dependencies?", "Y") # Test typo detection call_response(ins, outs, "Enter JLL package name:", "iso_codez_jll") + call_response(ins, outs, "What kind of dependency is this?", "\r"; newline=false) call_response(ins, outs, "Unable to resolve", "N") call_response(ins, outs, "Enter a name for this project", "check_deps") From 13788ae300bdd193ed442686193ca9a3213a9fcc Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Thu, 21 Sep 2023 19:43:21 +0000 Subject: [PATCH 3/3] Try to fix test --- src/wizard/interactive_build.jl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/wizard/interactive_build.jl b/src/wizard/interactive_build.jl index e6fe7d077..c9d2d7653 100644 --- a/src/wizard/interactive_build.jl +++ b/src/wizard/interactive_build.jl @@ -73,7 +73,7 @@ function step4(state::WizardState, ur::Runner, platform::AbstractPlatform, if choice == 1 # Link dependencies into the prefix again concrete_platform = get_concrete_platform(platform, state) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), concrete_platform) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], concrete_platform) return step3_interactive(state, prefix, platform, ur, build_path, artifact_paths) elseif choice == 2 state.step = :step3 @@ -231,7 +231,7 @@ function bb_add(client, state::WizardState, prefix::Prefix, prefix_artifacts::Un # Clear out the prefix artifacts directory in case this change caused # any previous dependencies to change cleanup_dependencies(prefix, get(prefix_artifacts, prefix, String[]), concrete_platform) - pkgs = getpkg.([state.dependencies; new_dep]) + pkgs = Pkg.Types.PackageSpec[getpkg(dep) for dep in [state.dependencies; new_dep]] prefix_artifacts[prefix] = setup_dependencies(prefix, pkgs, concrete_platform) push!(state.dependencies, new_dep) println(client, "[bb] Added dependency $jll. The dependency is available for use.") @@ -461,7 +461,7 @@ function step3_retry(state::WizardState) mkpath(build_path) concrete_platform = get_concrete_platform(platform, state) prefix = setup_workspace(build_path, vcat(state.source_files, state.patches), concrete_platform; verbose=false) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), concrete_platform) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], concrete_platform) ur = preferred_runner()( prefix.path; @@ -548,7 +548,7 @@ function step34(state::WizardState) concrete_platform; verbose=false ) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), concrete_platform; verbose=true) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], concrete_platform; verbose=true) provide_hints(state, joinpath(prefix, "srcdir")) @@ -593,7 +593,7 @@ function step5_internal(state::WizardState, platform::AbstractPlatform) prefix = setup_workspace(build_path, vcat(state.source_files, state.patches), concrete_platform; verbose=true) # Clean up artifacts in case there are some cleanup_dependencies(prefix, get(prefix_artifacts, prefix, String[]), concrete_platform) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), concrete_platform; verbose=true) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], concrete_platform; verbose=true) # Record newly added artifacts for this prefix prefix_artifacts[prefix] = artifact_paths ur = preferred_runner()( @@ -670,7 +670,7 @@ function step5_internal(state::WizardState, platform::AbstractPlatform) ) # Clean up artifacts in case there are some cleanup_dependencies(prefix, get(prefix_artifacts, prefix, String[]), concrete_platform) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), platform; verbose=true) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], platform; verbose=true) # Record newly added artifacts for this prefix prefix_artifacts[prefix] = artifact_paths @@ -804,7 +804,7 @@ function step5c(state::WizardState) concrete_platform; verbose=false, ) - artifact_paths = setup_dependencies(prefix, getpkg.(state.dependencies), concrete_platform; verbose=false) + artifact_paths = setup_dependencies(prefix, Pkg.Types.PackageSpec[getpkg(dep) for dep in state.dependencies], concrete_platform; verbose=false) ur = preferred_runner()( prefix.path; cwd="/workspace/srcdir",