| #!/usr/bin/env escript |
| %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*- |
| %% ex: ft=erlang ts=4 sw=4 et |
| |
| main(Args) -> |
| %% Get a string repr of build time |
| Built = build_time(), |
| |
| %% Get a string repr of first matching VCS changeset |
| VcsInfo = vcs_info([{hg, ".hg", "hg identify -i"}, |
| {git, ".git", "git describe --always"}]), |
| |
| %% Check for force=1 flag to force a rebuild |
| case lists:member("force=1", Args) of |
| true -> |
| rm("ebin/*.beam"); |
| false -> |
| rm("ebin/rebar_core.beam") |
| end, |
| |
| %% Add check for debug flag |
| DebugFlag = case lists:member("debug", Args) of |
| true -> debug_info; |
| false -> undefined |
| end, |
| |
| %% Extract the system info of the version of OTP we use to compile rebar |
| OtpInfo = string:strip(erlang:system_info(otp_release), both, $\n), |
| |
| %% Compile all src/*.erl to ebin |
| case make:files(filelib:wildcard("src/*.erl"), |
| [{outdir, "ebin"}, {i, "include"}, |
| DebugFlag, |
| {d, 'BUILD_TIME', Built}, |
| {d, 'VCS_INFO', VcsInfo}, |
| {d, 'OTP_INFO', OtpInfo}]) of |
| up_to_date -> |
| ok; |
| error -> |
| io:format("Failed to compile rebar files!\n"), |
| halt(1) |
| end, |
| |
| %% Make sure file:consult can parse the .app file |
| case file:consult("ebin/rebar.app") of |
| {ok, _} -> |
| ok; |
| {error, Reason} -> |
| io:format("Invalid syntax in ebin/rebar.app: ~p\n", [Reason]), |
| halt(1) |
| end, |
| |
| %% Add ebin/ to our path |
| true = code:add_path("ebin"), |
| |
| %% Run rebar to do proper .app validation and such |
| rebar:main(["compile"] ++ Args), |
| |
| %% Read the contents of the files in ebin and templates; note that we |
| %% place all the beam files at the top level of the code archive so |
| %% that code loading works properly. |
| Files = load_files("*", "ebin") ++ load_files("priv/templates/*", "."), |
| |
| case zip:create("mem", Files, [memory]) of |
| {ok, {"mem", ZipBin}} -> |
| %% Archive was successfully created. Prefix that binary with our |
| %% header and write to "rebar" file. |
| %% Without -noshell -noinput escript consumes all input that would |
| %% otherwise go to the shell for the next command. |
| Script = <<"#!/usr/bin/env escript\n%%! -noshell -noinput\n", |
| ZipBin/binary>>, |
| case file:write_file("rebar", Script) of |
| ok -> |
| ok; |
| {error, WriteError} -> |
| io:format("Failed to write rebar script: ~p\n", |
| [WriteError]), |
| halt(1) |
| end; |
| {error, ZipError} -> |
| io:format("Failed to construct rebar script archive: ~p\n", |
| [ZipError]), |
| halt(1) |
| end, |
| |
| %% Finally, update executable perms for our script on *nix, |
| %% or write out script files on win32. |
| case os:type() of |
| {unix,_} -> |
| [] = os:cmd("chmod u+x rebar"), |
| ok; |
| {win32,_} -> |
| write_windows_scripts(), |
| ok; |
| _ -> |
| ok |
| end, |
| |
| %% Add a helpful message |
| io:format("Congratulations! You now have a self-contained script called" |
| " \"rebar\" in\n" |
| "your current working directory. " |
| "Place this script anywhere in your path\n" |
| "and you can use rebar to build OTP-compliant apps.\n"). |
| |
| rm(Path) -> |
| NativePath = filename:nativename(Path), |
| Cmd = case os:type() of |
| {unix,_} -> "rm -f "; |
| {win32,_} -> "del /q " |
| end, |
| [] = os:cmd(Cmd ++ NativePath), |
| ok. |
| |
| build_time() -> |
| {{Y, M, D}, {H, Min, S}} = calendar:now_to_universal_time(now()), |
| lists:flatten(io_lib:format("~4..0w~2..0w~2..0w_~2..0w~2..0w~2..0w", |
| [Y, M, D, H, Min, S])). |
| |
| |
| load_files(Wildcard, Dir) -> |
| [read_file(Filename, Dir) || Filename <- filelib:wildcard(Wildcard, Dir)]. |
| |
| read_file(Filename, Dir) -> |
| {ok, Bin} = file:read_file(filename:join(Dir, Filename)), |
| {Filename, Bin}. |
| |
| vcs_info([]) -> |
| "No VCS info available."; |
| vcs_info([{Id, Dir, Cmd} | Rest]) -> |
| case filelib:is_dir(Dir) of |
| true -> |
| lists:concat([Id, " ", string:strip(os:cmd(Cmd), both, $\n)]); |
| false -> |
| vcs_info(Rest) |
| end. |
| |
| write_windows_scripts() -> |
| CmdScript= |
| "@echo off\r\n" |
| "setlocal\r\n" |
| "set rebarscript=%~f0\r\n" |
| "escript.exe \"%rebarscript:.cmd=%\" %*\r\n", |
| ok = file:write_file("rebar.cmd", CmdScript). |