mix.exs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807
  1. defmodule EMQXUmbrella.MixProject do
  2. use Mix.Project
  3. @moduledoc """
  4. The purpose of this file is to configure the release of EMQX under
  5. Mix. Since EMQX uses its own configuration conventions and startup
  6. procedures, one cannot simply use `iex -S mix`. Instead, it's
  7. recommendd to build and use the release.
  8. ## Profiles
  9. To control the profile and edition to build, we case split on the
  10. MIX_ENV value.
  11. The following profiles are valid:
  12. * `emqx`
  13. * `emqx-enterprise`
  14. * `emqx-pkg`
  15. * `emqx-enterprise-pkg`
  16. * `dev` -> same as `emqx`, for convenience
  17. ## Release Environment Variables
  18. The release build is controlled by a few environment variables.
  19. * `ELIXIR_MAKE_TAR` - If set to `yes`, will produce a `.tar.gz`
  20. tarball along with the release.
  21. """
  22. def project() do
  23. profile_info = check_profile!()
  24. [
  25. app: :emqx_mix,
  26. version: pkg_vsn(),
  27. deps: deps(profile_info),
  28. releases: releases()
  29. ]
  30. end
  31. defp deps(profile_info) do
  32. # we need several overrides here because dependencies specify
  33. # other exact versions, and not ranges.
  34. [
  35. {:lc, github: "emqx/lc", tag: "0.3.2", override: true},
  36. {:redbug, "2.0.8"},
  37. {:covertool, github: "zmstone/covertool", tag: "2.0.4.1", override: true},
  38. {:typerefl, github: "ieQu1/typerefl", tag: "0.9.1", override: true},
  39. {:ehttpc, github: "emqx/ehttpc", tag: "0.4.7", override: true},
  40. {:gproc, github: "uwiger/gproc", tag: "0.8.0", override: true},
  41. {:jiffy, github: "emqx/jiffy", tag: "1.0.5", override: true},
  42. {:cowboy, github: "emqx/cowboy", tag: "2.9.0", override: true},
  43. {:esockd, github: "emqx/esockd", tag: "5.9.4", override: true},
  44. {:rocksdb, github: "emqx/erlang-rocksdb", tag: "1.7.2-emqx-9", override: true},
  45. {:ekka, github: "emqx/ekka", tag: "0.14.5", override: true},
  46. {:gen_rpc, github: "emqx/gen_rpc", tag: "2.8.1", override: true},
  47. {:grpc, github: "emqx/grpc-erl", tag: "0.6.7", override: true},
  48. {:minirest, github: "emqx/minirest", tag: "1.3.8", override: true},
  49. {:ecpool, github: "emqx/ecpool", tag: "0.5.3", override: true},
  50. {:replayq, github: "emqx/replayq", tag: "0.3.7", override: true},
  51. {:pbkdf2, github: "emqx/erlang-pbkdf2", tag: "2.0.4", override: true},
  52. {:emqtt, github: "emqx/emqtt", tag: "1.8.5", override: true},
  53. {:rulesql, github: "emqx/rulesql", tag: "0.1.4"},
  54. {:observer_cli, "1.7.1"},
  55. {:system_monitor, github: "ieQu1/system_monitor", tag: "3.0.3"},
  56. {:telemetry, "1.1.0"},
  57. # in conflict by emqtt and hocon
  58. {:getopt, "1.0.2", override: true},
  59. {:snabbkaffe, github: "kafka4beam/snabbkaffe", tag: "1.0.7", override: true},
  60. {:hocon, github: "emqx/hocon", tag: "0.37.0", override: true},
  61. {:emqx_http_lib, github: "emqx/emqx_http_lib", tag: "0.5.2", override: true},
  62. {:esasl, github: "emqx/esasl", tag: "0.2.0"},
  63. {:jose, github: "potatosalad/erlang-jose", tag: "1.11.2"},
  64. # in conflict by ehttpc and emqtt
  65. {:gun, github: "emqx/gun", tag: "1.3.9", override: true},
  66. # in conflict by emqx_connector and system_monitor
  67. {:epgsql, github: "emqx/epgsql", tag: "4.7.0.1", override: true},
  68. # in conflict by emqx and observer_cli
  69. {:recon, github: "ferd/recon", tag: "2.5.1", override: true},
  70. {:jsx, github: "talentdeficit/jsx", tag: "v3.1.0", override: true},
  71. # dependencies of dependencies; we choose specific refs to match
  72. # what rebar3 chooses.
  73. # in conflict by gun and emqtt
  74. {:cowlib,
  75. github: "ninenines/cowlib", ref: "c6553f8308a2ca5dcd69d845f0a7d098c40c3363", override: true},
  76. # in conflict by cowboy_swagger and cowboy
  77. {:ranch,
  78. github: "ninenines/ranch", ref: "a692f44567034dacf5efcaa24a24183788594eb7", override: true},
  79. # in conflict by grpc and eetcd
  80. {:gpb, "4.19.5", override: true, runtime: false},
  81. {:hackney, github: "benoitc/hackney", tag: "1.18.1", override: true}
  82. ] ++
  83. umbrella_apps() ++
  84. enterprise_apps(profile_info) ++
  85. enterprise_deps(profile_info) ++ bcrypt_dep() ++ jq_dep() ++ quicer_dep()
  86. end
  87. defp umbrella_apps() do
  88. "apps/*"
  89. |> Path.wildcard()
  90. |> Enum.map(fn path ->
  91. app =
  92. path
  93. |> Path.basename()
  94. |> String.to_atom()
  95. {app, path: path, manager: :rebar3, override: true}
  96. end)
  97. end
  98. defp enterprise_apps(_profile_info = %{edition_type: :enterprise}) do
  99. "lib-ee/*"
  100. |> Path.wildcard()
  101. |> Enum.filter(&File.dir?/1)
  102. |> Enum.map(fn path ->
  103. app =
  104. path
  105. |> Path.basename()
  106. |> String.to_atom()
  107. {app, path: path, manager: :rebar3, override: true}
  108. end)
  109. end
  110. defp enterprise_apps(_profile_info) do
  111. []
  112. end
  113. defp enterprise_deps(_profile_info = %{edition_type: :enterprise}) do
  114. [
  115. {:hstreamdb_erl, github: "hstreamdb/hstreamdb_erl", tag: "0.2.5"},
  116. {:influxdb, github: "emqx/influxdb-client-erl", tag: "1.1.9", override: true},
  117. {:wolff, github: "kafka4beam/wolff", tag: "1.7.5"},
  118. {:kafka_protocol, github: "kafka4beam/kafka_protocol", tag: "4.1.2", override: true},
  119. {:brod_gssapi, github: "kafka4beam/brod_gssapi", tag: "v0.1.0-rc1"},
  120. {:brod, github: "kafka4beam/brod", tag: "3.16.8"},
  121. {:snappyer, "1.2.8", override: true},
  122. {:supervisor3, "1.1.11", override: true}
  123. ]
  124. end
  125. defp enterprise_deps(_profile_info) do
  126. []
  127. end
  128. defp releases() do
  129. [
  130. emqx: fn ->
  131. %{
  132. release_type: release_type,
  133. package_type: package_type,
  134. edition_type: edition_type
  135. } = check_profile!()
  136. base_steps = [
  137. &make_docs(&1),
  138. :assemble,
  139. &create_RELEASES/1,
  140. &copy_files(&1, release_type, package_type, edition_type),
  141. &copy_escript(&1, "nodetool"),
  142. &copy_escript(&1, "install_upgrade.escript")
  143. ]
  144. steps =
  145. if System.get_env("ELIXIR_MAKE_TAR") == "yes" do
  146. base_steps ++ [&prepare_tar_overlays/1, :tar]
  147. else
  148. base_steps
  149. end
  150. [
  151. applications: applications(edition_type),
  152. skip_mode_validation_for: [
  153. :emqx_gateway,
  154. :emqx_dashboard,
  155. :emqx_resource,
  156. :emqx_connector,
  157. :emqx_exhook,
  158. :emqx_bridge,
  159. :emqx_modules,
  160. :emqx_management,
  161. :emqx_statsd,
  162. :emqx_retainer,
  163. :emqx_prometheus,
  164. :emqx_auto_subscribe,
  165. :emqx_slow_subs,
  166. :emqx_plugins
  167. ],
  168. steps: steps,
  169. strip_beams: false
  170. ]
  171. end
  172. ]
  173. end
  174. def applications(edition_type) do
  175. [
  176. crypto: :permanent,
  177. public_key: :permanent,
  178. asn1: :permanent,
  179. syntax_tools: :permanent,
  180. ssl: :permanent,
  181. os_mon: :permanent,
  182. inets: :permanent,
  183. compiler: :permanent,
  184. runtime_tools: :permanent,
  185. redbug: :permanent,
  186. xmerl: :permanent,
  187. hocon: :load,
  188. telemetry: :permanent,
  189. emqx: :load,
  190. emqx_conf: :load,
  191. emqx_machine: :permanent
  192. ] ++
  193. if(enable_rocksdb?(),
  194. do: [mnesia_rocksdb: :load],
  195. else: []
  196. ) ++
  197. [
  198. mnesia: :load,
  199. ekka: :load,
  200. emqx_plugin_libs: :load,
  201. esasl: :load,
  202. observer_cli: :permanent,
  203. tools: :load,
  204. covertool: :load,
  205. system_monitor: :load,
  206. emqx_http_lib: :permanent,
  207. emqx_resource: :permanent,
  208. emqx_connector: :permanent,
  209. emqx_authn: :permanent,
  210. emqx_authz: :permanent,
  211. emqx_auto_subscribe: :permanent,
  212. emqx_gateway: :permanent,
  213. emqx_exhook: :permanent,
  214. emqx_bridge: :permanent,
  215. emqx_rule_engine: :permanent,
  216. emqx_modules: :permanent,
  217. emqx_management: :permanent,
  218. emqx_dashboard: :permanent,
  219. emqx_retainer: :permanent,
  220. emqx_statsd: :permanent,
  221. emqx_prometheus: :permanent,
  222. emqx_psk: :permanent,
  223. emqx_slow_subs: :permanent,
  224. emqx_plugins: :permanent,
  225. emqx_mix: :none
  226. ] ++
  227. if(enable_quicer?(), do: [quicer: :permanent], else: []) ++
  228. if(enable_bcrypt?(), do: [bcrypt: :permanent], else: []) ++
  229. if(enable_jq?(), do: [jq: :load], else: []) ++
  230. if(is_app(:observer),
  231. do: [observer: :load],
  232. else: []
  233. ) ++
  234. if(edition_type == :enterprise,
  235. do: [
  236. emqx_license: :permanent,
  237. emqx_ee_conf: :load,
  238. emqx_ee_connector: :permanent,
  239. emqx_ee_bridge: :permanent
  240. ],
  241. else: []
  242. )
  243. end
  244. defp is_app(name) do
  245. case Application.load(name) do
  246. :ok ->
  247. true
  248. {:error, {:already_loaded, _}} ->
  249. true
  250. _ ->
  251. false
  252. end
  253. end
  254. def check_profile!() do
  255. valid_envs = [
  256. :dev,
  257. :emqx,
  258. :"emqx-pkg",
  259. :"emqx-enterprise",
  260. :"emqx-enterprise-pkg"
  261. ]
  262. if Mix.env() not in valid_envs do
  263. formatted_envs =
  264. valid_envs
  265. |> Enum.map(&" * #{&1}")
  266. |> Enum.join("\n")
  267. Mix.raise("""
  268. Invalid env #{Mix.env()}. Valid options are:
  269. #{formatted_envs}
  270. """)
  271. end
  272. {
  273. release_type,
  274. package_type,
  275. edition_type
  276. } =
  277. case Mix.env() do
  278. :dev ->
  279. {:cloud, :bin, :community}
  280. :emqx ->
  281. {:cloud, :bin, :community}
  282. :"emqx-enterprise" ->
  283. {:cloud, :bin, :enterprise}
  284. :"emqx-pkg" ->
  285. {:cloud, :pkg, :community}
  286. :"emqx-enterprise-pkg" ->
  287. {:cloud, :pkg, :enterprise}
  288. end
  289. normalize_env!()
  290. %{
  291. release_type: release_type,
  292. package_type: package_type,
  293. edition_type: edition_type
  294. }
  295. end
  296. #############################################################################
  297. # Custom Steps
  298. #############################################################################
  299. defp make_docs(release) do
  300. profile = System.get_env("MIX_ENV")
  301. os_cmd("build", [profile, "docs"])
  302. release
  303. end
  304. defp copy_files(release, release_type, package_type, edition_type) do
  305. overwrite? = Keyword.get(release.options, :overwrite, false)
  306. bin = Path.join(release.path, "bin")
  307. etc = Path.join(release.path, "etc")
  308. log = Path.join(release.path, "log")
  309. Mix.Generator.create_directory(bin)
  310. Mix.Generator.create_directory(etc)
  311. Mix.Generator.create_directory(log)
  312. Mix.Generator.create_directory(Path.join(etc, "certs"))
  313. Enum.each(
  314. ["mnesia", "configs", "patches", "scripts"],
  315. fn dir ->
  316. path = Path.join([release.path, "data", dir])
  317. Mix.Generator.create_directory(path)
  318. end
  319. )
  320. Mix.Generator.copy_file(
  321. "apps/emqx_authz/etc/acl.conf",
  322. Path.join(etc, "acl.conf"),
  323. force: overwrite?
  324. )
  325. # required by emqx_authz
  326. File.cp_r!(
  327. "apps/emqx/etc/certs",
  328. Path.join(etc, "certs")
  329. )
  330. profile = System.get_env("MIX_ENV")
  331. Mix.Generator.copy_file(
  332. "_build/docgen/#{profile}/emqx.conf.en.example",
  333. Path.join(etc, "emqx.conf.example"),
  334. force: overwrite?
  335. )
  336. # this is required by the produced escript / nodetool
  337. Mix.Generator.copy_file(
  338. Path.join(release.version_path, "start_clean.boot"),
  339. Path.join(bin, "no_dot_erlang.boot"),
  340. force: overwrite?
  341. )
  342. assigns = template_vars(release, release_type, package_type, edition_type)
  343. # This is generated by `scripts/merge-config.escript` or `make merge-config`
  344. # So, this should be run before the release.
  345. # TODO: run as a "compiler" step???
  346. render_template(
  347. "apps/emqx_conf/etc/emqx.conf.all",
  348. assigns,
  349. Path.join(etc, "emqx.conf")
  350. )
  351. if edition_type == :enterprise do
  352. render_template(
  353. "apps/emqx_conf/etc/emqx-enterprise.conf.all",
  354. assigns,
  355. Path.join(etc, "emqx-enterprise.conf")
  356. )
  357. end
  358. render_template(
  359. "rel/emqx_vars",
  360. assigns,
  361. Path.join([release.path, "releases", "emqx_vars"])
  362. )
  363. vm_args_template_path =
  364. case release_type do
  365. :cloud ->
  366. "apps/emqx/etc/vm.args.cloud"
  367. end
  368. render_template(
  369. vm_args_template_path,
  370. assigns,
  371. [
  372. Path.join(etc, "vm.args"),
  373. Path.join(release.version_path, "vm.args")
  374. ]
  375. )
  376. for name <- [
  377. "emqx",
  378. "emqx_ctl"
  379. ] do
  380. Mix.Generator.copy_file(
  381. "bin/#{name}",
  382. Path.join(bin, name),
  383. force: overwrite?
  384. )
  385. # Files with the version appended are expected by the release
  386. # upgrade script `install_upgrade.escript`
  387. Mix.Generator.copy_file(
  388. Path.join(bin, name),
  389. Path.join(bin, name <> "-#{release.version}"),
  390. force: overwrite?
  391. )
  392. end
  393. for base_name <- ["emqx", "emqx_ctl"],
  394. suffix <- ["", "-#{release.version}"] do
  395. name = base_name <> suffix
  396. File.chmod!(Path.join(bin, name), 0o755)
  397. end
  398. Mix.Generator.copy_file(
  399. "bin/node_dump",
  400. Path.join(bin, "node_dump"),
  401. force: overwrite?
  402. )
  403. File.chmod!(Path.join(bin, "node_dump"), 0o755)
  404. Mix.Generator.copy_file(
  405. "bin/emqx_cluster_rescue",
  406. Path.join(bin, "emqx_cluster_rescue"),
  407. force: overwrite?
  408. )
  409. File.chmod!(Path.join(bin, "emqx_cluster_rescue"), 0o755)
  410. render_template(
  411. "rel/BUILD_INFO",
  412. assigns,
  413. Path.join(release.version_path, "BUILD_INFO")
  414. )
  415. release
  416. end
  417. defp render_template(template, assigns, target) when is_binary(target) do
  418. render_template(template, assigns, [target])
  419. end
  420. defp render_template(template, assigns, tartgets) when is_list(tartgets) do
  421. rendered =
  422. File.read!(template)
  423. |> from_rebar_to_eex_template()
  424. |> EEx.eval_string(assigns)
  425. for target <- tartgets do
  426. File.write!(target, rendered)
  427. end
  428. end
  429. # needed by nodetool and by release_handler
  430. defp create_RELEASES(release) do
  431. apps =
  432. Enum.map(release.applications, fn {app_name, app_props} ->
  433. app_vsn = Keyword.fetch!(app_props, :vsn)
  434. app_path =
  435. "./lib"
  436. |> Path.join("#{app_name}-#{app_vsn}")
  437. |> to_charlist()
  438. {app_name, app_vsn, app_path}
  439. end)
  440. release_entry = [
  441. {
  442. :release,
  443. to_charlist(release.name),
  444. to_charlist(release.version),
  445. release.erts_version,
  446. apps,
  447. :permanent
  448. }
  449. ]
  450. release.path
  451. |> Path.join("releases")
  452. |> Path.join("RELEASES")
  453. |> File.open!([:write, :utf8], fn handle ->
  454. IO.puts(handle, "%% coding: utf-8")
  455. :io.format(handle, ~c"~tp.~n", [release_entry])
  456. end)
  457. release
  458. end
  459. defp copy_escript(release, escript_name) do
  460. [shebang, rest] =
  461. "bin/#{escript_name}"
  462. |> File.read!()
  463. |> String.split("\n", parts: 2)
  464. # the elixir version of escript + start.boot required the boot_var
  465. # RELEASE_LIB to be defined.
  466. boot_var = "%%!-boot_var RELEASE_LIB $RUNNER_ROOT_DIR/lib"
  467. # Files with the version appended are expected by the release
  468. # upgrade script `install_upgrade.escript`
  469. Enum.each(
  470. [escript_name, escript_name <> "-" <> release.version],
  471. fn name ->
  472. path = Path.join([release.path, "bin", name])
  473. File.write!(path, [shebang, "\n", boot_var, "\n", rest])
  474. end
  475. )
  476. release
  477. end
  478. # The `:tar` built-in step in Mix Release does not currently add the
  479. # `etc` directory into the resulting tarball. The workaround is to
  480. # add those to the `:overlays` key before running `:tar`.
  481. # See: https://hexdocs.pm/mix/1.13.4/Mix.Release.html#__struct__/0
  482. defp prepare_tar_overlays(release) do
  483. Map.update!(
  484. release,
  485. :overlays,
  486. &[
  487. "etc",
  488. "data",
  489. "bin/node_dump"
  490. | &1
  491. ]
  492. )
  493. end
  494. #############################################################################
  495. # Helper functions
  496. #############################################################################
  497. defp template_vars(release, release_type, :bin = _package_type, edition_type) do
  498. [
  499. emqx_default_erlang_cookie: default_cookie(),
  500. platform_data_dir: "data",
  501. platform_etc_dir: "etc",
  502. platform_log_dir: "log",
  503. platform_plugins_dir: "plugins",
  504. runner_bin_dir: "$RUNNER_ROOT_DIR/bin",
  505. emqx_etc_dir: "$RUNNER_ROOT_DIR/etc",
  506. runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
  507. runner_log_dir: "$RUNNER_ROOT_DIR/log",
  508. runner_user: "",
  509. release_version: release.version,
  510. erts_vsn: release.erts_version,
  511. # FIXME: this is empty in `make emqx` ???
  512. erl_opts: "",
  513. emqx_description: emqx_description(release_type, edition_type),
  514. emqx_schema_mod: emqx_schema_mod(edition_type),
  515. is_elixir: "yes",
  516. is_enterprise: if(edition_type == :enterprise, do: "yes", else: "no")
  517. ] ++ build_info()
  518. end
  519. defp template_vars(release, release_type, :pkg = _package_type, edition_type) do
  520. [
  521. emqx_default_erlang_cookie: default_cookie(),
  522. platform_data_dir: "/var/lib/emqx",
  523. platform_etc_dir: "/etc/emqx",
  524. platform_log_dir: "/var/log/emqx",
  525. platform_plugins_dir: "/var/lib/emqx/plugins",
  526. runner_bin_dir: "/usr/bin",
  527. emqx_etc_dir: "/etc/emqx",
  528. runner_lib_dir: "$RUNNER_ROOT_DIR/lib",
  529. runner_log_dir: "/var/log/emqx",
  530. runner_user: "emqx",
  531. release_version: release.version,
  532. erts_vsn: release.erts_version,
  533. # FIXME: this is empty in `make emqx` ???
  534. erl_opts: "",
  535. emqx_description: emqx_description(release_type, edition_type),
  536. emqx_schema_mod: emqx_schema_mod(edition_type),
  537. is_elixir: "yes",
  538. is_enterprise: if(edition_type == :enterprise, do: "yes", else: "no")
  539. ] ++ build_info()
  540. end
  541. defp default_cookie() do
  542. "emqx50elixir"
  543. end
  544. defp emqx_description(release_type, edition_type) do
  545. case {release_type, edition_type} do
  546. {:cloud, :enterprise} ->
  547. "EMQX Enterprise"
  548. {:cloud, :community} ->
  549. "EMQX"
  550. end
  551. end
  552. defp emqx_schema_mod(:enterprise), do: :emqx_ee_conf_schema
  553. defp emqx_schema_mod(:community), do: :emqx_conf_schema
  554. defp bcrypt_dep() do
  555. if enable_bcrypt?(),
  556. do: [{:bcrypt, github: "emqx/erlang-bcrypt", tag: "0.6.0", override: true}],
  557. else: []
  558. end
  559. defp jq_dep() do
  560. if enable_jq?(),
  561. do: [{:jq, github: "emqx/jq", tag: "v0.3.9", override: true}],
  562. else: []
  563. end
  564. defp quicer_dep() do
  565. if enable_quicer?(),
  566. # in conflict with emqx and emqtt
  567. do: [{:quicer, github: "emqx/quic", tag: "0.0.113", override: true}],
  568. else: []
  569. end
  570. defp enable_bcrypt?() do
  571. not win32?()
  572. end
  573. defp enable_jq?() do
  574. not Enum.any?([
  575. build_without_jq?(),
  576. win32?()
  577. ]) or "1" == System.get_env("BUILD_WITH_JQ")
  578. end
  579. defp enable_quicer?() do
  580. not Enum.any?([
  581. build_without_quic?(),
  582. win32?(),
  583. centos6?(),
  584. macos?()
  585. ]) or "1" == System.get_env("BUILD_WITH_QUIC")
  586. end
  587. defp enable_rocksdb?() do
  588. not Enum.any?([
  589. build_without_rocksdb?(),
  590. raspbian?()
  591. ]) or "1" == System.get_env("BUILD_WITH_ROCKSDB")
  592. end
  593. defp pkg_vsn() do
  594. %{edition_type: edition_type} = check_profile!()
  595. basedir = Path.dirname(__ENV__.file)
  596. script = Path.join(basedir, "pkg-vsn.sh")
  597. os_cmd(script, [Atom.to_string(edition_type)])
  598. end
  599. defp os_cmd(script, args) do
  600. {str, 0} = System.cmd("bash", [script | args])
  601. String.trim(str)
  602. end
  603. defp win32?(),
  604. do: match?({:win_32, _}, :os.type())
  605. defp centos6?() do
  606. case File.read("/etc/centos-release") do
  607. {:ok, "CentOS release 6" <> _} ->
  608. true
  609. _ ->
  610. false
  611. end
  612. end
  613. defp macos?() do
  614. {:unix, :darwin} == :os.type()
  615. end
  616. defp raspbian?() do
  617. os_cmd("./scripts/get-distro.sh", []) =~ "raspbian"
  618. end
  619. defp build_without_jq?() do
  620. opt = System.get_env("BUILD_WITHOUT_JQ", "false")
  621. String.downcase(opt) != "false"
  622. end
  623. defp build_without_quic?() do
  624. opt = System.get_env("BUILD_WITHOUT_QUIC", "false")
  625. String.downcase(opt) != "false"
  626. end
  627. defp build_without_rocksdb?() do
  628. opt = System.get_env("BUILD_WITHOUT_ROCKSDB", "false")
  629. String.downcase(opt) != "false"
  630. end
  631. defp from_rebar_to_eex_template(str) do
  632. # we must not consider surrounding space in the template var name
  633. # because some help strings contain informative variables that
  634. # should not be interpolated, and those have no spaces.
  635. Regex.replace(
  636. ~r/\{\{ ([a-zA-Z0-9_]+) \}\}/,
  637. str,
  638. "<%= \\g{1} %>"
  639. )
  640. end
  641. defp build_info() do
  642. [
  643. build_info_arch: to_string(:erlang.system_info(:system_architecture)),
  644. build_info_wordsize: wordsize(),
  645. build_info_os: os_cmd("./scripts/get-distro.sh", []),
  646. build_info_erlang: otp_release(),
  647. build_info_elixir: System.version(),
  648. build_info_relform: System.get_env("EMQX_REL_FORM", "tgz")
  649. ]
  650. end
  651. # https://github.com/erlang/rebar3/blob/e3108ac187b88fff01eca6001a856283a3e0ec87/src/rebar_utils.erl#L142
  652. defp wordsize() do
  653. size =
  654. try do
  655. :erlang.system_info({:wordsize, :external})
  656. rescue
  657. ErlangError ->
  658. :erlang.system_info(:wordsize)
  659. end
  660. to_string(8 * size)
  661. end
  662. defp normalize_env!() do
  663. env =
  664. case Mix.env() do
  665. :dev ->
  666. :emqx
  667. env ->
  668. env
  669. end
  670. Mix.env(env)
  671. end
  672. # As from Erlang/OTP 17, the OTP release number corresponds to the
  673. # major OTP version number. No erlang:system_info() argument gives
  674. # the exact OTP version.
  675. # https://www.erlang.org/doc/man/erlang.html#system_info_otp_release
  676. # https://github.com/erlang/rebar3/blob/e3108ac187b88fff01eca6001a856283a3e0ec87/src/rebar_utils.erl#L572-L577
  677. defp otp_release() do
  678. major_version = System.otp_release()
  679. root_dir = to_string(:code.root_dir())
  680. [root_dir, "releases", major_version, "OTP_VERSION"]
  681. |> Path.join()
  682. |> File.read()
  683. |> case do
  684. {:error, _} ->
  685. major_version
  686. {:ok, version} ->
  687. version
  688. |> String.trim()
  689. |> String.split("**")
  690. |> List.first()
  691. end
  692. end
  693. end