25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

136 lines
4.4 KiB

  1. #!/usr/bin/env escript
  2. %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
  3. %% ex: ft=erlang ts=4 sw=4 et
  4. main(Args) ->
  5. %% Get a string repr of build time
  6. Built = build_time(),
  7. %% Get a string repr of first matching VCS changeset
  8. VcsInfo = vcs_info([{hg, ".hg", "hg identify -i", "hg status"},
  9. {git, ".git", "git describe --always --tags",
  10. "git status -s"}]),
  11. %% Check for force=1 flag to force a rebuild
  12. case lists:member("force=1", Args) of
  13. true ->
  14. rm("ebin/*.beam");
  15. false ->
  16. rm("ebin/rebar.beam")
  17. end,
  18. %% Add check for debug flag
  19. DebugFlag = case lists:member("debug", Args) of
  20. true -> debug_info;
  21. false -> undefined
  22. end,
  23. %% Extract the system info of the version of OTP we use to compile rebar
  24. OtpInfo = string:strip(erlang:system_info(otp_release), both, $\n),
  25. %% Types dict:dict() and digraph:digraph() have been introduced in
  26. %% Erlang 17.
  27. %% At the same time, their counterparts dict() and digraph() are to be
  28. %% deprecated in Erlang 18. namespaced_types option is used to select
  29. %% proper type name depending of the OTP version used.
  30. NamespacedTypes = case is_otp(OtpInfo, "^[0-9]+") of
  31. true -> {d, namespaced_types};
  32. false -> undefined
  33. end,
  34. %% Compile all src/*.erl to ebin
  35. case make:files(filelib:wildcard("src/*.erl"),
  36. [{outdir, "ebin"}, {i, "include"},
  37. DebugFlag,
  38. NamespacedTypes,
  39. {d, 'BUILD_TIME', Built},
  40. {d, 'VCS_INFO', VcsInfo},
  41. {d, 'OTP_INFO', OtpInfo}]) of
  42. up_to_date ->
  43. ok;
  44. error ->
  45. io:format("Failed to compile rebar files!\n"),
  46. halt(1)
  47. end,
  48. %% Make sure file:consult can parse the .app file
  49. case file:consult("ebin/rebar.app") of
  50. {ok, _} ->
  51. ok;
  52. {error, Reason} ->
  53. io:format("Invalid syntax in ebin/rebar.app: ~p\n", [Reason]),
  54. halt(1)
  55. end,
  56. %% Add ebin/ to our path
  57. true = code:add_path("ebin"),
  58. %% Run rebar compile to do proper .app validation etc.
  59. %% and rebar escriptize to create the rebar script
  60. RebarArgs = Args -- ["debug"], %% Avoid trying to run 'debug' command
  61. rebar:main(["compile", "escriptize"] ++ RebarArgs),
  62. %% Finally, update executable perms for our script on *nix,
  63. %% or write out script files on win32.
  64. case os:type() of
  65. {unix,_} ->
  66. [] = os:cmd("chmod u+x rebar"),
  67. ok;
  68. {win32,_} ->
  69. write_windows_scripts(),
  70. ok;
  71. _ ->
  72. ok
  73. end,
  74. %% Add a helpful message
  75. io:format("Congratulations! You now have a self-contained script called"
  76. " \"rebar\" in\n"
  77. "your current working directory. "
  78. "Place this script anywhere in your path\n"
  79. "and you can use rebar to build OTP-compliant apps.\n").
  80. is_otp(OtpInfo, Regex) ->
  81. case re:run(OtpInfo, Regex, [{capture, none}]) of
  82. match -> true;
  83. nomatch -> false
  84. end.
  85. rm(Path) ->
  86. NativePath = filename:nativename(Path),
  87. Cmd = case os:type() of
  88. {unix,_} -> "rm -f ";
  89. {win32,_} -> "del /q "
  90. end,
  91. [] = os:cmd(Cmd ++ NativePath),
  92. ok.
  93. build_time() ->
  94. {{Y, M, D}, {H, Min, S}} = calendar:now_to_universal_time(now()),
  95. lists:flatten(io_lib:format("~4..0w~2..0w~2..0w_~2..0w~2..0w~2..0w",
  96. [Y, M, D, H, Min, S])).
  97. vcs_info([]) ->
  98. "No VCS info available.";
  99. vcs_info([{Id, Dir, VsnCmd, StatusCmd} | Rest]) ->
  100. case filelib:is_dir(Dir) of
  101. true ->
  102. Vsn = string:strip(os:cmd(VsnCmd), both, $\n),
  103. Status = case string:strip(os:cmd(StatusCmd), both, $\n) of
  104. [] ->
  105. "";
  106. _ ->
  107. "-dirty"
  108. end,
  109. lists:concat([Id, " ", Vsn, Status]);
  110. false ->
  111. vcs_info(Rest)
  112. end.
  113. write_windows_scripts() ->
  114. CmdScript=
  115. "@echo off\r\n"
  116. "setlocal\r\n"
  117. "set rebarscript=%~f0\r\n"
  118. "escript.exe \"%rebarscript:.cmd=%\" %*\r\n",
  119. ok = file:write_file("rebar.cmd", CmdScript).