rebar.config.erl 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. -module('rebar.config').
  2. -export([do/2]).
  3. do(Dir, CONFIG) ->
  4. ok = assert_otp(),
  5. ok = warn_profile_env(),
  6. case iolist_to_binary(Dir) of
  7. <<".">> ->
  8. C1 = deps(CONFIG),
  9. Config = dialyzer(C1),
  10. maybe_dump(Config ++ [{overrides, overrides()}] ++ coveralls() ++ config());
  11. _ ->
  12. CONFIG
  13. end.
  14. assert_otp() ->
  15. Oldest = 25,
  16. Latest = 26,
  17. OtpRelease = list_to_integer(erlang:system_info(otp_release)),
  18. case OtpRelease < Oldest orelse OtpRelease > Latest of
  19. true ->
  20. io:format(
  21. standard_error,
  22. "ERROR: Erlang/OTP version ~p found. min=~p, recommended=~p~n",
  23. [OtpRelease, Oldest, Latest]
  24. ),
  25. halt(1);
  26. false when OtpRelease =/= Latest ->
  27. io:format(
  28. "WARNING: Erlang/OTP version ~p found, recommended==~p~n",
  29. [OtpRelease, Latest]
  30. );
  31. false ->
  32. ok
  33. end.
  34. quicer() ->
  35. {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.1.6"}}}.
  36. jq() ->
  37. {jq, {git, "https://github.com/emqx/jq", {tag, "v0.3.12"}}}.
  38. deps(Config) ->
  39. {deps, OldDeps} = lists:keyfind(deps, 1, Config),
  40. MoreDeps =
  41. [jq() || is_jq_supported()] ++
  42. [quicer() || is_quicer_supported()],
  43. lists:keystore(deps, 1, Config, {deps, OldDeps ++ MoreDeps}).
  44. overrides() ->
  45. [
  46. {add, [{extra_src_dirs, [{"etc", [{recursive, true}]}]}]}
  47. ] ++ snabbkaffe_overrides().
  48. %% Temporary workaround for a rebar3 erl_opts duplication
  49. %% bug. Ideally, we want to set this define globally
  50. snabbkaffe_overrides() ->
  51. Apps = [snabbkaffe, ekka, mria, gen_rpc],
  52. [{add, App, [{erl_opts, [{d, snk_kind, msg}]}]} || App <- Apps].
  53. config() ->
  54. [
  55. {cover_enabled, is_cover_enabled()},
  56. {profiles, profiles()},
  57. {plugins, plugins()}
  58. ].
  59. is_cover_enabled() ->
  60. case os:getenv("ENABLE_COVER_COMPILE") of
  61. "1" -> true;
  62. "true" -> true;
  63. _ -> false
  64. end.
  65. is_enterprise(ce) -> false;
  66. is_enterprise(ee) -> true.
  67. is_community_umbrella_app("apps/emqx_connector_aggregator") -> false;
  68. is_community_umbrella_app("apps/emqx_bridge_kafka") -> false;
  69. is_community_umbrella_app("apps/emqx_bridge_confluent") -> false;
  70. is_community_umbrella_app("apps/emqx_bridge_gcp_pubsub") -> false;
  71. is_community_umbrella_app("apps/emqx_bridge_cassandra") -> false;
  72. is_community_umbrella_app("apps/emqx_bridge_opents") -> false;
  73. is_community_umbrella_app("apps/emqx_bridge_clickhouse") -> false;
  74. is_community_umbrella_app("apps/emqx_bridge_dynamo") -> false;
  75. is_community_umbrella_app("apps/emqx_bridge_greptimedb") -> false;
  76. is_community_umbrella_app("apps/emqx_bridge_hstreamdb") -> false;
  77. is_community_umbrella_app("apps/emqx_bridge_influxdb") -> false;
  78. is_community_umbrella_app("apps/emqx_bridge_iotdb") -> false;
  79. is_community_umbrella_app("apps/emqx_bridge_matrix") -> false;
  80. is_community_umbrella_app("apps/emqx_bridge_mongodb") -> false;
  81. is_community_umbrella_app("apps/emqx_bridge_mysql") -> false;
  82. is_community_umbrella_app("apps/emqx_bridge_pgsql") -> false;
  83. is_community_umbrella_app("apps/emqx_bridge_pulsar") -> false;
  84. is_community_umbrella_app("apps/emqx_bridge_redis") -> false;
  85. is_community_umbrella_app("apps/emqx_bridge_rocketmq") -> false;
  86. is_community_umbrella_app("apps/emqx_bridge_tdengine") -> false;
  87. is_community_umbrella_app("apps/emqx_bridge_timescale") -> false;
  88. is_community_umbrella_app("apps/emqx_bridge_oracle") -> false;
  89. is_community_umbrella_app("apps/emqx_bridge_sqlserver") -> false;
  90. is_community_umbrella_app("apps/emqx_bridge_datalayers") -> false;
  91. is_community_umbrella_app("apps/emqx_oracle") -> false;
  92. is_community_umbrella_app("apps/emqx_bridge_rabbitmq") -> false;
  93. is_community_umbrella_app("apps/emqx_ft") -> false;
  94. is_community_umbrella_app("apps/emqx_s3") -> false;
  95. is_community_umbrella_app("apps/emqx_bridge_s3") -> false;
  96. is_community_umbrella_app("apps/emqx_bridge_azure_blob_storage") -> false;
  97. is_community_umbrella_app("apps/emqx_bridge_couchbase") -> false;
  98. is_community_umbrella_app("apps/emqx_bridge_snowflake") -> false;
  99. is_community_umbrella_app("apps/emqx_schema_registry") -> false;
  100. is_community_umbrella_app("apps/emqx_enterprise") -> false;
  101. is_community_umbrella_app("apps/emqx_bridge_kinesis") -> false;
  102. is_community_umbrella_app("apps/emqx_bridge_azure_event_hub") -> false;
  103. is_community_umbrella_app("apps/emqx_gcp_device") -> false;
  104. is_community_umbrella_app("apps/emqx_dashboard_rbac") -> false;
  105. is_community_umbrella_app("apps/emqx_dashboard_sso") -> false;
  106. is_community_umbrella_app("apps/emqx_audit") -> false;
  107. is_community_umbrella_app("apps/emqx_gateway_gbt32960") -> false;
  108. is_community_umbrella_app("apps/emqx_gateway_ocpp") -> false;
  109. is_community_umbrella_app("apps/emqx_gateway_jt808") -> false;
  110. is_community_umbrella_app("apps/emqx_bridge_syskeeper") -> false;
  111. is_community_umbrella_app("apps/emqx_schema_validation") -> false;
  112. is_community_umbrella_app("apps/emqx_message_transformation") -> false;
  113. is_community_umbrella_app("apps/emqx_eviction_agent") -> false;
  114. is_community_umbrella_app("apps/emqx_node_rebalance") -> false;
  115. is_community_umbrella_app("apps/emqx_ds_shared_sub") -> false;
  116. is_community_umbrella_app("apps/emqx_auth_ext") -> false;
  117. is_community_umbrella_app("apps/emqx_cluster_link") -> false;
  118. is_community_umbrella_app("apps/emqx_ds_builtin_raft") -> false;
  119. is_community_umbrella_app("apps/emqx_auth_kerberos") -> false;
  120. is_community_umbrella_app("apps/emqx_auth_cinfo") -> false;
  121. is_community_umbrella_app("apps/emqx_ds_fdb_backend") -> false;
  122. is_community_umbrella_app(_) -> true.
  123. %% BUILD_WITHOUT_JQ
  124. %% BUILD_WITHOUT_QUIC
  125. %% BUILD_WITHOUT_ROCKSDB
  126. is_build_without(Name) ->
  127. "1" =:= os:getenv("BUILD_WITHOUT_" ++ Name).
  128. %% BUILD_WITH_QUIC
  129. is_build_with(Name) ->
  130. "1" =:= os:getenv("BUILD_WITH_" ++ Name).
  131. is_jq_supported() ->
  132. not is_build_without("JQ").
  133. is_quicer_supported() ->
  134. %% for ones who want to build QUIC on macos
  135. %% export BUILD_WITH_QUIC=1
  136. is_build_with("QUIC") orelse
  137. is_quicer_supported(os:type()).
  138. is_quicer_supported({unix, darwin}) ->
  139. %% no quic on macos so far
  140. false;
  141. is_quicer_supported(_) ->
  142. not is_build_without("QUIC").
  143. is_rocksdb_supported() ->
  144. %% there is no way one can build rocksdb on raspbian
  145. %% so no need to check is_build_with
  146. Distro = os_cmd("./scripts/get-distro.sh"),
  147. is_rocksdb_supported(Distro).
  148. is_rocksdb_supported("respbian" ++ _) ->
  149. false;
  150. is_rocksdb_supported(_) ->
  151. not is_build_without("ROCKSDB").
  152. project_app_dirs() ->
  153. #{edition := Edition, reltype := RelType} = get_edition_from_profile_env(),
  154. project_app_dirs(Edition, RelType).
  155. project_app_dirs(Edition, RelType) ->
  156. IsEnterprise = is_enterprise(Edition),
  157. ExcludedApps = excluded_apps(RelType),
  158. UmbrellaApps = [
  159. Path
  160. || Path <- filelib:wildcard("apps/*"),
  161. not project_app_excluded(Path, ExcludedApps) andalso
  162. (is_community_umbrella_app(Path) orelse IsEnterprise)
  163. ],
  164. UmbrellaApps.
  165. project_app_excluded("apps/" ++ AppStr, ExcludedApps) ->
  166. App = list_to_atom(AppStr),
  167. lists:member(App, ExcludedApps).
  168. plugins() ->
  169. [
  170. {emqx_relup, {git, "https://github.com/emqx/emqx-relup.git", {tag, "0.2.1"}}},
  171. %% emqx main project does not require port-compiler
  172. %% pin at root level for deterministic
  173. {pc, "v1.14.0"}
  174. ] ++
  175. %% test plugins are concatenated to default profile plugins
  176. %% otherwise rebar3 test profile runs are super slow
  177. test_plugins().
  178. test_plugins() ->
  179. [
  180. {rebar3_proper, "0.12.1"},
  181. {coveralls, {git, "https://github.com/emqx/coveralls-erl", {tag, "v2.2.0-emqx-3"}}}
  182. ].
  183. test_deps() ->
  184. [
  185. {bbmustache, "1.10.0"},
  186. {meck, "0.9.2"},
  187. {proper, "1.4.0"},
  188. {er_coap_client, {git, "https://github.com/emqx/er_coap_client", {tag, "v1.0.5"}}},
  189. {erl_csv, "0.2.0"},
  190. {eministat, "0.10.1"}
  191. ].
  192. common_compile_opts() ->
  193. #{edition := Edition, reltype := RelType} = get_edition_from_profile_env(),
  194. common_compile_opts(Edition, RelType, undefined).
  195. common_compile_opts(Edition, _RelType, Vsn) ->
  196. % always include debug_info
  197. [
  198. debug_info,
  199. {compile_info, [{emqx_vsn, Vsn} || Vsn /= undefined]},
  200. {d, 'EMQX_RELEASE_EDITION', Edition}
  201. ] ++
  202. [{d, 'EMQX_BENCHMARK'} || os:getenv("EMQX_BENCHMARK") =:= "1"] ++
  203. [{d, 'STORE_STATE_IN_DS'} || os:getenv("STORE_STATE_IN_DS") =:= "1"] ++
  204. [{d, 'BUILD_WITHOUT_QUIC'} || not is_quicer_supported()].
  205. warn_profile_env() ->
  206. case os:getenv("PROFILE") of
  207. false ->
  208. io:format(
  209. standard_error,
  210. "WARN: environment variable PROFILE is not set, using 'emqx-enterprise'~n",
  211. []
  212. );
  213. _ ->
  214. ok
  215. end.
  216. %% this function is only used for test/check profiles
  217. get_edition_from_profile_env() ->
  218. case os:getenv("PROFILE") of
  219. "emqx-enterprise" ++ _ ->
  220. #{edition => ee, reltype => standard};
  221. "emqx" ++ _ ->
  222. #{edition => ce, reltype => standard};
  223. false ->
  224. #{edition => ee, reltype => standard};
  225. V ->
  226. io:format(standard_error, "ERROR: bad_PROFILE ~p~n", [V]),
  227. exit(bad_PROFILE)
  228. end.
  229. prod_compile_opts(Edition, RelType, Vsn) ->
  230. [
  231. compressed,
  232. deterministic,
  233. warnings_as_errors
  234. | common_compile_opts(Edition, RelType, Vsn)
  235. ].
  236. prod_overrides() ->
  237. [{add, [{erl_opts, [deterministic]}]}].
  238. profiles() ->
  239. #{edition := Edition, reltype := RelType} = get_edition_from_profile_env(),
  240. case Edition of
  241. ee ->
  242. profiles_ee(RelType);
  243. ce ->
  244. profiles_ce(RelType)
  245. end ++ profiles_dev(RelType).
  246. profiles_ce(RelType) ->
  247. Vsn = get_vsn(emqx),
  248. [
  249. {'emqx', [
  250. {erl_opts, prod_compile_opts(ce, RelType, Vsn)},
  251. {relx, relx(Vsn, RelType, bin, ce)},
  252. {overrides, prod_overrides()},
  253. {project_app_dirs, project_app_dirs(ce, RelType)}
  254. ]},
  255. {'emqx-pkg', [
  256. {erl_opts, prod_compile_opts(ce, RelType, Vsn)},
  257. {relx, relx(Vsn, RelType, pkg, ce)},
  258. {overrides, prod_overrides()},
  259. {project_app_dirs, project_app_dirs(ce, RelType)}
  260. ]}
  261. ].
  262. profiles_ee(RelType) ->
  263. Vsn = get_vsn('emqx-enterprise'),
  264. [
  265. {'emqx-enterprise', [
  266. {erl_opts, prod_compile_opts(ee, RelType, Vsn)},
  267. {relx, relx(Vsn, RelType, bin, ee)},
  268. {overrides, prod_overrides()},
  269. {project_app_dirs, project_app_dirs(ee, RelType)}
  270. ]},
  271. {'emqx-enterprise-pkg', [
  272. {erl_opts, prod_compile_opts(ee, RelType, Vsn)},
  273. {relx, relx(Vsn, RelType, pkg, ee)},
  274. {overrides, prod_overrides()},
  275. {project_app_dirs, project_app_dirs(ee, RelType)}
  276. ]}
  277. ].
  278. %% EE has more files than CE, always test/check with EE options.
  279. profiles_dev(_RelType) ->
  280. [
  281. {check, [
  282. {erl_opts, common_compile_opts()},
  283. {project_app_dirs, project_app_dirs()}
  284. ]},
  285. {test, [
  286. {deps, test_deps()},
  287. {erl_opts, common_compile_opts() ++ erl_opts_i()},
  288. {extra_src_dirs, [{"test", [{recursive, true}]}]},
  289. {project_app_dirs, project_app_dirs()}
  290. ]}
  291. ].
  292. %% RelType: standard
  293. %% PkgType: bin | pkg
  294. %% Edition: ce (opensource) | ee (enterprise)
  295. relx(Vsn, RelType, PkgType, Edition) ->
  296. [
  297. {include_src, false},
  298. {include_erts, true},
  299. {extended_start_script, false},
  300. {generate_start_script, false},
  301. {sys_config, false},
  302. {vm_args, false},
  303. {release, {emqx, Vsn}, relx_apps(RelType, Edition)},
  304. {tar_hooks, [
  305. "scripts/rel/cleanup-release-package.sh",
  306. "scripts/rel/macos-sign-binaries.sh",
  307. "scripts/rel/macos-notarize-package.sh"
  308. ]},
  309. {overlay, relx_overlay(RelType, Edition)},
  310. {overlay_vars_values,
  311. build_info() ++
  312. [
  313. {emqx_description, emqx_description(RelType, Edition)}
  314. | overlay_vars(RelType, PkgType, Edition)
  315. ]}
  316. ].
  317. %% Make a HOCON compatible format
  318. build_info() ->
  319. Os = os_cmd("./scripts/get-distro.sh"),
  320. [
  321. {build_info_arch, erlang:system_info(system_architecture)},
  322. {build_info_wordsize, rebar_utils:wordsize()},
  323. {build_info_os, Os},
  324. {build_info_erlang, rebar_utils:otp_release()},
  325. {build_info_elixir, none},
  326. {build_info_relform, relform()}
  327. ].
  328. relform() ->
  329. case os:getenv("EMQX_REL_FORM") of
  330. false -> "tgz";
  331. Other -> Other
  332. end.
  333. emqx_description(_, ee) -> "EMQX Enterprise";
  334. emqx_description(_, ce) -> "EMQX".
  335. overlay_vars(_RelType, PkgType, Edition) ->
  336. [
  337. {emqx_default_erlang_cookie, "emqxsecretcookie"}
  338. ] ++
  339. overlay_vars_pkg(PkgType) ++
  340. overlay_vars_edition(Edition).
  341. overlay_vars_edition(ce) ->
  342. [
  343. {emqx_schema_mod, emqx_conf_schema},
  344. {is_enterprise, "no"},
  345. {emqx_configuration_doc,
  346. "https://www.emqx.io/docs/en/latest/configuration/configuration.html"},
  347. {emqx_configuration_doc_log, "https://www.emqx.io/docs/en/latest/configuration/logs.html"}
  348. ];
  349. overlay_vars_edition(ee) ->
  350. [
  351. {emqx_schema_mod, emqx_enterprise_schema},
  352. {is_enterprise, "yes"},
  353. {emqx_configuration_doc,
  354. "https://docs.emqx.com/en/enterprise/latest/configuration/configuration.html"},
  355. {emqx_configuration_doc_log,
  356. "https://docs.emqx.com/en/enterprise/latest/configuration/logs.html"}
  357. ].
  358. %% vars per packaging type, bin(zip/tar.gz/docker) or pkg(rpm/deb)
  359. overlay_vars_pkg(bin) ->
  360. [
  361. {platform_data_dir, "data"},
  362. {platform_etc_dir, "etc"},
  363. {platform_plugins_dir, "plugins"},
  364. {runner_bin_dir, "$RUNNER_ROOT_DIR/bin"},
  365. {emqx_etc_dir, "$BASE_RUNNER_ROOT_DIR/etc"},
  366. {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"},
  367. {runner_log_dir, "$BASE_RUNNER_ROOT_DIR/log"},
  368. {runner_user, ""},
  369. {is_elixir, "no"}
  370. ];
  371. overlay_vars_pkg(pkg) ->
  372. [
  373. {platform_data_dir, "/var/lib/emqx"},
  374. {platform_etc_dir, "/etc/emqx"},
  375. {platform_plugins_dir, "/var/lib/emqx/plugins"},
  376. {runner_bin_dir, "/usr/bin"},
  377. {emqx_etc_dir, "/etc/emqx"},
  378. {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"},
  379. {runner_log_dir, "/var/log/emqx"},
  380. {runner_user, "emqx"},
  381. {is_elixir, "no"}
  382. ].
  383. relx_apps(ReleaseType, Edition) ->
  384. {ok, [
  385. #{
  386. db_apps := DBApps,
  387. system_apps := SystemApps,
  388. common_business_apps := CommonBusinessApps,
  389. ee_business_apps := EEBusinessApps,
  390. ce_business_apps := CEBusinessApps
  391. }
  392. ]} = file:consult("apps/emqx_machine/priv/reboot_lists.eterm"),
  393. EditionSpecificApps =
  394. case Edition of
  395. ee -> EEBusinessApps;
  396. ce -> CEBusinessApps
  397. end,
  398. BusinessApps = CommonBusinessApps ++ EditionSpecificApps,
  399. ExcludedApps = excluded_apps(ReleaseType),
  400. Apps =
  401. ([App || App <- SystemApps, not lists:member(App, ExcludedApps)] ++
  402. %% EMQX starts the DB and the business applications:
  403. [{App, load} || App <- DBApps, not lists:member(App, ExcludedApps)] ++
  404. [emqx_machine] ++
  405. [{App, load} || App <- BusinessApps, not lists:member(App, ExcludedApps)]),
  406. Apps.
  407. excluded_apps(standard) ->
  408. OptionalApps = [
  409. {quicer, is_quicer_supported()},
  410. {jq, is_jq_supported()},
  411. {observer, is_app(observer)},
  412. {mnesia_rocksdb, is_rocksdb_supported()},
  413. {emqx_fdb_ds, false},
  414. {emqx_ds_fdb_backend, false},
  415. {emqx_fdb_cli, false},
  416. {emqx_fdb_management, false},
  417. {emqx_event_history, false}
  418. ],
  419. [App || {App, false} <- OptionalApps];
  420. excluded_apps(platform) ->
  421. OptionalApps = [
  422. {quicer, is_quicer_supported()},
  423. {jq, is_jq_supported()},
  424. {observer, is_app(observer)},
  425. {mnesia_rocksdb, is_rocksdb_supported()}
  426. ],
  427. [App || {App, false} <- OptionalApps].
  428. is_app(Name) ->
  429. case application:load(Name) of
  430. ok -> true;
  431. {error, {already_loaded, _}} -> true;
  432. _ -> false
  433. end.
  434. relx_overlay(ReleaseType, Edition) ->
  435. [
  436. {mkdir, "log/"},
  437. {mkdir, "data/"},
  438. {mkdir, "plugins"},
  439. {mkdir, "data/mnesia"},
  440. {mkdir, "data/configs"},
  441. {mkdir, "data/patches"},
  442. {mkdir, "data/scripts"},
  443. {template, "rel/emqx_vars", "releases/emqx_vars"},
  444. {template, "rel/BUILD_INFO", "releases/{{release_version}}/BUILD_INFO"},
  445. {copy, "bin/emqx", "bin/emqx"},
  446. {copy, "bin/emqx_ctl", "bin/emqx_ctl"},
  447. {copy, "bin/emqx_cluster_rescue", "bin/emqx_cluster_rescue"},
  448. {copy, "bin/node_dump", "bin/node_dump"},
  449. {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript"},
  450. {copy, "bin/emqx", "bin/emqx-{{release_version}}"},
  451. {copy, "bin/emqx_ctl", "bin/emqx_ctl-{{release_version}}"},
  452. {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript-{{release_version}}"},
  453. {copy, "apps/emqx_gateway_lwm2m/lwm2m_xml", "etc/lwm2m_xml"},
  454. {copy, "apps/emqx_auth/etc/acl.conf", "etc/acl.conf"},
  455. {copy, "apps/emqx_auth/etc/auth-built-in-db-bootstrap.csv",
  456. "etc/auth-built-in-db-bootstrap.csv"},
  457. {template, "bin/emqx.cmd", "bin/emqx.cmd"},
  458. {template, "bin/emqx_ctl.cmd", "bin/emqx_ctl.cmd"},
  459. {copy, "bin/nodetool", "bin/nodetool"},
  460. {copy, "bin/nodetool", "bin/nodetool-{{release_version}}"}
  461. ] ++ etc_overlay(ReleaseType, Edition).
  462. etc_overlay(ReleaseType, Edition) ->
  463. Templates = emqx_etc_overlay(ReleaseType),
  464. [
  465. {mkdir, "etc/"},
  466. {copy, "{{base_dir}}/lib/emqx/etc/certs", "etc/"}
  467. | copy_examples(Edition)
  468. ] ++
  469. lists:map(
  470. fun
  471. ({From, To}) -> {template, From, To};
  472. (FromTo) -> {template, FromTo, FromTo}
  473. end,
  474. Templates
  475. ).
  476. copy_examples(ce) ->
  477. [{copy, "rel/config/examples", "etc/"}];
  478. copy_examples(ee) ->
  479. [
  480. {copy, "rel/config/examples", "etc/"},
  481. {copy, "rel/config/ee-examples/*", "etc/examples/"}
  482. ].
  483. emqx_etc_overlay(ReleaseType) ->
  484. emqx_etc_overlay_per_rel(ReleaseType) ++
  485. emqx_etc_overlay().
  486. emqx_etc_overlay_per_rel(_RelType) ->
  487. [{"{{base_dir}}/lib/emqx/etc/vm.args.cloud", "etc/vm.args"}].
  488. emqx_etc_overlay() ->
  489. [
  490. {"{{base_dir}}/lib/emqx/etc/ssl_dist.conf", "etc/ssl_dist.conf"},
  491. {"{{base_dir}}/lib/emqx_conf/etc/emqx.conf.all", "etc/emqx.conf"}
  492. ].
  493. get_vsn(Profile) ->
  494. case os:getenv("PKG_VSN") of
  495. false ->
  496. os_cmd("pkg-vsn.sh " ++ atom_to_list(Profile));
  497. Vsn ->
  498. Vsn
  499. end.
  500. %% to make it compatible to Linux and Windows,
  501. %% we must use bash to execute the bash file
  502. %% because "./" will not be recognized as an internal or external command
  503. os_cmd(Cmd) ->
  504. Output = os:cmd("bash " ++ Cmd),
  505. re:replace(Output, "\n", "", [{return, list}]).
  506. maybe_dump(Config) ->
  507. is_debug() andalso
  508. file:write_file("rebar.config.rendered", [io_lib:format("~p.\n", [I]) || I <- Config]),
  509. Config.
  510. is_debug() -> is_debug("DEBUG") orelse is_debug("DIAGNOSTIC").
  511. is_debug(VarName) ->
  512. case os:getenv(VarName) of
  513. false -> false;
  514. "" -> false;
  515. _ -> true
  516. end.
  517. erl_opts_i() ->
  518. [{i, "apps"}] ++
  519. [{i, Dir} || Dir <- filelib:wildcard(filename:join(["apps", "*", "include"]))].
  520. dialyzer(Config) ->
  521. {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config),
  522. AppsToAnalyse =
  523. case os:getenv("DIALYZER_ANALYSE_APP") of
  524. false ->
  525. [];
  526. Value ->
  527. [list_to_atom(App) || App <- string:tokens(Value, ",")]
  528. end,
  529. AppNames = app_names(),
  530. KnownApps = [Name || Name <- AppsToAnalyse, lists:member(Name, AppNames)],
  531. ExcludedApps = excluded_apps(standard),
  532. AppsToExclude = ExcludedApps ++ (AppNames -- KnownApps),
  533. Extra =
  534. [system_monitor, tools] ++
  535. [jq || is_jq_supported()] ++
  536. [quicer || is_quicer_supported()],
  537. NewDialyzerConfig =
  538. OldDialyzerConfig ++
  539. [{exclude_apps, AppsToExclude} || length(AppsToAnalyse) > 0] ++
  540. [{plt_extra_apps, Extra} || length(Extra) > 0],
  541. lists:keystore(
  542. dialyzer,
  543. 1,
  544. Config,
  545. {dialyzer, NewDialyzerConfig}
  546. ).
  547. coveralls() ->
  548. case {os:getenv("GITHUB_ACTIONS"), os:getenv("GITHUB_TOKEN")} of
  549. {"true", Token} when is_list(Token) ->
  550. Cfgs = [
  551. {coveralls_repo_token, Token},
  552. {coveralls_service_job_id, os:getenv("GITHUB_RUN_ID")},
  553. {coveralls_commit_sha, os:getenv("GITHUB_SHA")},
  554. {coveralls_coverdata, "_build/test/cover/*.coverdata"},
  555. {coveralls_parallel, true},
  556. {coveralls_service_name, "github"}
  557. ],
  558. case
  559. os:getenv("GITHUB_EVENT_NAME") =:= "pull_request" andalso
  560. string:tokens(os:getenv("GITHUB_REF"), "/")
  561. of
  562. [_, "pull", PRNO, _] ->
  563. [{coveralls_service_pull_request, PRNO} | Cfgs];
  564. _ ->
  565. Cfgs
  566. end;
  567. _ ->
  568. []
  569. end.
  570. app_names() -> list_dir("apps").
  571. list_dir(Dir) ->
  572. case filelib:is_dir(Dir) of
  573. true ->
  574. {ok, Names} = file:list_dir(Dir),
  575. [list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))];
  576. false ->
  577. []
  578. end.