mirror of
https://github.com/processone/ejabberd.git
synced 2024-11-24 16:23:40 +01:00
cd30538130
The version number in ejabberd is 24.02, but Elixir requires semver, that is, 24.2. Use the version() function, which does the conversion.
419 lines
14 KiB
Elixir
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: [©_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: "⟹ 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
|