This repository has been archived by the owner on Sep 22, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
/
bootstrap
executable file
·113 lines (98 loc) · 3.67 KB
/
bootstrap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env escript
%%! -noshell -noinput
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
%% ex: ft=erlang ts=4 sw=4 et
-include_lib("kernel/include/file.hrl").
main(_) ->
Filename = "erlangpl",
Files = get_files(),
case zip:create("mem", Files, [memory]) of
{ok, {"mem", ZipBin}} ->
Shebang = "#!/usr/bin/env escript\n",
EmuArgs = "%%! -setcookie erlangpl\n",
Script = iolist_to_binary([Shebang, EmuArgs, ZipBin]),
case file:write_file(Filename, Script) of
ok ->
ok;
{error, WriteError} ->
io:format("Failed to write escript: ~p\n",
[WriteError])
end;
{error, ZipError} ->
io:format("Failed to zip: ~p\n", [ZipError])
end,
{ok, #file_info{mode = Mode}} = file:read_file_info(Filename),
ok = file:change_mode(Filename, Mode bor 8#00100).
get_files() ->
%% find all directories in apps/ and deps/
%% each directory represents an erlang application
Apps = filelib:wildcard("{apps,deps}/*"),
%% read contents of all .app and .beam files
%% as well as contents of priv/ directories
Fun = fun(Path, Acc) when Path == "apps/epl/ebin/erlangpl.beam" ->
%% escript requires us to put erlangpl.beam in top-level dir
[{"erlangpl.beam", file_contents(Path)} | Acc];
(Path, Acc) ->
%% all other files will appear under application dir
%% e.g. {"epl/ebin/epl.app", "...<contents>..."}
Filename = filename:join(tl(filename:split(Path))),
[{Filename, file_contents(Path)} | Acc]
end,
%% include all compiled modules and the .app file
Beams = [filelib:fold_files(Dir, "\\.app$|\\.beam$", true, Fun, [])
|| Dir <- Apps] ++ elixir_beams(),
%% include all contents of the priv dirs
%% except for .js.map files, which are heavy but unnecessary
Privs = [filelib:fold_files(filename:join([Dir, "priv"]),
"^((?!\\.js\\.map).)*$", true, Fun, [])
|| Dir <- Apps],
lists:flatten([Beams, Privs]).
file_contents(Filename) ->
{ok, Bin} = file:read_file(Filename),
case filename:extension(Filename) of
".beam" ->
{ok, {_, Stripped}} = beam_lib:strip(Bin),
Stripped;
_ ->
Bin
end.
elixir_beams() ->
Args = init:get_plain_arguments(),
Path = get_elixir_ebin_path(Args),
case Path of
undefined ->
[];
Ebin ->
Paths = filelib:wildcard(filename:join(Ebin, "*")),
[read_elixir_beam(BeamPath) || BeamPath <- Paths]
end.
get_elixir_ebin_path(Args) ->
ElixirRoot = find_in_args(Args),
case ensure_elixir_root(ElixirRoot) of
undefined ->
undefined;
Path ->
filename:join([Path, "lib", "elixir", "ebin"])
end.
find_in_args(["--with-elixir", Path]) ->
filename:absname(Path);
find_in_args([_ | Tail]) ->
find_in_args(Tail);
find_in_args([]) ->
undefined.
read_elixir_beam(Path) ->
Contents = file_contents(Path),
Filename = filename:basename(Path),
{filename:join(["elixir", "ebin", Filename]), Contents}.
ensure_elixir_root(undefined) ->
undefined;
ensure_elixir_root(Path) ->
AppFile = filename:join([Path, "lib", "elixir", "ebin", "elixir.app"]),
case filelib:is_regular(AppFile) of
true ->
Path;
false ->
io:format("ERROR: path provided to --with-elixir option is not "
"Elixir root path~n"),
undefined
end.