bootstrap.mk 7.8 KB

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