Skip to content

use @main for juliac executable entry point #57588

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions contrib/juliac-buildscript.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
# Script to run in the process that generates juliac's object file output

inputfile = ARGS[1]
output_type = ARGS[2]
add_ccallables = ARGS[3] == "true"

# Run the verifier in the current world (before modifications), so that error
# messages and types print in their usual way.
Core.Compiler._verify_trim_world_age[] = Base.get_world_counter()
Expand Down Expand Up @@ -189,13 +185,37 @@ end

import Base.Experimental.entrypoint

let mod = Base.include(Base.__toplevel__, inputfile)
if !isa(mod, Module)
mod = Main
end
# for use as C main if needed
function _main(argc::Cint, argv::Ptr{Ptr{Cchar}})::Cint
args = ccall(:jl_set_ARGS, Any, (Cint, Ptr{Ptr{Cchar}}), argc, argv)::Vector{String}
return Main.main(args)
end

let mod = Base.include(Main, ARGS[1])
Core.@latestworld
if output_type == "--output-exe" && isdefined(mod, :main) && !add_ccallables
entrypoint(mod.main, ())
if ARGS[2] == "--output-exe"
have_cmain = false
if isdefined(Main, :main)
for m in methods(Main.main)
if isdefined(m, :ccallable)
# TODO: possibly check signature and return type
have_cmain = true
break
end
end
end
if !have_cmain
if Base.should_use_main_entrypoint()
if hasmethod(Main.main, Tuple{Vector{String}})
entrypoint(_main, (Cint, Ptr{Ptr{Cchar}}))
Base._ccallable("main", Cint, Tuple{typeof(_main), Cint, Ptr{Ptr{Cchar}}})
else
error("`@main` must accept a `Vector{String}` argument.")
end
else
error("To generate an executable a `@main` function must be defined.")
end
end
end
#entrypoint(join, (Base.GenericIOBuffer{Memory{UInt8}}, Array{Base.SubString{String}, 1}, String))
#entrypoint(join, (Base.GenericIOBuffer{Memory{UInt8}}, Array{String, 1}, Char))
Expand All @@ -204,7 +224,7 @@ let mod = Base.include(Base.__toplevel__, inputfile)
entrypoint(Base.wait_forever, ())
entrypoint(Base.trypoptask, (Base.StickyWorkqueue,))
entrypoint(Base.checktaskempty, ())
if add_ccallables
if ARGS[3] == "true"
ccall(:jl_add_ccallable_entrypoints, Cvoid, ())
end
end
Expand Down
2 changes: 0 additions & 2 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4642,8 +4642,6 @@ JL_DLLEXPORT void jl_extern_c(jl_value_t *name, jl_value_t *declrt, jl_tupletype
jl_error("@ccallable: function object must be a singleton");

// compute / validate return type
if (!jl_is_concrete_type(declrt) || jl_is_kind(declrt))
jl_error("@ccallable: return type must be concrete and correspond to a C type");
if (!jl_type_mappable_to_c(declrt))
jl_error("@ccallable: return type doesn't correspond to a C type");

Expand Down
34 changes: 19 additions & 15 deletions src/jlapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,24 +50,28 @@ JL_DLLEXPORT int jl_is_initialized(void)
* @param argc The number of command line arguments.
* @param argv Array of command line arguments.
*/
JL_DLLEXPORT void jl_set_ARGS(int argc, char **argv)
JL_DLLEXPORT jl_value_t *jl_set_ARGS(int argc, char **argv)
{
if (jl_core_module != NULL) {
jl_array_t *args = (jl_array_t*)jl_get_global(jl_core_module, jl_symbol("ARGS"));
if (args == NULL) {
args = jl_alloc_vec_any(0);
JL_GC_PUSH1(&args);
jl_array_t *args = NULL;
jl_value_t *vecstr = NULL;
JL_GC_PUSH2(&args, &vecstr);
if (jl_core_module != NULL)
args = (jl_array_t*)jl_get_global(jl_core_module, jl_symbol("ARGS"));
if (args == NULL) {
vecstr = jl_apply_array_type((jl_value_t*)jl_string_type, 1);
args = jl_alloc_array_1d(vecstr, 0);
if (jl_core_module != NULL)
jl_set_const(jl_core_module, jl_symbol("ARGS"), (jl_value_t*)args);
JL_GC_POP();
}
assert(jl_array_nrows(args) == 0);
jl_array_grow_end(args, argc);
int i;
for (i = 0; i < argc; i++) {
jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]);
jl_array_ptr_set(args, i, s);
}
}
assert(jl_array_nrows(args) == 0);
jl_array_grow_end(args, argc);
int i;
for (i = 0; i < argc; i++) {
jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]);
jl_array_ptr_set(args, i, s);
}
JL_GC_POP();
return (jl_value_t*)args;
}

JL_DLLEXPORT void jl_init_with_image_handle(void *handle) {
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -2579,7 +2579,7 @@ uint64_t parse_heap_size_hint(const char *optarg, const char *option_name);

// Set julia-level ARGS array according to the arguments provided in
// argc/argv
JL_DLLEXPORT void jl_set_ARGS(int argc, char **argv);
JL_DLLEXPORT jl_value_t *jl_set_ARGS(int argc, char **argv);

JL_DLLEXPORT int jl_generating_output(void) JL_NOTSAFEPOINT;

Expand Down
6 changes: 1 addition & 5 deletions test/trimming/basic_jll.jl
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
module MyApp

using Libdl
using Zstd_jll

Base.@ccallable function main()::Cint
function @main(args::Vector{String})::Cint
println(Core.stdout, "Julia! Hello, world!")
fptr = dlsym(Zstd_jll.libzstd_handle, :ZSTD_versionString)
println(Core.stdout, unsafe_string(ccall(fptr, Cstring, ())))
println(Core.stdout, unsafe_string(ccall((:ZSTD_versionString, libzstd), Cstring, ())))
return 0
end

end
7 changes: 2 additions & 5 deletions test/trimming/hello.jl
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
module MyApp

world::String = "world!"
const str = OncePerProcess{String}() do
return "Hello, " * world
end

Base.@ccallable function main()::Cint
function @main(args::Vector{String})::Cint
println(Core.stdout, str())
foreach(x->println(Core.stdout, x), args)
return 0
end

end
2 changes: 1 addition & 1 deletion test/trimming/trimming.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ bindir = dirname(ARGS[1])
let exe_suffix = splitext(Base.julia_exename())[2]

hello_exe = joinpath(bindir, "hello" * exe_suffix)
@test readchomp(`$hello_exe`) == "Hello, world!"
@test readchomp(`$hello_exe arg1 arg2`) == "Hello, world!\n$hello_exe\narg1\narg2"
@test filesize(hello_exe) < 2_000_000

basic_jll_exe = joinpath(bindir, "basic_jll" * exe_suffix)
Expand Down