Skip to content

Commit

Permalink
Each GAP.jl session uses fresh dir for mutable GAP root
Browse files Browse the repository at this point in the history
  • Loading branch information
fingolfin committed Dec 12, 2024
1 parent e1afb0c commit d8459a9
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 49 deletions.
4 changes: 4 additions & 0 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d"
Artifacts = "56f22d72-fd6d-98f1-02f0-08ddc0907c33"
BinaryWrappers = "f01c122e-0ea1-4f85-ad8f-907073ad7a9f"
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
GAP_jll = "5cd7a574-2c56-5be2-91dc-c8bc375b9ddf"
GAP_lib_jll = "de1ad85e-c930-5cd4-919d-ccd3fcafd1a3"
Expand Down Expand Up @@ -41,6 +42,7 @@ Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a"
Ncurses_jll = "68e3532b-a499-55ff-9963-d1c0c0748b3a"
Pidfile = "fa939f87-e72e-5be4-a000-7fc836dbe307"
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
Scratch = "6c6a2e73-6563-6170-7368-637461726353"
Expand All @@ -52,6 +54,7 @@ AbstractAlgebra = "0.41.11, 0.42.1, 0.43"
Artifacts = "1.6"
BinaryWrappers = "0.1.3"
Compat = "4.4.0"
Dates = "1.6"
Downloads = "1.4.3"
GAP_jll = "~400.1400.000"
GAP_lib_jll = "~400.1400.000"
Expand Down Expand Up @@ -85,6 +88,7 @@ Markdown = "1.6"
Ncurses_jll = "6.4.1"
Pidfile = "1.3"
Pkg = "1.6"
PrecompileTools = "1.2.1"
REPL = "1.6"
Random = "1.6"
Scratch = "1.1"
Expand Down
20 changes: 16 additions & 4 deletions src/GAP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,7 @@ import Libdl
import Random

# setup the initial sysinfo dictionary; we'll update this later in __init__
# this also ensures that Setup.regenerate_gaproot gets precompiled, reducing
# the startup time a little bit
const sysinfo = Setup.regenerate_gaproot()

const sysinfo = Dict{String, String}()

include("types.jl")

Expand Down Expand Up @@ -336,4 +333,19 @@ include("doctestfilters.jl")

include("GAP_pkg.jl")

################################################################################
#
# Precompilation
#
################################################################################

using PrecompileTools: @setup_workload, @compile_workload

@setup_workload begin
@compile_workload begin
sysinfo = Setup.regenerate_gaproot()
Setup.locate_JuliaInterface_so(sysinfo)
end
end

end
114 changes: 69 additions & 45 deletions src/setup.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,40 @@ import GAP_jll
import GAP_lib_jll
import GAP_pkg_juliainterface_jll
import Scratch: @get_scratch!
import Pidfile
import TOML
import Dates

# We use a scratch space to store subdirectories created via mktempdir
# that are then set up to contain a mutable gap root directory. A fresh
# one of these is created each time GAP.jl is loaded.
# This has the advantage that multiple GAP.jl sessions don't interfere
# with each other. Their mutable temp directories are usually cleaned up
# when Julia exits.
#
# The reason we don't just put these into `/tmp` is that files in there
# are cleaned out by the operating system at regular intervals, which
# could mess up long-running computations. Hence we use a Julia scratch space
# instead.
#
# We put the year & month into the scratch space name to ensure each is
# only used for about a month. Then after a time, `Pkg.gc()` will reap it
# (and using the Julia package manager will also automatically perform a gc
# from time to time).
const scratch_key = "gap_$(Dates.format(Dates.today(), "yyyy-mm"))"
const _gaproot = Ref("")

function __init__()
_gaproot[] = ""
end

# to separate the scratchspaces of different GAP.jl copies and Julia versions
# put the Julia version and the hash of the path to this file into the key
const scratch_key = "gap_$(hash(@__FILE__))-$(VERSION.major).$(VERSION.minor)"

gaproot() = @get_scratch!(scratch_key)
function gaproot()
if isempty(_gaproot[])
parent = @get_scratch!(scratch_key)
_gaproot[] = mktempdir(parent; prefix="gap_$(Dates.today())_", cleanup=true)
println("#I Setting gaproot to $(_gaproot[])")
end
return _gaproot[]
end

#############################################################################
#
Expand Down Expand Up @@ -160,50 +186,48 @@ function regenerate_gaproot()

# create the mutable gaproot
mkpath(gaproot_mutable)
Pidfile.mkpidlock("$gaproot_mutable.lock"; stale_age=10) do
# create fake sysinfo.gap
unquoted = Set(["GAParch", "GAP_ABI", "GAP_HPCGAP", "GAP_KERNEL_MAJOR_VERSION", "GAP_KERNEL_MINOR_VERSION", "GAP_OBJEXT"])
open("$gaproot_mutable/sysinfo.gap", "w") do file
write(file, """
# This file has been generated by the GAP build system,
# do not edit manually!
""")
for key in sort(collect(keys(sysinfo)))
if key in unquoted
str = "$(key)=$(sysinfo[key])"
else
str = "$(key)=\"$(sysinfo[key])\""
end
write(file, str, "\n")

# create fake sysinfo.gap
unquoted = Set(["GAParch", "GAP_ABI", "GAP_HPCGAP", "GAP_KERNEL_MAJOR_VERSION", "GAP_KERNEL_MINOR_VERSION", "GAP_OBJEXT"])
open("$gaproot_mutable/sysinfo.gap", "w") do file
write(file, """
# This file has been generated by the GAP build system,
# do not edit manually!
""")
for key in sort(collect(keys(sysinfo)))
if key in unquoted
str = "$(key)=$(sysinfo[key])"
else
str = "$(key)=\"$(sysinfo[key])\""
end
write(file, str, "\n")
end
end

# patch gac to load correct sysinfo.gap
gac = read(joinpath(gap_prefix, "bin", "gac"), String)
gac = replace(gac, r"^\. \"[^\"]+\"$"m => ". \"$(gaproot_mutable)/sysinfo.gap\"")
write("$gaproot_mutable/gac", gac)
chmod("$gaproot_mutable/gac", 0o755)

#
mkpath(joinpath(gaproot_mutable, "bin"))
for d in (("include/gap", "src"), ("lib", "lib"), ("bin/gap", "gap"))
force_symlink(joinpath(gap_prefix, d[1]), joinpath(gaproot_mutable, d[2]))
end
# patch gac to load correct sysinfo.gap
gac = read(joinpath(gap_prefix, "bin", "gac"), String)
gac = replace(gac, r"^\. \"[^\"]+\"$"m => ". \"$(gaproot_mutable)/sysinfo.gap\"")
write("$gaproot_mutable/gac", gac)
chmod("$gaproot_mutable/gac", 0o755)

# emulate the "compat mode" of the GAP build system, to help certain
# packages like Browse with an outdated build system
mkpath(joinpath(gaproot_mutable, "bin", sysinfo["GAParch"]))
force_symlink("../../gac",
joinpath(gaproot_mutable, "bin", sysinfo["GAParch"], "gac"))

# create a `pkg` directory with symlinks to all the GAP packages artifacts
mkpath(joinpath(gaproot_mutable, "pkg"))
pkg_artifacts = filter(startswith("GAP_pkg_"), keys(TOML.parsefile(find_artifacts_toml(@__FILE__))))
for name in pkg_artifacts
force_symlink(@artifact_str(name), joinpath(gaproot_mutable, "pkg", name))
end
#
mkpath(joinpath(gaproot_mutable, "bin"))
for d in (("include/gap", "src"), ("lib", "lib"), ("bin/gap", "gap"))
force_symlink(joinpath(gap_prefix, d[1]), joinpath(gaproot_mutable, d[2]))
end

end # mkpidlock
# emulate the "compat mode" of the GAP build system, to help certain
# packages like Browse with an outdated build system
mkpath(joinpath(gaproot_mutable, "bin", sysinfo["GAParch"]))
force_symlink("../../gac",
joinpath(gaproot_mutable, "bin", sysinfo["GAParch"], "gac"))

# create a `pkg` directory with symlinks to all the GAP packages artifacts
mkpath(joinpath(gaproot_mutable, "pkg"))
pkg_artifacts = filter(startswith("GAP_pkg_"), keys(TOML.parsefile(find_artifacts_toml(@__FILE__))))
for name in pkg_artifacts
force_symlink(@artifact_str(name), joinpath(gaproot_mutable, "pkg", name))
end

return sysinfo
end
Expand Down

0 comments on commit d8459a9

Please sign in to comment.