Skip to content

Commit 4a6fee9

Browse files
committed
modify + merge efforts
1 parent d66c9c6 commit 4a6fee9

File tree

7 files changed

+321
-358
lines changed

7 files changed

+321
-358
lines changed

REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
julia 0.6
22
SnoopCompile
33
@windows WinRPM
4+
ArgParse

juliastatic.jl

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
## Assumptions:
2+
## 1. gcc / x86_64-w64-mingw32-gcc is available and is in path
3+
## 2. Package ArgParse is installed
4+
5+
using PackageCompiler, ArgParse
6+
7+
function main(args)
8+
9+
s = ArgParseSettings("Static Julia Compiler",
10+
version = "$(basename(@__FILE__)) version 0.7-DEV",
11+
add_version = true)
12+
13+
@add_arg_table s begin
14+
"juliaprog"
15+
arg_type = String
16+
required = true
17+
help = "Julia program to compile"
18+
"cprog"
19+
arg_type = String
20+
default = nothing
21+
help = "C program to compile (required only when building an executable; if not provided a minimal driver program is used)"
22+
"builddir"
23+
arg_type = String
24+
default = "builddir"
25+
help = "build directory, either absolute or relative to the Julia program directory"
26+
"--verbose", "-v"
27+
action = :store_true
28+
help = "increase verbosity"
29+
"--quiet", "-q"
30+
action = :store_true
31+
help = "suppress non-error messages"
32+
"--clean", "-c"
33+
action = :store_true
34+
help = "delete builddir"
35+
"--sysimage", "-J"
36+
arg_type = String
37+
default = nothing
38+
metavar = "<file>"
39+
help = "start up with the given system image file"
40+
"--compile"
41+
arg_type = String
42+
default = nothing
43+
metavar = "{yes|no|all|min}"
44+
range_tester = (x -> x == "yes" || x == "no" || x == "all" || x == "min")
45+
help = "enable or disable JIT compiler, or request exhaustive compilation"
46+
"--cpu-target", "-C"
47+
arg_type = String
48+
default = nothing
49+
metavar = "<target>"
50+
help = "limit usage of CPU features up to <target>"
51+
"--optimize", "-O"
52+
arg_type = Int
53+
default = nothing
54+
metavar = "{0,1,2,3}"
55+
range_tester = (x -> 0 <= x <= 3)
56+
help = "set optimization level"
57+
"-g"
58+
arg_type = Int
59+
default = nothing
60+
dest_name = "debug"
61+
metavar = "{0,1,2}"
62+
range_tester = (x -> 0 <= x <= 2)
63+
help = "set debugging information level"
64+
"--inline"
65+
arg_type = String
66+
default = nothing
67+
metavar = "{yes|no}"
68+
range_tester = (x -> x == "yes" || x == "no")
69+
help = "control whether inlining is permitted"
70+
"--check-bounds"
71+
arg_type = String
72+
default = nothing
73+
metavar = "{yes|no}"
74+
range_tester = (x -> x == "yes" || x == "no")
75+
help = "emit bounds checks always or never"
76+
"--math-mode"
77+
arg_type = String
78+
default = nothing
79+
metavar = "{ieee,fast}"
80+
range_tester = (x -> x == "ieee" || x == "fast")
81+
help = "set floating point optimizations"
82+
"--depwarn"
83+
arg_type = String
84+
default = nothing
85+
metavar = "{yes|no|error}"
86+
range_tester = (x -> x == "yes" || x == "no" || x == "error")
87+
help = "set syntax and method deprecation warnings"
88+
"--autodeps", "-a"
89+
action = :store_true
90+
help = "automatically build required dependencies"
91+
"--object", "-o"
92+
action = :store_true
93+
help = "build object file"
94+
"--shared", "-s"
95+
action = :store_true
96+
help = "build shared library"
97+
"--executable", "-e"
98+
action = :store_true
99+
help = "build executable file"
100+
"--julialibs", "-j"
101+
action = :store_true
102+
help = "sync Julia libraries to builddir"
103+
end
104+
105+
s.epilog = """
106+
examples:\n
107+
\ua0\ua0juliac.jl -vae hello.jl # verbose, build executable and deps\n
108+
\ua0\ua0juliac.jl -vae hello.jl prog.c # embed into user defined C program\n
109+
\ua0\ua0juliac.jl -qo hello.jl # quiet, build object file only\n
110+
\ua0\ua0juliac.jl -vosej hello.jl # build all and sync Julia libs\n
111+
"""
112+
113+
parsed_args = parse_args(args, s)
114+
115+
# TODO: in future it may be possible to broadcast dictionary indexing, see: https://discourse.julialang.org/t/accessing-multiple-values-of-a-dictionary/8648
116+
if !any(getindex.(parsed_args, ["clean", "object", "shared", "executable", "julialibs"]))
117+
parsed_args["quiet"] || println("Nothing to do, exiting\nTry \"$(basename(@__FILE__)) -h\" for more information")
118+
exit(0)
119+
end
120+
121+
kw_args = map(parsed_args) do kv
122+
Symbol(replace(kv[1], "-", "_")) => kv[2]
123+
end
124+
kw_args = filter((k, v)-> k != :juliaprog, kw_args)
125+
PackageCompiler.julia_compile(
126+
parsed_args["juliaprog"];
127+
kw_args...
128+
)
129+
end
130+
131+
main(ARGS)

src/PackageCompiler.jl

Lines changed: 28 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,24 @@
11
__precompile__()
22
module PackageCompiler
33

4+
5+
# TODO: remove once Julia v0.7 is released
6+
const julia_v07 = VERSION > v"0.7-"
7+
8+
49
using SnoopCompile
10+
using ArgParse
11+
julia_v07 && using Libdl
512

13+
14+
include("juliac.jl")
615
include("build_sysimg.jl")
16+
include("snooping.jl")
717

818
const sysimage_binaries = (
919
"sys.o", "sys.$(Libdl.dlext)", "sys.ji", "inference.o", "inference.ji"
1020
)
1121

12-
function snoop(path, compilationfile, csv)
13-
cd(@__DIR__)
14-
# Snoop compiler can't handle the path as a variable, so we just create a file
15-
open(joinpath("snoopy.jl"), "w") do io
16-
println(io, "include(\"$(escape_string(path))\")")
17-
end
18-
SnoopCompile.@snoop csv begin
19-
include("snoopy.jl")
20-
end
21-
data = SnoopCompile.read(csv)
22-
pc = SnoopCompile.parcel(reverse!(data[2]))
23-
delims = r"([\{\} \n\(\),])_([\{\} \n\(\),])"
24-
tmp_mod = eval(:(module $(gensym()) end))
25-
open(compilationfile, "w") do io
26-
for (k, v) in pc
27-
k == :unknown && continue
28-
try
29-
eval(tmp_mod, :(using $k))
30-
println(io, "using $k")
31-
info("using $k")
32-
catch e
33-
println("Module not found: $k")
34-
end
35-
end
36-
for (k, v) in pc
37-
for ln in v
38-
# replace `_` for free parameters, which print out a warning otherwise
39-
ln = replace(ln, delims, s"\1XXX\2")
40-
# only print out valid lines
41-
# TODO figure out the actual problems and why snoop compile emits invalid code
42-
try
43-
parse(ln) # parse to make sure expression is parsing without error
44-
# wrap in try catch to catch problematic code emitted by SnoopCompile
45-
# without interupting the whole precompilation
46-
# (usually, SnoopCompile emits 1% erroring statements)
47-
println(io, "try\n ", ln, "\nend")
48-
catch e
49-
warn("Not emitted because code couldn't parse: ", ln)
50-
end
51-
end
52-
end
53-
end
54-
end
5522

5623
function copy_system_image(src, dest, ignore_missing = false)
5724
for file in sysimage_binaries
@@ -67,6 +34,19 @@ function copy_system_image(src, dest, ignore_missing = false)
6734
end
6835
end
6936

37+
"""
38+
Replaces the julia system image forcefully with a system image located at `image_path`
39+
"""
40+
function replace_jl_sysimg(image_path, debug = false)
41+
syspath = default_sysimg_path(debug)
42+
backup = sysimgbackup_folder()
43+
# create a backup
44+
# if syspath has missing files, ignore, since it will get replaced anyways
45+
copy_system_image(syspath, backup, true)
46+
info("Overwriting system image!")
47+
copy_system_image(image_path, syspath)
48+
end
49+
7050

7151
"""
7252
Builds a clean system image, similar to a fresh Julia install.
@@ -140,38 +120,7 @@ function compile_package(packages...; kw_args...)
140120
compile_package(args...; kw_args...)
141121
end
142122

143-
"""
144-
snoop_userimg(userimg, packages::Tuple{String, String}...)
145123

146-
Traces all function calls in packages and writes out `precompile` statements into the file `userimg`
147-
"""
148-
function snoop_userimg(userimg, packages::Tuple{String, String}...)
149-
snooped_precompiles = map(packages) do package_snoopfile
150-
package, snoopfile = package_snoopfile
151-
abs_package_path = if ispath(package)
152-
normpath(abspath(package))
153-
else
154-
Pkg.dir(package)
155-
end
156-
file2snoop = normpath(abspath(joinpath(abs_package_path, snoopfile)))
157-
package = package_folder(get_root_dir(abs_package_path))
158-
isdir(package) || mkpath(package)
159-
precompile_file = joinpath(package, "precompile.jl")
160-
snoop(
161-
file2snoop,
162-
precompile_file,
163-
joinpath(package, "snooped.csv")
164-
)
165-
precompile_file
166-
end
167-
open(userimg, "w") do io
168-
for path in snooped_precompiles
169-
write(io, open(read, path))
170-
println(io)
171-
end
172-
end
173-
userimg
174-
end
175124

176125

177126
"""
@@ -187,11 +136,12 @@ function compile_package(packages::Tuple{String, String}...; force = false, reus
187136
snoop_userimg(userimg, packages...)
188137
end
189138
!isfile(userimg) && reuse && error("Nothing to reuse. Please run `compile_package(reuse = true)`")
190-
image_path = sysimg_folder("sys")
139+
image_path = sysimg_folder()
191140
build_sysimg(image_path, "native", userimg)
141+
imgfile = joinpath(image_path, "sys.$(Libdl.dlext)")
192142
if force
193143
try
194-
replace_jl_sysimg(sysimg_folder(), debug)
144+
replace_jl_sysimg(image_path, debug)
195145
info(
196146
"Replaced system image successfully. Next start of julia will load the newly compiled system image.
197147
If you encounter any errors with the new julia image, try `PackageCompiler.revert([debug = false])`"
@@ -213,28 +163,15 @@ function compile_package(packages::Tuple{String, String}...; force = false, reus
213163
else
214164
info("""
215165
Not replacing system image.
216-
You can start julia with julia -J $(image_path) to load the compiled files.
166+
You can start julia with julia -J $(imgfile) to load the compiled files.
217167
""")
218168
end
169+
imgfile
219170
end
220171

221-
"""
222-
Replaces the julia system image forcefully with a system image located at `image_path`
223-
"""
224-
function replace_jl_sysimg(image_path, debug = false)
225-
syspath = default_sysimg_path(debug)
226-
backup = sysimgbackup_folder()
227-
# create a backup
228-
# if syspath has missing files, ignore, since it will get replaced anyways
229-
copy_system_image(syspath, backup, true)
230-
info("Overwriting system image!")
231-
copy_system_image(image_path, syspath)
232-
end
233172

234173

235174
export compile_package, revert, build_clean_image
236175

237176

238177
end # module
239-
240-

0 commit comments

Comments
 (0)