erlang各种有用的函数包括一些有用nif封装,还有一些性能测试case。
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

71 行
2.4 KiB

  1. #!/usr/bin/env escript
  2. %% -*- erlang -*-
  3. %%% Run with 'escript app_deps.erl'
  4. %%% Change the path in filelib:wildcard/1 as required to capture
  5. %%% all your dependencies.
  6. %%%
  7. %%% Rectangular nodes will represent library apps (no processes
  8. %%% involved) and the circular nodes will represent regular apps.
  9. %%% An arrow going from 'A -> B' means 'A depends on B'.
  10. %%%
  11. %%% This script depends on graphviz being present on the system.
  12. -module(app_deps).
  13. -export([main/1]).
  14. main(_) ->
  15. AppFiles = filelib:wildcard("deps/*/ebin/*.app")
  16. ++
  17. filelib:wildcard("apps/*/ebin/*.app")
  18. ++
  19. filelib:wildcard("ebin/*.app")
  20. ++
  21. filelib:wildcard("_build/default/lib/*/ebin/*.app"),
  22. to_graphviz(read_deps(AppFiles)).
  23. read_deps(AppFiles) ->
  24. [{App,
  25. proplists:get_value(applications, Props, []),
  26. apptype(Props)}
  27. || {ok, [{_,App,Props}]} <-
  28. [file:consult(AppFile) || AppFile <- AppFiles]].
  29. apptype(Props) ->
  30. case proplists:get_value(mod, Props) of
  31. undefined -> library;
  32. _ -> regular
  33. end.
  34. to_graphviz(Deps) ->
  35. AllApps = lists:usort(lists:flatten(
  36. [[{App,Type},DepList] || {App,DepList,Type} <- Deps]
  37. )),
  38. Bytes = ["digraph G { ",
  39. "K=0.25; ratio=0.75; overlap=\"9:prism\"; ",
  40. [io_lib:format("~p [shape=box] ", [App])
  41. || App <- libapps(AllApps -- [kernel,stdlib])],
  42. [[io_lib:format("~p->~p ", [App,Dep])
  43. || Dep <- DepList -- [kernel, stdlib]]
  44. || {App, DepList, _} <- Deps],
  45. "}"],
  46. file:write_file("app-deps.dot", Bytes),
  47. os:cmd("dot app-deps.dot -Tpng -o app-deps.png").
  48. libapps([]) -> [];
  49. libapps([{App,library}|Apps]) -> [App|libapps(Apps)];
  50. libapps([{_,_}|Apps]) -> libapps(Apps);
  51. libapps([App|Apps]) ->
  52. Dir = case code:lib_dir(App) of
  53. {error, _} -> ""; % not an OTP app
  54. DirPath -> DirPath
  55. end,
  56. Path = filename:join([Dir, "ebin", atom_to_list(App)++".app"]),
  57. case lists:prefix(code:lib_dir(), Path) of
  58. false ->
  59. [App|libapps(Apps)]; % not OTP app, we don't care
  60. true -> % deps of OTP deps: we don't care either.
  61. {ok, [{_,App,Props}]} = file:consult(Path),
  62. case apptype(Props) of
  63. library -> [App | libapps(Apps)];
  64. regular -> libapps(Apps)
  65. end
  66. end.