mix.exs 22 KB

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