flan build and flan run of a file with no main say so and show one, rather than failing at the link
This commit is contained in:
parent
8b4c6f81df
commit
0b9ae9318e
@ -736,6 +736,8 @@ let () =
|
|||||||
if List.mem warn_memory_flag rest then
|
if List.mem warn_memory_flag rest then
|
||||||
print_memory_warnings ~file:path p)
|
print_memory_warnings ~file:path p)
|
||||||
in
|
in
|
||||||
|
Flan.Build.need_main ~file:path ~doing:"flan build has nothing to link"
|
||||||
|
f.program;
|
||||||
ignore (Flan.Build.executable
|
ignore (Flan.Build.executable
|
||||||
~opts:{ Flan.Build.default with checks; dev; debug; sanitize;
|
~opts:{ Flan.Build.default with checks; dev; debug; sanitize;
|
||||||
target; x86;
|
target; x86;
|
||||||
@ -915,6 +917,8 @@ let () =
|
|||||||
(Printf.sprintf "flan-run-%d" (Unix.getpid ()))
|
(Printf.sprintf "flan-run-%d" (Unix.getpid ()))
|
||||||
in
|
in
|
||||||
let f = Flan.Front.linked ~all:true path in
|
let f = Flan.Front.linked ~all:true path in
|
||||||
|
Flan.Build.need_main ~file:path ~doing:"flan run has nothing to run"
|
||||||
|
f.program;
|
||||||
ignore (Flan.Build.executable
|
ignore (Flan.Build.executable
|
||||||
~opts:{ Flan.Build.default with checks; debug; sanitize;
|
~opts:{ Flan.Build.default with checks; debug; sanitize;
|
||||||
x86;
|
x86;
|
||||||
|
|||||||
16
lib/build.ml
16
lib/build.ml
@ -744,6 +744,22 @@ let compile_c ~opts ?tflags ?(warn = []) ~src ~name () =
|
|||||||
end;
|
end;
|
||||||
obj
|
obj
|
||||||
|
|
||||||
|
(* A program with no [main] builds every function and then fails at the link,
|
||||||
|
as an undefined reference from the C startup code — a message about crt1.o
|
||||||
|
for a mistake in the .flan file. Asked here, by the commands that make an
|
||||||
|
executable, rather than inside [executable], whose callers include hosts
|
||||||
|
and tests that supply their own [main]. *)
|
||||||
|
let need_main ~file ~doing (p : Tast.program) =
|
||||||
|
if not (List.exists (fun (f : Tast.fn) -> f.Tast.name = "main") p.Tast.fns)
|
||||||
|
then
|
||||||
|
failwith
|
||||||
|
(Printf.sprintf
|
||||||
|
"%s has no main, so %s. A program starts at a function named main, \
|
||||||
|
for example:\n\n\
|
||||||
|
\ (defn main [] i32\n\
|
||||||
|
\ 0)"
|
||||||
|
file doing)
|
||||||
|
|
||||||
(* [csrcs] and [lflags] come from the imported packages (see [Load]): the C
|
(* [csrcs] and [lflags] come from the imported packages (see [Load]): the C
|
||||||
shim a package binds through, and the arguments needed to link the library
|
shim a package binds through, and the arguments needed to link the library
|
||||||
it binds to.
|
it binds to.
|
||||||
|
|||||||
13
lib/dev.ml
13
lib/dev.ml
@ -4520,17 +4520,8 @@ let make_session_dir ~file dir =
|
|||||||
would find that out at the link — as a missing symbol, or as the merged
|
would find that out at the link — as a missing symbol, or as the merged
|
||||||
build's rename finding nothing to rename. *)
|
build's rename finding nothing to rename. *)
|
||||||
let need_main ~file (session : Session.t) =
|
let need_main ~file (session : Session.t) =
|
||||||
if not
|
Build.need_main ~file ~doing:"flan dev has nothing to run"
|
||||||
(List.exists (fun (f : Tast.fn) -> f.Tast.name = "main")
|
session.Session.host
|
||||||
session.Session.host.Tast.fns)
|
|
||||||
then
|
|
||||||
failwith
|
|
||||||
(Printf.sprintf
|
|
||||||
"%s has no main, so flan dev has nothing to run. A program starts at \
|
|
||||||
a function named main, for example:\n\n\
|
|
||||||
\ (defn main [] i32\n\
|
|
||||||
\ 0)"
|
|
||||||
file)
|
|
||||||
|
|
||||||
(* [debug] is off by default, which keeps [flan dev] exactly what it was: a
|
(* [debug] is off by default, which keeps [flan dev] exactly what it was: a
|
||||||
-O2 host and -O2 modules. It is opt-in rather than always-on because a debug
|
-O2 host and -O2 modules. It is opt-in rather than always-on because a debug
|
||||||
|
|||||||
@ -6472,6 +6472,18 @@ level "1"
|
|||||||
cli_case "--debug and an explicit -O are refused together"
|
cli_case "--debug and an explicit -O are refused together"
|
||||||
"build ../calc-me.flan --debug -O2 -o /dev/null" ~code:2
|
"build ../calc-me.flan --debug -O2 -o /dev/null" ~code:2
|
||||||
~says:[ "--debug"; "-O2"; "Drop one of the two" ];
|
~says:[ "--debug"; "-O2"; "Drop one of the two" ];
|
||||||
|
(* A file with no main is refused by name before the link, which would
|
||||||
|
otherwise report an undefined reference from crt1.o. *)
|
||||||
|
let nomain = Filename.concat scratch "no-main.flan" in
|
||||||
|
Out_channel.with_open_bin nomain (fun oc ->
|
||||||
|
output_string oc "(defn f [] i32 0)\n");
|
||||||
|
cli_case "build of a file with no main names main"
|
||||||
|
(Printf.sprintf "build %s -o /dev/null" (Filename.quote nomain)) ~code:1
|
||||||
|
~says:[ "has no main"; "(defn main [] i32" ];
|
||||||
|
cli_case "run of a file with no main names main"
|
||||||
|
(Printf.sprintf "run %s" (Filename.quote nomain)) ~code:1
|
||||||
|
~says:[ "has no main"; "(defn main [] i32" ];
|
||||||
|
Sys.remove nomain;
|
||||||
|
|
||||||
(* Every row above that went through the pool has been forked; nothing
|
(* Every row above that went through the pool has been forked; nothing
|
||||||
after this point may look at [failures] until every one of them has
|
after this point may look at [failures] until every one of them has
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user