Skip to content

Instantly share code, notes, and snippets.

@martenlienen
Created October 6, 2020 23:08
Show Gist options
  • Save martenlienen/d4ab84617a8e532dc0cedcd5469fb715 to your computer and use it in GitHub Desktop.
Save martenlienen/d4ab84617a8e532dc0cedcd5469fb715 to your computer and use it in GitHub Desktop.
Iteratively compile all project dependencies into a custom sysimage
#!/usr/bin/env julia
import Pkg
using UUIDs
using PackageCompiler
function flatten_dependencies(uuid::UUID, package_infos::Dict{UUID, Pkg.Types.PackageInfo})
deps = Set{UUID}()
new = [uuid]
while !isempty(new)
package = popfirst!(new)
package_deps = Set(values(package_infos[package].dependencies))
unseen = setdiff(package_deps, deps)
append!(new, unseen)
union!(deps, unseen)
end
deps
end
function dfs_topo_sort(packages, dependents)
remaining = Set(packages)
sorted = empty(packages)
seen = Set(empty(packages))
function follow(package)
if package ∉ seen
push!(seen, package)
map(follow, dependents[package])
pushfirst!(sorted, package)
end
end
map(follow, packages)
sorted
end
Pkg.activate(".")
all_dependencies = Pkg.dependencies()
direct_dependencies = Pkg.project().dependencies
package_dependencies = let
name(uuid::UUID) = all_dependencies[uuid].name
direct_uuids = Set(values(direct_dependencies))
dependency_names(uuid) = name.(flatten_dependencies(uuid, all_dependencies) ∩ direct_uuids)
Dict(name => dependency_names(uuid) for (name, uuid) in direct)
end
packages = collect(keys(direct_dependencies))
dependents = Dict(p => [q for (q, deps) in package_dependencies if p ∈ deps] for p in packages)
packages = dfs_topo_sort(packages, dependents)
root = mktempdir(cleanup=false)
base_sysimage = nothing
while !isempty(packages)
package = popfirst!(packages)
println("Adding $package")
new_sysimage = joinpath(root, "sysimage-$(package).so")
create_sysimage(Symbol(package); sysimage_path=new_sysimage, base_sysimage)
process = run(Cmd(`julia -J $(new_sysimage) -q -e ''`; ignorestatus=true))
works = process.exitcode == 0 && process.termsignal == 0
if works
global base_sysimage
base_sysimage = new_sysimage
else
println("Could not add $package")
if length(dependents[package]) > 0
println("Also excluding dependents $(dependents[package])")
setdiff!(packages, dependents[package])
end
end
end
if base_sysimage !== nothing
cp(base_sysimage, "sysimage.so"; force=true)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment