22# # 1. gcc / x86_64-w64-mingw32-gcc is available and is in path
33# # 2. Package ArgParse is installed
44
5+ # TODO : remove once Julia v0.7 is released
6+ julia_v07 = VERSION > v " 0.7-"
7+
58using ArgParse
9+ julia_v07 && using Libdl
610
711function main (args)
812
9- s = ArgParseSettings (" Julia AOT compiler" *
10- " \n\n helper script to build libraries and executables from Julia code" ,
11- version = " $(basename (@__FILE__ )) version 0.6" ,
13+ s = ArgParseSettings (" Static Julia Compiler" ,
14+ version = " $(basename (@__FILE__ )) version 0.7-DEV" ,
1215 add_version = true )
1316
1417 @add_arg_table s begin
@@ -19,7 +22,7 @@ function main(args)
1922 " cprog"
2023 arg_type = String
2124 default = nothing
22- help = " C program to compile (required only when building an executable; if not provided a minimal standard program is used)"
25+ help = " C program to compile (required only when building an executable; if not provided a minimal driver program is used)"
2326 " builddir"
2427 arg_type = String
2528 default = " builddir"
@@ -86,7 +89,7 @@ function main(args)
8689 metavar = " {yes|no|error}"
8790 range_tester = (x -> x == " yes" || x == " no" || x == " error" )
8891 help = " set syntax and method deprecation warnings"
89- " --auto " , " -a"
92+ " --autodeps " , " -a"
9093 action = :store_true
9194 help = " automatically build required dependencies"
9295 " --object" , " -o"
@@ -105,15 +108,16 @@ function main(args)
105108
106109 s. epilog = """
107110 examples:\n
108- \u a0\u a0juliac.jl -vae hello.jl # verbose, auto, build executable\n
109- \u a0\u a0juliac.jl -vae hello.jl myprog .c # embed into user defined C program\n
110- \u a0\u a0juliac.jl -qo hello.jl # quiet, build object file only\n
111- \u a0\u a0juliac.jl -vosej hello.jl # build all and sync Julia libs\n
111+ \u a0\u a0juliac.jl -vae hello.jl # verbose, build executable and deps \n
112+ \u a0\u a0juliac.jl -vae hello.jl prog .c # embed into user defined C program\n
113+ \u a0\u a0juliac.jl -qo hello.jl # quiet, build object file only\n
114+ \u a0\u a0juliac.jl -vosej hello.jl # build all and sync Julia libs\n
112115 """
113116
114117 parsed_args = parse_args (args, s)
115118
116- if ! any ([parsed_args[" clean" ], parsed_args[" object" ], parsed_args[" shared" ], parsed_args[" executable" ], parsed_args[" julialibs" ]])
119+ # TODO : in future it may be possible to broadcast dictionary indexing, see: https://discourse.julialang.org/t/accessing-multiple-values-of-a-dictionary/8648
120+ if ! any (getindex .(parsed_args, [" clean" , " object" , " shared" , " executable" , " julialibs" ]))
117121 parsed_args[" quiet" ] || println (" Nothing to do, exiting\n Try \" $(basename (@__FILE__ )) -h\" for more information" )
118122 exit (0 )
119123 end
@@ -134,7 +138,7 @@ function main(args)
134138 parsed_args[" check-bounds" ],
135139 parsed_args[" math-mode" ],
136140 parsed_args[" depwarn" ],
137- parsed_args[" auto " ],
141+ parsed_args[" autodeps " ],
138142 parsed_args[" object" ],
139143 parsed_args[" shared" ],
140144 parsed_args[" executable" ],
@@ -145,11 +149,11 @@ end
145149function julia_compile (julia_program, c_program= nothing , build_dir= " builddir" , verbose= false , quiet= false ,
146150 clean= false , sysimage = nothing , compile= nothing , cpu_target= nothing , optimize= nothing ,
147151 debug= nothing , inline= nothing , check_bounds= nothing , math_mode= nothing , depwarn= nothing ,
148- auto = false , object= false , shared= false , executable= true , julialibs= true )
152+ autodeps = false , object= false , shared= false , executable= true , julialibs= true )
149153
150- verbose && quiet && (verbose = false )
154+ verbose && quiet && (quiet = false )
151155
152- if auto
156+ if autodeps
153157 executable && (shared = true )
154158 shared && (object = true )
155159 end
@@ -193,12 +197,21 @@ function julia_compile(julia_program, c_program=nothing, build_dir="builddir", v
193197 julia_program_basename = splitext (basename (julia_program))[1 ]
194198 o_file = julia_program_basename * " .o"
195199 s_file = " lib" * julia_program_basename * " .$(Libdl. dlext) "
196- e_file = julia_program_basename * (is_windows () ? " .exe" : " " )
200+ if julia_v07
201+ e_file = julia_program_basename * (Sys. iswindows () ? " .exe" : " " )
202+ else
203+ e_file = julia_program_basename * (is_windows () ? " .exe" : " " )
204+ end
197205 tmp_dir = " tmp_v$VERSION "
198206
199207 # TODO : these should probably be emitted from julia-config also:
200- shlibdir = is_windows () ? JULIA_HOME : abspath (JULIA_HOME, Base. LIBDIR)
201- private_shlibdir = abspath (JULIA_HOME, Base. PRIVATE_LIBDIR)
208+ if julia_v07
209+ shlibdir = Sys. iswindows () ? Sys. BINDIR : abspath (Sys. BINDIR, Base. LIBDIR)
210+ private_shlibdir = abspath (Sys. BINDIR, Base. PRIVATE_LIBDIR)
211+ else
212+ shlibdir = is_windows () ? JULIA_HOME : abspath (JULIA_HOME, Base. LIBDIR)
213+ private_shlibdir = abspath (JULIA_HOME, Base. PRIVATE_LIBDIR)
214+ end
202215
203216 if object
204217 julia_cmd = ` $(Base. julia_cmd ()) `
@@ -215,66 +228,111 @@ function julia_compile(julia_program, c_program=nothing, build_dir="builddir", v
215228 check_bounds == nothing || push! (julia_cmd. exec, " --check-bounds=$check_bounds " )
216229 math_mode == nothing || push! (julia_cmd. exec, " --math-mode=$math_mode " )
217230 depwarn == nothing || (julia_cmd. exec[5 ] = " --depwarn=$depwarn " )
218- is_windows () && (julia_program = replace (julia_program, " \\ " , " \\\\ " ))
219- expr = "
220- VERSION >= v\" 0.7+\" && Base.init_load_path($(repr (JULIA_HOME)) ) # initialize location of site-packages
231+ if julia_v07
232+ Sys. iswindows () && (julia_program = replace (julia_program, " \\ " , " \\\\ " ))
233+ expr = "
234+ Base.init_depot_path() # initialize package depots
235+ Base.init_load_path() # initialize location of site-packages
221236 empty!(Base.LOAD_CACHE_PATH) # reset / remove any builtin paths
222237 push!(Base.LOAD_CACHE_PATH, abspath(\" $tmp_dir \" )) # enable usage of precompiled files
223- include($( repr ( julia_program)) ) # include \" julia_program\" file
238+ include(\" $ julia_program\" ) # include \" julia_program\" file
224239 empty!(Base.LOAD_CACHE_PATH) # reset / remove build-system-relative paths"
240+ else
241+ is_windows () && (julia_program = replace (julia_program, " \\ " , " \\\\ " ))
242+ expr = "
243+ empty!(Base.LOAD_CACHE_PATH) # reset / remove any builtin paths
244+ push!(Base.LOAD_CACHE_PATH, abspath(\" $tmp_dir \" )) # enable usage of precompiled files
245+ include(\" $julia_program \" ) # include \" julia_program\" file
246+ empty!(Base.LOAD_CACHE_PATH) # reset / remove build-system-relative paths"
247+ end
248+ isdir (tmp_dir) || mkpath (tmp_dir)
225249 command = ` $julia_cmd -e $expr `
226- verbose && println (" Build \" .ji\" files :\n $command " )
250+ verbose && println (" Build module image files \" .ji\" in subdirectory \" $tmp_dir \" :\n $command " )
227251 run (command)
228252 command = ` $julia_cmd --output-o $(joinpath (tmp_dir, o_file)) -e $expr `
229- verbose && println (" Build object file \" $o_file \" :\n $command " )
253+ verbose && println (" Build object file \" $o_file \" in subdirectory \" $tmp_dir \" :\n $command " )
230254 run (command)
231255 end
232256
233257 if shared || executable
234- command = ` $(Base. julia_cmd ()) --startup-file=no $(joinpath (dirname (JULIA_HOME), " share" , " julia" , " julia-config.jl" )) `
235- cflags = Base. shell_split (readstring (` $command --cflags` ))
236- ldflags = Base. shell_split (readstring (` $command --ldflags` ))
237- ldlibs = Base. shell_split (readstring (` $command --ldlibs` ))
238- cc = is_windows () ? " x86_64-w64-mingw32-gcc" : " gcc"
258+ if julia_v07
259+ cc = Sys. iswindows () ? " x86_64-w64-mingw32-gcc" : " gcc"
260+ command = ` $(Base. julia_cmd ()) --startup-file=no $(joinpath (dirname (Sys. BINDIR), " share" , " julia" , " julia-config.jl" )) `
261+ flags = ` $(Base. shell_split (read (\ ` $command --allflags\` , String)))`
262+ else
263+ cc = is_windows () ? " x86_64-w64-mingw32-gcc" : " gcc"
264+ command = ` $(Base. julia_cmd ()) --startup-file=no $(joinpath (dirname (JULIA_HOME), " share" , " julia" , " julia-config.jl" )) `
265+ cflags = ` $(Base. shell_split (readstring (\ ` $command --cflags\` )))`
266+ ldflags = ` $(Base. shell_split (readstring (\ ` $command --ldflags\` )))`
267+ ldlibs = ` $(Base. shell_split (readstring (\ ` $command --ldlibs\` )))`
268+ flags = ` $cflags $ldflags $ldlibs `
269+ end
239270 end
240271
241272 if shared
242- command = ` $cc -m64 -shared -o $s_file $(joinpath (tmp_dir, o_file)) $cflags $ldflags $ldlibs `
243- if is_apple ()
244- command = ` $command -Wl,-install_name,@rpath/lib$julia_program_basename .dylib`
245- elseif is_windows ()
246- command = ` $command -Wl,--export-all-symbols`
273+ command = ` $cc -m64 -shared -o $s_file $(joinpath (tmp_dir, o_file)) $flags `
274+ if julia_v07
275+ if Sys. isapple ()
276+ command = ` $command -Wl,-install_name,@rpath/\" $s_file \" `
277+ elseif Sys. iswindows ()
278+ command = ` $command -Wl,--export-all-symbols`
279+ end
280+ else
281+ if is_apple ()
282+ command = ` $command -Wl,-install_name,@rpath/\" $s_file \" `
283+ elseif is_windows ()
284+ command = ` $command -Wl,--export-all-symbols`
285+ end
247286 end
248- verbose && println (" Build shared library \" $s_file \" :\n $command " )
287+ verbose && println (" Build shared library \" $s_file \" in build directory :\n $command " )
249288 run (command)
250289 end
251290
252291 if executable
253- push! (cflags, " -DJULIAC_PROGRAM_LIBNAME=\" lib$julia_program_basename \" " )
254- command = ` $cc -m64 -o $e_file $c_program $s_file $cflags $ldflags $ldlibs `
255- if is_apple ()
256- command = ` $command -Wl,-rpath,@executable_path`
257- elseif is_unix ()
258- command = ` $command -Wl,-rpath,\$ ORIGIN`
292+ command = ` $cc -m64 -DJULIAC_PROGRAM_LIBNAME=\" lib$julia_program_basename \" -o $e_file $c_program $s_file $flags `
293+ if julia_v07
294+ if Sys. isapple ()
295+ command = ` $command -Wl,-rpath,@executable_path`
296+ elseif Sys. isunix ()
297+ command = ` $command -Wl,-rpath,\$ ORIGIN`
298+ end
299+ else
300+ if is_apple ()
301+ command = ` $command -Wl,-rpath,@executable_path`
302+ elseif is_unix ()
303+ command = ` $command -Wl,-rpath,\$ ORIGIN`
304+ end
259305 end
260- verbose && println (" Build executable file \" $e_file \" :\n $command " )
306+ verbose && println (" Build executable file \" $e_file \" in build directory :\n $command " )
261307 run (command)
262308 end
263309
264310 if julialibs
265- verbose && println (" Sync Julia libraries:" )
311+ verbose && println (" Sync Julia libraries to build directory :" )
266312 libfiles = String[]
267313 dlext = " ." * Libdl. dlext
268314 for dir in (shlibdir, private_shlibdir)
269- if is_windows () || is_apple ()
270- append! (libfiles, joinpath .(dir, filter (x -> endswith (x, dlext), readdir (dir))))
315+ if julia_v07
316+ if Sys. iswindows () || Sys. isapple ()
317+ append! (libfiles, joinpath .(dir, filter (x -> endswith (x, dlext), readdir (dir))))
318+ else
319+ append! (libfiles, joinpath .(dir, filter (x -> contains (x, r" ^lib.+\. so(?:\.\d +)*$" ), readdir (dir))))
320+ end
271321 else
272- append! (libfiles, joinpath .(dir, filter (x -> ismatch (r" ^lib.+\. so(?:\.\d +)*$" , x), readdir (dir))))
322+ if is_windows () || is_apple ()
323+ append! (libfiles, joinpath .(dir, filter (x -> endswith (x, dlext), readdir (dir))))
324+ else
325+ append! (libfiles, joinpath .(dir, filter (x -> ismatch (r" ^lib.+\. so(?:\.\d +)*$" , x), readdir (dir))))
326+ end
273327 end
274328 end
275329 sync = false
276330 for src in libfiles
277- ismatch (r" debug" , src) && continue
331+ if julia_v07
332+ contains (src, r" debug" ) && continue
333+ else
334+ ismatch (r" debug" , src) && continue
335+ end
278336 dst = basename (src)
279337 if filesize (src) != filesize (dst) || ctime (src) > ctime (dst) || mtime (src) > mtime (dst)
280338 verbose && println (" $dst " )
0 commit comments