1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
|
# This file is a part of Julia. License is MIT: https://julialang.org/license
# Prevent this from being put into the Main namespace
let
M = Module()
@eval M begin
if !isdefined(Base, :uv_eventloop)
Base.reinit_stdio()
end
Base.include(@__MODULE__, joinpath(Sys.BINDIR, "..", "share", "julia", "test", "testhelpers", "FakePTYs.jl"))
import .FakePTYs: open_fake_pty
CTRL_C = '\x03'
UP_ARROW = "\e[A"
DOWN_ARROW = "\e[B"
precompile_script = """
2+2
print("")
@time 1+1
; pwd
? reinterpret
using Ra\t$CTRL_C
\\alpha\t$CTRL_C
\e[200~paste here ;)\e[201~"$CTRL_C
$UP_ARROW$DOWN_ARROW$CTRL_C
123\b\b\b$CTRL_C
\b\b$CTRL_C
f(x) = x03
f(1,2)
[][1]
cd("complet_path\t\t$CTRL_C
"""
julia_cmd() = (julia = joinpath(Sys.BINDIR, Base.julia_exename()); `$julia`)
have_repl = haskey(Base.loaded_modules,
Base.PkgId(Base.UUID("3fa0cd96-eef1-5676-8a61-b3b8758bbffb"), "REPL"))
Pkg = get(Base.loaded_modules,
Base.PkgId(Base.UUID("44cfe95a-1eb2-52ea-b672-e2afdf69b78f"), "Pkg"),
nothing)
if Pkg !== nothing
precompile_script *= Pkg.precompile_script
end
push!(LOAD_PATH, Sys.STDLIB)
using Sockets
Sockets.__init__()
using Libdl
empty!(LOAD_PATH)
function generate_precompile_statements()
start_time = time()
# Precompile a package
mktempdir() do prec_path
push!(DEPOT_PATH, prec_path)
push!(LOAD_PATH, prec_path)
pkgname = "__PackagePrecompilationStatementModule"
mkpath(joinpath(prec_path, pkgname, "src"))
write(joinpath(prec_path, pkgname, "src", "$pkgname.jl"),
"""
module $pkgname
end
""")
@eval using __PackagePrecompilationStatementModule
empty!(LOAD_PATH)
empty!(DEPOT_PATH)
end
print("Generating precompile statements...")
sysimg = Base.unsafe_string(Base.JLOptions().image_file)
mktemp() do precompile_file, _
# Run a repl process and replay our script
repl_output_buffer = IOBuffer()
@static if Sys.iswindows()
# Fake being cygwin
pipename = """\\\\?\\pipe\\cygwin-$("0"^16)-pty10-abcdef"""
server = listen(pipename)
slave = connect(pipename)
@assert ccall(:jl_ispty, Cint, (Ptr{Cvoid},), slave.handle) == 1
master = accept(server)
else
slave, master = open_fake_pty()
end
done = false
blackhole = Sys.isunix() ? "/dev/null" : "nul"
withenv("JULIA_HISTORY" => blackhole, "JULIA_PROJECT" => nothing,
"TERM" => "") do
if have_repl
p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg
--compile=all --startup-file=no --color=yes
-e 'import REPL; REPL.Terminals.is_precompiling[] = true'
-i`,
slave, slave, slave; wait=false)
readuntil(master, "julia>", keep=true)
t = @async begin
while true
sleep(0.5)
s = String(readavailable(master))
write(repl_output_buffer, s)
if occursin("__PRECOMPILE_END__", s)
break
end
end
end
if have_repl
for l in split(precompile_script, '\n'; keepempty=false)
write(master, l, '\n')
end
end
write(master, "print(\"__PRECOMPILE\", \"_END__\")", '\n')
wait(t)
# TODO Figure out why exit() on Windows doesn't exit the process
if Sys.iswindows()
print(master, "ccall(:_exit, Cvoid, (Cint,), 0)\n")
else
write(master, "exit()\n")
readuntil(master, "exit()\r\e[13C\r\n")
# @assert bytesavailable(master) == 0
end
wait(p)
else
# Is this even needed or is this already recorded just from starting this process?
p = run(`$(julia_cmd()) -O0 --trace-compile=$precompile_file --sysimage $sysimg
--compile=all --startup-file=no
-e0`)
end
end
close(master)
# Check what the REPL displayed
# repl_output = String(take!(repl_output_buffer))
# println(repl_output)
# Extract the precompile statements from stderr
statements = Set{String}()
for statement in split(read(precompile_file, String), '\n')
occursin("Main.", statement) && continue
push!(statements, statement)
end
if have_repl
# Seems like a reasonable number right now, adjust as needed
# comment out if debugging script
@assert length(statements) > 700
end
# Create a staging area where all the loaded packages are available
PrecompileStagingArea = Module()
for (_pkgid, _mod) in Base.loaded_modules
if !(_pkgid.name in ("Main", "Core", "Base"))
eval(PrecompileStagingArea, :($(Symbol(_mod)) = $_mod))
end
end
# Execute the collected precompile statements
include_time = @elapsed for statement in sort(collect(statements))
# println(statement)
# Work around #28808
occursin("\"YYYY-mm-dd\\THH:MM:SS\"", statement) && continue
try
Base.include_string(PrecompileStagingArea, statement)
catch ex
@error "Failed to precompile $statement"
rethrow(ex)
end
end
print(" $(length(statements)) generated in ")
tot_time = time() - start_time
Base.time_print(tot_time * 10^9)
print(" (overhead "); Base.time_print((tot_time - include_time) * 10^9); println(")")
end
return
end
generate_precompile_statements()
end # @eval
end # let
|