From 8c72883dddf2d68159de71bc259886337a9e99f7 Mon Sep 17 00:00:00 2001 From: Luca Trevisani Date: Tue, 8 May 2018 22:46:55 +0200 Subject: [PATCH] Add other Julia compilation flags --- README.md | 31 +++++++++++++----- juliac.jl | 42 +++++++++++++++++++------ src/api.jl | 76 +++++++++++++++++++++++---------------------- src/snooping.jl | 4 +-- src/static_julia.jl | 55 ++++++++++++++++++++------------ test/runtests.jl | 31 +++++++++--------- 6 files changed, 146 insertions(+), 93 deletions(-) diff --git a/README.md b/README.md index e8808087..ead14baa 100644 --- a/README.md +++ b/README.md @@ -64,12 +64,15 @@ Run `juliac.jl -h` for help: ``` usage: juliac.jl [-v] [-q] [-d ] [-n ] [-c] [-a] [-o] [-s] - [-e] [-j] [-J ] [--compile {yes|no|all|min}] - [-C ] [-O {0,1,2,3}] [-g {0,1,2}] - [--inline {yes|no}] [--check-bounds {yes|no}] - [--math-mode {ieee,fast}] [--depwarn {yes|no|error}] - [--cc ] [--cc-flags ] [--version] [-h] - juliaprog [cprog] + [-e] [-j] [-J ] [--precompiled {yes|no}] + [--compilecache {yes|no}] [-H ] + [--startup-file {yes|no}] [--handle-signals {yes|no}] + [--compile {yes|no|all|min}] [-C ] + [-O {0,1,2,3}] [-g ] [--inline {yes|no}] + [--check-bounds {yes|no}] [--math-mode {ieee,fast}] + [--depwarn {yes|no|error}] [--cc ] + [--cc-flags ] [--version] [-h] juliaprog + [cprog] Static Julia Compiler @@ -92,15 +95,27 @@ optional arguments: -j, --julialibs copy Julia libraries to build directory -J, --sysimage start up with the given system image file + --precompiled {yes|no} + use precompiled code from system image if + available + --compilecache {yes|no} + enable/disable incremental precompilation of + modules + -H, --home set location of `julia` executable + --startup-file {yes|no} + load ~/.juliarc.jl + --handle-signals {yes|no} + enable or disable Julia's default signal + handlers --compile {yes|no|all|min} enable or disable JIT compiler, or request exhaustive compilation -C, --cpu-target limit usage of CPU features up to - (forces --precompiled=no) + (implies default `--precompiled=no`) -O, --optimize {0,1,2,3} set the optimization level (type: Int64) - -g {0,1,2} enable / set the level of debug info + -g enable / set the level of debug info generation (type: Int64) --inline {yes|no} control whether inlining is permitted --check-bounds {yes|no} diff --git a/juliac.jl b/juliac.jl index 5b051dd3..aef14d9f 100644 --- a/juliac.jl +++ b/juliac.jl @@ -50,45 +50,69 @@ Base.@ccallable function julia_main(args::Vector{String})::Cint arg_type = String metavar = "" help = "start up with the given system image file" + "--precompiled" + arg_type = String + metavar = "{yes|no}" + range_tester = (x -> x ∈ ("yes", "no")) + help = "use precompiled code from system image if available" + "--compilecache" + arg_type = String + metavar = "{yes|no}" + range_tester = (x -> x ∈ ("yes", "no")) + help = "enable/disable incremental precompilation of modules" + "--home", "-H" + arg_type = String + metavar = "" + help = "set location of `julia` executable" + "--startup-file" + arg_type = String + metavar = "{yes|no}" + range_tester = (x -> x ∈ ("yes", "no")) + help = "load ~/.juliarc.jl" + "--handle-signals" + arg_type = String + metavar = "{yes|no}" + range_tester = (x -> x ∈ ("yes", "no")) + help = "enable or disable Julia's default signal handlers" "--compile" arg_type = String metavar = "{yes|no|all|min}" - range_tester = (x -> x == "yes" || x == "no" || x == "all" || x == "min") + range_tester = (x -> x ∈ ("yes", "no", "all", "min")) help = "enable or disable JIT compiler, or request exhaustive compilation" "--cpu-target", "-C" arg_type = String metavar = "" - help = "limit usage of CPU features up to (forces --precompiled=no)" + help = "limit usage of CPU features up to (implies default `--precompiled=no`)" "--optimize", "-O" arg_type = Int metavar = "{0,1,2,3}" - range_tester = (x -> 0 <= x <= 3) + range_tester = (x -> x ∈ (0, 1, 2, 3)) help = "set the optimization level" "-g" arg_type = Int dest_name = "debug" - metavar = "{0,1,2}" - range_tester = (x -> 0 <= x <= 2) + metavar = "" + range_tester = (x -> x ∈ (0, 1, 2)) help = "enable / set the level of debug info generation" "--inline" arg_type = String metavar = "{yes|no}" - range_tester = (x -> x == "yes" || x == "no") + range_tester = (x -> x ∈ ("yes", "no")) help = "control whether inlining is permitted" "--check-bounds" arg_type = String metavar = "{yes|no}" - range_tester = (x -> x == "yes" || x == "no") + range_tester = (x -> x ∈ ("yes", "no")) help = "emit bounds checks always or never" "--math-mode" arg_type = String metavar = "{ieee,fast}" - range_tester = (x -> x == "ieee" || x == "fast") + range_tester = (x -> x ∈ ("ieee", "fast")) help = "disallow or enable unsafe floating point optimizations" "--depwarn" arg_type = String metavar = "{yes|no|error}" - range_tester = (x -> x == "yes" || x == "no" || x == "error") + range_tester = (x -> x ∈ ("yes", "no", "error")) help = "enable or disable syntax and method deprecation warnings" "--cc" arg_type = String diff --git a/src/api.jl b/src/api.jl index a74526ff..20159759 100644 --- a/src/api.jl +++ b/src/api.jl @@ -10,41 +10,43 @@ current processor. Include the user image file given by `userimg_path`, which sh directives such as `using MyPackage` to include that package in the new system image. New system image will not replace an older image unless `force` is set to true. """ -function build_sysimg(sysimg_path, userimg_path = nothing; +function build_sysimg( + sysimg_path, userimg_path = nothing; verbose = false, quiet = false, - cpu_target = nothing, optimize = nothing, - debug = nothing, inline = nothing, check_bounds = nothing, - math_mode = nothing + precompiled = nothing, compilecache = nothing, + home = nothing, startup_file = nothing, handle_signals = nothing, + compile = nothing, cpu_target = nothing, optimize = nothing, debug = nothing, + inline = nothing, check_bounds = nothing, math_mode = nothing, depwarn = nothing ) # build vanilla backup system image clean_sysimg = get_backup!(contains(basename(Base.julia_cmd().exec[1]), "debug"), cpu_target) static_julia( - userimg_path, outname = "sys", - cpu_target = cpu_target, optimize = optimize, - debug = debug, inline = inline, check_bounds = check_bounds, - math_mode = math_mode, verbose = verbose, quiet = quiet, - cprog = nothing, builddir = sysimg_path, - clean = false, sysimage = clean_sysimg, - compile = nothing, depwarn = nothing, autodeps = false, - object = true, shared = true, executable = false, julialibs = false, + userimg_path, verbose = verbose, quiet = quiet, + builddir = sysimg_path, outname = "sys", + object = true, shared = true, + sysimage = clean_sysimg, precompiled = precompiled, compilecache = compilecache, + home = home, startup_file = startup_file, handle_signals = handle_signals, + compile = compile, cpu_target = cpu_target, optimize = optimize, debug = debug, + inline = inline, check_bounds = check_bounds, math_mode = math_mode, depwarn = depwarn ) end function build_shared_lib( library, library_name; verbose = false, quiet = false, - cpu_target = nothing, optimize = nothing, debug = nothing, - inline = nothing, check_bounds = nothing, math_mode = nothing + sysimage = nothing, precompiled = nothing, compilecache = nothing, + home = nothing, startup_file = nothing, handle_signals = nothing, + compile = nothing, cpu_target = nothing, optimize = nothing, debug = nothing, + inline = nothing, check_bounds = nothing, math_mode = nothing, depwarn = nothing ) static_julia( - library, outname = library_name, - cpu_target = cpu_target, optimize = optimize, - debug = debug, inline = inline, check_bounds = check_bounds, - math_mode = math_mode, verbose = verbose, quiet = quiet, - cprog = nothing, builddir = sysimg_path, - clean = false, sysimage = nothing, - compile = nothing, depwarn = nothing, autodeps = false, - object = true, shared = true, executable = false, julialibs = true, + library, verbose = verbose, quiet = quiet, + builddir = sysimg_path, outname = library_name, + object = true, shared = true, julialibs = true, + sysimage = sysimage, precompiled = precompiled, compilecache = compilecache, + home = home, startup_file = startup_file, handle_signals = handle_signals, + compile = compile, cpu_target = cpu_target, optimize = optimize, debug = debug, + inline = inline, check_bounds = check_bounds, math_mode = math_mode, depwarn = depwarn ) end @@ -52,8 +54,8 @@ end build_executable( library, library_name = splitext(basename(library))[1], - cprogram = joinpath(@__DIR__, "..", "examples", "program.c"); - snoopfile = nothing, builddir = "build", + cprog = joinpath(@__DIR__, "..", "examples", "program.c"); + snoopfile = nothing, builddir = "builddir", verbose = false, quiet = false, cpu_target = nothing, optimize = nothing, debug = nothing, inline = nothing, check_bounds = nothing, math_mode = nothing @@ -63,13 +65,14 @@ end `builddir` is where library_name.exe and shared libraries will end up """ function build_executable( - library, - library_name = splitext(basename(library))[1], - cprogram = joinpath(@__DIR__, "..", "examples", "program.c"); - snoopfile = nothing, builddir = "build", + library, library_name = splitext(basename(library))[1], + cprog = joinpath(@__DIR__, "..", "examples", "program.c"); + snoopfile = nothing, builddir = "builddir", verbose = false, quiet = false, - cpu_target = nothing, optimize = nothing, debug = nothing, - inline = nothing, check_bounds = nothing, math_mode = nothing + sysimage = nothing, precompiled = nothing, compilecache = nothing, + home = nothing, startup_file = nothing, handle_signals = nothing, + compile = nothing, cpu_target = nothing, optimize = nothing, debug = nothing, + inline = nothing, check_bounds = nothing, math_mode = nothing, depwarn = nothing ) if snoopfile != nothing precompfile = joinpath(builddir, "precompiled.jl") @@ -82,14 +85,13 @@ function build_executable( library = jlmain end static_julia( - library, outname = library_name, - cpu_target = cpu_target, optimize = optimize, - debug = debug, inline = inline, check_bounds = check_bounds, - math_mode = math_mode, verbose = verbose, quiet = quiet, - cprog = cprogram, builddir = builddir, - clean = false, sysimage = nothing, - compile = nothing, depwarn = nothing, autodeps = false, + library, cprog = cprog, verbose = verbose, quiet = quiet, + builddir = builddir, outname = library_name, object = true, shared = true, executable = true, julialibs = true, + sysimage = sysimage, precompiled = precompiled, compilecache = compilecache, + home = home, startup_file = startup_file, handle_signals = handle_signals, + compile = compile, cpu_target = cpu_target, optimize = optimize, debug = debug, + inline = inline, check_bounds = check_bounds, math_mode = math_mode, depwarn = depwarn ) end diff --git a/src/snooping.jl b/src/snooping.jl index abe40dd9..3bf839ec 100644 --- a/src/snooping.jl +++ b/src/snooping.jl @@ -6,8 +6,8 @@ function snoop_vanilla(filename, path) end """ julia_cmd = build_julia_cmd( - get_backup!(false, nothing), nothing, nothing, nothing, nothing, - nothing, nothing, nothing, nothing, false + get_backup!(false, nothing), nothing, nothing, nothing, nothing, nothing, + nothing, nothing, nothing, nothing, nothing, nothing, nothing, nothing ) @show julia_cmd in, io = open(`$julia_cmd --eval $code_object`, "w", STDOUT) diff --git a/src/static_julia.jl b/src/static_julia.jl index e4216316..2f29007a 100644 --- a/src/static_julia.jl +++ b/src/static_julia.jl @@ -42,10 +42,15 @@ compiles the Julia file at path `juliaprog` with keyword arguments: executable build executable file julialibs copy Julia libraries to build directory sysimage start up with the given system image file + precompiled {yes|no} use precompiled code from system image if available + compilecache {yes|no} enable/disable incremental precompilation of modules + home set location of `julia` executable + startup_file {yes|no} load ~/.juliarc.jl + handle_signals {yes|no} enable or disable Julia's default signal handlers compile {yes|no|all|min} enable or disable JIT compiler, or request exhaustive compilation cpu_target limit usage of CPU features up to (forces --precompiled=no) optimize {0,1,2,3} set the optimization level - debug {0,1,2} enable / set the level of debug info generation + debug enable / set the level of debug info generation inline {yes|no} control whether inlining is permitted check_bounds {yes|no} emit bounds checks always or never math_mode {ieee,fast} disallow or enable unsafe floating point optimizations @@ -58,9 +63,10 @@ function static_julia( cprog = joinpath(@__DIR__, "..", "examples", "program.c"), verbose = false, quiet = false, builddir = "builddir", outname = splitext(basename(juliaprog))[1], clean = false, autodeps = false, object = false, shared = false, executable = false, julialibs = false, - sysimage = nothing, compile = nothing, cpu_target = nothing, - optimize = nothing, debug = nothing, inline = nothing, - check_bounds = nothing, math_mode = nothing, depwarn = nothing, + sysimage = nothing, precompiled = nothing, compilecache = nothing, + home = nothing, startup_file = nothing, handle_signals = nothing, + compile = nothing, cpu_target = nothing, optimize = nothing, debug = nothing, + inline = nothing, check_bounds = nothing, math_mode = nothing, depwarn = nothing, cc = system_compiler(), cc_flags = nothing ) @@ -121,8 +127,8 @@ function static_julia( object && build_object( juliaprog, o_file, verbose, - sysimage, compile, cpu_target, optimize, debug, inline, check_bounds, - math_mode, depwarn + sysimage, precompiled, compilecache, home, startup_file, handle_signals, + compile, cpu_target, optimize, debug, inline, check_bounds, math_mode, depwarn ) shared && build_shared(s_file, o_file, verbose, optimize, debug, cc, cc_flags) @@ -156,36 +162,43 @@ function julia_flags(optimize, debug, cc_flags) end function build_julia_cmd( - sysimage, compile, cpu_target, optimize, debug, inline, check_bounds, - math_mode, depwarn, startupfile = false + sysimage, precompiled, compilecache, home, startup_file, handle_signals, + compile, cpu_target, optimize, debug, inline, check_bounds, math_mode, depwarn ) + # TODO: `precompiled` and `compilecache` may be removed in future, see: https://github.com/JuliaLang/PackageCompiler.jl/issues/47 + precompiled == nothing && cpu_target != nothing && (precompiled = "no") + compilecache == nothing && (compilecache = "no") + # TODO: `startup_file` may be removed in future with `julia-compile`, see: https://github.com/JuliaLang/julia/issues/15864 + startup_file == nothing && (startup_file = "no") julia_cmd = `$(Base.julia_cmd())` if length(julia_cmd.exec) != 5 || !all(startswith.(julia_cmd.exec[2:5], ["-C", "-J", "--compile", "--depwarn"])) error("Unexpected format of \"Base.julia_cmd()\", you may be using an incompatible version of Julia") end sysimage == nothing || (julia_cmd.exec[3] = "-J$sysimage") - push!(julia_cmd.exec, string("--startup-file=", startupfile ? "yes" : "no")) + precompiled == nothing || push!(julia_cmd.exec, "--precompiled=$precompiled") + compilecache == nothing || push!(julia_cmd.exec, "--compilecache=$compilecache") + home == nothing || push!(julia_cmd.exec, "-H=$home") + startup_file == nothing || push!(julia_cmd.exec, "--startup-file=$startup_file") + handle_signals == nothing || push!(julia_cmd.exec, "--handle-signals=$handle_signals") compile == nothing || (julia_cmd.exec[4] = "--compile=$compile") - cpu_target == nothing || (julia_cmd.exec[2] = "-C$cpu_target"; - push!(julia_cmd.exec, "--precompiled=no")) + cpu_target == nothing || (julia_cmd.exec[2] = "-C$cpu_target") optimize == nothing || push!(julia_cmd.exec, "-O$optimize") debug == nothing || push!(julia_cmd.exec, "-g$debug") inline == nothing || push!(julia_cmd.exec, "--inline=$inline") check_bounds == nothing || push!(julia_cmd.exec, "--check-bounds=$check_bounds") math_mode == nothing || push!(julia_cmd.exec, "--math-mode=$math_mode") depwarn == nothing || (julia_cmd.exec[5] = "--depwarn=$depwarn") - push!(julia_cmd.exec, "--compilecache=no") julia_cmd end function build_object( juliaprog, o_file, verbose, - sysimage, compile, cpu_target, optimize, debug, inline, check_bounds, - math_mode, depwarn + sysimage, precompiled, compilecache, home, startup_file, handle_signals, + compile, cpu_target, optimize, debug, inline, check_bounds, math_mode, depwarn ) julia_cmd = build_julia_cmd( - sysimage, compile, cpu_target, optimize, debug, inline, check_bounds, - math_mode, depwarn, false + sysimage, precompiled, compilecache, home, startup_file, handle_signals, + compile, cpu_target, optimize, debug, inline, check_bounds, math_mode, depwarn ) if julia_v07 iswindows() && (juliaprog = replace(juliaprog, "\\", "\\\\")) @@ -205,9 +218,11 @@ function build_object( include(\"$juliaprog\") # include Julia program file empty!(Base.LOAD_CACHE_PATH) # reset / remove build-system-relative paths" end - command = `$julia_cmd -e $expr` - verbose && println("Build \".ji\" local cache:\n $command") - run(command) + if compilecache == "yes" + command = `$julia_cmd -e $expr` + verbose && println("Build \".ji\" local cache:\n $command") + run(command) + end command = `$julia_cmd --output-o $o_file -e $expr` verbose && println("Build object file \"$o_file\":\n $command") run(command) @@ -279,5 +294,5 @@ function copy_julia_libs(verbose) copy = true end end - copy || verbose && println(" none") + verbose && !copy && println(" none") end diff --git a/test/runtests.jl b/test/runtests.jl index e54e632c..c280fa70 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -23,48 +23,45 @@ julia = Base.julia_cmd().exec[1] end end - @testset "juliac" begin - mktempdir() do build + mktempdir() do builddir juliac = joinpath(@__DIR__, "..", "juliac.jl") jlfile = joinpath(@__DIR__, "..", "examples", "hello.jl") cfile = joinpath(@__DIR__, "..", "examples", "program.c") - @test success(`$julia $juliac -vosej $jlfile $cfile --builddir $build`) - @test isfile(joinpath(build, "hello.$(Libdl.dlext)")) - @test isfile(joinpath(build, "hello$(executable_ext())")) - cd(build) do + @test success(`$julia $juliac -vosej $jlfile $cfile --builddir $builddir`) + @test isfile(joinpath(builddir, "hello.$(Libdl.dlext)")) + @test isfile(joinpath(builddir, "hello$(executable_ext())")) + cd(builddir) do @test success(`./$("hello$(executable_ext())")`) end @testset "--cc-flags" begin # Try passing `--help` to $cc. This should work for any system compiler. # Then grep the output for "-g", which should be present on any system. - @test contains(readstring(`$julia $juliac -se --cc-flags='--help' $jlfile $cfile --builddir $build`), "-g") + @test contains(readstring(`$julia $juliac -se --cc-flags='--help' $jlfile $cfile --builddir $builddir`), "-g") # Just as a control, make sure that without passing '--help', we don't see "-g" - @test !contains(readstring(`$julia $juliac -se $jlfile $cfile --builddir $build`), "-g") + @test !contains(readstring(`$julia $juliac -se $jlfile $cfile --builddir $builddir`), "-g") end end end @testset "build_executable" begin - build = mktempdir() + builddir = mktempdir() jlfile = joinpath(@__DIR__, "..", "examples", "hello.jl") - snoopfile = open(joinpath(build, "snoop.jl"), "w") do io + snoopfile = open(joinpath(builddir, "snoop.jl"), "w") do io write(io, open(read, jlfile)) println(io) println(io, "using .Hello; Hello.julia_main(String[])") end build_executable( - jlfile, - snoopfile = snoopfile, builddir = build, - verbose = false, quiet = false, + jlfile, snoopfile = snoopfile, builddir = builddir ) - @test isfile(joinpath(build, "hello.$(Libdl.dlext)")) - @test isfile(joinpath(build, "hello$(executable_ext())")) - cd(build) do + @test isfile(joinpath(builddir, "hello.$(Libdl.dlext)")) + @test isfile(joinpath(builddir, "hello$(executable_ext())")) + cd(builddir) do @test success(`./$("hello$(executable_ext())")`) end for i = 1:100 - try rm(build, recursive = true) end + try rm(builddir, recursive = true) end sleep(1/100) end end