diff --git a/NEWS.md b/NEWS.md index 6fb80a21d219b..16afb8c168443 100644 --- a/NEWS.md +++ b/NEWS.md @@ -16,12 +16,6 @@ Compiler/Runtime improvements Command-line option changes --------------------------- -* The entry point for Julia has been standardized to `Main.main(ARGS)`. When julia is invoked to run a script or expression -(i.e. using `julia script.jl` or `julia -e expr`), julia will subsequently run the `Main.main` function automatically if -such a function has been defined. This is intended to unify script and compilation workflows, where code loading may happen -in the compiler and execution of `Main.main` may happen in the resulting executable. For interactive use, there is no semantic -difference between defining a `main` function and executing the code directly at the end of the script. ([50974]) - Multi-threading changes ----------------------- diff --git a/base/client.jl b/base/client.jl index 7baef9d0010f0..0b11a330cf179 100644 --- a/base/client.jl +++ b/base/client.jl @@ -228,8 +228,11 @@ incomplete_tag(exc::Meta.ParseError) = incomplete_tag(exc.detail) cmd_suppresses_program(cmd) = cmd in ('e', 'E') function exec_options(opts) + quiet = (opts.quiet != 0) startup = (opts.startupfile != 2) - global have_color = (opts.color != 0) ? (opts.color == 1) : nothing # --color=on + history_file = (opts.historyfile != 0) + color_set = (opts.color != 0) # --color!=auto + global have_color = color_set ? (opts.color == 1) : nothing # --color=on global is_interactive = (opts.isinteractive != 0) # pre-process command line argument list @@ -320,8 +323,15 @@ function exec_options(opts) end end end - - return repl + if repl || is_interactive::Bool + b = opts.banner + auto = b == -1 + banner = b == 0 || (auto && !interactiveinput) ? :no : + b == 1 || (auto && interactiveinput) ? :yes : + :short # b == 2 + run_main_repl(interactiveinput, quiet, banner, history_file, color_set) + end + nothing end function _global_julia_startup_file() @@ -538,28 +548,13 @@ function _start() append!(ARGS, Core.ARGS) # clear any postoutput hooks that were saved in the sysimage empty!(Base.postoutput_hooks) - local ret = 0 try - repl_was_requested = exec_options(JLOptions()) - if isdefined(Main, :main) && !is_interactive - if Core.Compiler.generating_sysimg() - precompile(Main.main, (typeof(ARGS),)) - else - ret = invokelatest(Main.main, ARGS) - end - elseif (repl_was_requested || is_interactive) - if isassigned(REPL_MODULE_REF) - ret = REPL_MODULE_REF[].main(ARGS) - end - end - ret === nothing && (ret = 0) - ret = Cint(ret) + exec_options(JLOptions()) catch - ret = Cint(1) invokelatest(display_error, scrub_repl_backtrace(current_exceptions())) + exit(1) end if is_interactive && get(stdout, :color, false) print(color_normal) end - return ret end diff --git a/doc/src/manual/command-line-interface.md b/doc/src/manual/command-line-interface.md index 69763d14a7668..3a522079409a6 100644 --- a/doc/src/manual/command-line-interface.md +++ b/doc/src/manual/command-line-interface.md @@ -39,58 +39,6 @@ $ julia --color=yes -O -- script.jl arg1 arg2.. See also [Scripting](@ref man-scripting) for more information on writing Julia scripts. -## The `Main.main` entry point - -At the conclusion of executing a script or expression, `julia` will attempt to execute the function -`Main.main(ARGS)` (if such a function has been defined). This feature is intended to aid in the unification -of compiled and interactive workflows. In compiled workflows, loading the code that defines the `main` -function may be spatially and temporally separated from the invocation. However, for interactive workflows, -the behavior is equivalent to explicitly calling `exit(main(ARGS))` at the end of the evaluated script or -expression. - -!!! compat "Julia 1.11" - The special entry point `Main.main` was added in Julia 1.11. For compatibility with prior julia versions, - add an explicit `VERSION < v"1.11" && exit(main(ARGS))` at the end of your scripts. - -To see this feature in action, consider the following definition, which will execute the print function despite there being no explicit call to `main`: - -``` -$ julia -e 'main(ARGS) = println("Hello World!")' -Hello World! -$ -``` - -Only the `main` binding in the `Main`, module has this special behavior. For example, using `hello` -instead of `main` will result in the `hello` function not executing: - -``` -$ julia -e 'hello(ARGS) = println("Hello World!")' -$ -``` - -The `main` binding may be imported from a package. A hello package defined as - -``` -module Hello - -export main -main(ARGS) = println("Hello from the package!") - -end -``` - -may be used as: - -``` -$ julia -e 'using Hello' -Hello from the package! -$ julia -e 'import Hello' # N.B.: Execution depends on the binding not whether the package is loaded -$ -``` - -However, note that the current best practice recommendation is to not mix application and reusable library -code in the same package. Helper applications may be distributed as separate pacakges or as scripts with -separate `main` entry points in a package's `bin` folder. ## Parallel mode diff --git a/src/jlapi.c b/src/jlapi.c index 29be3b9e6179c..0dffaac627288 100644 --- a/src/jlapi.c +++ b/src/jlapi.c @@ -576,20 +576,16 @@ static NOINLINE int true_main(int argc, char *argv[]) if (start_client) { jl_task_t *ct = jl_current_task; - int ret = 1; JL_TRY { size_t last_age = ct->world_age; ct->world_age = jl_get_world_counter(); - jl_value_t *r = jl_apply(&start_client, 1); - if (jl_typeof(r) != (jl_value_t*)jl_int32_type) - jl_type_error("typeassert", (jl_value_t*)jl_int32_type, r); - ret = jl_unbox_int32(r); + jl_apply(&start_client, 1); ct->world_age = last_age; } JL_CATCH { jl_no_exc_handler(jl_current_exception(), ct); } - return ret; + return 0; } // run program if specified, otherwise enter REPL diff --git a/stdlib/REPL/src/REPL.jl b/stdlib/REPL/src/REPL.jl index 518514a960638..fe543ad2d512f 100644 --- a/stdlib/REPL/src/REPL.jl +++ b/stdlib/REPL/src/REPL.jl @@ -1506,20 +1506,4 @@ end import .Numbered.numbered_prompt! -# TODO: Move more of this implementation into REPL. -function main(ARGS) - opts = Base.JLOptions() - interactiveinput = isa(stdin, Base.TTY) - b = opts.banner - auto = b == -1 - banner = b == 0 || (auto && !interactiveinput) ? :no : - b == 1 || (auto && interactiveinput) ? :yes : - :short # b == 2 - - quiet = (opts.quiet != 0) - history_file = (opts.historyfile != 0) - color_set = (opts.color != 0) # --color!=auto - Base.run_main_repl(interactiveinput, quiet, banner, history_file, color_set) -end - end # module diff --git a/test/cmdlineargs.jl b/test/cmdlineargs.jl index 86c2994655295..b29904fb5eb6c 100644 --- a/test/cmdlineargs.jl +++ b/test/cmdlineargs.jl @@ -977,15 +977,3 @@ end #heap-size-hint, we reserve 250 MB for non GC memory (llvm, etc.) @test readchomp(`$(Base.julia_cmd()) --startup-file=no --heap-size-hint=500M -e "println(@ccall jl_gc_get_max_memory()::UInt64)"`) == "$((500-250)*1024*1024)" end - -## `Main.main` entrypoint - -# Basic usage -@test readchomp(`$(Base.julia_cmd()) -e 'main(ARGS) = println("hello")'`) == "hello" - -# Test ARGS with -e -@test readchomp(`$(Base.julia_cmd()) -e 'main(ARGS) = println(ARGS)' a b`) == repr(["a", "b"]) - -# Test import from module -@test readchomp(`$(Base.julia_cmd()) -e 'module Hello; export main; main(ARGS) = println("hello"); end; using .Hello'`) == "hello" -@test readchomp(`$(Base.julia_cmd()) -e 'module Hello; export main; main(ARGS) = println("hello"); end; import .Hello'`) == ""