diff --git a/README.md b/README.md index 4222716..10d7a54 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,18 @@ They can be placed in your `rebar.config` file, or issued on the command line. The options are as follows: * `--verbose -v` Lots of output for debugging. - * `--encoding -e` Pick the encoding used by the asn compiler. Options are `ber`, `per`, and `uper`. `ber` is the default. - * `--compile_opts -o` A comma-separated list of options to send to erlang's asn.1 compiler. See http://erlang.org/doc/man/asn1ct.html#compile-2 for available options. + * `--encoding -e` Pick the encoding used by the asn compiler. Options + are `ber`, `per`, and `uper`. `ber` is the default. + * `--compile_opts -o` A comma-separated list of options to send to + Erlang's ASN.1 compiler. See + http://erlang.org/doc/man/asn1ct.html#compile-2 for available + options. + * `--compile_order -c` An Erlang term consisting of a tuple-list of + the specific order to compile the ASN.1 files where the first + tuple-element is one of `wildcard` | `file` | `dir` and the second + the filename in string format. Defaults to + `[{wildcard, \"**/*.asn1\"}]`. + Example: ``` diff --git a/src/provider_asn1_compile.erl b/src/provider_asn1_compile.erl index 486f569..c9fffa4 100644 --- a/src/provider_asn1_compile.erl +++ b/src/provider_asn1_compile.erl @@ -5,7 +5,8 @@ -define(PROVIDER, 'compile'). -define(DEPS, [{default, app_discovery}]). --define(DEFAULTS, [{verbose, false}, {encoding, ber}, {compile_opts, []}]). +-define(DEFAULTS, [{verbose, false}, {encoding, ber}, {compile_opts, []}, + {compile_order, [{wildcard, "**/*.asn1"}]}]). %% =================================================================== %% Public API @@ -22,22 +23,44 @@ init(State) -> % list of options understood by the plugin {opts, [{verbose, $v, "verbose", boolean, "Be Verbose."}, {encoding, $e, "encoding", atom, "The encoding to use (atom). ber by default."}, - {compile_opts, $o, "compile_opts", binary, "A comma-separated list of options to send to erlang's asn.1 compiler."}]}, + {compile_opts, $o, "compile_opts", binary, + "A comma-separated list of options to send to Erlang's ASN.1 compiler."}, + {compile_order, $c, "compile_order", binary, + "An Erlang term consisting of a tuple-list of the specific order " + "to compile the ASN.1 files where the first tuple-element is " + "one of `wildcard' | `file' | `dir' and the second the filename " + "in string format. Defaults to `[{wildcard, \"**/*.asn1\"}]'."} + ]}, {short_desc, "Compile ASN.1 with Rebar3"}, {desc, "Compile ASN.1 with Rebar3"} ]), {ok, rebar_state:add_provider(State, Provider)}. resolve_special_args(PreState) -> - NewState = provider_asn1_util:resolve_args(PreState, ?DEFAULTS), - CompileOpts = provider_asn1_util:get_arg(NewState, compile_opts), + DefaultState = provider_asn1_util:resolve_args(PreState, ?DEFAULTS), + lists:foldl(fun (F, State) -> F(State) end, + DefaultState, + [fun resolve_compile_opts/1, + fun resolve_compile_order/1]). + +resolve_compile_opts(State) -> + CompileOpts = provider_asn1_util:get_arg(State, compile_opts), if is_binary(CompileOpts) -> NewCompileOpts = lists:map(fun(X) -> binary_to_atom(X, utf8) end, re:split(CompileOpts, ",")), - provider_asn1_util:set_arg(NewState, compile_opts, NewCompileOpts); - true -> NewState + provider_asn1_util:set_arg(State, compile_opts, NewCompileOpts); + true -> State + end. +resolve_compile_order(State) -> + CompileOrder = provider_asn1_util:get_arg(State, compile_order), + if + is_binary(CompileOrder) -> + {ok, Toks, _} = erl_scan:string(binary_to_list(CompileOrder) ++ "."), + {ok, NewCompileOrder} = erl_parse:parse_term(Toks), + provider_asn1_util:set_arg(State, compile_order, NewCompileOrder); + true -> State end. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. @@ -61,7 +84,7 @@ process_app(State, AppPath) -> SrcPath = filename:join(AppPath, "src"), ensure_dir(State, SrcPath), - case to_recompile(ASNPath, GenPath) of + case to_recompile(State, ASNPath, GenPath) of [] -> ok; Asns -> @@ -108,14 +131,36 @@ ensure_dir(State, Path) -> provider_asn1_util:verbose_out(State, "Making ~p ~p~n", [Path, file:make_dir(Path)]) end. -to_recompile(ASNPath, GenPath) -> +to_recompile(State, ASNPath, GenPath) -> lists:filtermap(fun (File) -> is_latest(File, ASNPath, GenPath) end, - find_asn_files(ASNPath)). + find_asn_files(State, ASNPath)). + +find_asn_files(State, BasePath) -> + Order = provider_asn1_util:get_arg(State, compile_order), + Fs = lists:flatmap(fun ({wildcard, Wildcard}) -> + [filename:join(BasePath, F) || F <- filelib:wildcard(Wildcard, BasePath)]; + ({file, File}) -> + [filename:join(BasePath, File)]; + ({dir, Dir}) -> + D = filename:join(BasePath, Dir), + [filename:join(D, F) || F <- filelib:wildcard("*.asn1", D)] + end, Order), + uniq(Fs). -find_asn_files(Path) -> - [filename:join(Path, F) || F <- filelib:wildcard("**/*.asn1", Path)]. +-ifdef(OTP_RELEASE). + -if(?OTP_RELEASE >= 25). +uniq(Fs) -> + lists:uniq(Fs). + -elif(?OTP_RELEASE < 25). +uniq(Fs) -> + Fs. + -endif. +-else. +uniq(Fs) -> + Fs. +-endif. is_latest(ASNFileName, ASNPath, GenPath) -> Source = filename:join(ASNPath, ASNFileName),