From 2ade47c81ca37639695025cda218a83d2179f4a7 Mon Sep 17 00:00:00 2001 From: Sebastian Weddmark Olsson Date: Wed, 21 Jun 2023 16:27:06 +0200 Subject: [PATCH] Add compile option overrides (#18) One can now specify a list of tuples with some file-pattern and the overrides it should do for that file-pattern. Use {file, Filename} for overriding specific files, and {re, Regex} to override for all files with full path matching the regex. Fixes #8 --- README.md | 10 +++++-- src/provider_asn1_compile.erl | 56 ++++++++++++++++++++++++++++++----- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 10d7a54..f2c1e27 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,10 @@ The options are as follows: tuple-element is one of `wildcard` | `file` | `dir` and the second the filename in string format. Defaults to `[{wildcard, \"**/*.asn1\"}]`. - + * `--overrides -O` An Erlang term consisting of a tuple-list of the + compile options that will override the options per file. The first + tuple-element is one of `file` | `re` and the second the filename + or match pattern in string format. Example: ``` @@ -119,7 +122,10 @@ As mentioned, these options can be put in your `rebar.config` file: ``` {asn1_args, [{encoding, per}, {verbose, true}, - {compile_opts, [der, compact_bit_string]}]}. + {compile_opts, [der, compact_bit_string]}, + {overrides, [{{file, "CAP_PHASE1.set.asn1"}, [{encoding, [ber]}, + {compile_opts, [{i, "asn1-lib/"}]}]}, + {{re, "/uper/"}, [{encoding, uper}]}]}]}. ``` Options in `rebar.config` will be overridden by command-line options. diff --git a/src/provider_asn1_compile.erl b/src/provider_asn1_compile.erl index c9fffa4..0213b95 100644 --- a/src/provider_asn1_compile.erl +++ b/src/provider_asn1_compile.erl @@ -29,7 +29,9 @@ init(State) -> "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\"}]'."} + "in string format. Defaults to `[{wildcard, \"**/*.asn1\"}]'."}, + {overrides, $O, "overrides", binary, + "An Erlang term [{file | re, string}, [Opt]}] with specific options."} ]}, {short_desc, "Compile ASN.1 with Rebar3"}, {desc, "Compile ASN.1 with Rebar3"} @@ -41,7 +43,9 @@ resolve_special_args(PreState) -> lists:foldl(fun (F, State) -> F(State) end, DefaultState, [fun resolve_compile_opts/1, - fun resolve_compile_order/1]). + fun resolve_compile_order/1, + fun resolve_compile_overrides/1 + ]). resolve_compile_opts(State) -> CompileOpts = provider_asn1_util:get_arg(State, compile_opts), @@ -62,6 +66,15 @@ resolve_compile_order(State) -> provider_asn1_util:set_arg(State, compile_order, NewCompileOrder); true -> State end. +resolve_compile_overrides(State) -> + FileCompileOpts = provider_asn1_util:get_arg(State, overrides), + if + is_binary(FileCompileOpts) -> + {ok, Toks, _} = erl_scan:string(binary_to_list(FileCompileOpts) ++ "."), + {ok, NewFileCompileOpts} = erl_parse:parse_term(Toks), + provider_asn1_util:set_arg(State, overrides, NewFileCompileOpts); + true -> State + end. -spec do(rebar_state:t()) -> {ok, rebar_state:t()} | {error, string()}. do(PreState) -> @@ -90,7 +103,7 @@ process_app(State, AppPath) -> Asns -> ensure_dir(State, GenPath), ensure_dir(State, IncludePath), - lists:foreach(fun(AsnFile) -> generate_asn(State, GenPath, AsnFile) end, Asns), + lists:foreach(fun(AsnFile) -> generate_asn(State, GenPath, AsnFile, AppPath) end, Asns), move_asns(State, GenPath, SrcPath, IncludePath, Asns) end. @@ -107,14 +120,14 @@ move_asns(State, GenPath, SrcPath, IncludePath, Asns) -> format_error(Reason) -> provider_asn1_util:format_error(Reason). -generate_asn(State, Path, AsnFile) -> +generate_asn(State, Path, AsnFile, AppPath) -> rebar_api:info("~s", [AsnFile]), - Args = provider_asn1_util:get_args(State), + Args = apply_file_overrides(AsnFile, provider_asn1_util:get_args(State)), provider_asn1_util:verbose_out(State, "Args: ~p", [Args]), Encoding = proplists:get_value(encoding, Args), Verbose = proplists:get_value(verbose, Args), - CompileArgs = [verbose || Verbose] ++ [noobj, Encoding, {outdir, Path}] - ++ proplists:get_value(compile_opts, Args), + CompileOpts = fix_paths(AppPath, proplists:get_value(compile_opts, Args)), + CompileArgs = CompileOpts ++ [verbose || Verbose] ++ [noobj, Encoding, {outdir, Path}], provider_asn1_util:verbose_out(State, "Beginning compile with opts: ~p", [CompileArgs]), case asn1ct:compile(AsnFile, CompileArgs) of {error, E} -> @@ -167,3 +180,32 @@ is_latest(ASNFileName, ASNPath, GenPath) -> TargetFileName = filename:basename(ASNFileName, ".asn1") ++ ".erl", Target = filename:join(GenPath, TargetFileName), filelib:last_modified(Source) > filelib:last_modified(Target). + +apply_file_overrides(File, Args) -> + {[OverridesArgs], OtherArgs} = proplists:split(Args, [overrides]), + case OverridesArgs of + [{overrides, Overrides}] -> match_file_overrides(File, Overrides); + [] -> [] + end ++ OtherArgs. + +match_file_overrides(_File, []) -> []; +match_file_overrides(File, [{{file, BName}, Args}|Rest]) -> + case filename:basename(File) of + BName -> Args; + _ -> match_file_overrides(File, Rest) + end; +match_file_overrides(File, [{{re, Pat}, Args}|Rest]) -> + case re:run(File, Pat, [{capture, none}]) of + nomatch -> match_file_overrides(File, Rest); + match -> Args + end; +match_file_overrides(File, [ _ | Rest ]) -> + match_file_overrides(File, Rest). + +fix_paths(AppPath, Args) -> + % there are issues when using relative paths in nested applications, + % make them absolut be prepending the AppPath. + lists:map(fun + ({i, Path}) -> {i, filename:absname(Path, AppPath)}; + (Arg) -> Arg + end, Args).