Canviant namespaces jerarquic
[makerl.git] / src / makerl.erl
blobb53cb1e4952ee0e802ed189f06866fb0ee553b11
1 %%
2 %% This file is the main entry point for command-line usage.
3 %%
5 -module(makerl).
6 -include("makerl.hrl").
8 -define(EXIT(Str, Args, ExitCode), throw({error, ExitCode, ?FMT(Str, Args)})).
10 -define(DEFAULT_SCRIPT_NAME, "MakErlFile.erl").
12 -export([main/1]).
14 %% ----------------------------------------------------------------------
15 %% Parsed ARGS
16 %% ----------------------------------------------------------------------
17 -record(parsed_args, { options :: options_type(),
18 targets :: [string()],
19 log_level :: log_level_type(),
20 filename :: string() }).
22 -spec default_args() -> #parsed_args{}.
23 default_args() ->
24 #parsed_args{ options = [],
25 targets = [],
26 log_level = warn,
27 filename = ?DEFAULT_SCRIPT_NAME }.
29 -spec args_append_option(#parsed_args{}, option_type()) -> #parsed_args{}.
30 args_append_option(Arg, Option) ->
31 Arg#parsed_args{ options = [Option | Arg#parsed_args.options] }.
33 %% ----------------------------------------------------------------------
34 %% Main(s)
35 %% ----------------------------------------------------------------------
36 -spec main([string()]) -> [build_result()].
37 main(Args) ->
38 process_flag(trap_exit, true),
39 case catch(unsafe_main(Args)) of
40 {error, ErrCode, Msg} ->
41 ?ERROR("[ERROR] ~s~n", [Msg]),
42 halt(ErrCode);
43 {error, {targets_unknown, T}} ->
44 ?ERROR("Don't know how to build: ~p~n", [T]);
45 {'EXIT', Reason} ->
46 ?ERROR("[EXIT RECEIVED] ~p~n", [Reason]);
47 X -> ?DEBUG("[Result]: ~p ~n", [X])
48 end.
50 -spec unsafe_main([string()]) -> [build_result()].
51 unsafe_main(Args) ->
52 %% Load environment
53 ok = init(),
55 ParsedArgs = parse_args(Args),
56 makerl.log:set_level(ParsedArgs#parsed_args.log_level),
57 ?DEBUG("[PARSED ARGS] ~p~n", [ParsedArgs]),
59 case ParsedArgs#parsed_args.targets of
60 [] -> help();
61 _ -> execution:execute(ParsedArgs#parsed_args.filename,
62 ParsedArgs#parsed_args.targets,
63 ParsedArgs#parsed_args.options)
64 end.
66 -spec init() -> ok.
67 init() ->
68 %% io:format("~p~n", [escript:script_name()]),
69 ok = application:load(makerl),
70 task_registry:start_link(), %% This is per-execution, in the future...
71 makerl.log:init(),
72 ok.
75 %% ----------------------------------------------------------------------
76 %% Argument parsing
77 %% ----------------------------------------------------------------------
78 -spec parse_args([string()]) -> #parsed_args{}.
79 parse_args(Args) ->
80 case getopt:parse(option_spec_list(), Args) of
81 {ok, {Options, Rest}} ->
82 ParsedWithOptions = parse_options(Options),
83 ParsedWithOptions#parsed_args{ targets = Rest };
84 X -> X
85 end.
87 parse_options(Options) ->
88 lists:foldl(fun parse_option/2, default_args(), Options).
89 parse_option({define, Txt}, Acc) ->
90 case string:tokens(Txt, ".:") of
91 [ModStr, OptStr, Value] ->
92 args_append_option(Acc, {list_to_atom(ModStr), OptStr, Value});
93 [ModStr, OptStr] ->
94 args_append_option(Acc, {list_to_atom(ModStr), OptStr});
95 E ->
96 ?EXIT("Cmdline parsing error expanding option ~p~n~p~n", [{define, Txt}, E], 1)
97 end;
98 parse_option({file, File}, Acc) ->
99 Acc#parsed_args{ filename = File };
100 parse_option(help, _Acc) ->
101 help();
102 parse_option({log_level, 0}, Acc) -> Acc#parsed_args{ log_level = error };
103 parse_option({log_level, 1}, Acc) -> Acc#parsed_args{ log_level = warn };
104 parse_option({log_level, 2}, Acc) -> Acc#parsed_args{ log_level = info };
105 parse_option({log_level, 3}, Acc) -> Acc#parsed_args{ log_level = debug };
106 parse_option(FallBack, _) ->
107 ?EXIT("Unknown option: ~p~n", [FallBack], 1).
111 -spec help() -> no_return().
112 help() ->
113 Usage = getopt:usage(option_spec_list(), "makerl", ["target ..."]),
114 ?EXIT("~p~n", [Usage], 0).
116 option_spec_list() ->
118 %% {Name, ShortOpt, LongOpt, ArgSpec, HelpMsg}
119 {help, $h, "help", undefined, "Show help and exit"},
120 {define, $d, "define", string, "Define processing variable"},
121 {file, $f, "file", string, "The script file to build. Default is " ++ ?DEFAULT_SCRIPT_NAME },
122 {log_level, $l, "log-level", integer, "The verbosity level from 0 to 3 (most verbose). Default is 1."}