25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-24 16:23:40 +01:00
xmpp.chapril.org-ejabberd/mix.exs
Badlop cd30538130 Fix "ejabberdctl iexlive" after "make prod" when using Elixir
The version number in ejabberd is 24.02,
but Elixir requires semver, that is, 24.2.
Use the version() function, which does the conversion.
2024-03-06 15:25:38 +01:00

419 lines
14 KiB
Elixir

defmodule Ejabberd.MixProject do
use Mix.Project
def project do
[app: :ejabberd,
source_url: "https://github.com/processone/ejabberd",
version: version(),
description: description(),
elixir: elixir_required_version(),
elixirc_paths: ["lib"],
compile_path: ".",
compilers: [:asn1, :yecc] ++ Mix.compilers(),
erlc_options: erlc_options(),
erlc_paths: ["asn1", "src"],
# Elixir tests are starting the part of ejabberd they need
aliases: [test: "test --no-start"],
start_permanent: Mix.env() == :prod,
language: :erlang,
releases: releases(),
package: package(),
docs: docs(),
deps: deps()]
end
def version do
case config(:vsn) do
:false -> "0.0.0" # ./configure wasn't run: vars.config not created
~c"0.0" -> "0.0.0" # the full git repository wasn't downloaded
~c"latest.0" -> "0.0.0" # running 'docker-ejabberd/ecs/build.sh latest'
[_, _, ?., _, _] = x ->
head = String.replace(:erlang.list_to_binary(x), ~r/\.0+([0-9])/, ".\\1")
"#{head}.0"
vsn -> String.replace(:erlang.list_to_binary(vsn), ~r/\.0+([0-9])/, ".\\1")
end
end
def description do
"""
Robust, Ubiquitous and Massively Scalable Messaging Platform (XMPP, MQTT, SIP Server)
"""
end
def application do
[mod: {:ejabberd_app, []},
applications: [:idna, :inets, :kernel, :sasl, :ssl, :stdlib, :mix,
:base64url, :fast_tls, :fast_xml, :fast_yaml, :jiffy, :jose,
:p1_utils, :stringprep, :syntax_tools, :yconf]
++ cond_apps(),
included_applications: [:mnesia, :os_mon,
:cache_tab, :eimp, :mqtree, :p1_acme,
:p1_oauth2, :pkix, :xmpp]
++ cond_included_apps()]
end
defp if_version_above(ver, okResult) do
if :erlang.system_info(:otp_release) > ver do
okResult
else
[]
end
end
defp if_version_below(ver, okResult) do
if :erlang.system_info(:otp_release) < ver do
okResult
else
[]
end
end
defp erlc_options do
# Use our own includes + includes from all dependencies
includes = ["include", deps_include()]
result = [{:d, :ELIXIR_ENABLED}] ++
cond_options() ++
Enum.map(includes, fn (path) -> {:i, path} end) ++
if_version_above(~c"20", [{:d, :DEPRECATED_GET_STACKTRACE}]) ++
if_version_above(~c"20", [{:d, :HAVE_URI_STRING}]) ++
if_version_above(~c"20", [{:d, :HAVE_ERL_ERROR}]) ++
if_version_below(~c"21", [{:d, :USE_OLD_HTTP_URI}]) ++
if_version_below(~c"22", [{:d, :LAGER}]) ++
if_version_below(~c"21", [{:d, :NO_CUSTOMIZE_HOSTNAME_CHECK}]) ++
if_version_below(~c"23", [{:d, :USE_OLD_CRYPTO_HMAC}]) ++
if_version_below(~c"23", [{:d, :USE_OLD_PG2}]) ++
if_version_below(~c"24", [{:d, :COMPILER_REPORTS_ONLY_LINES}]) ++
if_version_below(~c"24", [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) ++
if_version_below(~c"24", [{:d, :OTP_BELOW_24}]) ++
if_version_below(~c"25", [{:d, :OTP_BELOW_25}])
defines = for {:d, value} <- result, do: {:d, value}
result ++ [{:d, :ALL_DEFS, defines}]
end
defp cond_options do
for {:true, option} <- [{config(:sip), {:d, :SIP}},
{config(:stun), {:d, :STUN}},
{config(:debug), :debug_info},
{not config(:debug), {:debug_info, false}},
{config(:roster_gateway_workaround), {:d, :ROSTER_GATEWAY_WORKAROUND}},
{config(:new_sql_schema), {:d, :NEW_SQL_SCHEMA}}
], do:
option
end
defp deps do
[{:base64url, "~> 1.0"},
{:cache_tab, "~> 1.0"},
{:eimp, "~> 1.0"},
{:ex_doc, "~> 0.31", only: [:dev, :edoc], runtime: false},
{:fast_tls, ">= 1.1.18"},
{:fast_xml, ">= 1.1.51"},
{:fast_yaml, "~> 1.0"},
{:idna, "~> 6.0"},
{:jiffy, "~> 1.1.1"},
{:jose, "~> 1.11.5"},
{:mqtree, "~> 1.0"},
{:p1_acme, "~> 1.0"},
{:p1_oauth2, "~> 0.6"},
{:p1_utils, "~> 1.0"},
{:pkix, "~> 1.0"},
{:stringprep, ">= 1.0.26"},
{:xmpp, ">= 1.8.0"},
{:yconf, "~> 1.0"}]
++ cond_deps()
end
defp deps_include() do
if Mix.Project.umbrella?() do
"../../deps"
else
case Mix.Project.deps_paths()[:ejabberd] do
nil -> "deps"
_ -> ".."
end
end
end
defp cond_deps do
for {:true, dep} <- [{config(:pam), {:epam, "~> 1.0"}},
{Mix.env() == :translations,
{:ejabberd_po, git: "https://github.com/processone/ejabberd-po.git"}},
{config(:redis), {:eredis, "~> 1.2.0"}},
{config(:sip), {:esip, "~> 1.0"}},
{config(:zlib), {:ezlib, "~> 1.0"}},
{if_version_below(~c"22", true), {:lager, "~> 3.9.1"}},
{config(:lua) and if_version_below(~c"27", true),
{:luerl, "~> 1.1.1"}},
{config(:lua) and if_version_above(~c"26", true),
{:luerl, git: "https://github.com/processone/luerl", branch: "otp27"}},
{config(:mysql), {:p1_mysql, ">= 1.0.23" }},
{config(:pgsql), {:p1_pgsql, "~> 1.1"}},
{config(:sqlite), {:sqlite3, "~> 1.1"}},
{config(:stun), {:stun, "~> 1.0"}}], do:
dep
end
defp cond_apps do
for {:true, app} <- [{config(:stun), :stun},
{config(:tools), :observer}], do:
app
end
defp cond_included_apps do
for {:true, app} <- [{config(:pam), :epam},
{config(:lua), :luerl},
{config(:redis), :eredis},
{Mix.env() == :edoc, :ex_doc},
{if_version_below(~c"22", true), :lager},
{config(:mysql), :p1_mysql},
{config(:sip), :esip},
{config(:odbc), :odbc},
{config(:pgsql), :p1_pgsql},
{config(:sqlite), :sqlite3}], do:
app
end
defp package do
[# These are the default files included in the package
files: ["include", "lib", "priv", "sql", "src",
"COPYING", "README.md",
"mix.exs", "rebar.config", "rebar.config.script", "vars.config"],
maintainers: ["ProcessOne"],
licenses: ["GPL-2.0-or-later"],
links: %{"Site" => "https://www.ejabberd.im",
"Documentation" => "http://docs.ejabberd.im",
"Source" => "https://github.com/processone/ejabberd",
"ProcessOne" => "http://www.process-one.net/"}]
end
defp vars do
filepath = case Application.fetch_env(:ejabberd, :vars_config_path) do
:error ->
"vars.config"
{:ok, path} ->
path
end
config2 = case :file.consult(filepath) do
{:ok,config} -> config
_ -> [stun: true, zlib: true]
end
case Mix.env() do
:dev -> List.keystore(config2, :tools, 0, {:tools, true})
_ -> config2
end
end
defp config(key) do
case vars()[key] do
nil -> false
value -> value
end
end
defp elixir_required_version do
case {Map.get(System.get_env(), "RELIVE", "false"),
MapSet.member?(MapSet.new(System.argv()), "release")}
do
{"true", _} ->
case Version.match?(System.version(), "~> 1.11") do
false ->
IO.puts("ERROR: To use 'make relive', Elixir 1.11.0 or higher is required.")
_ -> :ok
end
"~> 1.11"
{_, true} ->
case Version.match?(System.version(), "~> 1.10") do
false ->
IO.puts("ERROR: To build releases, Elixir 1.10.0 or higher is required.")
_ -> :ok
end
case Version.match?(System.version(), "< 1.11.4")
and :erlang.system_info(:otp_release) > ~c"23" do
true ->
IO.puts("ERROR: To build releases with Elixir lower than 1.11.4, Erlang/OTP lower than 24 is required.")
_ -> :ok
end
"~> 1.10"
_ ->
"~> 1.4"
end
end
defp releases do
maybe_tar = case Mix.env() do
:prod -> [:tar]
_ -> []
end
[
ejabberd: [
include_executables_for: [:unix],
# applications: [runtime_tools: :permanent]
steps: [&copy_extra_files/1, :assemble | maybe_tar]
]
]
end
defp copy_extra_files(release) do
assigns = [
version: version(),
rootdir: config(:rootdir),
installuser: config(:installuser),
libdir: config(:libdir),
sysconfdir: config(:sysconfdir),
localstatedir: config(:localstatedir),
config_dir: config(:config_dir),
logs_dir: config(:logs_dir),
spool_dir: config(:spool_dir),
vsn: version(),
iexpath: config(:iexpath),
erl: config(:erl),
epmd: config(:epmd),
bindir: Path.join([config(:release_dir), "releases", version()]),
release_dir: config(:release_dir),
erts_dir: config(:erts_dir),
erts_vsn: "erts-#{release.erts_version}"
]
ro = "rel/overlays"
File.rm_rf(ro)
# Elixir lower than 1.12.0 don't have System.shell
execute = fn(command) ->
case function_exported?(System, :shell, 1) do
true ->
System.shell(command, into: IO.stream())
false ->
:os.cmd(to_charlist(command))
end
end
# Mix/Elixir lower than 1.11.0 use config/releases.exs instead of runtime.exs
case Version.match?(System.version(), "~> 1.11") do
true ->
:ok
false ->
execute.("cp config/runtime.exs config/releases.exs")
end
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.template > ejabberdctl.example1")
Mix.Generator.copy_template("ejabberdctl.example1", "ejabberdctl.example2", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2> ejabberdctl.example2a")
Mix.Generator.copy_template("ejabberdctl.example2a", "ejabberdctl.example2b", assigns)
execute.("sed -e 's|{{\\(\[_a-z\]*\\)}}|<%= @\\1 %>|g' ejabberdctl.example2b > ejabberdctl.example4")
execute.("sed -e 's|^ERLANG_OPTS=\"|ERLANG_OPTS=\"-boot ../releases/#{release.version}/start_clean -boot_var RELEASE_LIB ../lib |' ejabberdctl.example4 > ejabberdctl.example5")
execute.("sed -e 's|^INSTALLUSER=|ERL_OPTIONS=\"-setcookie \\$\\(cat \"\\${SCRIPT_DIR%/*}/releases/COOKIE\")\"\\nINSTALLUSER=|g' ejabberdctl.example5 > ejabberdctl.example6")
Mix.Generator.copy_template("ejabberdctl.example6", "#{ro}/bin/ejabberdctl", assigns)
File.chmod("#{ro}/bin/ejabberdctl", 0o755)
File.rm("ejabberdctl.example1")
File.rm("ejabberdctl.example2")
File.rm("ejabberdctl.example2a")
File.rm("ejabberdctl.example2b")
File.rm("ejabberdctl.example3")
File.rm("ejabberdctl.example4")
File.rm("ejabberdctl.example5")
File.rm("ejabberdctl.example6")
suffix = case Mix.env() do
:dev ->
Mix.Generator.copy_file("test/ejabberd_SUITE_data/ca.pem", "#{ro}/conf/ca.pem")
Mix.Generator.copy_file("test/ejabberd_SUITE_data/cert.pem", "#{ro}/conf/cert.pem")
".example"
_ -> ""
end
Mix.Generator.copy_file("ejabberd.yml.example", "#{ro}/conf/ejabberd.yml#{suffix}")
Mix.Generator.copy_file("ejabberdctl.cfg.example", "#{ro}/conf/ejabberdctl.cfg#{suffix}")
Mix.Generator.copy_file("inetrc", "#{ro}/conf/inetrc")
Enum.each(File.ls!("sql"),
fn x ->
Mix.Generator.copy_file("sql/#{x}", "#{ro}/lib/ejabberd-#{release.version}/priv/sql/#{x}")
end)
File.cp_r!("include", "#{ro}/lib/ejabberd-#{release.version}/include")
for {name, details} <- Map.to_list(release.applications) do
{_, is_otp_app} = List.keyfind(details, :otp_app?, 0)
{_, vsn} = List.keyfind(details, :vsn, 0)
{_, path} = List.keyfind(details, :path, 0)
source_dir = case is_otp_app do
:true -> "#{path}/include"
:false -> "deps/#{name}/include"
end
target_dir = "#{ro}/lib/#{name}-#{vsn}/include"
File.exists?(source_dir)
&& File.mkdir_p(target_dir)
&& File.cp_r!(source_dir, target_dir)
end
case Mix.env() do
:dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh mix")
_ -> :ok
end
release
end
defp docs do
[
main: "readme",
logo: "_build/edoc/logo.png",
source_ref: "master",
extra_section: "", # No need for Pages section name, it's the only one
api_reference: false, # API section has just Elixir, hide it
filter_modules: "aaaaa", # Module section has just Elixir modules, hide them
extras: [
"README.md": [title: "Readme"],
"COMPILE.md": [title: "Compile and Install"],
"CONTAINER.md": [title: "Container Image"],
"CONTRIBUTING.md": [title: "Contributing"],
"CONTRIBUTORS.md": [title: "Contributors"],
"CODE_OF_CONDUCT.md": [title: "Code of Conduct"],
"CHANGELOG.md": [title: "ChangeLog"],
"COPYING": [title: "Copying License"],
"_build/edoc/docs.md": [title: "&xrArr; ejabberd Docs"]
],
groups_for_extras: [
"": Path.wildcard("*.md") ++ ["COPYING"],
"For more documentation": "_build/edoc/docs.md"
]
]
end
end
defmodule Mix.Tasks.Compile.Asn1 do
use Mix.Task
alias Mix.Compilers.Erlang
@recursive true
@manifest ".compile.asn1"
def run(args) do
{opts, _, _} = OptionParser.parse(args, switches: [force: :boolean])
project = Mix.Project.config()
source_paths = project[:asn1_paths] || ["asn1"]
dest_paths = project[:asn1_target] || ["src"]
mappings = Enum.zip(source_paths, dest_paths)
options = project[:asn1_options] || []
force = case opts[:force] do
:true -> [force: true]
_ -> [force: false]
end
Erlang.compile(manifest(), mappings, :asn1, :erl, force, fn
input, output ->
options = options ++ [:noobj, outdir: Erlang.to_erl_file(Path.dirname(output))]
case :asn1ct.compile(Erlang.to_erl_file(input), options) do
:ok -> {:ok, :done}
error -> error
end
end)
end
def manifests, do: [manifest()]
defp manifest, do: Path.join(Mix.Project.manifest_path(), @manifest)
def clean, do: Erlang.clean(manifest())
end