From ef382d0a7aec1a44d4463527551a92326d71b2be Mon Sep 17 00:00:00 2001 From: jake bolewski Date: Thu, 18 Dec 2014 14:09:01 -0500 Subject: [PATCH] Parse all command line options in repl.c - consolidate all compiler / cmdline options into jl_options_t struct in julia.h - add options.jl to base/ with an immutable type JLOptions that reflects the jl_options_t struct - add --procs= command line flag (equivalent to -p ) - add --history-file={yes|no} and --startup-file={yes|no} cmdline opts - deprecate -f, -F, --no-startup, --no-history-file cmdline flags - add tests for cmdline arguments in test/cmdlineargs.jl - modify test/Makefile and tests to use long command line option, add command line argument tests to runtests.jl - update relevant docs in the manual and manpages --- Makefile | 2 +- base/client.jl | 227 +++++++++++++----------- base/deprecated.jl | 2 +- base/inference.jl | 23 +-- base/options.jl | 33 ++++ base/sysimg.jl | 1 + base/util.jl | 2 +- doc/man/julia.1 | 84 +++++---- doc/manual/getting-started.rst | 78 +++++---- src/ast.c | 6 +- src/cgutils.cpp | 12 +- src/codegen.cpp | 20 +-- src/dump.c | 2 +- src/gf.c | 2 +- src/init.c | 110 +++++++----- src/jlapi.c | 10 +- src/julia.h | 59 +++++-- src/toplevel.c | 2 +- test/Makefile | 2 +- test/cmdlineargs.jl | 157 +++++++++++++++++ test/repl.jl | 4 +- test/runtests.jl | 2 +- test/spawn.jl | 2 +- ui/repl.c | 312 +++++++++++++++++++++++---------- 24 files changed, 767 insertions(+), 387 deletions(-) create mode 100644 base/options.jl create mode 100644 test/cmdlineargs.jl diff --git a/Makefile b/Makefile index aaaabf3909c33..59e0596c21815 100644 --- a/Makefile +++ b/Makefile @@ -148,7 +148,7 @@ BASE_SRCS := $(wildcard base/*.jl base/*/*.jl base/*/*/*.jl) $(build_private_libdir)/sys.o: VERSION $(BASE_SRCS) $(build_docdir)/helpdb.jl $(build_private_libdir)/sys0.$(SHLIB_EXT) @$(call PRINT_JULIA, cd base && \ $(call spawn,$(JULIA_EXECUTABLE)) -C $(JULIA_CPU_TARGET) --build $(call cygpath_w,$(build_private_libdir)/sys) \ - -J$(call cygpath_w,$(build_private_libdir))/$$([ -e $(build_private_libdir)/sys.ji ] && echo sys.ji || echo sys0.ji) -f sysimg.jl \ + -J$(call cygpath_w,$(build_private_libdir))/$$([ -e $(build_private_libdir)/sys.ji ] && echo sys.ji || echo sys0.ji) --startup-file=no sysimg.jl \ || { echo '*** This error is usually fixed by running `make clean`. If the error persists$(,) try `make cleanall`. ***' && false; } ) $(build_bindir)/stringreplace: contrib/stringreplace.c | $(build_bindir) diff --git a/base/client.jl b/base/client.jl index fb0a71e980792..24030c4c874e6 100644 --- a/base/client.jl +++ b/base/client.jl @@ -183,12 +183,10 @@ end # try to include() a file, ignoring if not found try_include(path::AbstractString) = isfile(path) && include(path) -function init_bind_addr(args::Vector{UTF8String}) - # Treat --bind-to in a position independent manner in ARGS since - # --worker, -n and --machinefile options are affected by it - btoidx = findfirst(args, "--bind-to") - if btoidx > 0 - bind_to = split(args[btoidx+1], ":") +# initialize the local proc network address / port +function init_bind_addr(opts::JLOptions) + if opts.bindto != C_NULL + bind_to = split(bytestring(opts.bindto), ":") bind_addr = string(parseip(bind_to[1])) if length(bind_to) > 1 bind_port = parseint(bind_to[2]) @@ -210,113 +208,122 @@ function init_bind_addr(args::Vector{UTF8String}) LPROC.bind_port = uint16(bind_port) end - -function process_options(args::Vector{UTF8String}) - quiet = false - repl = true - startup = true - color_set = false - no_history_file = false - i = 1 - while i <= length(args) - if args[i]=="-q" || args[i]=="--quiet" - quiet = true - elseif args[i]=="--worker" - start_worker() - # doesn't return - elseif args[i]=="--bind-to" - i+=1 # has already been processed - elseif args[i]=="-e" || args[i]=="--eval" - i == length(args) && error("-e,--eval no provided") - repl = false - i+=1 - splice!(ARGS, 1:length(ARGS), args[i+1:end]) - eval(Main,parse_input_line(args[i])) - break - elseif args[i]=="-E" || args[i]=="--print" - i == length(args) && error("-E,--print no provided") - repl = false - i+=1 - splice!(ARGS, 1:length(ARGS), args[i+1:end]) - show(eval(Main,parse_input_line(args[i]))) - println() - break - elseif args[i]=="-P" || args[i]=="--post-boot" - i == length(args) && error("-P,--post-boot no provided") - i+=1 - eval(Main,parse_input_line(args[i])) - elseif args[i]=="-L" || args[i]=="--load" - i == length(args) && error("-L, --load no provided") - i+=1 - require(args[i]) - elseif args[i]=="-p" - i == length(args) && error("-p processes not provided") - i+=1 - if i > length(args) || !isdigit(args[i][1]) - np = Sys.CPU_CORES - i -= 1 - else - np = int(args[i]) - np < 1 && error("-p must be ≥ 1") +# NOTE: This set of required arguments need to be kept in sync with the required arguments defined in ui/repl.c +let reqarg = Set(UTF8String["--home", "-H", + "--eval", "-e", + "--print", "-E", + "--post-boot", "-P", + "--load", "-L", + "--sysimage", "-J", + "--cpu-target", "-C", + "--procs", "-p", + "--machinefile", + "--color", + "--history-file", + "--startup-file", + "--compile", + "--check-bounds", + "--int-literals", + "--dump-bitcode", + "--depwarn", + "--inline", + "--build", "-b", + "--bind-to"]) + global process_options + function process_options(opts::JLOptions, args::Vector{UTF8String}) + if !isempty(args) && (arg = first(args); arg[1] == '-' && in(arg, reqarg)) + println(STDERR, "julia: option `$arg` is missing an argument") + exit(1) + end + quiet = false + repl = true + startup = true + color_set = false + no_history_file = false + while true + # show julia VERSION and quit + if bool(opts.version) + println(STDOUT, "julia version ", VERSION) + exit(0) end - addprocs(np) - elseif args[i]=="--machinefile" - i == length(args) && error("--machinefile no provided") - i+=1 - machines = load_machine_file(args[i]) - addprocs(machines) - elseif args[i]=="-v" || args[i]=="--version" - println("julia version ", VERSION) - exit(0) - elseif args[i]=="--no-history" - # deprecated in v0.3 - warn("'--no-history' is deprecated; use '--no-history-file'") - no_history_file = true - elseif args[i] == "--no-history-file" - no_history_file = true - elseif args[i] == "-f" || args[i] == "--no-startup" - startup = false - elseif args[i] == "-F" - # load juliarc now before processing any more options - load_juliarc() - startup = false - elseif args[i] == "-i" - global is_interactive = true - elseif startswith(args[i], "--color") - if args[i] == "--color" - color_set = true - global have_color = true - elseif args[i][8] == '=' - val = args[i][9:end] - if in(val, ("no","0","false")) - color_set = true - global have_color = false - elseif in(val, ("yes","1","true")) - color_set = true - global have_color = true - end + # startup worker + if bool(opts.worker) + start_worker() # does not return end - if !color_set - error("invalid option: ", args[i]) + # load file immediately on all processors + if opts.load != C_NULL + require(bytestring(opts.load)) end - elseif args[i][1]!='-' - if startup + # show banner + quiet = bool(opts.quiet) + # load ~/.juliarc file + if opts.startupfile == 1 load_juliarc() startup = false + elseif opts.startupfile == 2 + startup = false + end + # load ~/.julia_history file + no_history_file = bool(opts.historyfile) + # add processors + if opts.nprocs > 1 + addprocs(opts.nprocs) + end + # load processes from machine file + if opts.machinefile != C_NULL + addprocs(load_machine_file(bytestring(opts.machinefile))) + end + global is_interactive = bool(opts.isinteractive) + # REPL color + if opts.color == 0 + color_set = false + global have_color = false + elseif opts.color == 1 + color_set = true + global have_color = true + elseif opts.color == 2 + color_set = true + global have_color = false + end + # eval expression + if opts.eval != C_NULL + repl = false + eval(Main, parse_input_line(bytestring(opts.eval))) + break + end + # eval expression and show result + if opts.print != C_NULL + repl = false + show(eval(Main, parse_input_line(bytestring(opts.print)))) + println() + break + end + # eval expression but don't disable interactive mode + if opts.postboot != C_NULL + eval(Main, parse_input_line(bytestring(opts.postboot))) + end + # load file + if !isempty(args) + if args[1][1] != '-' + if startup + load_juliarc() + startup = false + end + # program + repl = false + # remove filename from ARGS + shift!(ARGS) + ccall(:jl_exit_on_sigint, Void, (Cint,), 1) + include(args[1]) + else + println(STDERR, "julia: unknown option `$(args[1])`") + exit(1) + end end - # program - repl = false - # remove julia's arguments - splice!(ARGS, 1:length(ARGS), args[i+1:end]) - ccall(:jl_exit_on_sigint, Void, (Cint,), 1) - include(args[i]) break - else - error("unknown option: ", args[i]) end - i += 1 + return (quiet,repl,startup,color_set,no_history_file) end - return (quiet,repl,startup,color_set,no_history_file) end const roottask = current_task() @@ -334,6 +341,8 @@ function init_load_path() push!(LOAD_PATH,abspath(JULIA_HOME,"..","share","julia","site",vers)) end +# start local process as head "master" process with process id 1 +# register this process as a local worker function init_head_sched() # start in "head node" mode global PGRP @@ -377,6 +386,8 @@ function early_init() end end +# starts the gc message task (for distrubuted gc) and +# registers worker process termination method function init_parallel() start_gc_msgs_task() atexit(terminate_all_workers) @@ -386,11 +397,13 @@ import .Terminals import .REPL function _start() + opts = JLOptions() try init_parallel() - init_bind_addr(ARGS) - any(a->(a=="--worker"), ARGS) || init_head_sched() - (quiet,repl,startup,color_set,no_history_file) = process_options(copy(ARGS)) + init_bind_addr(opts) + # if this process is not a worker, + bool(opts.worker) || init_head_sched() + (quiet,repl,startup,color_set,no_history_file) = process_options(opts,copy(ARGS)) local term global active_repl diff --git a/base/deprecated.jl b/base/deprecated.jl index 7eac86a21f797..0d026226a2f74 100644 --- a/base/deprecated.jl +++ b/base/deprecated.jl @@ -36,7 +36,7 @@ macro deprecate(old,new) end function depwarn(msg, funcsym) - if bool(compileropts().depwarn) + if bool(JLOptions().depwarn) bt = backtrace() caller = firstcaller(bt, funcsym) warn(msg, once=(caller!=C_NULL), key=caller, bt=bt) diff --git a/base/inference.jl b/base/inference.jl index 1dfc6d3c3b0c7..100b788016759 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -34,26 +34,6 @@ end inference_stack = EmptyCallStack() -# Julia compiler options struct (see jl_compileropts_t in src/julia.h) -immutable JLCompilerOpts - julia_home::Ptr{Cchar} - julia_bin::Ptr{Cchar} - build_path::Ptr{Cchar} - image_file::Ptr{Cchar} - cpu_target::Ptr{Cchar} - code_coverage::Int8 - malloc_log::Int8 - check_bounds::Int8 - dumpbitcode::Int8 - int_literals::Cint - compile_enabled::Int8 - opt_level::Int8 - depwarn::Int8 - can_inline::Int8 -end - -compileropts() = unsafe_load(cglobal(:jl_compileropts, JLCompilerOpts)) - function is_static_parameter(sv::StaticVarInfo, s::Symbol) sp = sv.sp for i=1:2:length(sp) @@ -1181,6 +1161,7 @@ function tmerge(typea::ANY, typeb::ANY) return u end + tchanged(n::ANY, o::ANY) = is(o,NF) || (!is(n,NF) && !(n <: o)) stupdate(state::(), changes::VarTable, vars) = copy(changes) @@ -1592,7 +1573,7 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) if !rec @assert fulltree.args[3].head === :body - if compileropts().can_inline == 1 + if JLOptions().can_inline == 1 fulltree.args[3] = inlining_pass(fulltree.args[3], sv, fulltree)[1] # inlining can add variables sv.vars = append_any(f_argnames(fulltree), fulltree.args[2][1]) diff --git a/base/options.jl b/base/options.jl new file mode 100644 index 0000000000000..12424db84dff0 --- /dev/null +++ b/base/options.jl @@ -0,0 +1,33 @@ +# NOTE: This type needs to be kept in sync with jl_options in src/julia.h +immutable JLOptions + version::Int8 + quiet::Int8 + julia_home::Ptr{Cchar} + julia_bin::Ptr{Cchar} + build_path::Ptr{Cchar} + eval::Ptr{Cchar} + print::Ptr{Cchar} + postboot::Ptr{Cchar} + load::Ptr{Cchar} + image_file::Ptr{Cchar} + cpu_target::Ptr{Cchar} + nprocs::Clong + machinefile::Ptr{Cchar} + isinteractive::Int8 + color::Int8 + historyfile::Int8 + startupfile::Int8 + compile_enabled::Int8 + code_coverage::Int8 + malloc_log::Int8 + opt_level::Int8 + check_bounds::Int8 + int_literals::Cint + dumpbitcode::Int8 + depwarn::Int8 + can_inline::Int8 + worker::Int8 + bindto::Ptr{Cchar} +end + +JLOptions() = unsafe_load(cglobal(:jl_options, JLOptions)) diff --git a/base/sysimg.jl b/base/sysimg.jl index 868885f62d075..0cc4b317a5d29 100644 --- a/base/sysimg.jl +++ b/base/sysimg.jl @@ -31,6 +31,7 @@ include("reflection.jl") include("build_h.jl") include("version_git.jl") include("c.jl") +include("options.jl") # core operations & types include("promotion.jl") diff --git a/base/util.jl b/base/util.jl index af7ac1495332e..cbe44658dd508 100644 --- a/base/util.jl +++ b/base/util.jl @@ -243,7 +243,7 @@ warn(err::Exception; prefix="ERROR: ", kw...) = warn(sprint(io->showerror(io,err)), prefix=prefix; kw...) function julia_cmd(julia=joinpath(JULIA_HOME, "julia")) - opts = compileropts() + opts = JLOptions() cpu_target = bytestring(opts.cpu_target) image_file = bytestring(opts.image_file) `$julia -C$cpu_target -J$image_file` diff --git a/doc/man/julia.1 b/doc/man/julia.1 index 62762e548d34a..67f2bdb552e34 100644 --- a/doc/man/julia.1 +++ b/doc/man/julia.1 @@ -56,6 +56,22 @@ If a Julia source file is given as a \fIprogram\fP (optionally followed by .SH "COMMAND-LINE OPTIONS" .TP 25 +.TP +-v, --version +Display version information + +.TP +-h, --help +Print help message + +.TP +-q, --quiet +Quiet startup without banner + +.TP +-H, --home +Set location of julia executable + .TP -e, --eval Evaluate @@ -65,56 +81,60 @@ Evaluate Evaluate and show .TP --f, --no-startup -Don't load ~/.juliarc.jl +-P, --post-boot +Evaluate , but don't disable interactive mode .TP --F -Load ~/.juliarc.jl, then handle remaining inputs +-L, --load +Load immediately on all processors .TP --h, --help -Print this message +-J, --sysimage +Start up with the given system image file .TP --H, --home -Set location of julia executable +-C, --cpu-target +Limit usage of cpu features up to .TP --i -Force isinteractive() to be true +-p, --procs +Run n local processes .TP --J, --sysimage -Start up with the given system image file +--machinefile +Run processes on hosts listed in .TP --L, --load -Load right after boot on all processors +-i +Force isinteractive() to be true .TP --p -Run n local processes +--color={yes|no} +Enable or disable color text .TP --P, --post-boot -Evaluate right after boot +--history-file={yes|no} +Load or save history .TP --q, --quiet -Quiet startup without banner +--startup-file={yes|no} +Load ~/.juliarc.jl .TP --v, --version -Display version information +--compile={yes|no|all} +Enable or disable compiler, or request exhaustive compilation .TP ---code-coverage -Count executions of source lines +--code-coverage={none|user|all}, --code-coverage +Count executions of source lines (omitting setting is equivalent to 'user') .TP ---color={yes|no} -Enable or disable color text +--track-allocation={none|user|all}, --track-allocation +Count bytes allocated by each source line + +.TP +-O, --optimize +Run time-intensive code optimizations .TP --check-bounds={yes|no} @@ -125,12 +145,16 @@ Emit bounds checks always or never (ignoring declarations) Select integer literal size independent of platform .TP ---machinefile -Run processes on hosts listed in +--dump-bitcode={yes|no} +Dump bitcode for the system image (used with --build) + +.TP +--depwarn={yes|no} +Enable or disable syntax and method deprecation warnings .TP ---no-history-file -Don't load or save history +--inline={yes|no} +Control whether inlining is permitted (overrides functions declared as @inline) .SH FILES .I ~/.juliarc.jl diff --git a/doc/manual/getting-started.rst b/doc/manual/getting-started.rst index 533b3f5d7187a..a5a21496ae319 100644 --- a/doc/manual/getting-started.rst +++ b/doc/manual/getting-started.rst @@ -1,7 +1,7 @@ .. _man-getting-started: ***************** - Getting Started + Getting Started ***************** Julia installation is straightforward, whether using precompiled @@ -75,11 +75,11 @@ passwordless ``ssh`` login, with Julia installed at the same location as the current host. Each machine definition takes the form ``[count*][user@]host[:port] [bind_addr[:port]]`` . ``user`` defaults to current user, ``port`` to the standard ssh port. ``count`` is the number of workers to spawn -on the node, and defaults to 1. The optional ``bind-to bind_addr[:port]`` -specifies the ip-address and port that other workers should use to +on the node, and defaults to 1. The optional ``bind-to bind_addr[:port]`` +specifies the ip-address and port that other workers should use to connect to this worker. - - + + If you have code that you want executed whenever julia is run, you can put it in ``~/.juliarc.jl``: @@ -92,7 +92,7 @@ put it in ``~/.juliarc.jl``: $ echo 'println("Greetings! 你好! 안녕하세요?")' > ~/.juliarc.jl $ julia Greetings! 你好! 안녕하세요? - + ... .. raw:: latex @@ -103,38 +103,46 @@ There are various ways to run Julia code and provide options, similar to those available for the ``perl`` and ``ruby`` programs:: julia [options] [program] [args...] - -v, --version Display version information - -h, --help Print this message - -q, --quiet Quiet startup without banner - -H, --home Set location of julia executable - - -e, --eval Evaluate - -E, --print Evaluate and show - -P, --post-boot Evaluate , but don't disable interactive mode - -L, --load Load immediately on all processors - -J, --sysimage Start up with the given system image file - - -p Run n local processes - --machinefile Run processes on hosts listed in - - -i Force isinteractive() to be true - --no-history-file Don't load or save history - -f, --no-startup Don't load ~/.juliarc.jl - -F Load ~/.juliarc.jl, then handle remaining inputs - --color={yes|no} Enable or disable color text - - --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation - - --code-coverage={none|user|all}, --code-coverage + -v, --version Display version information + -h, --help Print this message + -q, --quiet Quiet startup without banner + -H, --home Set location of julia executable + + -e, --eval Evaluate + -E, --print Evaluate and show + -P, --post-boot Evaluate , but don't disable interactive mode + -L, --load Load immediately on all processors + -J, --sysimage Start up with the given system image file + -C, --cpu-target Limit usage of cpu features up to + + -p, --procs Run n local processes + --machinefile Run processes on hosts listed in + + -i Force isinteractive() to be true + --color={yes|no} Enable or disable color text + + --history-file={yes|no} Load or save history + --no-history-file Don't load history file (deprecated, use --history-file=no) + --startup-file={yes|no} Load ~/.juliarc.jl + -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no) + -F Load ~/.juliarc (deprecated, use --startup-file=yes) + + --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation + + --code-coverage={none|user|all}, --code-coverage Count executions of source lines (omitting setting is equivalent to 'user') - --track-allocation={none|user|all} + + --track-allocation={none|user|all}, --track-allocation Count bytes allocated by each source line - --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations) - -O, --optimize Run time-intensive code optimizations - --int-literals={32|64} Select integer literal size independent of platform - --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build) - --depwarn={yes|no} Enable or disable syntax and method deprecation warnings + -O, --optimize + Run time-intensive code optimizations + + --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations) + --int-literals={32|64} Select integer literal size independent of platform + --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build) + --depwarn={yes|no} Enable or disable syntax and method deprecation warnings + --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline) Resources --------- diff --git a/src/ast.c b/src/ast.c index 767d9bd71151e..a8ff4cc29e50a 100644 --- a/src/ast.c +++ b/src/ast.c @@ -140,7 +140,7 @@ void jl_init_frontend(void) fl_null_sym = symbol("null"); // Enable / disable syntax deprecation warnings - jl_parse_depwarn((int)jl_compileropts.depwarn); + jl_parse_depwarn((int)jl_options.depwarn); } DLLEXPORT void jl_lisp_prompt(void) @@ -247,9 +247,9 @@ static jl_value_t *scm_to_julia_(value_t e, int eo) } if ( #ifdef _P64 - jl_compileropts.int_literals==32 + jl_options.int_literals==32 #else - jl_compileropts.int_literals!=64 + jl_options.int_literals!=64 #endif ) { if (i64 > (int64_t)S32_MAX || i64 < (int64_t)S32_MIN) diff --git a/src/cgutils.cpp b/src/cgutils.cpp index d13e115139178..161b421a19d87 100644 --- a/src/cgutils.cpp +++ b/src/cgutils.cpp @@ -296,7 +296,7 @@ static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVectorgetType(), @@ -306,7 +306,7 @@ static void jl_gen_llvm_gv_array(llvm::Module *mod, SmallVectorboundsCheck.empty() || ctx->boundsCheck.back()==true) && - jl_compileropts.check_bounds != JL_COMPILEROPT_CHECK_BOUNDS_OFF) || - jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_ON) { + jl_options.check_bounds != JL_OPTIONS_CHECK_BOUNDS_OFF) || + jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_ON) { Value *ok = builder.CreateICmpULT(im1, len); BasicBlock *failBB = BasicBlock::Create(getGlobalContext(),"fail",ctx->f); BasicBlock *passBB = BasicBlock::Create(getGlobalContext(),"pass"); @@ -1427,8 +1427,8 @@ static Value *emit_array_nd_index(Value *a, jl_value_t *ex, size_t nd, jl_value_ Value *stride = ConstantInt::get(T_size, 1); #if CHECK_BOUNDS==1 bool bc = ((ctx->boundsCheck.empty() || ctx->boundsCheck.back()==true) && - jl_compileropts.check_bounds != JL_COMPILEROPT_CHECK_BOUNDS_OFF) || - jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_ON; + jl_options.check_bounds != JL_OPTIONS_CHECK_BOUNDS_OFF) || + jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_ON; BasicBlock *failBB=NULL, *endBB=NULL; if (bc) { failBB = BasicBlock::Create(getGlobalContext(), "oob"); diff --git a/src/codegen.cpp b/src/codegen.cpp index a9f2e388787ce..1dc53938ca03b 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -893,7 +893,7 @@ static void coverageVisitLine(std::string filename, int line) void write_log_data(logdata_t logData, const char *extension) { - std::string base = std::string(jl_compileropts.julia_home); + std::string base = std::string(jl_options.julia_home); base = base + "/../share/julia/base/"; logdata_t::iterator it = logData.begin(); for (; it != logData.end(); it++) { @@ -3194,7 +3194,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool isboxed, } else if (head == boundscheck_sym) { if (jl_array_len(ex->args) > 0 && - jl_compileropts.check_bounds == JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT) { + jl_options.check_bounds == JL_OPTIONS_CHECK_BOUNDS_DEFAULT) { jl_value_t *arg = args[0]; if (arg == jl_true) { ctx->boundsCheck.push_back(true); @@ -3735,8 +3735,8 @@ static Function *emit_function(jl_lambda_info_t *lam, bool cstyle) // step 5. set up debug info context and create first basic block bool in_user_code = !jl_is_submodule(lam->module, jl_base_module) && !jl_is_submodule(lam->module, jl_core_module); - bool do_coverage = jl_compileropts.code_coverage == JL_LOG_ALL || (jl_compileropts.code_coverage == JL_LOG_USER && in_user_code); - bool do_malloc_log = jl_compileropts.malloc_log == JL_LOG_ALL || (jl_compileropts.malloc_log == JL_LOG_USER && in_user_code); + bool do_coverage = jl_options.code_coverage == JL_LOG_ALL || (jl_options.code_coverage == JL_LOG_USER && in_user_code); + bool do_malloc_log = jl_options.malloc_log == JL_LOG_ALL || (jl_options.malloc_log == JL_LOG_USER && in_user_code); jl_value_t *stmt = jl_cellref(stmts,0); std::string filename = "no file"; char *dbgFuncName = lam->name->name; @@ -4813,7 +4813,7 @@ static void init_julia_llvm_env(Module *m) jl_TargetMachine->addAnalysisPasses(*FPM); #endif FPM->add(createTypeBasedAliasAnalysisPass()); - if (jl_compileropts.opt_level>=1) + if (jl_options.opt_level>=1) FPM->add(createBasicAliasAnalysisPass()); // list of passes from vmkit FPM->add(createCFGSimplificationPass()); // Clean up disgusting code @@ -4882,13 +4882,13 @@ static void init_julia_llvm_env(Module *m) FPM->add(createJumpThreadingPass()); // Thread jumps FPM->add(createDeadStoreEliminationPass()); // Delete dead stores #if LLVM33 && !defined(INSTCOMBINE_BUG) - if (jl_compileropts.opt_level>=1) + if (jl_options.opt_level>=1) FPM->add(createSLPVectorizerPass()); // Vectorize straight-line code #endif FPM->add(createAggressiveDCEPass()); // Delete dead instructions #if LLVM33 && !defined(INSTCOMBINE_BUG) - if (jl_compileropts.opt_level>=1) + if (jl_options.opt_level>=1) FPM->add(createInstructionCombiningPass()); // Clean up after SLP loop vectorizer #endif #if LLVM35 @@ -4905,7 +4905,7 @@ extern "C" void jl_init_codegen(void) #ifdef JL_DEBUG_BUILD cl::ParseEnvironmentOptions("Julia", "JULIA_LLVM_ARGS"); #endif - imaging_mode = jl_compileropts.build_path != NULL; + imaging_mode = jl_options.build_path != NULL; #if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 3 // this option disables LLVM's signal handlers @@ -5002,9 +5002,9 @@ extern "C" void jl_init_codegen(void) TheTriple, "", #if LLVM35 - strcmp(jl_compileropts.cpu_target,"native") ? jl_compileropts.cpu_target : sys::getHostCPUName().data(), + strcmp(jl_options.cpu_target,"native") ? jl_options.cpu_target : sys::getHostCPUName().data(), #else - strcmp(jl_compileropts.cpu_target,"native") ? jl_compileropts.cpu_target : "", + strcmp(jl_options.cpu_target,"native") ? jl_options.cpu_target : "", #endif MAttrs); assert(jl_TargetMachine); diff --git a/src/dump.c b/src/dump.c index ae220b78d9663..0db25eda4e544 100644 --- a/src/dump.c +++ b/src/dump.c @@ -184,7 +184,7 @@ static void jl_load_sysimg_so(char *fname) sysimg_gvars = (jl_value_t***)jl_dlsym(jl_sysimg_handle, "jl_sysimg_gvars"); globalUnique = *(size_t*)jl_dlsym(jl_sysimg_handle, "jl_globalUnique"); const char *cpu_target = (const char*)jl_dlsym(jl_sysimg_handle, "jl_sysimg_cpu_target"); - if (strcmp(cpu_target,jl_compileropts.cpu_target) != 0) + if (strcmp(cpu_target,jl_options.cpu_target) != 0) jl_error("Julia and the system image were compiled for different architectures.\n" "Please delete or regenerate sys.{so,dll,dylib}.\n"); uint32_t info[4]; diff --git a/src/gf.c b/src/gf.c index 5dc3cede44578..ffaba35f04e52 100644 --- a/src/gf.c +++ b/src/gf.c @@ -817,7 +817,7 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tuple_t *type, return newmeth; } else { - if (jl_compileropts.compile_enabled == 0) { + if (jl_options.compile_enabled == 0) { if (method->linfo->unspecialized == NULL) { JL_PRINTF(JL_STDERR,"code missing for %s", method->linfo->name->name); jl_static_show(JL_STDERR, (jl_value_t*)type); diff --git a/src/init.c b/src/init.c index c222bf63da4eb..21c705467165f 100644 --- a/src/init.c +++ b/src/init.c @@ -88,20 +88,34 @@ DLLEXPORT void gdblookup(ptrint_t ip); static const char system_image_path[256] = JL_SYSTEM_IMAGE_PATH; -jl_compileropts_t jl_compileropts = { NULL, // julia_home - NULL, // julia_bin - NULL, // build_path - system_image_path, // image_file - NULL, // cpu_target ("native", "core2", etc...) - 0, // code_coverage - 0, // malloc_log - JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT, - JL_COMPILEROPT_DUMPBITCODE_OFF, - 0, // int_literals - JL_COMPILEROPT_COMPILE_DEFAULT, - 0, // opt_level - 1, // depwarn - 1 // can_inline +jl_options_t jl_options = { 0, // version + 0, // quiet + NULL, // julia_home + NULL, // julia_bin + NULL, // build_path + NULL, // eval + NULL, // print + NULL, // postboot + NULL, // load + system_image_path, // image_file + NULL, // cpu_taget ("native", "core2", etc...) + 0, // nprocs + NULL, // machinefile + 0, // isinteractive + 0, // color + 0, // historyfile + 0, // startupfile + JL_OPTIONS_COMPILE_DEFAULT, // compile_enabled + 0, // code_coverage + 0, // malloc_log + 0, // opt_level + JL_OPTIONS_CHECK_BOUNDS_DEFAULT, // check_bounds + 0, // int_literals + JL_OPTIONS_DUMPBITCODE_OFF, // dump_bitcode + 1, // depwarn + 1, // can_inline + 0, // worker + NULL, // bindto }; int jl_boot_file_loaded = 0; @@ -485,9 +499,9 @@ DLLEXPORT void jl_atexit_hook() #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); #endif - if (jl_compileropts.code_coverage) + if (jl_options.code_coverage) jl_write_coverage_data(); - if (jl_compileropts.malloc_log) + if (jl_options.malloc_log) jl_write_malloc_log(); if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); @@ -809,7 +823,7 @@ static int isabspath(const char *in) } } #else - if (jl_compileropts.image_file[0] == '/') return 1; // absolute path + if (jl_options.image_file[0] == '/') return 1; // absolute path #endif return 0; // relative path } @@ -842,13 +856,13 @@ static char *abspath(const char *in) #else DWORD n = GetFullPathName(in, 0, NULL, NULL); if (n <= 0) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); + ios_printf(ios_stderr, "fatal error: jl_options.image_file path too long or GetFullPathName failed\n"); exit(1); } char *out = (char*)malloc(n); DWORD m = GetFullPathName(in, n, out, NULL); if (n != m + 1) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long or GetFullPathName failed\n"); + ios_printf(ios_stderr, "fatal error: jl_options.image_file path too long or GetFullPathName failed\n"); exit(1); } #endif @@ -856,12 +870,12 @@ static char *abspath(const char *in) } static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) -{ // this function resolves the paths in jl_compileropts to absolute file locations as needed +{ // this function resolves the paths in jl_options to absolute file locations as needed // and it replaces the pointers to `julia_home`, `julia_bin`, `image_file`, and `build_path` // it may fail, print an error, and exit(1) if any of these paths are longer than PATH_MAX // // note: if you care about lost memory, you should call the appropriate `free()` function - // on the original pointer for each `char*` you've inserted into `jl_compileropts`, after + // on the original pointer for each `char*` you've inserted into `jl_options`, after // calling `julia_init()` char *free_path = (char*)malloc(PATH_MAX); size_t path_size = PATH_MAX; @@ -870,41 +884,41 @@ static void jl_resolve_sysimg_location(JL_IMAGE_SEARCH rel) exit(1); } if (path_size >= PATH_MAX) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.julia_bin path too long\n"); + ios_printf(ios_stderr, "fatal error: jl_options.julia_bin path too long\n"); exit(1); } - jl_compileropts.julia_bin = strdup(free_path); - if (!jl_compileropts.julia_home) { - jl_compileropts.julia_home = getenv("JULIA_HOME"); - if (!jl_compileropts.julia_home) { - jl_compileropts.julia_home = dirname(free_path); + jl_options.julia_bin = strdup(free_path); + if (!jl_options.julia_home) { + jl_options.julia_home = getenv("JULIA_HOME"); + if (!jl_options.julia_home) { + jl_options.julia_home = dirname(free_path); } } - if (jl_compileropts.julia_home) - jl_compileropts.julia_home = abspath(jl_compileropts.julia_home); + if (jl_options.julia_home) + jl_options.julia_home = abspath(jl_options.julia_home); free(free_path); free_path = NULL; - if (jl_compileropts.image_file) { - if (rel == JL_IMAGE_JULIA_HOME && !isabspath(jl_compileropts.image_file)) { + if (jl_options.image_file) { + if (rel == JL_IMAGE_JULIA_HOME && !isabspath(jl_options.image_file)) { // build time path, relative to JULIA_HOME free_path = (char*)malloc(PATH_MAX); int n = snprintf(free_path, PATH_MAX, "%s" PATHSEPSTRING "%s", - jl_compileropts.julia_home, jl_compileropts.image_file); + jl_options.julia_home, jl_options.image_file); if (n >= PATH_MAX || n < 0) { - ios_printf(ios_stderr, "fatal error: jl_compileropts.image_file path too long\n"); + ios_printf(ios_stderr, "fatal error: jl_options.image_file path too long\n"); exit(1); } - jl_compileropts.image_file = free_path; + jl_options.image_file = free_path; } - if (jl_compileropts.image_file) - jl_compileropts.image_file = abspath(jl_compileropts.image_file); + if (jl_options.image_file) + jl_options.image_file = abspath(jl_options.image_file); if (free_path) { free(free_path); free_path = NULL; } } - if (jl_compileropts.build_path) - jl_compileropts.build_path = abspath(jl_compileropts.build_path); + if (jl_options.build_path) + jl_options.build_path = abspath(jl_options.build_path); } void _julia_init(JL_IMAGE_SEARCH rel) @@ -916,11 +930,11 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_resolve_sysimg_location(rel); // If we are able to load the sysimg and get a cpu_target, use that unless user has overridden - if (jl_compileropts.cpu_target == NULL) { - const char * sysimg_cpu_target = jl_get_system_image_cpu_target(jl_compileropts.image_file); + if (jl_options.cpu_target == NULL) { + const char * sysimg_cpu_target = jl_get_system_image_cpu_target(jl_options.image_file); // If we can't load anything from the sysimg, default to native - jl_compileropts.cpu_target = sysimg_cpu_target ? sysimg_cpu_target : "native"; + jl_options.cpu_target = sysimg_cpu_target ? sysimg_cpu_target : "native"; } jl_page_size = jl_getpagesize(); @@ -998,7 +1012,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_init_serializer(); - if (!jl_compileropts.image_file) { + if (!jl_options.image_file) { jl_core_module = jl_new_module(jl_symbol("Core")); jl_init_intrinsic_functions(); jl_init_primitives(); @@ -1015,9 +1029,9 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_init_box_caches(); } - if (jl_compileropts.image_file) { + if (jl_options.image_file) { JL_TRY { - jl_restore_system_image(jl_compileropts.image_file); + jl_restore_system_image(jl_options.image_file); } JL_CATCH { JL_PRINTF(JL_STDERR, "error during init:\n"); @@ -1175,7 +1189,7 @@ void _julia_init(JL_IMAGE_SEARCH rel) jl_gc_enable(); #endif - if (jl_compileropts.image_file) + if (jl_options.image_file) jl_init_restored_modules(); jl_install_sigint_handler(); @@ -1205,15 +1219,15 @@ void jl_compile_all(void); DLLEXPORT void julia_save() { - const char *build_path = jl_compileropts.build_path; + const char *build_path = jl_options.build_path; if (build_path) { - if (jl_compileropts.compile_enabled == JL_COMPILEROPT_COMPILE_ALL) + if (jl_options.compile_enabled == JL_OPTIONS_COMPILE_ALL) jl_compile_all(); char *build_ji; if (asprintf(&build_ji, "%s.ji",build_path) > 0) { jl_save_system_image(build_ji); free(build_ji); - if (jl_compileropts.dumpbitcode == JL_COMPILEROPT_DUMPBITCODE_ON) { + if (jl_options.dumpbitcode == JL_OPTIONS_DUMPBITCODE_ON) { char *build_bc; if (asprintf(&build_bc, "%s.bc",build_path) > 0) { jl_dump_bitcode(build_bc); diff --git a/src/jlapi.c b/src/jlapi.c index 59a3733d1f4bc..96becb40edcb9 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -36,9 +36,9 @@ DLLEXPORT void jl_init_with_image(const char *julia_home_dir, const char *image_ { if (jl_is_initialized()) return; libsupport_init(); - jl_compileropts.julia_home = julia_home_dir; + jl_options.julia_home = julia_home_dir; if (image_relative_path != NULL) - jl_compileropts.image_file = image_relative_path; + jl_options.image_file = image_relative_path; julia_init(JL_IMAGE_JULIA_HOME); //TODO: these should be part of Multi.__init__() //currently, we have them here since we may not want them @@ -246,17 +246,17 @@ DLLEXPORT int jl_is_debugbuild(void) DLLEXPORT jl_value_t *jl_get_julia_home(void) { - return jl_cstr_to_string(jl_compileropts.julia_home); + return jl_cstr_to_string(jl_options.julia_home); } DLLEXPORT jl_value_t *jl_get_julia_bin(void) { - return jl_cstr_to_string(jl_compileropts.julia_bin); + return jl_cstr_to_string(jl_options.julia_bin); } DLLEXPORT jl_value_t *jl_get_image_file(void) { - return jl_cstr_to_string(jl_compileropts.image_file); + return jl_cstr_to_string(jl_options.image_file); } DLLEXPORT int jl_ver_major(void) diff --git a/src/julia.h b/src/julia.h index c3879f7c1a696..29a9798d23e91 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1323,42 +1323,67 @@ void jl_print_gc_stats(JL_STREAM *s); // debugging void show_execution_point(char *filename, int lno); -// compiler options ----------------------------------------------------------- - +// julia options ----------------------------------------------------------- +// NOTE: This struct needs to be kept in sync with JLOptions type in base/options.jl typedef struct { + int8_t version; + int8_t quiet; const char *julia_home; const char *julia_bin; const char *build_path; + const char *eval; + const char *print; + const char *postboot; + const char *load; const char *image_file; const char *cpu_target; + long nprocs; + const char *machinefile; + int8_t isinteractive; + int8_t color; + int8_t historyfile; + int8_t startupfile; + int8_t compile_enabled; int8_t code_coverage; int8_t malloc_log; + int8_t opt_level; int8_t check_bounds; + int int_literals; int8_t dumpbitcode; - int int_literals; - int8_t compile_enabled; - int8_t opt_level; int8_t depwarn; int8_t can_inline; -} jl_compileropts_t; + int8_t worker; + const char *bindto; +} jl_options_t; -extern DLLEXPORT jl_compileropts_t jl_compileropts; +extern DLLEXPORT jl_options_t jl_options; -// Settings for code_coverage and mallog_log +// Settings for code_coverage and malloc_log +// NOTE: if these numbers change, test/cmdlineargs.jl will have to be updated #define JL_LOG_NONE 0 #define JL_LOG_USER 1 #define JL_LOG_ALL 2 -#define JL_COMPILEROPT_CHECK_BOUNDS_DEFAULT 0 -#define JL_COMPILEROPT_CHECK_BOUNDS_ON 1 -#define JL_COMPILEROPT_CHECK_BOUNDS_OFF 2 -#define JL_COMPILEROPT_COMPILE_DEFAULT 1 -#define JL_COMPILEROPT_COMPILE_OFF 0 -#define JL_COMPILEROPT_COMPILE_ON 1 -#define JL_COMPILEROPT_COMPILE_ALL 2 +#define JL_OPTIONS_CHECK_BOUNDS_DEFAULT 0 +#define JL_OPTIONS_CHECK_BOUNDS_ON 1 +#define JL_OPTIONS_CHECK_BOUNDS_OFF 2 + +#define JL_OPTIONS_COMPILE_DEFAULT 1 +#define JL_OPTIONS_COMPILE_OFF 0 +#define JL_OPTIONS_COMPILE_ON 1 +#define JL_OPTIONS_COMPILE_ALL 2 + +#define JL_OPTIONS_DUMPBITCODE_ON 1 +#define JL_OPTIONS_DUMPBITCODE_OFF 2 + +#define JL_OPTIONS_COLOR_ON 1 +#define JL_OPTIONS_COLOR_OFF 2 + +#define JL_OPTIONS_HISTORYFILE_ON 1 +#define JL_OPTIONS_HISTORYFILE_OFF 0 -#define JL_COMPILEROPT_DUMPBITCODE_ON 1 -#define JL_COMPILEROPT_DUMPBITCODE_OFF 2 +#define JL_OPTIONS_STARTUPFILE_ON 1 +#define JL_OPTIONS_STARTUPFILE_OFF 2 // Version information #include "julia_version.h" diff --git a/src/toplevel.c b/src/toplevel.c index 82e3dd03e3d67..4f7834c0c4caa 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -70,7 +70,7 @@ jl_array_t *jl_module_init_order = NULL; // load time init procedure: in build mode, only record order void jl_module_load_time_initialize(jl_module_t *m) { - int build_mode = (jl_compileropts.build_path != NULL); + int build_mode = (jl_options.build_path != NULL); if (build_mode) { if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_cell_1d(0); diff --git a/test/Makefile b/test/Makefile index 2fe67f6e0ca40..8c97294bc5bc1 100644 --- a/test/Makefile +++ b/test/Makefile @@ -6,7 +6,7 @@ TESTS = all linalg $(filter-out TestHelpers runtests testdefs,$(subst .jl,,$(wil default: all $(TESTS) :: - @$(call PRINT_JULIA, $(call spawn,$(JULIA_EXECUTABLE)) --check-bounds=yes -f ./runtests.jl $@) + @$(call PRINT_JULIA, $(call spawn,$(JULIA_EXECUTABLE)) --check-bounds=yes --startup-file=no ./runtests.jl $@) perf: @$(MAKE) -C perf all diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl new file mode 100644 index 0000000000000..37476f4771c91 --- /dev/null +++ b/test/cmdlineargs.jl @@ -0,0 +1,157 @@ +let exename = joinpath(JULIA_HOME, (ccall(:jl_is_debugbuild, Cint, ()) == 0 ? "julia" : "julia-debug")) + # --version + let v = split(readall(`$exename -v`), "julia version ")[end] + @test VERSION == VersionNumber(v) + end + @test readall(`$exename -v`) == readall(`$exename --version`) + + # --help + @unix_only begin + @test startswith(readall(`$exename -h`), "julia [options] [program] [args...]") + @test startswith(readall(`$exename --help`), "julia [options] [program] [args...]") + end + + # --quiet + # This flag is indirectly tested in test/repl.jl + + # --home + @test success(`$exename -H $JULIA_HOME`) + @test success(`$exename --home=$JULIA_HOME`) + + # --eval + @test success(`$exename -e "exit(0)"`) + @test !success(`$exename -e "exit(1)"`) + @test success(`$exename --eval="exit(0)"`) + @test !success(`$exename --eval="exit(1)"`) + @test !success(`$exename -e`) + @test !success(`$exename --eval`) + + # --print + @test readall(`$exename -E "1+1"`) == "2\n" + @test readall(`$exename --print="1+1"`) == "2\n" + @test !success(`$exename -E`) + @test !success(`$exename --print`) + + # --post-boot + @test success(`$exename -P "exit(0)"`) + @test !success(`$exename -P "exit(1)"`) + @test success(`$exename --post-boot="exit(0)"`) + @test !success(`$exename --post-boot="exit(1)"`) + @test !success(`$exename -P`) + @test !success(`$exename --post-boot`) + + # --load + let testfile = tempname() + try + open(testfile, "w") do io + println(io, "testvar = :test") + end + @test split(readchomp(`$exename --load=$testfile -P "println(testvar)"`), '\n')[end] == "test" + @test split(readchomp(`$exename -P "println(testvar)" -L $testfile`), '\n')[end] == "test" + finally + rm(testfile) + end + end + # -L, --load requires an argument + @test !success(`$exename -L`) + @test !success(`$exename --load`) + + # --cpu-target + @test !success(`$exename -C invalidtarget`) + @test !success(`$exename --cpu-target=invalidtarget`) + + # --procs + @test readchomp(`$exename -q -p 2 -P "println(nworkers()); exit(0)"`) == "2" + @test !success(`$exename -p 0`) + @test !success(`$exename --procs=1.0`) + + # --machinefile + # this does not check that machinefile works, + # only that the filename gets correctly passed to the option struct + let fname = tempname() + touch(fname) + try + @test readchomp(`$exename --machinefile $fname -e "println(bytestring(Base.JLOptions().machinefile))"`) == fname + finally + rm(fname) + end + end + + # -i, isinteractive + @test readchomp(`$exename -E "isinteractive()"`) == "false" + @test readchomp(`$exename -E "isinteractive()" -i`) == "true" + + # --color + @test readchomp(`$exename --color=yes -E "Base.have_color"`) == "true" + @test readchomp(`$exename --color=no -E "Base.have_color"`) == "false" + @test !success(`$exename --color=false`) + + # --history-file + @test readchomp(`$exename -E "bool(Base.JLOptions().historyfile)" --history-file=yes`) == "true" + @test readchomp(`$exename -E "bool(Base.JLOptions().historyfile)" --history-file=no`) == "false" + @test !success(`$exename --history-file=false`) + + # --startup-file + let JL_OPTIONS_STARTUPFILE_ON = 1, + JL_OPTIONS_STARTUPFILE_OFF = 2 + @test int(readchomp(`$exename -E "Base.JLOptions().startupfile" --startup-file=yes`)) == JL_OPTIONS_STARTUPFILE_ON + @test int(readchomp(`$exename -E "Base.JLOptions().startupfile" --startup-file=no`)) == JL_OPTIONS_STARTUPFILE_OFF + end + @test !success(`$exename --startup-file=false`) + + # --code-coverage + @test readchomp(`$exename -E "bool(Base.JLOptions().code_coverage)"`) == "false" + @test readchomp(`$exename -E "bool(Base.JLOptions().code_coverage)" --code-coverage=none`) == "false" + + @test readchomp(`$exename -E "bool(Base.JLOptions().code_coverage)" --code-coverage`) == "true" + @test readchomp(`$exename -E "bool(Base.JLOptions().code_coverage)" --code-coverage=user`) == "true" + + # --track-allocation + @test readchomp(`$exename -E "bool(Base.JLOptions().malloc_log)"`) == "false" + @test readchomp(`$exename -E "bool(Base.JLOptions().malloc_log)" --track-allocation=none`) == "false" + + @test readchomp(`$exename -E "bool(Base.JLOptions().malloc_log)" --track-allocation`) == "true" + @test readchomp(`$exename -E "bool(Base.JLOptions().malloc_log)" --track-allocation=user`) == "true" + + # --optimize + @test readchomp(`$exename -E "bool(Base.JLOptions().opt_level)"`) == "false" + @test readchomp(`$exename -E "bool(Base.JLOptions().opt_level)" -O`) == "true" + @test readchomp(`$exename -E "bool(Base.JLOptions().opt_level)" --optimize`) == "true" + + # --check-bounds + let JL_OPTIONS_CHECK_BOUNDS_DEFAULT = 0, + JL_OPTIONS_CHECK_BOUNDS_ON = 1, + JL_OPTIONS_CHECK_BOUNDS_OFF = 2 + @test int(readchomp(`$exename -E "int(Base.JLOptions().check_bounds)"`)) == JL_OPTIONS_CHECK_BOUNDS_DEFAULT + @test int(readchomp(`$exename -E "int(Base.JLOptions().check_bounds)" --check-bounds=yes`)) == JL_OPTIONS_CHECK_BOUNDS_ON + @test int(readchomp(`$exename -E "int(Base.JLOptions().check_bounds)" --check-bounds=no`)) == JL_OPTIONS_CHECK_BOUNDS_OFF + end + # check-bounds takes yes/no as argument + @test !success(`$exename -E "exit(0)" --check-bounds=false`) + + # --depwarn + @test readchomp(`$exename --depwarn=no -E "Base.syntax_deprecation_warnings(true)"`) == "false" + @test readchomp(`$exename --depwarn=yes -E "Base.syntax_deprecation_warnings(false)"`) == "true" + @test !success(`$exename --depwarn=false`) + + # --inline + @test readchomp(`$exename -E "bool(Base.JLOptions().can_inline)"`) == "true" + @test readchomp(`$exename --inline=yes -E "bool(Base.JLOptions().can_inline)"`) == "true" + @test readchomp(`$exename --inline=no -E "bool(Base.JLOptions().can_inline)"`) == "false" + # --inline takes yes/no as arugment + @test !success(`$exename --inline=false`) + + # test passing arguments + let testfile = tempname() + try + # write a julia source file that just prints ARGS to STDOUT and exits + open(testfile, "w") do io + println(io, "println(ARGS)") + end + @test readchomp(`$exename $testfile foo -bar --baz`) == "UTF8String[\"foo\",\"-bar\",\"--baz\"]" + @test !success(`$exename --foo $testfile`) + finally + rm(testfile) + end + end +end diff --git a/test/repl.jl b/test/repl.jl index 52ff4bf0a21be..48537b77a6af6 100644 --- a/test/repl.jl +++ b/test/repl.jl @@ -240,7 +240,7 @@ master = Base.TTY(RawFD(fdm); readable = true) nENV = copy(ENV) nENV["TERM"] = "dumb" -p = spawn(setenv(`$exename -f --quiet`,nENV),slave,slave,slave) +p = spawn(setenv(`$exename --startup-file=no --quiet`,nENV),slave,slave,slave) start_reading(master) Base.wait_readnb(master,1) write(master,"1\nquit()\n") @@ -255,7 +255,7 @@ close(master) end # Test stream mode -outs, ins, p = readandwrite(`$exename -f --quiet`) +outs, ins, p = readandwrite(`$exename --startup-file=no --quiet`) write(ins,"1\nquit()\n") @test readall(outs) == "1\n" end diff --git a/test/runtests.jl b/test/runtests.jl index d9154c168b5a5..410f8c06c5c6f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -11,7 +11,7 @@ testnames = [ "sysinfo", "rounding", "ranges", "mod2pi", "euler", "show", "lineedit", "replcompletions", "repl", "test", "goto", "llvmcall", "grisu", "nullable", "meta", "profile", - "libgit2", "docs", "base64" + "libgit2", "docs", "base64", "cmdlineargs" ] if isdir(joinpath(JULIA_HOME, Base.DOCDIR, "examples")) diff --git a/test/spawn.jl b/test/spawn.jl index b5154d8870c97..c22fa6c23c464 100644 --- a/test/spawn.jl +++ b/test/spawn.jl @@ -151,7 +151,7 @@ close(sock) # issue #4535 exename=joinpath(JULIA_HOME,(ccall(:jl_is_debugbuild,Cint,())==0?"julia":"julia-debug")) -@test readall(`$exename -f -e 'println(STDERR,"Hello World")'` .> `cat`) == "Hello World\n" +@test readall(`$exename --startup-file=no -e 'println(STDERR,"Hello World")'` .> `cat`) == "Hello World\n" # issue #6310 @test readall(`echo "2+2"` |> `$exename -f`) == "4\n" diff --git a/ui/repl.c b/ui/repl.c index d9576e25f4127..3399760cbed86 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -44,62 +44,101 @@ static int imagepathspecified = 0; static const char *usage = "julia [options] [program] [args...]\n"; static const char *opts = - " -v, --version Display version information\n" - " -h, --help Print this message\n" - " -q, --quiet Quiet startup without banner\n" - " -H, --home Set location of julia executable\n\n" + " -v, --version Display version information\n" + " -h, --help Print this message\n" + " -q, --quiet Quiet startup without banner\n" + " -H, --home Set location of julia executable\n\n" - " -e, --eval Evaluate \n" - " -E, --print Evaluate and show \n" - " -P, --post-boot Evaluate , but don't disable interactive mode\n" - " -L, --load Load immediately on all processors\n" - " -J, --sysimage Start up with the given system image file\n" - " -C --cpu-target Limit usage of cpu features up to \n\n" + " -e, --eval Evaluate \n" + " -E, --print Evaluate and show \n" + " -P, --post-boot Evaluate , but don't disable interactive mode\n" + " -L, --load Load immediately on all processors\n" + " -J, --sysimage Start up with the given system image file\n" + " -C, --cpu-target Limit usage of cpu features up to \n\n" - " -p Run n local processes\n" - " --machinefile Run processes on hosts listed in \n\n" + " -p, --procs Run n local processes\n" + " --machinefile Run processes on hosts listed in \n\n" - " -i Force isinteractive() to be true\n" - " --no-history-file Don't load or save history\n" - " -f, --no-startup Don't load ~/.juliarc.jl\n" - " -F Load ~/.juliarc.jl, then handle remaining inputs\n" - " --color={yes|no} Enable or disable color text\n\n" + " -i Force isinteractive() to be true\n" + " --color={yes|no} Enable or disable color text\n\n" + " --history-file={yes|no} Load or save history\n" + " --no-history-file Don't load history file (deprecated, use --history-file=no)\n" + " --startup-file={yes|no} Load ~/.juliarc.jl\n" + " -f, --no-startup Don't load ~/.juliarc (deprecated, use --startup-file=no)\n" + " -F Load ~/.juliarc (deprecated, use --startup-file=yes)\n\n" - " --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation\n\n" + " --compile={yes|no|all} Enable or disable compiler, or request exhaustive compilation\n\n" " --code-coverage={none|user|all}, --code-coverage\n" - " Count executions of source lines (omitting setting is equivalent to 'user')\n" - " --track-allocation={none|user|all}\n" - " Count bytes allocated by each source line\n" - " --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)\n" - " --inline={yes|no} Control whether inlining is permitted (even for functions declared as @inline)\n" - " -O, --optimize Run time-intensive code optimizations\n" - " --int-literals={32|64} Select integer literal size independent of platform\n" - " --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build)\n" - " --depwarn={yes|no} Enable or disable syntax and method deprecation warnings\n"; + " Count executions of source lines (omitting setting is equivalent to 'user')\n\n" + + " --track-allocation={none|user|all}, --track-allocation\n" + " Count bytes allocated by each source line\n\n" + " -O, --optimize\n" + " Run time-intensive code optimizations\n\n" + + " --check-bounds={yes|no} Emit bounds checks always or never (ignoring declarations)\n" + " --int-literals={32|64} Select integer literal size independent of platform\n" + " --dump-bitcode={yes|no} Dump bitcode for the system image (used with --build)\n" + " --depwarn={yes|no} Enable or disable syntax and method deprecation warnings\n" + " --inline={yes|no} Control whether inlining is permitted (overrides functions declared as @inline)\n"; void parse_opts(int *argcp, char ***argvp) { - static char* shortopts = "+H:hJ:C:O"; + enum { machinefile = 300, + color, + history_file, + no_history_file, + startup_file, + compile, + code_coverage, + track_allocation, + check_bounds, + int_literals, + dump_bitcode, + depwarn, + can_inline, + worker, + bind_to + }; + static char* shortopts = "+vhqFfH:e:E:P:L:J:C:ip:Ob:"; static struct option longopts[] = { - { "home", required_argument, 0, 'H' }, - { "build", required_argument, 0, 'b' }, - { "lisp", no_argument, &lisp_prompt, 1 }, - { "help", no_argument, 0, 'h' }, - { "sysimage", required_argument, 0, 'J' }, - { "code-coverage", optional_argument, 0, 'c' }, - { "cpu-target", required_argument, 0, 'C' }, - { "track-allocation",required_argument, 0, 'm' }, - { "check-bounds", required_argument, 0, 300 }, - { "optimize", no_argument, 0, 'O' }, - { "int-literals", required_argument, 0, 301 }, - { "dump-bitcode", required_argument, 0, 302 }, - { "compile", required_argument, 0, 303 }, - { "depwarn", required_argument, 0, 304 }, - { "inline", required_argument, 0, 305 }, + // exposed command line options + { "version", no_argument, 0, 'v' }, + { "help", no_argument, 0, 'h' }, + { "quiet", no_argument, 0, 'q' }, + { "home", required_argument, 0, 'H' }, + { "eval", required_argument, 0, 'e' }, + { "print", required_argument, 0, 'E' }, + { "post-boot", required_argument, 0, 'P' }, + { "load", required_argument, 0, 'L' }, + { "sysimage", required_argument, 0, 'J' }, + { "cpu-target", required_argument, 0, 'C' }, + { "procs", required_argument, 0, 'p' }, + { "machinefile", required_argument, 0, machinefile }, + { "color", required_argument, 0, color }, + { "history-file", required_argument, 0, history_file }, + { "no-history-file", no_argument, 0, no_history_file }, // deprecated + { "startup-file", required_argument, 0, startup_file }, + { "no-startup", no_argument, 0, 'f' }, // deprecated + { "compile", required_argument, 0, compile }, + { "code-coverage", optional_argument, 0, code_coverage }, + { "track-allocation",optional_argument, 0, track_allocation }, + { "optimize", no_argument, 0, 'O' }, + { "check-bounds", required_argument, 0, check_bounds }, + { "int-literals", required_argument, 0, int_literals }, + { "dump-bitcode", required_argument, 0, dump_bitcode }, + { "depwarn", required_argument, 0, depwarn }, + { "inline", required_argument, 0, can_inline}, + // hidden command line options + { "build", required_argument, 0, 'b' }, + { "worker", no_argument, 0, worker }, + { "bind-to", required_argument, 0, bind_to }, + { "lisp", no_argument, &lisp_prompt, 1 }, { 0, 0, 0, 0 } }; int c; + char *endptr; opterr = 0; int skip = 0; int lastind = optind; @@ -108,31 +147,103 @@ void parse_opts(int *argcp, char ***argvp) case 0: break; case '?': - if (optind != lastind) skip++; - lastind = optind; + if (optind != lastind) skip++; + lastind = optind; + break; + case 'v': // version + jl_options.version = 1; + break; + case 'h': // help + ios_printf(ios_stdout, "%s%s", usage, opts); + exit(0); + case 'q': // quiet + jl_options.quiet = 1; break; - case 'H': - jl_compileropts.julia_home = strdup(optarg); + case 'H': // home + jl_options.julia_home = strdup(optarg); break; - case 'b': - jl_compileropts.build_path = strdup(optarg); - if (!imagepathspecified) - jl_compileropts.image_file = NULL; + case 'e': // eval + jl_options.eval = strdup(optarg); + break; + case 'E': // print + jl_options.print = strdup(optarg); break; - case 'J': - jl_compileropts.image_file = strdup(optarg); + case 'P': // post-boot + jl_options.postboot = strdup(optarg); + break; + case 'L': // load + jl_options.load = strdup(optarg); + break; + case 'J': // sysimage + jl_options.image_file = strdup(optarg); imagepathspecified = 1; break; - case 'C': - jl_compileropts.cpu_target = strdup(optarg); + case 'C': // cpu-target + jl_options.cpu_target = strdup(optarg); break; - case 'h': - ios_printf(ios_stdout, "%s%s", usage, opts); - exit(0); - case 'O': - jl_compileropts.opt_level = 1; + case 'p': // procs + errno = 0; + jl_options.nprocs = strtol(optarg, &endptr, 10); + if (errno != 0 || optarg == endptr || *endptr != 0 || jl_options.nprocs < 1) { + ios_printf(ios_stderr, "julia: -p,--procs= must be an integer >= 1\n"); + exit(1); + } + break; + case machinefile: + jl_options.machinefile = strdup(optarg); + break; + case color: + if (!strcmp(optarg,"yes")) + jl_options.color = JL_OPTIONS_COLOR_ON; + else if (!strcmp(optarg,"no")) + jl_options.color = JL_OPTIONS_COLOR_OFF; + else { + ios_printf(ios_stderr, "julia: invalid argument to --color={yes|no} (%s)\n", optarg); + exit(1); + } + break; + case history_file: + if (!strcmp(optarg,"yes")) + jl_options.historyfile = JL_OPTIONS_HISTORYFILE_ON; + else if (!strcmp(optarg,"no")) + jl_options.historyfile = JL_OPTIONS_HISTORYFILE_OFF; + else { + ios_printf(ios_stderr, "julia: invalid argument to --history-file={yes|no} (%s)\n", optarg); + exit(1); + } + break; + case no_history_file: + jl_options.historyfile = JL_OPTIONS_HISTORYFILE_OFF; + break; + case startup_file: + if (!strcmp(optarg,"yes")) + jl_options.startupfile = JL_OPTIONS_STARTUPFILE_ON; + else if (!strcmp(optarg,"no")) + jl_options.startupfile = JL_OPTIONS_STARTUPFILE_OFF; + else { + ios_printf(ios_stderr, "julia: invalid argument to --startup-file={yes|no} (%s)\n", optarg); + exit(1); + } break; - case 'c': + case 'f': + jl_options.startupfile = JL_OPTIONS_STARTUPFILE_OFF; + break; + case 'F': + jl_options.startupfile = JL_OPTIONS_STARTUPFILE_ON; + break; + case compile: + if (!strcmp(optarg,"yes")) + jl_options.compile_enabled = JL_OPTIONS_COMPILE_ON; + else if (!strcmp(optarg,"no")) + jl_options.compile_enabled = JL_OPTIONS_COMPILE_OFF; + else if (!strcmp(optarg,"all")) + jl_options.compile_enabled = JL_OPTIONS_COMPILE_ALL; + else { + ios_printf(ios_stderr, "julia: invalid argument to --compile (%s)\n", optarg); + exit(1); + } + break; + case code_coverage: if (optarg != NULL) { if (!strcmp(optarg,"user")) codecov = JL_LOG_USER; @@ -146,7 +257,7 @@ void parse_opts(int *argcp, char ***argvp) codecov = JL_LOG_USER; } break; - case 'm': + case track_allocation: if (optarg != NULL) { if (!strcmp(optarg,"user")) malloclog = JL_LOG_USER; @@ -156,72 +267,85 @@ void parse_opts(int *argcp, char ***argvp) malloclog = JL_LOG_NONE; break; } - case 300: + else { + malloclog = JL_LOG_USER; + } + break; + case 'O': // optimize + jl_options.opt_level = 1; + break; + case 'i': // isinteractive + jl_options.isinteractive = 1; + break; + case check_bounds: if (!strcmp(optarg,"yes")) - jl_compileropts.check_bounds = JL_COMPILEROPT_CHECK_BOUNDS_ON; + jl_options.check_bounds = JL_OPTIONS_CHECK_BOUNDS_ON; else if (!strcmp(optarg,"no")) - jl_compileropts.check_bounds = JL_COMPILEROPT_CHECK_BOUNDS_OFF; + jl_options.check_bounds = JL_OPTIONS_CHECK_BOUNDS_OFF; + else { + ios_printf(ios_stderr, "julia: invalid argument to --check-bounds={yes|no} (%s)\n", optarg); + exit(1); + } break; - case 301: + case int_literals: if (!strcmp(optarg,"32")) - jl_compileropts.int_literals = 32; + jl_options.int_literals = 32; else if (!strcmp(optarg,"64")) - jl_compileropts.int_literals = 64; + jl_options.int_literals = 64; else { - ios_printf(ios_stderr, "julia: invalid integer literal size (%s)\n", optarg); + ios_printf(ios_stderr, "julia: invalid argument to --int-literals={32|64} (%s)\n", optarg); exit(1); } break; - case 302: + case dump_bitcode: if (!strcmp(optarg,"yes")) - jl_compileropts.dumpbitcode = JL_COMPILEROPT_DUMPBITCODE_ON; + jl_options.dumpbitcode = JL_OPTIONS_DUMPBITCODE_ON; else if (!strcmp(optarg,"no")) - jl_compileropts.dumpbitcode = JL_COMPILEROPT_DUMPBITCODE_OFF; + jl_options.dumpbitcode = JL_OPTIONS_DUMPBITCODE_OFF; break; - case 303: + case depwarn: if (!strcmp(optarg,"yes")) - jl_compileropts.compile_enabled = 1; + jl_options.depwarn = 1; else if (!strcmp(optarg,"no")) - jl_compileropts.compile_enabled = 0; - else if (!strcmp(optarg,"all")) - jl_compileropts.compile_enabled = 2; + jl_options.depwarn = 0; else { - ios_printf(ios_stderr, "julia: invalid argument to --compile (%s)\n", optarg); + ios_printf(ios_stderr, "julia: invalid argument to --depwarn={yes|no} (%s)\n", optarg); exit(1); } break; - case 304: + case can_inline: if (!strcmp(optarg,"yes")) - jl_compileropts.depwarn = 1; + jl_options.can_inline = 1; else if (!strcmp(optarg,"no")) - jl_compileropts.depwarn = 0; - else { - ios_printf(ios_stderr, "julia: invalid argument to --depwarn (%s)\n", optarg); - exit(1); - } - break; - case 305: /* inline */ - if (!strcmp(optarg,"yes")) - jl_compileropts.can_inline = 1; - else if (!strcmp(optarg,"no")) - jl_compileropts.can_inline = 0; + jl_options.can_inline = 0; else { ios_printf(ios_stderr, "julia: invalid argument to --inline (%s)\n", optarg); exit(1); } break; + case 'b': // build + jl_options.build_path = strdup(optarg); + if (!imagepathspecified) + jl_options.image_file = NULL; + break; + case worker: + jl_options.worker = 1; + break; + case bind_to: + jl_options.bindto = strdup(optarg); + break; default: ios_printf(ios_stderr, "julia: unhandled option -- %c\n", c); ios_printf(ios_stderr, "This is a bug, please report it.\n"); exit(1); } } - jl_compileropts.code_coverage = codecov; - jl_compileropts.malloc_log = malloclog; + jl_options.code_coverage = codecov; + jl_options.malloc_log = malloclog; optind -= skip; *argvp += optind; *argcp -= optind; - if (jl_compileropts.image_file==NULL && *argcp > 0) { + if (jl_options.image_file==NULL && *argcp > 0) { if (strcmp((*argvp)[0], "-")) { program = (*argvp)[0]; }