|
|
- #!/usr/bin/env escript
- %% -*- erlang -*-
- %%% Run with 'escript app_deps.erl'
- %%% Change the path in filelib:wildcard/1 as required to capture
- %%% all your dependencies.
- %%%
- %%% Rectangular nodes will represent library apps (no processes
- %%% involved) and the circular nodes will represent regular apps.
- %%% An arrow going from 'A -> B' means 'A depends on B'.
- %%%
- %%% This script depends on graphviz being present on the system.
- -module(app_deps).
- -export([main/1]).
-
- main(_) ->
- AppFiles = filelib:wildcard("deps/*/ebin/*.app")
- ++
- filelib:wildcard("apps/*/ebin/*.app")
- ++
- filelib:wildcard("ebin/*.app")
- ++
- filelib:wildcard("_build/default/lib/*/ebin/*.app"),
- to_graphviz(read_deps(AppFiles)).
-
- read_deps(AppFiles) ->
- [{App,
- proplists:get_value(applications, Props, []),
- apptype(Props)}
- || {ok, [{_,App,Props}]} <-
- [file:consult(AppFile) || AppFile <- AppFiles]].
-
- apptype(Props) ->
- case proplists:get_value(mod, Props) of
- undefined -> library;
- _ -> regular
- end.
-
- to_graphviz(Deps) ->
- AllApps = lists:usort(lists:flatten(
- [[{App,Type},DepList] || {App,DepList,Type} <- Deps]
- )),
- Bytes = ["digraph G { ",
- "K=0.25; ratio=0.75; overlap=\"9:prism\"; ",
- [io_lib:format("~p [shape=box] ", [App])
- || App <- libapps(AllApps -- [kernel,stdlib])],
- [[io_lib:format("~p->~p ", [App,Dep])
- || Dep <- DepList -- [kernel, stdlib]]
- || {App, DepList, _} <- Deps],
- "}"],
- file:write_file("app-deps.dot", Bytes),
- os:cmd("dot app-deps.dot -Tpng -o app-deps.png").
-
- libapps([]) -> [];
- libapps([{App,library}|Apps]) -> [App|libapps(Apps)];
- libapps([{_,_}|Apps]) -> libapps(Apps);
- libapps([App|Apps]) ->
- Dir = case code:lib_dir(App) of
- {error, _} -> ""; % not an OTP app
- DirPath -> DirPath
- end,
- Path = filename:join([Dir, "ebin", atom_to_list(App)++".app"]),
- case lists:prefix(code:lib_dir(), Path) of
- false ->
- [App|libapps(Apps)]; % not OTP app, we don't care
- true -> % deps of OTP deps: we don't care either.
- {ok, [{_,App,Props}]} = file:consult(Path),
- case apptype(Props) of
- library -> [App | libapps(Apps)];
- regular -> libapps(Apps)
- end
- end.
|