rebar3 服务器
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env escript
|
||||
%% -*- erlang -*-
|
||||
%% Decompile .beam files into .erl source files when debug_info is available.
|
||||
%% Usage: escript decompile_beam.erl <beam file or directory> [more paths...]
|
||||
|
||||
-mode(compile).
|
||||
|
||||
main(Args) ->
|
||||
case Args of
|
||||
[] ->
|
||||
usage();
|
||||
Paths ->
|
||||
lists:foreach(fun decompile_path/1, Paths)
|
||||
end.
|
||||
|
||||
usage() ->
|
||||
io:format("Usage: escript decompile_beam.erl <beam file or directory> [more paths...]~n", []),
|
||||
io:format("Example: escript decompile_beam.erl module.beam~n", []),
|
||||
io:format(" escript decompile_beam.erl ./ebin~n", []),
|
||||
io:format("~nNote: readable source can only be generated when the .beam was compiled with debug_info.~n", []),
|
||||
io:format(" Example: compile:file(File, [debug_info])~n", []),
|
||||
halt(1).
|
||||
|
||||
decompile_path(Path) ->
|
||||
case filelib:is_dir(Path) of
|
||||
true ->
|
||||
decompile_dir(Path);
|
||||
false ->
|
||||
case filelib:is_file(Path) of
|
||||
true ->
|
||||
case filename:extension(Path) of
|
||||
".beam" -> decompile_beam(Path);
|
||||
_ -> io:format("Skip non-.beam file: ~s~n", [Path])
|
||||
end;
|
||||
false ->
|
||||
io:format("Path does not exist: ~s~n", [Path])
|
||||
end
|
||||
end.
|
||||
|
||||
decompile_dir(Dir) ->
|
||||
case file:list_dir(Dir) of
|
||||
{ok, Files} ->
|
||||
Beams = [filename:join(Dir, F) || F <- Files, filename:extension(F) =:= ".beam"],
|
||||
io:format("Found ~p .beam files in ~s~n", [length(Beams), Dir]),
|
||||
lists:foreach(fun decompile_beam/1, Beams);
|
||||
{error, Reason} ->
|
||||
io:format("Failed to read directory ~s: ~p~n", [Dir, Reason])
|
||||
end.
|
||||
|
||||
decompile_beam(BeamPath) ->
|
||||
case beam_lib:chunks(BeamPath, [abstract_code]) of
|
||||
{ok, {_Module, [{abstract_code, {raw_abstract_v1, Forms}}]}} ->
|
||||
ErlPath = to_erl_path(BeamPath),
|
||||
case format_and_write(Forms, ErlPath) of
|
||||
ok ->
|
||||
io:format("Generated: ~s~n", [ErlPath]);
|
||||
{error, Reason} ->
|
||||
io:format("Write failed ~s: ~p~n", [ErlPath, Reason])
|
||||
end;
|
||||
{ok, {_Module, _}} ->
|
||||
io:format("Skip ~s: no abstract_code chunk (likely built without debug_info)~n", [BeamPath]);
|
||||
{error, beam_lib, {missing_chunk, _, "Abst"}} ->
|
||||
io:format("Skip ~s: missing abstract code chunk, rebuild with debug_info~n", [BeamPath]);
|
||||
{error, beam_lib, Reason} ->
|
||||
io:format("Read failed ~s: ~p~n", [BeamPath, Reason])
|
||||
end.
|
||||
|
||||
to_erl_path(BeamPath) ->
|
||||
Dir = filename:dirname(BeamPath),
|
||||
Base = filename:basename(BeamPath, ".beam"),
|
||||
OutDir =
|
||||
case filename:basename(Dir) of
|
||||
"ebin" -> filename:join(filename:dirname(Dir), "src");
|
||||
_ -> Dir
|
||||
end,
|
||||
filename:join(OutDir, Base ++ ".erl").
|
||||
|
||||
format_and_write(Forms, ErlPath) ->
|
||||
try
|
||||
Strings = lists:map(fun(F) -> erl_pp:form(F) end, Forms),
|
||||
Content = lists:flatten([S ++ ".\n\n" || S <- Strings]),
|
||||
ok = filelib:ensure_dir(ErlPath),
|
||||
file:write_file(ErlPath, Content, [write, {encoding, utf8}])
|
||||
catch
|
||||
_:Reason -> {error, Reason}
|
||||
end.
|
||||
Reference in New Issue
Block a user