diff options
| author | theiw <none@none> | 2010-02-05 17:34:38 +0000 | 
|---|---|---|
| committer | theiw <none@none> | 2010-02-05 17:34:38 +0000 | 
| commit | 788bd3df726933334ee9c570e1e920829c5d1c4c (patch) | |
| tree | ed11edbb52295a81179f7e181c40a4ce30827c87 /src | |
| parent | 30a3816c8649bbafb3695780c78c4eabbaa92eda (diff) | |
Provide package support for eunit; build_plt now includes listed applications; begin including -spec annotations
Diffstat (limited to 'src')
| -rw-r--r-- | src/rebar_core.erl | 2 | ||||
| -rw-r--r-- | src/rebar_dialyzer.erl | 43 | ||||
| -rw-r--r-- | src/rebar_erlc_compiler.erl | 35 | ||||
| -rw-r--r-- | src/rebar_eunit.erl | 29 | ||||
| -rw-r--r-- | src/rebar_otp_app.erl | 11 | ||||
| -rw-r--r-- | src/rebar_utils.erl | 14 | 
6 files changed, 85 insertions, 49 deletions
| diff --git a/src/rebar_core.erl b/src/rebar_core.erl index 68391e7..1cefe84 100644 --- a/src/rebar_core.erl +++ b/src/rebar_core.erl @@ -188,7 +188,7 @@ process_dir(Dir, ParentConfig, Commands) ->      %% Get the list of modules for "any dir". This is a catch-all list of modules      %% that are processed in addion to modules associated with this directory -    %5 type. These any_dir modules are processed FIRST. +    %% type. These any_dir modules are processed FIRST.      {ok, AnyDirModules} = application:get_env(rebar, any_dir_modules),      Modules = AnyDirModules ++ DirModules, diff --git a/src/rebar_dialyzer.erl b/src/rebar_dialyzer.erl index c725e48..35bb201 100644 --- a/src/rebar_dialyzer.erl +++ b/src/rebar_dialyzer.erl @@ -28,7 +28,7 @@  %% @doc rebar_dialyzer supports the following commands:  %% <ul>  %%   <li>analyze (essentially "dialyzer -r ebin")</li> -%%   <li>build_plt (essentially "dialyzer --build_plt -r &rt;stdlib_lib< &rt;kernel_lib< &rt;mnesia_lib<")</li> +%%   <li>build_plt (essentially "dialyzer --build_plt -r <app_dirs>")</li>  %%   <li>check_plt (essentially "dialyzer --check_plt")</li>  %% </ul>  %% A single option <code>plt</code> can be presented in the <code>dialyzer_opts</code> @@ -59,8 +59,8 @@  %% @doc Perform static analysis on the contents of the ebin directory.  %% @spec analyze(Config::#config{}, File::string()) -> ok.  -spec(analyze(Config::#config{}, File::string()) -> ok). -analyze(Config, _File) -> -    Plt = plt_path(Config), +analyze(Config, File) -> +    Plt = plt_path(Config, File),      case dialyzer:plt_info(Plt) of          {ok, _} ->              try dialyzer:run([{files_rec, ["ebin"]}, {init_plt, Plt}]) of @@ -82,17 +82,14 @@ analyze(Config, _File) ->  %% @doc Build the PLT.  %% @spec build_plt(Config::#config{}, File::string()) -> ok  -spec(build_plt(Config::#config{}, File::string()) -> ok). -build_plt(Config, _File) -> -    Plt = plt_path(Config), +build_plt(Config, File) -> +    Plt = plt_path(Config, File), -    %% This is the recommended minimal PLT for OTP -    %% (see http://www.erlang.org/doc/apps/dialyzer/dialyzer_chapter.html#id2256857). +    {ok, _AppName, AppData} = rebar_app_utils:load_app_file(File), +    Apps = proplists:get_value(applications, AppData), +          Warnings = dialyzer:run([{analysis_type, plt_build}, -                             {files_rec, [ -                                 filename:join(code:lib_dir(stdlib), "ebin"), -                                 filename:join(code:lib_dir(kernel), "ebin"), -                                 filename:join(code:lib_dir(mnesia), "ebin") -                             ]}, +                             {files_rec, app_dirs(Apps)},                               {output_plt, Plt}]),      case Warnings of          [] -> @@ -105,8 +102,8 @@ build_plt(Config, _File) ->  %% @doc Check whether the PLT is up-to-date (rebuilding it if not).  %% @spec check_plt(Config::#config{}, File::string()) -> ok  -spec(check_plt(Config::#config{}, File::string()) -> ok). -check_plt(Config, _File) -> -    Plt = plt_path(Config), +check_plt(Config, File) -> +    Plt = plt_path(Config, File),      try dialyzer:run([{analysis_type, plt_check}, {init_plt, Plt}]) of          [] ->              ?CONSOLE("The PLT ~s is up-to-date~n", [Plt]); @@ -123,8 +120,15 @@ check_plt(Config, _File) ->  %% Internal functions  %% =================================================================== +%% @doc Obtain the library paths for the supplied applications. +%% @spec app_dirs(Apps::[atom()]) -> [string()] +-spec(app_dirs(Apps::[atom()]) -> [string()]). +app_dirs(Apps) -> +    [filename:join(Path, "ebin") || +        Path <- lists:map(fun(App) -> code:lib_dir(App) end, Apps), erlang:is_list(Path)]. +  %% @doc Render the warnings on the console. -%% @spec output_warnings(Warnings::[warning()]) -> void() +%% @spec output_warnings(Warnings::[warning()]) -> none()  -spec(output_warnings(Warnings::[warning()]) -> none()).  output_warnings(Warnings) ->      lists:foreach(fun(Warning) -> @@ -133,13 +137,14 @@ output_warnings(Warnings) ->  %% @doc If the plt option is present in rebar.config return its value, otherwise  %% return $HOME/.dialyzer_plt. -%% @spec plt_path(Config::#config{}) -> string() --spec(plt_path(Config::#config{}) -> string()). -plt_path(Config) -> +%% @spec plt_path(Config::#config{}, File::string()) -> string() +-spec(plt_path(Config::#config{}, File::string()) -> string()). +plt_path(Config, File) -> +    {ok, AppName, _AppData} = rebar_app_utils:load_app_file(File),      DialyzerOpts = rebar_config:get(Config, dialyzer_opts, []),      case proplists:get_value(plt, DialyzerOpts) of          undefined -> -            filename:join(os:getenv("HOME"), ".dialyzer_plt"); +            filename:join(os:getenv("HOME"), "." ++ atom_to_list(AppName) ++ "_dialyzer_plt");          Plt ->              Plt      end. diff --git a/src/rebar_erlc_compiler.erl b/src/rebar_erlc_compiler.erl index 04878c3..51b7f17 100644 --- a/src/rebar_erlc_compiler.erl +++ b/src/rebar_erlc_compiler.erl @@ -4,7 +4,7 @@  %%  %% rebar: Erlang Build Tools  %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% Copyright (c) 2009, 2010 Dave Smith (dizzyd@dizzyd.com)  %%  %% Permission is hereby granted, free of charge, to any person obtaining a copy  %% of this software and associated documentation files (the "Software"), to deal @@ -38,12 +38,14 @@  %% Public API  %% =================================================================== +-spec compile(Config::#config{}, AppFile::string()) -> 'ok'.  compile(Config, _AppFile) ->      doterl_compile(Config, "ebin"),      rebar_base_compiler:run(Config, rebar_config:get_list(Config, mib_first_files, []),                              "mibs", ".mib", "priv/mibs", ".bin",                              fun compile_mib/3). +-spec clean(Config::#config{}, AppFile::string()) -> 'ok'.  clean(_Config, _AppFile) ->      %% TODO: This would be more portable if it used Erlang to traverse      %%       the dir structure and delete each file; however it would also @@ -64,26 +66,33 @@ clean(_Config, _AppFile) ->  %% .erl Compilation API (externally used by only eunit)  %% =================================================================== +-spec doterl_compile(Config::#config{}, OutDir::string()) -> 'ok'.  doterl_compile(Config, OutDir) ->      doterl_compile(Config, OutDir, []).  doterl_compile(Config, OutDir, MoreSources) ->      FirstErls = rebar_config:get_list(Config, erl_first_files, []), -    RestErls  = [Source || Source <- rebar_utils:find_files("src", ".*\\.erl\$") ++ MoreSources, +    ErlOpts = rebar_config:get(Config, erl_opts, []), +    %% Support the src_dirs option allowing multiple directories to +    %% contain erlang source. This might be used, for example, should eunit tests be +    %% separated from the core application source. +    SrcDirs = src_dirs(proplists:append_values(src_dirs, ErlOpts)), +    RestErls  = [Source || Source <- gather_src(SrcDirs, []) ++ MoreSources,                             lists:member(Source, FirstErls) == false],      rebar_base_compiler:run(Config, FirstErls, RestErls,                              fun(S, C) -> internal_erl_compile(S, C, OutDir) end). -  %% ===================================================================  %% Internal functions  %% =================================================================== +-spec include_path(Source::string(), Config::#config{}) -> [string()].  include_path(Source, Config) ->      ErlOpts = rebar_config:get(Config, erl_opts, []),      [filename:dirname(Source)] ++ proplists:get_all_values(i, ErlOpts). +-spec inspect(Source::string(), IncludePath::[string()]) -> {string(), [string()]}.  inspect(Source, IncludePath) ->      ModuleDefault = filename:basename(Source, ".erl"),      case epp:open(Source, IncludePath) of @@ -94,9 +103,10 @@ inspect(Source, IncludePath) ->              {ModuleDefault, []}      end. +-spec inspect_epp(Epp::pid(), Module::string(), Includes::[string()]) -> {string(), [string()]}.  inspect_epp(Epp, Module, Includes) ->      case epp:parse_erl_form(Epp) of -        {ok, {attribute, _, module, ActualModule}} when is_list(ActualModule) -> +        {ok, {attribute, _, module, ActualModule}} ->              %% If the module name includes package info, we get a list of atoms...              case is_list(ActualModule) of                  true -> @@ -116,12 +126,13 @@ inspect_epp(Epp, Module, Includes) ->              inspect_epp(Epp, Module, Includes)      end. +-spec needs_compile(Source::string(), Target::string(), Hrls::[string()]) -> boolean().  needs_compile(Source, Target, Hrls) ->      TargetLastMod = filelib:last_modified(Target),      lists:any(fun(I) -> TargetLastMod < filelib:last_modified(I) end,                [Source] ++ Hrls). - +-spec internal_erl_compile(Source::string(), Config::#config{}, Outdir::string()) -> 'ok' | 'skipped'.  internal_erl_compile(Source, Config, Outdir) ->      %% Determine the target name and includes list by inspecting the source file      {Module, Hrls} = inspect(Source, include_path(Source, Config)), @@ -154,6 +165,7 @@ internal_erl_compile(Source, Config, Outdir) ->              skipped      end. +-spec compile_mib(Source::string(), Target::string(), Config::#config{}) -> 'ok'.  compile_mib(Source, Target, Config) ->      ok = rebar_utils:ensure_dir(Target),      Opts = [{outdir, "priv/mibs"}, {i, ["priv/mibs"]}] ++ @@ -165,9 +177,22 @@ compile_mib(Source, Target, Config) ->              ?FAIL      end. +gather_src([], Srcs) -> +    Srcs; +gather_src([Dir|Rest], Srcs) -> +    gather_src(Rest, Srcs ++ rebar_utils:find_files(Dir, ".*\\.erl\$")). + +-spec src_dirs(SrcDirs::[string()]) -> [string()]. +src_dirs([]) -> +    ["src"]; +src_dirs(SrcDirs) -> +    SrcDirs ++ src_dirs([]). + +-spec dirs(Dir::string()) -> [string()].  dirs(Dir) ->      [F || F <- filelib:wildcard(filename:join([Dir, "*"])), filelib:is_dir(F)]. +-spec delete_dir(Dir::string(), Subdirs::[string()]) -> 'ok' | {'error', atom()}.  delete_dir(Dir, []) ->      file:del_dir(Dir);  delete_dir(Dir, Subdirs) -> diff --git a/src/rebar_eunit.erl b/src/rebar_eunit.erl index 6ef7a25..d51c35d 100644 --- a/src/rebar_eunit.erl +++ b/src/rebar_eunit.erl @@ -4,7 +4,7 @@  %%  %% rebar: Erlang Build Tools  %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% Copyright (c) 2009, 2010 Dave Smith (dizzyd@dizzyd.com)  %%  %% Permission is hereby granted, free of charge, to any person obtaining a copy  %% of this software and associated documentation files (the "Software"), to deal @@ -24,14 +24,21 @@  %% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN  %% THE SOFTWARE.  %% ------------------------------------------------------------------- -%% -%% Targets: -%% eunit - runs eunit tests -%% clean - remove .eunit directory -%% -%% Global options: -%% verbose=1 - show extra output from the eunit test -%% suite="foo"" - runs test/foo_tests.erl +%% @author Dave Smith <dizzyd@dizzyd.com> +%% @doc rebar_eunit supports the following commands: +%% <ul> +%%   <li>eunit - runs eunit tests</li> +%%   <li>clean - remove .eunit directory</li> +%% </ul> +%% The following Global options are supported: +%% <ul> +%%   <li>verbose=1 - show extra output from the eunit test</li> +%%   <li>suite="foo"" - runs test/foo_tests.erl</li> +%% </ul> +%% Additionally, for projects that have separate folders for the core +%% implementation, and for the unit tests, then the following <code>rebar.config</code> +%% option can be provided: <code>{eunit_compile_opts, [{src_dirs, ["dir"]}]}.</code>. +%% @copyright 2009, 2010 Dave Smith  %% -------------------------------------------------------------------  -module(rebar_eunit). @@ -61,9 +68,7 @@ eunit(Config, _File) ->      %% with that scan and causes any cover compilation info to be lost. So,      %% we do it by hand. :(      %% -    %% TODO: Not currently compatible with package modules -    Modules = [list_to_atom(filename:basename(N, ".beam")) || -                  N <- filelib:wildcard("*.beam", ?EUNIT_DIR)], +    Modules = [rebar_utils:beam_to_mod(?EUNIT_DIR, N) || N <- rebar_utils:beams(?EUNIT_DIR)],      %% TODO: If there are other wildcards specified in eunit_sources, compile them diff --git a/src/rebar_otp_app.erl b/src/rebar_otp_app.erl index 136c5cb..f20ce0c 100644 --- a/src/rebar_otp_app.erl +++ b/src/rebar_otp_app.erl @@ -131,7 +131,7 @@ validate_modules(AppName, undefined) ->  validate_modules(AppName, Mods) ->      %% Construct two sets -- one for the actual .beam files in ebin/ and one for the modules      %% listed in the .app file -    EbinSet = ordsets:from_list([beam_to_mod(N) || N <- beams()]), +    EbinSet = ordsets:from_list([rebar_utils:beam_to_mod("ebin", N) || N <- rebar_utils:beams("ebin")]),      ModSet = ordsets:from_list(Mods),      %% Identify .beam files listed in the .app, but not present in ebin/ @@ -155,12 +155,3 @@ validate_modules(AppName, Mods) ->                     [AppName, Msg2]),              ?FAIL      end. - -beam_to_mod(Filename) -> -    ["ebin" | Rest] = filename:split(Filename), -    list_to_atom(filename:basename(string:join(Rest, "."), ".beam")). - -beams() -> -    filelib:fold_files("ebin", ".*\.beam\$", true, -                       fun(F, Acc) -> [F | Acc] end, []). - diff --git a/src/rebar_utils.erl b/src/rebar_utils.erl index 5f1612c..7265058 100644 --- a/src/rebar_utils.erl +++ b/src/rebar_utils.erl @@ -4,7 +4,7 @@  %%  %% rebar: Erlang Build Tools  %% -%% Copyright (c) 2009 Dave Smith (dizzyd@dizzyd.com) +%% Copyright (c) 2009, 2010 Dave Smith (dizzyd@dizzyd.com)  %%  %% Permission is hereby granted, free of charge, to any person obtaining a copy  %% of this software and associated documentation files (the "Software"), to deal @@ -33,7 +33,8 @@           sh_failfast/2,           find_files/2,           now_str/0, -         ensure_dir/1]). +         ensure_dir/1, +         beam_to_mod/2, beams/1]).  -include("rebar.hrl"). @@ -132,3 +133,12 @@ sh_loop(Port) ->          {Port, {exit_status, Rc}} ->              {error, Rc}      end. + +beam_to_mod(Dir, Filename) -> +    [Dir | Rest] = filename:split(Filename), +    list_to_atom(filename:basename(string:join(Rest, "."), ".beam")). + +beams(Dir) -> +    filelib:fold_files(Dir, ".*\.beam\$", true, +                       fun(F, Acc) -> [F | Acc] end, []). + | 
