rebar.config.erl 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  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 = 24,
  16. Latest = 25,
  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. bcrypt() ->
  35. {bcrypt, {git, "https://github.com/emqx/erlang-bcrypt.git", {tag, "0.6.0"}}}.
  36. quicer() ->
  37. {quicer, {git, "https://github.com/emqx/quic.git", {tag, "0.0.114"}}}.
  38. jq() ->
  39. {jq, {git, "https://github.com/emqx/jq", {tag, "v0.3.10"}}}.
  40. deps(Config) ->
  41. {deps, OldDeps} = lists:keyfind(deps, 1, Config),
  42. MoreDeps =
  43. [bcrypt() || provide_bcrypt_dep()] ++
  44. [jq() || is_jq_supported()] ++
  45. [quicer() || is_quicer_supported()],
  46. lists:keystore(deps, 1, Config, {deps, OldDeps ++ MoreDeps}).
  47. overrides() ->
  48. [{add, [{extra_src_dirs, [{"etc", [{recursive, true}]}]}]}] ++ snabbkaffe_overrides().
  49. %% Temporary workaround for a rebar3 erl_opts duplication
  50. %% bug. Ideally, we want to set this define globally
  51. snabbkaffe_overrides() ->
  52. Apps = [snabbkaffe, ekka, mria, gen_rpc],
  53. [{add, App, [{erl_opts, [{d, snk_kind, msg}]}]} || App <- Apps].
  54. config() ->
  55. [
  56. {cover_enabled, is_cover_enabled()},
  57. {profiles, profiles()},
  58. {plugins, plugins()}
  59. ].
  60. is_cover_enabled() ->
  61. case os:getenv("ENABLE_COVER_COMPILE") of
  62. "1" -> true;
  63. "true" -> true;
  64. _ -> false
  65. end.
  66. is_enterprise(ce) -> false;
  67. is_enterprise(ee) -> true.
  68. is_community_umbrella_app("apps/emqx_bridge_kafka") -> false;
  69. is_community_umbrella_app("apps/emqx_bridge_gcp_pubsub") -> false;
  70. is_community_umbrella_app("apps/emqx_bridge_cassandra") -> false;
  71. is_community_umbrella_app("apps/emqx_bridge_opents") -> false;
  72. is_community_umbrella_app("apps/emqx_bridge_clickhouse") -> false;
  73. is_community_umbrella_app("apps/emqx_bridge_dynamo") -> false;
  74. is_community_umbrella_app("apps/emqx_bridge_hstreamdb") -> false;
  75. is_community_umbrella_app("apps/emqx_bridge_influxdb") -> false;
  76. is_community_umbrella_app("apps/emqx_bridge_iotdb") -> false;
  77. is_community_umbrella_app("apps/emqx_bridge_matrix") -> false;
  78. is_community_umbrella_app("apps/emqx_bridge_mongodb") -> false;
  79. is_community_umbrella_app("apps/emqx_bridge_mysql") -> false;
  80. is_community_umbrella_app("apps/emqx_bridge_pgsql") -> false;
  81. is_community_umbrella_app("apps/emqx_bridge_pulsar") -> false;
  82. is_community_umbrella_app("apps/emqx_bridge_redis") -> false;
  83. is_community_umbrella_app("apps/emqx_bridge_rocketmq") -> false;
  84. is_community_umbrella_app("apps/emqx_bridge_tdengine") -> false;
  85. is_community_umbrella_app("apps/emqx_bridge_timescale") -> false;
  86. is_community_umbrella_app("apps/emqx_bridge_oracle") -> false;
  87. is_community_umbrella_app("apps/emqx_bridge_sqlserver") -> false;
  88. is_community_umbrella_app("apps/emqx_oracle") -> false;
  89. is_community_umbrella_app("apps/emqx_bridge_rabbitmq") -> false;
  90. is_community_umbrella_app("apps/emqx_ft") -> false;
  91. is_community_umbrella_app("apps/emqx_s3") -> false;
  92. is_community_umbrella_app("apps/emqx_schema_registry") -> false;
  93. is_community_umbrella_app("apps/emqx_enterprise") -> false;
  94. is_community_umbrella_app("apps/emqx_bridge_kinesis") -> false;
  95. is_community_umbrella_app(_) -> true.
  96. is_jq_supported() ->
  97. not (false =/= os:getenv("BUILD_WITHOUT_JQ") orelse
  98. is_win32()) orelse
  99. "1" == os:getenv("BUILD_WITH_JQ").
  100. is_quicer_supported() ->
  101. not (false =/= os:getenv("BUILD_WITHOUT_QUIC") orelse
  102. is_macos() orelse
  103. is_win32() orelse is_centos_6()) orelse
  104. "1" == os:getenv("BUILD_WITH_QUIC").
  105. is_rocksdb_supported() ->
  106. not (false =/= os:getenv("BUILD_WITHOUT_ROCKSDB") orelse
  107. is_raspbian()) orelse
  108. "1" == os:getenv("BUILD_WITH_ROCKSDB").
  109. is_macos() ->
  110. {unix, darwin} =:= os:type().
  111. is_centos_6() ->
  112. %% reason:
  113. %% glibc is too old
  114. case file:read_file("/etc/centos-release") of
  115. {ok, <<"CentOS release 6", _/binary>>} ->
  116. true;
  117. _ ->
  118. false
  119. end.
  120. is_raspbian() ->
  121. case os_cmd("./scripts/get-distro.sh") of
  122. "raspbian" ++ _ ->
  123. true;
  124. _ ->
  125. false
  126. end.
  127. is_win32() ->
  128. win32 =:= element(1, os:type()).
  129. project_app_dirs() ->
  130. project_app_dirs(get_edition_from_profile_env()).
  131. project_app_dirs(Edition) ->
  132. IsEnterprise = is_enterprise(Edition),
  133. UmbrellaApps = [
  134. Path
  135. || Path <- filelib:wildcard("apps/*"),
  136. is_community_umbrella_app(Path) orelse IsEnterprise
  137. ],
  138. UmbrellaApps ++
  139. case IsEnterprise of
  140. true -> ["lib-ee/*"];
  141. false -> []
  142. end.
  143. plugins() ->
  144. [
  145. %{relup_helper, {git, "https://github.com/emqx/relup_helper", {tag, "2.1.0"}}},
  146. %% emqx main project does not require port-compiler
  147. %% pin at root level for deterministic
  148. {pc, "v1.14.0"}
  149. ] ++
  150. %% test plugins are concatenated to default profile plugins
  151. %% otherwise rebar3 test profile runs are super slow
  152. test_plugins().
  153. test_plugins() ->
  154. [
  155. {rebar3_proper, "0.12.1"},
  156. {coveralls, {git, "https://github.com/emqx/coveralls-erl", {tag, "v2.2.0-emqx-1"}}}
  157. ].
  158. test_deps() ->
  159. [
  160. {bbmustache, "1.10.0"},
  161. {meck, "0.9.2"},
  162. {proper, "1.4.0"},
  163. {er_coap_client, {git, "https://github.com/emqx/er_coap_client", {tag, "v1.0.5"}}},
  164. {erl_csv, "0.2.0"}
  165. ].
  166. common_compile_opts() ->
  167. common_compile_opts(get_edition_from_profile_env(), undefined).
  168. common_compile_opts(Edition, Vsn) ->
  169. % always include debug_info
  170. [
  171. debug_info,
  172. {compile_info, [{emqx_vsn, Vsn} || Vsn /= undefined]},
  173. {d, 'EMQX_RELEASE_EDITION', Edition}
  174. ] ++
  175. [{d, 'EMQX_BENCHMARK'} || os:getenv("EMQX_BENCHMARK") =:= "1"] ++
  176. [{d, 'BUILD_WITHOUT_QUIC'} || not is_quicer_supported()].
  177. warn_profile_env() ->
  178. case os:getenv("PROFILE") of
  179. false ->
  180. io:format(
  181. standard_error,
  182. "WARN: environment variable PROFILE is not set, using 'emqx-enterprise'~n",
  183. []
  184. );
  185. _ ->
  186. ok
  187. end.
  188. %% this function is only used for test/check profiles
  189. get_edition_from_profile_env() ->
  190. case os:getenv("PROFILE") of
  191. "emqx-enterprise" ++ _ ->
  192. ee;
  193. "emqx" ++ _ ->
  194. ce;
  195. false ->
  196. ee;
  197. V ->
  198. io:format(standard_error, "ERROR: bad_PROFILE ~p~n", [V]),
  199. exit(bad_PROFILE)
  200. end.
  201. prod_compile_opts(Edition, Vsn) ->
  202. [
  203. compressed,
  204. deterministic,
  205. warnings_as_errors
  206. | common_compile_opts(Edition, Vsn)
  207. ].
  208. prod_overrides() ->
  209. [{add, [{erl_opts, [deterministic]}]}].
  210. profiles() ->
  211. case get_edition_from_profile_env() of
  212. ee ->
  213. profiles_ee();
  214. ce ->
  215. profiles_ce()
  216. end ++ profiles_dev().
  217. profiles_ce() ->
  218. Vsn = get_vsn(emqx),
  219. [
  220. {'emqx', [
  221. {erl_opts, prod_compile_opts(ce, Vsn)},
  222. {relx, relx(Vsn, cloud, bin, ce)},
  223. {overrides, prod_overrides()},
  224. {project_app_dirs, project_app_dirs(ce)}
  225. ]},
  226. {'emqx-pkg', [
  227. {erl_opts, prod_compile_opts(ce, Vsn)},
  228. {relx, relx(Vsn, cloud, pkg, ce)},
  229. {overrides, prod_overrides()},
  230. {project_app_dirs, project_app_dirs(ce)}
  231. ]}
  232. ].
  233. profiles_ee() ->
  234. Vsn = get_vsn('emqx-enterprise'),
  235. [
  236. {'emqx-enterprise', [
  237. {erl_opts, prod_compile_opts(ee, Vsn)},
  238. {relx, relx(Vsn, cloud, bin, ee)},
  239. {overrides, prod_overrides()},
  240. {project_app_dirs, project_app_dirs(ee)}
  241. ]},
  242. {'emqx-enterprise-pkg', [
  243. {erl_opts, prod_compile_opts(ee, Vsn)},
  244. {relx, relx(Vsn, cloud, pkg, ee)},
  245. {overrides, prod_overrides()},
  246. {project_app_dirs, project_app_dirs(ee)}
  247. ]}
  248. ].
  249. %% EE has more files than CE, always test/check with EE options.
  250. profiles_dev() ->
  251. [
  252. {check, [
  253. {erl_opts, common_compile_opts()},
  254. {project_app_dirs, project_app_dirs()}
  255. ]},
  256. {test, [
  257. {deps, test_deps()},
  258. {erl_opts, common_compile_opts() ++ erl_opts_i()},
  259. {extra_src_dirs, [{"test", [{recursive, true}]}]},
  260. {project_app_dirs, project_app_dirs()}
  261. ]}
  262. ].
  263. %% RelType: cloud (full size)
  264. %% PkgType: bin | pkg
  265. %% Edition: ce (opensource) | ee (enterprise)
  266. relx(Vsn, RelType, PkgType, Edition) ->
  267. [
  268. {include_src, false},
  269. {include_erts, true},
  270. {extended_start_script, false},
  271. {generate_start_script, false},
  272. {sys_config, false},
  273. {vm_args, false},
  274. {release, {emqx, Vsn}, relx_apps(RelType, Edition)},
  275. {overlay, relx_overlay(RelType, Edition)},
  276. {overlay_vars_values,
  277. build_info() ++
  278. [
  279. {emqx_description, emqx_description(RelType, Edition)}
  280. | overlay_vars(RelType, PkgType, Edition)
  281. ]}
  282. ].
  283. %% Make a HOCON compatible format
  284. build_info() ->
  285. Os = os_cmd("./scripts/get-distro.sh"),
  286. [
  287. {build_info_arch, erlang:system_info(system_architecture)},
  288. {build_info_wordsize, rebar_utils:wordsize()},
  289. {build_info_os, Os},
  290. {build_info_erlang, rebar_utils:otp_release()},
  291. {build_info_elixir, none},
  292. {build_info_relform, relform()}
  293. ].
  294. relform() ->
  295. case os:getenv("EMQX_REL_FORM") of
  296. false -> "tgz";
  297. Other -> Other
  298. end.
  299. emqx_description(cloud, ee) -> "EMQX Enterprise";
  300. emqx_description(cloud, ce) -> "EMQX".
  301. overlay_vars(cloud, PkgType, Edition) ->
  302. [
  303. {emqx_default_erlang_cookie, "emqxsecretcookie"}
  304. ] ++
  305. overlay_vars_pkg(PkgType) ++
  306. overlay_vars_edition(Edition).
  307. overlay_vars_edition(ce) ->
  308. [
  309. {emqx_schema_mod, emqx_conf_schema},
  310. {emqx_configuration_doc,
  311. "https://www.emqx.io/docs/en/v5.0/configuration/configuration.html"},
  312. {is_enterprise, "no"}
  313. ];
  314. overlay_vars_edition(ee) ->
  315. [
  316. {emqx_schema_mod, emqx_enterprise_schema},
  317. {emqx_configuration_doc,
  318. "https://docs.emqx.com/en/enterprise/v5.0/configuration/configuration.html"},
  319. {is_enterprise, "yes"}
  320. ].
  321. %% vars per packaging type, bin(zip/tar.gz/docker) or pkg(rpm/deb)
  322. overlay_vars_pkg(bin) ->
  323. [
  324. {platform_data_dir, "data"},
  325. {platform_etc_dir, "etc"},
  326. {platform_plugins_dir, "plugins"},
  327. {runner_bin_dir, "$RUNNER_ROOT_DIR/bin"},
  328. {emqx_etc_dir, "$RUNNER_ROOT_DIR/etc"},
  329. {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"},
  330. {runner_log_dir, "$RUNNER_ROOT_DIR/log"},
  331. {runner_user, ""},
  332. {is_elixir, "no"}
  333. ];
  334. overlay_vars_pkg(pkg) ->
  335. [
  336. {platform_data_dir, "/var/lib/emqx"},
  337. {platform_etc_dir, "/etc/emqx"},
  338. {platform_plugins_dir, "/var/lib/emqx/plugins"},
  339. {runner_bin_dir, "/usr/bin"},
  340. {emqx_etc_dir, "/etc/emqx"},
  341. {runner_lib_dir, "$RUNNER_ROOT_DIR/lib"},
  342. {runner_log_dir, "/var/log/emqx"},
  343. {runner_user, "emqx"},
  344. {is_elixir, "no"}
  345. ].
  346. relx_apps(ReleaseType, Edition) ->
  347. [
  348. kernel,
  349. sasl,
  350. crypto,
  351. public_key,
  352. asn1,
  353. syntax_tools,
  354. ssl,
  355. os_mon,
  356. inets,
  357. compiler,
  358. runtime_tools,
  359. redbug,
  360. xmerl,
  361. {hocon, load},
  362. telemetry,
  363. % started by emqx_machine
  364. {emqx, load},
  365. {emqx_conf, load},
  366. emqx_machine
  367. ] ++
  368. [{mnesia_rocksdb, load} || is_rocksdb_supported()] ++
  369. [
  370. {mnesia, load},
  371. {ekka, load},
  372. {esasl, load},
  373. observer_cli,
  374. tools,
  375. {covertool, load},
  376. % started by emqx_machine
  377. {system_monitor, load},
  378. {emqx_utils, load},
  379. emqx_http_lib,
  380. emqx_resource,
  381. emqx_connector,
  382. emqx_authn,
  383. emqx_authz,
  384. emqx_auto_subscribe,
  385. emqx_gateway,
  386. emqx_gateway_stomp,
  387. emqx_gateway_mqttsn,
  388. emqx_gateway_coap,
  389. emqx_gateway_lwm2m,
  390. emqx_gateway_exproto,
  391. emqx_exhook,
  392. emqx_bridge,
  393. emqx_bridge_mqtt,
  394. emqx_bridge_http,
  395. emqx_rule_engine,
  396. emqx_modules,
  397. emqx_management,
  398. emqx_dashboard,
  399. emqx_retainer,
  400. emqx_prometheus,
  401. emqx_psk,
  402. emqx_slow_subs,
  403. emqx_mongodb,
  404. emqx_redis,
  405. emqx_mysql,
  406. emqx_plugins
  407. ] ++
  408. [quicer || is_quicer_supported()] ++
  409. [bcrypt || provide_bcrypt_release(ReleaseType)] ++
  410. %% Started automatically when needed (only needs to be started when the
  411. %% port implementation is used)
  412. [{jq, load} || is_jq_supported()] ++
  413. [{observer, load} || is_app(observer)] ++
  414. relx_apps_per_edition(Edition).
  415. is_app(Name) ->
  416. case application:load(Name) of
  417. ok -> true;
  418. {error, {already_loaded, _}} -> true;
  419. _ -> false
  420. end.
  421. relx_apps_per_edition(ee) ->
  422. [
  423. emqx_license,
  424. {emqx_enterprise, load},
  425. emqx_bridge_kafka,
  426. emqx_bridge_pulsar,
  427. emqx_bridge_gcp_pubsub,
  428. emqx_bridge_cassandra,
  429. emqx_bridge_opents,
  430. emqx_bridge_clickhouse,
  431. emqx_bridge_dynamo,
  432. emqx_bridge_hstreamdb,
  433. emqx_bridge_influxdb,
  434. emqx_bridge_iotdb,
  435. emqx_bridge_matrix,
  436. emqx_bridge_mongodb,
  437. emqx_bridge_mysql,
  438. emqx_bridge_pgsql,
  439. emqx_bridge_redis,
  440. emqx_bridge_rocketmq,
  441. emqx_bridge_tdengine,
  442. emqx_bridge_timescale,
  443. emqx_bridge_sqlserver,
  444. emqx_oracle,
  445. emqx_bridge_oracle,
  446. emqx_bridge_rabbitmq,
  447. emqx_schema_registry,
  448. emqx_eviction_agent,
  449. emqx_node_rebalance,
  450. emqx_ft,
  451. emqx_bridge_kinesis
  452. ];
  453. relx_apps_per_edition(ce) ->
  454. [emqx_telemetry].
  455. relx_overlay(ReleaseType, Edition) ->
  456. [
  457. {mkdir, "log/"},
  458. {mkdir, "data/"},
  459. {mkdir, "plugins"},
  460. {mkdir, "data/mnesia"},
  461. {mkdir, "data/configs"},
  462. {mkdir, "data/patches"},
  463. {mkdir, "data/scripts"},
  464. {template, "rel/emqx_vars", "releases/emqx_vars"},
  465. {template, "rel/BUILD_INFO", "releases/{{release_version}}/BUILD_INFO"},
  466. {copy, "bin/emqx", "bin/emqx"},
  467. {copy, "bin/emqx_ctl", "bin/emqx_ctl"},
  468. {copy, "bin/emqx_cluster_rescue", "bin/emqx_cluster_rescue"},
  469. {copy, "bin/node_dump", "bin/node_dump"},
  470. {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript"},
  471. {copy, "bin/emqx", "bin/emqx-{{release_version}}"},
  472. {copy, "bin/emqx_ctl", "bin/emqx_ctl-{{release_version}}"},
  473. {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript-{{release_version}}"},
  474. {copy, "apps/emqx_gateway_lwm2m/lwm2m_xml", "etc/lwm2m_xml"},
  475. {copy, "apps/emqx_authz/etc/acl.conf", "etc/acl.conf"},
  476. {template, "bin/emqx.cmd", "bin/emqx.cmd"},
  477. {template, "bin/emqx_ctl.cmd", "bin/emqx_ctl.cmd"},
  478. {copy, "bin/nodetool", "bin/nodetool"},
  479. {copy, "bin/nodetool", "bin/nodetool-{{release_version}}"}
  480. ] ++ etc_overlay(ReleaseType, Edition).
  481. etc_overlay(ReleaseType, Edition) ->
  482. Templates = emqx_etc_overlay(ReleaseType),
  483. [
  484. {mkdir, "etc/"},
  485. {copy, "{{base_dir}}/lib/emqx/etc/certs", "etc/"}
  486. | copy_examples(Edition)
  487. ] ++
  488. lists:map(
  489. fun
  490. ({From, To}) -> {template, From, To};
  491. (FromTo) -> {template, FromTo, FromTo}
  492. end,
  493. Templates
  494. ).
  495. copy_examples(ce) ->
  496. [{copy, "rel/config/examples", "etc/"}];
  497. copy_examples(ee) ->
  498. [
  499. {copy, "rel/config/examples", "etc/"},
  500. {copy, "rel/config/ee-examples/*", "etc/examples/"}
  501. ].
  502. emqx_etc_overlay(ReleaseType) ->
  503. emqx_etc_overlay_per_rel(ReleaseType) ++
  504. emqx_etc_overlay().
  505. emqx_etc_overlay_per_rel(cloud) ->
  506. [{"{{base_dir}}/lib/emqx/etc/vm.args.cloud", "etc/vm.args"}].
  507. emqx_etc_overlay() ->
  508. [
  509. {"{{base_dir}}/lib/emqx/etc/ssl_dist.conf", "etc/ssl_dist.conf"},
  510. {"{{base_dir}}/lib/emqx_conf/etc/emqx.conf.all", "etc/emqx.conf"}
  511. ].
  512. get_vsn(Profile) ->
  513. case os:getenv("PKG_VSN") of
  514. false ->
  515. os_cmd("pkg-vsn.sh " ++ atom_to_list(Profile));
  516. Vsn ->
  517. Vsn
  518. end.
  519. %% to make it compatible to Linux and Windows,
  520. %% we must use bash to execute the bash file
  521. %% because "./" will not be recognized as an internal or external command
  522. os_cmd(Cmd) ->
  523. Output = os:cmd("bash " ++ Cmd),
  524. re:replace(Output, "\n", "", [{return, list}]).
  525. maybe_dump(Config) ->
  526. is_debug() andalso
  527. file:write_file("rebar.config.rendered", [io_lib:format("~p.\n", [I]) || I <- Config]),
  528. Config.
  529. is_debug() -> is_debug("DEBUG") orelse is_debug("DIAGNOSTIC").
  530. is_debug(VarName) ->
  531. case os:getenv(VarName) of
  532. false -> false;
  533. "" -> false;
  534. _ -> true
  535. end.
  536. provide_bcrypt_dep() ->
  537. not is_win32().
  538. provide_bcrypt_release(ReleaseType) ->
  539. provide_bcrypt_dep() andalso ReleaseType =:= cloud.
  540. erl_opts_i() ->
  541. [{i, "apps"}] ++
  542. [{i, Dir} || Dir <- filelib:wildcard(filename:join(["apps", "*", "include"]))] ++
  543. [{i, Dir} || Dir <- filelib:wildcard(filename:join(["lib-ee", "*", "include"]))].
  544. dialyzer(Config) ->
  545. {dialyzer, OldDialyzerConfig} = lists:keyfind(dialyzer, 1, Config),
  546. AppsToAnalyse =
  547. case os:getenv("DIALYZER_ANALYSE_APP") of
  548. false ->
  549. [];
  550. Value ->
  551. [list_to_atom(App) || App <- string:tokens(Value, ",")]
  552. end,
  553. AppNames = app_names(),
  554. KnownApps = [Name || Name <- AppsToAnalyse, lists:member(Name, AppNames)],
  555. AppsToExclude = AppNames -- KnownApps,
  556. Extra =
  557. [bcrypt || provide_bcrypt_dep()] ++
  558. [jq || is_jq_supported()] ++
  559. [quicer || is_quicer_supported()],
  560. NewDialyzerConfig =
  561. OldDialyzerConfig ++
  562. [{exclude_apps, AppsToExclude} || length(AppsToAnalyse) > 0] ++
  563. [{plt_extra_apps, Extra} || length(Extra) > 0],
  564. lists:keystore(
  565. dialyzer,
  566. 1,
  567. Config,
  568. {dialyzer, NewDialyzerConfig}
  569. ).
  570. coveralls() ->
  571. case {os:getenv("GITHUB_ACTIONS"), os:getenv("GITHUB_TOKEN")} of
  572. {"true", Token} when is_list(Token) ->
  573. Cfgs = [
  574. {coveralls_repo_token, Token},
  575. {coveralls_service_job_id, os:getenv("GITHUB_RUN_ID")},
  576. {coveralls_commit_sha, os:getenv("GITHUB_SHA")},
  577. {coveralls_coverdata, "_build/test/cover/*.coverdata"},
  578. {coveralls_service_name, "github"}
  579. ],
  580. case
  581. os:getenv("GITHUB_EVENT_NAME") =:= "pull_request" andalso
  582. string:tokens(os:getenv("GITHUB_REF"), "/")
  583. of
  584. [_, "pull", PRNO, _] ->
  585. [{coveralls_service_pull_request, PRNO} | Cfgs];
  586. _ ->
  587. Cfgs
  588. end;
  589. _ ->
  590. []
  591. end.
  592. app_names() -> list_dir("apps") ++ list_dir("lib-ee").
  593. list_dir(Dir) ->
  594. case filelib:is_dir(Dir) of
  595. true ->
  596. {ok, Names} = file:list_dir(Dir),
  597. [list_to_atom(Name) || Name <- Names, filelib:is_dir(filename:join([Dir, Name]))];
  598. false ->
  599. []
  600. end.