bootstrap.mk 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. # Copyright (c) 2014-2015, Loïc Hoguin <essen@ninenines.eu>
  2. # This file is part of erlang.mk and subject to the terms of the ISC License.
  3. .PHONY: bootstrap bootstrap-lib bootstrap-rel new list-templates
  4. # Core targets.
  5. help::
  6. $(verbose) printf "%s\n" "" \
  7. "Bootstrap targets:" \
  8. " bootstrap Generate a skeleton of an OTP application" \
  9. " bootstrap-lib Generate a skeleton of an OTP library" \
  10. " bootstrap-rel Generate the files needed to build a release" \
  11. " new t=TPL n=NAME Generate a module NAME based on the template TPL" \
  12. " list-templates List available templates"
  13. # Bootstrap templates.
  14. define bs_appsrc
  15. {application, $(PROJECT), [
  16. {description, ""},
  17. {vsn, "0.1.0"},
  18. {id, "git"},
  19. {modules, []},
  20. {registered, []},
  21. {applications, [
  22. kernel,
  23. stdlib
  24. ]},
  25. {mod, {$(PROJECT)_app, []}},
  26. {env, []}
  27. ]}.
  28. endef
  29. define bs_appsrc_lib
  30. {application, $(PROJECT), [
  31. {description, ""},
  32. {vsn, "0.1.0"},
  33. {id, "git"},
  34. {modules, []},
  35. {registered, []},
  36. {applications, [
  37. kernel,
  38. stdlib
  39. ]}
  40. ]}.
  41. endef
  42. ifdef SP
  43. define bs_Makefile
  44. PROJECT = $(PROJECT)
  45. # Whitespace to be used when creating files from templates.
  46. SP = $(SP)
  47. include erlang.mk
  48. endef
  49. else
  50. define bs_Makefile
  51. PROJECT = $(PROJECT)
  52. include erlang.mk
  53. endef
  54. endif
  55. define bs_app
  56. -module($(PROJECT)_app).
  57. -behaviour(application).
  58. -export([start/2]).
  59. -export([stop/1]).
  60. start(_Type, _Args) ->
  61. $(PROJECT)_sup:start_link().
  62. stop(_State) ->
  63. ok.
  64. endef
  65. define bs_relx_config
  66. {release, {$(PROJECT)_release, "1"}, [$(PROJECT)]}.
  67. {extended_start_script, true}.
  68. {sys_config, "rel/sys.config"}.
  69. {vm_args, "rel/vm.args"}.
  70. endef
  71. define bs_sys_config
  72. [
  73. ].
  74. endef
  75. define bs_vm_args
  76. -name $(PROJECT)@127.0.0.1
  77. -setcookie $(PROJECT)
  78. -heart
  79. endef
  80. # Normal templates.
  81. define tpl_supervisor
  82. -module($(n)).
  83. -behaviour(supervisor).
  84. -export([start_link/0]).
  85. -export([init/1]).
  86. start_link() ->
  87. supervisor:start_link({local, ?MODULE}, ?MODULE, []).
  88. init([]) ->
  89. Procs = [],
  90. {ok, {{one_for_one, 1, 5}, Procs}}.
  91. endef
  92. define tpl_gen_server
  93. -module($(n)).
  94. -behaviour(gen_server).
  95. %% API.
  96. -export([start_link/0]).
  97. %% gen_server.
  98. -export([init/1]).
  99. -export([handle_call/3]).
  100. -export([handle_cast/2]).
  101. -export([handle_info/2]).
  102. -export([terminate/2]).
  103. -export([code_change/3]).
  104. -record(state, {
  105. }).
  106. %% API.
  107. -spec start_link() -> {ok, pid()}.
  108. start_link() ->
  109. gen_server:start_link(?MODULE, [], []).
  110. %% gen_server.
  111. init([]) ->
  112. {ok, #state{}}.
  113. handle_call(_Request, _From, State) ->
  114. {reply, ignored, State}.
  115. handle_cast(_Msg, State) ->
  116. {noreply, State}.
  117. handle_info(_Info, State) ->
  118. {noreply, State}.
  119. terminate(_Reason, _State) ->
  120. ok.
  121. code_change(_OldVsn, State, _Extra) ->
  122. {ok, State}.
  123. endef
  124. define tpl_cowboy_http
  125. -module($(n)).
  126. -behaviour(cowboy_http_handler).
  127. -export([init/3]).
  128. -export([handle/2]).
  129. -export([terminate/3]).
  130. -record(state, {
  131. }).
  132. init(_, Req, _Opts) ->
  133. {ok, Req, #state{}}.
  134. handle(Req, State=#state{}) ->
  135. {ok, Req2} = cowboy_req:reply(200, Req),
  136. {ok, Req2, State}.
  137. terminate(_Reason, _Req, _State) ->
  138. ok.
  139. endef
  140. define tpl_gen_fsm
  141. -module($(n)).
  142. -behaviour(gen_fsm).
  143. %% API.
  144. -export([start_link/0]).
  145. %% gen_fsm.
  146. -export([init/1]).
  147. -export([state_name/2]).
  148. -export([handle_event/3]).
  149. -export([state_name/3]).
  150. -export([handle_sync_event/4]).
  151. -export([handle_info/3]).
  152. -export([terminate/3]).
  153. -export([code_change/4]).
  154. -record(state, {
  155. }).
  156. %% API.
  157. -spec start_link() -> {ok, pid()}.
  158. start_link() ->
  159. gen_fsm:start_link(?MODULE, [], []).
  160. %% gen_fsm.
  161. init([]) ->
  162. {ok, state_name, #state{}}.
  163. state_name(_Event, StateData) ->
  164. {next_state, state_name, StateData}.
  165. handle_event(_Event, StateName, StateData) ->
  166. {next_state, StateName, StateData}.
  167. state_name(_Event, _From, StateData) ->
  168. {reply, ignored, state_name, StateData}.
  169. handle_sync_event(_Event, _From, StateName, StateData) ->
  170. {reply, ignored, StateName, StateData}.
  171. handle_info(_Info, StateName, StateData) ->
  172. {next_state, StateName, StateData}.
  173. terminate(_Reason, _StateName, _StateData) ->
  174. ok.
  175. code_change(_OldVsn, StateName, StateData, _Extra) ->
  176. {ok, StateName, StateData}.
  177. endef
  178. define tpl_cowboy_loop
  179. -module($(n)).
  180. -behaviour(cowboy_loop_handler).
  181. -export([init/3]).
  182. -export([info/3]).
  183. -export([terminate/3]).
  184. -record(state, {
  185. }).
  186. init(_, Req, _Opts) ->
  187. {loop, Req, #state{}, 5000, hibernate}.
  188. info(_Info, Req, State) ->
  189. {loop, Req, State, hibernate}.
  190. terminate(_Reason, _Req, _State) ->
  191. ok.
  192. endef
  193. define tpl_cowboy_rest
  194. -module($(n)).
  195. -export([init/3]).
  196. -export([content_types_provided/2]).
  197. -export([get_html/2]).
  198. init(_, _Req, _Opts) ->
  199. {upgrade, protocol, cowboy_rest}.
  200. content_types_provided(Req, State) ->
  201. {[{{<<"text">>, <<"html">>, '*'}, get_html}], Req, State}.
  202. get_html(Req, State) ->
  203. {<<"<html><body>This is REST!</body></html>">>, Req, State}.
  204. endef
  205. define tpl_cowboy_ws
  206. -module($(n)).
  207. -behaviour(cowboy_websocket_handler).
  208. -export([init/3]).
  209. -export([websocket_init/3]).
  210. -export([websocket_handle/3]).
  211. -export([websocket_info/3]).
  212. -export([websocket_terminate/3]).
  213. -record(state, {
  214. }).
  215. init(_, _, _) ->
  216. {upgrade, protocol, cowboy_websocket}.
  217. websocket_init(_, Req, _Opts) ->
  218. Req2 = cowboy_req:compact(Req),
  219. {ok, Req2, #state{}}.
  220. websocket_handle({text, Data}, Req, State) ->
  221. {reply, {text, Data}, Req, State};
  222. websocket_handle({binary, Data}, Req, State) ->
  223. {reply, {binary, Data}, Req, State};
  224. websocket_handle(_Frame, Req, State) ->
  225. {ok, Req, State}.
  226. websocket_info(_Info, Req, State) ->
  227. {ok, Req, State}.
  228. websocket_terminate(_Reason, _Req, _State) ->
  229. ok.
  230. endef
  231. define tpl_ranch_protocol
  232. -module($(n)).
  233. -behaviour(ranch_protocol).
  234. -export([start_link/4]).
  235. -export([init/4]).
  236. -type opts() :: [].
  237. -export_type([opts/0]).
  238. -record(state, {
  239. socket :: inet:socket(),
  240. transport :: module()
  241. }).
  242. start_link(Ref, Socket, Transport, Opts) ->
  243. Pid = spawn_link(?MODULE, init, [Ref, Socket, Transport, Opts]),
  244. {ok, Pid}.
  245. -spec init(ranch:ref(), inet:socket(), module(), opts()) -> ok.
  246. init(Ref, Socket, Transport, _Opts) ->
  247. ok = ranch:accept_ack(Ref),
  248. loop(#state{socket=Socket, transport=Transport}).
  249. loop(State) ->
  250. loop(State).
  251. endef
  252. # Plugin-specific targets.
  253. define render_template
  254. $(verbose) echo "$${_$(1)}" > $(2)
  255. endef
  256. ifndef WS
  257. ifdef SP
  258. WS = $(subst a,,a $(wordlist 1,$(SP),a a a a a a a a a a a a a a a a a a a a))
  259. else
  260. WS = $(tab)
  261. endif
  262. endif
  263. $(foreach template,$(filter bs_% tpl_%,$(.VARIABLES)), \
  264. $(eval _$(template) = $$(subst $$(tab),$$(WS),$$($(template)))) \
  265. $(eval export _$(template)))
  266. bootstrap:
  267. ifneq ($(wildcard src/),)
  268. $(error Error: src/ directory already exists)
  269. endif
  270. $(call render_template,bs_Makefile,Makefile)
  271. $(verbose) mkdir src/
  272. $(call render_template,bs_appsrc,src/$(PROJECT).app.src)
  273. $(call render_template,bs_app,src/$(PROJECT)_app.erl)
  274. $(eval n := $(PROJECT)_sup)
  275. $(call render_template,tpl_supervisor,src/$(PROJECT)_sup.erl)
  276. bootstrap-lib:
  277. ifneq ($(wildcard src/),)
  278. $(error Error: src/ directory already exists)
  279. endif
  280. $(call render_template,bs_Makefile,Makefile)
  281. $(verbose) mkdir src/
  282. $(call render_template,bs_appsrc_lib,src/$(PROJECT).app.src)
  283. bootstrap-rel:
  284. ifneq ($(wildcard relx.config),)
  285. $(error Error: relx.config already exists)
  286. endif
  287. ifneq ($(wildcard rel/),)
  288. $(error Error: rel/ directory already exists)
  289. endif
  290. $(call render_template,bs_relx_config,relx.config)
  291. $(verbose) mkdir rel/
  292. $(call render_template,bs_sys_config,rel/sys.config)
  293. $(call render_template,bs_vm_args,rel/vm.args)
  294. new:
  295. ifeq ($(wildcard src/),)
  296. $(error Error: src/ directory does not exist)
  297. endif
  298. ifndef t
  299. $(error Usage: $(MAKE) new t=TEMPLATE n=NAME)
  300. endif
  301. ifndef tpl_$(t)
  302. $(error Unknown template)
  303. endif
  304. ifndef n
  305. $(error Usage: $(MAKE) new t=TEMPLATE n=NAME)
  306. endif
  307. $(call render_template,tpl_$(t),src/$(n).erl)
  308. list-templates:
  309. $(verbose) echo Available templates: $(sort $(patsubst tpl_%,%,$(filter tpl_%,$(.VARIABLES))))