diff --git a/.github/container/ejabberdctl.template b/.github/container/ejabberdctl.template index 1a8df3e12..9afc96a81 100755 --- a/.github/container/ejabberdctl.template +++ b/.github/container/ejabberdctl.template @@ -187,8 +187,8 @@ livewarning() echo "Please be extremely cautious with your actions," echo "and exit immediately if you are not completely sure." echo "" - echo "To exit this LIVE mode and stop ejabberd, press:" - echo " q(). and press the Enter key" + echo "To exit and detach this shell from ejabberd, press:" + echo " control+g and then q" echo "" echo "--------------------------------------------------------------------" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" diff --git a/.github/workflows/runtime.yml b/.github/workflows/runtime.yml index 4b62858f8..714edd269 100644 --- a/.github/workflows/runtime.yml +++ b/.github/workflows/runtime.yml @@ -33,9 +33,6 @@ jobs: matrix: otp: ['20.3', '25.3', '26'] rebar: ['rebar', 'rebar3'] - exclude: - - otp: '26' - rebar: 'rebar' runs-on: ubuntu-latest container: image: erlang:${{ matrix.otp }} @@ -44,6 +41,16 @@ jobs: - uses: actions/checkout@v4 + - name: Get compatible Rebar binaries + if: matrix.otp < 23 + run: | + rm rebar + rm rebar3 + wget https://github.com/processone/ejabberd/raw/21.12/rebar + wget https://github.com/processone/ejabberd/raw/21.12/rebar3 + chmod +x rebar + chmod +x rebar3 + - name: Prepare libraries run: | apt-get -qq update @@ -54,78 +61,224 @@ jobs: - name: Compile run: | ./autogen.sh - ./configure --with-rebar=`which ${{ matrix.rebar }}` \ + ./configure --with-rebar=${{ matrix.rebar }} \ --prefix=/tmp/ejabberd \ --enable-all \ --disable-elixir \ + --disable-tools \ --disable-odbc make update make - run: make xref - - name: Test rel (rebar2) + - name: Prepare rel (rebar2) if: matrix.rebar == 'rebar' run: | - make rel - rel/ejabberd/bin/ejabberdctl start \ - && rel/ejabberd/bin/ejabberdctl started - rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass - rel/ejabberd/bin/ejabberdctl registered_users localhost - cat rel/ejabberd/logs/* + mkdir -p _build/prod && ln -s `pwd`/rel/ _build/prod/rel + mkdir -p _build/dev && ln -s `pwd`/rel/ _build/dev/rel - - name: Test rel - if: matrix.rebar != 'rebar' + - name: Run rel run: | make rel _build/prod/rel/ejabberd/bin/ejabberdctl start \ && _build/prod/rel/ejabberd/bin/ejabberdctl started _build/prod/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass - _build/prod/rel/ejabberd/bin/ejabberdctl registered_users localhost + _build/prod/rel/ejabberd/bin/ejabberdctl registered_users localhost > registered.log _build/prod/rel/ejabberd/bin/ejabberdctl stop \ && _build/prod/rel/ejabberd/bin/ejabberdctl stopped - cat _build/prod/rel/ejabberd/logs/* - - name: Test dev - if: matrix.rebar != 'rebar' + - name: Run dev run: | make dev _build/dev/rel/ejabberd/bin/ejabberdctl start \ && _build/dev/rel/ejabberd/bin/ejabberdctl started - _build/dev/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass - _build/dev/rel/ejabberd/bin/ejabberdctl registered_users localhost + _build/dev/rel/ejabberd/bin/ejabberdctl register user2 localhost s0mePass + _build/dev/rel/ejabberd/bin/ejabberdctl registered_users localhost >> registered.log _build/dev/rel/ejabberd/bin/ejabberdctl stop \ && _build/dev/rel/ejabberd/bin/ejabberdctl stopped + + - name: Run install + run: | + make install + /tmp/ejabberd/sbin/ejabberdctl start \ + && /tmp/ejabberd/sbin/ejabberdctl started + /tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass + /tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log + /tmp/ejabberd/sbin/ejabberdctl stop \ + && /tmp/ejabberd/sbin/ejabberdctl stopped + + - name: View logs + run: | + echo "===> Registered:" + cat registered.log + echo "===> Prod:" + cat _build/prod/rel/ejabberd/logs/* + echo "===> Dev:" cat _build/dev/rel/ejabberd/logs/* + echo "===> Install:" + cat /tmp/ejabberd/var/log/ejabberd/* + + - name: Check logs + run: | + grep -q '^user1$' registered.log + grep -q '^user2$' registered.log + grep -q '^user3$' registered.log + grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log + grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log + test $(find _build/prod/rel/ -empty -name error.log) + grep -q 'is started' _build/dev/rel/ejabberd/logs/ejabberd.log + grep -q 'is stopped' _build/dev/rel/ejabberd/logs/ejabberd.log + test $(find _build/dev/rel/ -empty -name error.log) + grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + test $(find /tmp/ejabberd/var/log/ejabberd/ -empty -name error.log) + + - name: View logs failures + if: always() + run: | + cat _build/prod/rel/ejabberd/logs/ejabberd.log + cat _build/prod/rel/ejabberd/logs/error.log + cat _build/dev/rel/ejabberd/logs/ejabberd.log + cat _build/dev/rel/ejabberd/logs/error.log + cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log + cat /tmp/ejabberd/var/log/ejabberd/error.log + + rebar3-elixir: + name: Rebar3+Elixir + strategy: + fail-fast: false + matrix: + otp: ['23.0', '25.3', '26'] + elixir: ['1.13.4', '1.15.7', '1.16'] + exclude: + - otp: '23.0' + elixir: '1.15.7' + - otp: '23.0' + elixir: '1.16' + - otp: '26' + elixir: '1.13.4' + runs-on: ubuntu-20.04 + + steps: + + - uses: actions/checkout@v4 + + - name: Get specific Erlang/OTP + uses: erlef/setup-beam@v1 + with: + otp-version: ${{matrix.otp}} + elixir-version: ${{matrix.elixir}} + + - name: Prepare libraries + run: | + sudo apt-get -qq update + sudo apt-get -y purge libgd3 nginx + sudo apt-get -qq install libexpat1-dev libgd-dev libpam0g-dev \ + libsqlite3-dev libwebp-dev libyaml-dev + + - name: Enable ModPresenceDemo and an Elixir dependency + run: | + sed -i "s|^modules:|modules:\n 'ModPresenceDemo': {}|g" ejabberd.yml.example + cat ejabberd.yml.example + sed -i 's|^{deps, \(.*\)|{deps, \1\n {decimal, ".*", {git, "https://github.com/ericmj/decimal", {branch, "main"}}}, |g' rebar.config + cat rebar.config + + - name: Compile + run: | + ./autogen.sh + ./configure --with-rebar=rebar3 \ + --prefix=/tmp/ejabberd \ + --enable-all \ + --disable-odbc + make update + make + + - run: make xref + + - name: Run rel + run: | + make rel + _build/prod/rel/ejabberd/bin/ejabberdctl start \ + && _build/prod/rel/ejabberd/bin/ejabberdctl started + _build/prod/rel/ejabberd/bin/ejabberdctl register user1 localhost s0mePass + _build/prod/rel/ejabberd/bin/ejabberdctl registered_users localhost > registered.log + _build/prod/rel/ejabberd/bin/ejabberdctl stop \ + && _build/prod/rel/ejabberd/bin/ejabberdctl stopped + + - name: Run dev + run: | + make dev + _build/dev/rel/ejabberd/bin/ejabberdctl start \ + && _build/dev/rel/ejabberd/bin/ejabberdctl started + _build/dev/rel/ejabberd/bin/ejabberdctl register user2 localhost s0mePass + _build/dev/rel/ejabberd/bin/ejabberdctl registered_users localhost >> registered.log + _build/dev/rel/ejabberd/bin/ejabberdctl stop \ + && _build/dev/rel/ejabberd/bin/ejabberdctl stopped + + - name: Run install + run: | + make install + /tmp/ejabberd/sbin/ejabberdctl start \ + && /tmp/ejabberd/sbin/ejabberdctl started + /tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass + /tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log + /tmp/ejabberd/sbin/ejabberdctl stop \ + && /tmp/ejabberd/sbin/ejabberdctl stopped + + - name: View logs + if: always() + run: | + echo "===> Registered:" + cat registered.log + echo "===> Prod:" + cat _build/prod/rel/ejabberd/logs/* + echo "===> Dev:" + cat _build/dev/rel/ejabberd/logs/* + echo "===> Install:" + cat /tmp/ejabberd/var/log/ejabberd/* + + - name: Check logs + if: always() + run: | + grep -q '^user1$' registered.log + grep -q '^user2$' registered.log + grep -q '^user3$' registered.log + grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log + grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log + grep -q 'module Presence Demo' _build/prod/rel/ejabberd/logs/ejabberd.log + test $(find _build/prod/ -empty -name error.log) + grep -q 'is started' _build/dev/rel/ejabberd/logs/ejabberd.log + grep -q 'is stopped' _build/dev/rel/ejabberd/logs/ejabberd.log + grep -q 'module Presence Demo' _build/dev/rel/ejabberd/logs/ejabberd.log + test $(find _build/dev/ -empty -name error.log) + grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + grep -q 'module Presence Demo' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + test $(find /tmp/ejabberd/var/log/ejabberd/ -empty -name error.log) + + - name: View logs failures + if: failure() + run: | + cat _build/prod/rel/ejabberd/logs/ejabberd.log + cat _build/prod/rel/ejabberd/logs/error.log + cat _build/dev/rel/ejabberd/logs/ejabberd.log + cat _build/dev/rel/ejabberd/logs/error.log + cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log + cat /tmp/ejabberd/var/log/ejabberd/error.log mix: name: Mix strategy: fail-fast: false matrix: - otp: ['21.3', '25.0', '26'] - elixir: ['1.10.3', '1.11.4', '1.12.3', '1.13.4', '1.14.5', '1.15'] + otp: ['23.0', '25.3', '26'] + elixir: ['1.13.4', '1.15.7', '1.16'] exclude: - - otp: '21.3' - elixir: '1.12.3' - - otp: '21.3' - elixir: '1.13.4' - - otp: '21.3' - elixir: '1.14.5' - - otp: '21.3' - elixir: '1.15' - - otp: '25.0' - elixir: '1.10.3' - - otp: '25.0' - elixir: '1.11.4' - - otp: '25.0' - elixir: '1.12.3' - - otp: '26' - elixir: '1.10.3' - - otp: '26' - elixir: '1.11.4' - - otp: '26' - elixir: '1.12.3' + - otp: '23.0' + elixir: '1.15.7' + - otp: '23.0' + elixir: '1.16' - otp: '26' elixir: '1.13.4' runs-on: ubuntu-20.04 @@ -155,13 +308,19 @@ jobs: echo "::remove-matcher owner=elixir-mixTestFailure::" echo "::remove-matcher owner=elixir-dialyzerOutputDefault::" + - name: Enable ModPresenceDemo and an Elixir dependency + run: | + sed -i "s|^modules:|modules:\n 'ModPresenceDemo': {}|g" ejabberd.yml.example + cat ejabberd.yml.example + sed -i 's|^{deps, \(.*\)|{deps, \1\n {decimal, ".*", {git, "https://github.com/ericmj/decimal", {branch, "main"}}}, |g' rebar.config + cat rebar.config + - name: Compile run: | ./autogen.sh ./configure --with-rebar=mix \ --prefix=/tmp/ejabberd \ --enable-all \ - --disable-elixir \ --disable-odbc mix deps.get make @@ -188,17 +347,46 @@ jobs: _build/dev/rel/ejabberd/bin/ejabberdctl stop \ && _build/dev/rel/ejabberd/bin/ejabberdctl stopped - - name: Check rel + - name: Run install + run: | + make install + /tmp/ejabberd/sbin/ejabberdctl start \ + && /tmp/ejabberd/sbin/ejabberdctl started + /tmp/ejabberd/sbin/ejabberdctl register user3 localhost s0mePass + /tmp/ejabberd/sbin/ejabberdctl registered_users localhost >> registered.log + /tmp/ejabberd/sbin/ejabberdctl stop \ + && /tmp/ejabberd/sbin/ejabberdctl stopped + + - name: View logs + if: always() + run: | + echo "===> Registered:" + cat registered.log + echo "===> Prod:" + cat _build/prod/rel/ejabberd/logs/* + echo "===> Dev:" + cat _build/dev/rel/ejabberd/logs/* + echo "===> Install:" + cat /tmp/ejabberd/var/log/ejabberd/* + + - name: Check logs if: always() run: | grep -q '^user1$' registered.log grep -q '^user2$' registered.log + grep -q '^user3$' registered.log grep -q 'is started' _build/prod/rel/ejabberd/logs/ejabberd.log grep -q 'is stopped' _build/prod/rel/ejabberd/logs/ejabberd.log + grep -q 'module Presence Demo' _build/prod/rel/ejabberd/logs/ejabberd.log test $(find _build/prod/ -empty -name error.log) grep -q 'is started' _build/dev/rel/ejabberd/logs/ejabberd.log grep -q 'is stopped' _build/dev/rel/ejabberd/logs/ejabberd.log + grep -q 'module Presence Demo' _build/dev/rel/ejabberd/logs/ejabberd.log test $(find _build/dev/ -empty -name error.log) + grep -q 'is started' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + grep -q 'is stopped' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + grep -q 'module Presence Demo' /tmp/ejabberd/var/log/ejabberd/ejabberd.log + test $(find /tmp/ejabberd/var/log/ejabberd/ -empty -name error.log) - name: View logs failures if: failure() @@ -207,3 +395,5 @@ jobs: cat _build/prod/rel/ejabberd/logs/error.log cat _build/dev/rel/ejabberd/logs/ejabberd.log cat _build/dev/rel/ejabberd/logs/error.log + cat /tmp/ejabberd/var/log/ejabberd/ejabberd.log + cat /tmp/ejabberd/var/log/ejabberd/error.log diff --git a/COMPILE.md b/COMPILE.md index c6b10800a..80e932d65 100644 --- a/COMPILE.md +++ b/COMPILE.md @@ -28,7 +28,8 @@ Other optional libraries are: - PAM library, for Pluggable Authentication Modules (PAM) - ImageMagick's Convert program and Ghostscript fonts, for CAPTCHA challenges -- Elixir ≥ 1.10.3, to support Elixir, and alternative to rebar/rebar3 +- Elixir ≥ 1.10.3, for Elixir support. It is recommended Elixir 1.13.4 or higher + and Erlang/OTP 23.0 or higher. If your system splits packages in libraries and development headers, install the development packages too. @@ -89,7 +90,7 @@ Build an OTP Release Instead of installing ejabberd in the system, you can build an OTP release that includes all necessary to run ejabberd in a subdirectory: - ./configure --with-rebar=rebar3 + ./configure make rel Or, if you have Elixir available and plan to develop Elixir code: diff --git a/Makefile.in b/Makefile.in index c56070eec..c287cbbd9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,12 @@ +#. +#' definitions +# + REBAR = @ESCRIPT@ @rebar@ MIX = @rebar@ +AWK = @AWK@ INSTALL = @INSTALL@ +MKDIR_P = @MKDIR_P@ SED = @SED@ ERL = @ERL@ @@ -71,6 +77,10 @@ SPOOLDIR = @localstatedir@/lib/ejabberd # /var/log/ejabberd/ LOGDIR = @localstatedir@/log/ejabberd +#. +#' install user +# + INSTALLUSER=@INSTALLUSER@ # if no user was enabled, don't set privileges or ownership ifeq ($(INSTALLUSER),) @@ -92,14 +102,20 @@ ifneq ($(INSTALLGROUP),) G_USER=-g $(INSTALLGROUP) endif -ifeq "$(MIX)" "mix" +#. +#' rebar / rebar3 / mix +# + +ifeq "$(notdir $(MIX))" "mix" REBAR_VER:=6 REBAR_VER_318:=0 else -REBAR_VER:=$(shell $(REBAR) --version | awk -F '[ .]' '/rebar / {print $$2}') -REBAR_VER_318:=$(shell $(REBAR) --version | awk -F '[ .]' '/rebar / {print ($$2 == 3 && $$3 >= 18 ? 1 : 0)}') +REBAR_VER:=$(shell $(REBAR) --version | $(AWK) -F '[ .]' '/rebar / {print $$2}') +REBAR_VER_318:=$(shell $(REBAR) --version | $(AWK) -F '[ .]' '/rebar / {print ($$2 == 3 && $$3 >= 18 ? 1 : 0)}') endif +REBAR_ENABLE_ELIXIR = @elixir@ + ifeq "$(REBAR_VER)" "6" REBAR=$(MIX) SKIPDEPS= @@ -113,10 +129,20 @@ ifeq "$(REBAR_VER)" "6" EBINDIR=$(DEPSDIR)/ejabberd/ebin XREFOPTIONS=graph CLEANARG=--deps + ELIXIR_LIBDIR_RAW=$(shell elixir -e "IO.puts(:filename.dirname(:code.lib_dir(:elixir)))" -e ":erlang.halt") + ELIXIR_LIBDIR=":$(ELIXIR_LIBDIR_RAW)" REBARREL=MIX_ENV=prod $(REBAR) release --overwrite REBARDEV=MIX_ENV=dev $(REBAR) release --overwrite RELIVECMD=escript rel/relive.escript && MIX_ENV=dev RELIVE=true iex --name ejabberd@localhost -S mix run + REL_LIB_DIR = _build/dev/rel/ejabberd/lib + COPY_REL_TARGET = dev else +ifeq ($(REBAR_ENABLE_ELIXIR),true) + ELIXIR_LIBDIR_RAW=$(shell elixir -e "IO.puts(:filename.dirname(:code.lib_dir(:elixir)))" -e ":erlang.halt") + ELIXIR_LIBDIR=":$(ELIXIR_LIBDIR_RAW)" + EXPLICIT_ELIXIR_COMPILE=MIX_ENV=default mix compile.elixir + PREPARE_ELIXIR_SCRIPTS=$(MKDIR_P) rel/overlays; cp $(ELIXIR_LIBDIR_RAW)/../bin/iex rel/overlays/; cp $(ELIXIR_LIBDIR_RAW)/../bin/elixir rel/overlays/; sed -i 's|ERTS_BIN=$$|ERTS_BIN=$$SCRIPT_PATH/../../erts-{{erts_vsn}}/bin/|' rel/overlays/elixir +endif ifeq "$(REBAR_VER)" "3" SKIPDEPS= LISTDEPS=tree @@ -136,6 +162,8 @@ endif REBARREL=$(REBAR) as prod tar REBARDEV=REBAR_PROFILE=dev $(REBAR) release RELIVECMD=$(REBAR) relive + REL_LIB_DIR = _build/dev/rel/ejabberd/lib + COPY_REL_TARGET = dev else SKIPDEPS=skip_deps=true LISTDEPS=-q list-deps @@ -152,9 +180,15 @@ else REBARDEV= RELIVECMD=@echo "Rebar2 detected... relive not supported.\ \nTry: ./configure --with-rebar=./rebar3 ; make relive" + REL_LIB_DIR = rel/ejabberd/lib + COPY_REL_TARGET = rel endif endif +#. +#' main targets +# + all: scripts deps src deps: $(DEPSDIR)/.got @@ -162,7 +196,7 @@ deps: $(DEPSDIR)/.got $(DEPSDIR)/.got: rm -rf $(DEPSDIR)/.got rm -rf $(DEPSDIR)/.built - mkdir -p $(DEPSDIR) + $(MKDIR_P) $(DEPSDIR) $(REBAR) $(GET_DEPS) && :> $(DEPSDIR)/.got $(CONFIGURE_DEPS) @@ -171,6 +205,7 @@ $(DEPSDIR)/.built: $(DEPSDIR)/.got src: $(DEPSDIR)/.built $(REBAR) $(SKIPDEPS) compile + $(EXPLICIT_ELIXIR_COMPILE) update: rm -rf $(DEPSDIR)/.got @@ -197,6 +232,10 @@ edoc: $(ERL) -noinput +B -eval \ 'case edoc:application(ejabberd, ".", []) of ok -> halt(0); error -> halt(1) end.' +#. +#' copy-files +# + JOIN_PATHS=$(if $(wordlist 2,1000,$(1)),$(firstword $(1))/$(call JOIN_PATHS,$(wordlist 2,1000,$(1))),$(1)) VERSIONED_DEP=$(if $(DEP_$(1)_VERSION),$(DEP_$(1)_VERSION),$(1)) @@ -282,24 +321,54 @@ copy-files: copy-files-sub: copy-files-sub2 +#. +#' copy-files-rel +# + +copy-files-rel: $(COPY_REL_TARGET) + # + # Libraries + (cd $(REL_LIB_DIR) && find . -follow -type f ! -executable -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;) + # + # *.so: + (cd $(REL_LIB_DIR) && find . -follow -type f -executable -name *.so -exec $(INSTALL) -vDm 640 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;) + # + # Executable files + (cd $(REL_LIB_DIR) && find . -follow -type f -executable ! -name *.so -exec $(INSTALL) -vDm 550 $(G_USER) {} $(DESTDIR)$(LIBDIR)/{} \;) + +#. +#' uninstall-librel +# + +uninstall-librel: + (cd $(REL_LIB_DIR) && find . -follow -type f -exec rm -fv -v $(DESTDIR)$(LIBDIR)/{} \;) + (cd $(REL_LIB_DIR) && find . -follow -depth -type d -exec rm -dv -v $(DESTDIR)$(LIBDIR)/{} \;) + +#. +#' relive +# + relive: $(RELIVECMD) relivelibdir=$(shell pwd)/$(DEPSDIR) relivedir=$(shell pwd)/_build/relive -iexpath=$(shell which iex) CONFIG_DIR = ${relivedir}/conf SPOOL_DIR = ${relivedir}/database LOGS_DIR = ${relivedir}/logs +#. +#' scripts +# + ejabberdctl.relive: $(SED) -e "s*{{installuser}}*@INSTALLUSER@*g" \ -e "s*{{config_dir}}*${CONFIG_DIR}*g" \ -e "s*{{logs_dir}}*${LOGS_DIR}*g" \ -e "s*{{spool_dir}}*${SPOOL_DIR}*g" \ - -e "s*{{bindir}}/iex*$(iexpath)*g" \ -e "s*{{bindir}}*@bindir@*g" \ - -e "s*{{libdir}}*${relivelibdir}*g" \ + -e "s*{{libdir}}*${relivelibdir}${ELIXIR_LIBDIR}*g" \ + -e "s*{{iexpath}}*@IEX@*g" \ -e "s*{{erl}}*@ERL@*g" \ -e "s*{{epmd}}*@EPMD@*g" ejabberdctl.template \ > ejabberdctl.relive @@ -322,14 +391,23 @@ ejabberdctl.example: vars.config -e "s*{{logs_dir}}*${LOGDIR}*g" \ -e "s*{{spool_dir}}*${SPOOLDIR}*g" \ -e "s*{{bindir}}*@bindir@*g" \ - -e "s*{{libdir}}*@libdir@*g" \ + -e "s*{{libdir}}*@libdir@${ELIXIR_LIBDIR}*g" \ + -e "s*{{iexpath}}*@IEX@*g" \ -e "s*{{erl}}*@ERL@*g" \ -e "s*{{epmd}}*@EPMD@*g" ejabberdctl.template \ > ejabberdctl.example scripts: ejabberd.init ejabberd.service ejabberdctl.example -install: copy-files +#. +#' install +# + +install: copy-files install-main + +install-rel: copy-files-rel install-main + +install-main: # # Configuration files $(INSTALL) -d -m 750 $(G_USER) $(DESTDIR)$(ETCDIR) @@ -368,8 +446,14 @@ install: copy-files || echo "Man page not included in sources" $(INSTALL) -m 644 COPYING $(DESTDIR)$(DOCDIR) +#. +#' uninstall +# + uninstall: uninstall-binary +uninstall-rel: uninstall-binary uninstall-librel + uninstall-binary: rm -f $(DESTDIR)$(SBINDIR)/ejabberdctl rm -f $(DESTDIR)$(BINDIR)/iex @@ -398,6 +482,7 @@ uninstall-binary: rm -fr $(DESTDIR)$(LUADIR) rm -fr $(DESTDIR)$(PRIVDIR) rm -fr $(DESTDIR)$(EJABBERDDIR) + rm -f $(DESTDIR)$(MANDIR)/ejabberd.yml.5 uninstall-all: uninstall-binary rm -rf $(DESTDIR)$(ETCDIR) @@ -405,6 +490,10 @@ uninstall-all: uninstall-binary rm -rf $(DESTDIR)$(SPOOLDIR) rm -rf $(DESTDIR)$(LOGDIR) +#. +#' clean +# + clean: rm -rf $(DEPSDIR)/.got rm -rf $(DEPSDIR)/.built @@ -427,19 +516,39 @@ distclean: clean clean-rel rm -f Makefile rm -f vars.config -rel: +#. +#' releases +# + +rel: prod + +prod: + $(PREPARE_ELIXIR_SCRIPTS) $(REBARREL) DEV_CONFIG = _build/dev/rel/ejabberd/conf/ejabberd.yml dev $(DEV_CONFIG): + $(PREPARE_ELIXIR_SCRIPTS) $(REBARDEV) +#. +#' tags +# + TAGS: - etags *.erl + etags src/*.erl + +#. +#' makefile +# Makefile: Makefile.in +#. +#' dialyzer +# + ifeq "$(REBAR_VER)" "3" dialyzer: find src/*_opt.erl -type f \! -regex ".*git.*" -exec sed -i 's/re:mp/ tuple/g' {} \; @@ -449,7 +558,7 @@ else deps := $(wildcard $(DEPSDIR)/*/ebin) dialyzer/erlang.plt: - @mkdir -p dialyzer + @$(MKDIR_P) dialyzer @dialyzer --build_plt --output_plt dialyzer/erlang.plt \ -o dialyzer/erlang.log --apps kernel stdlib sasl crypto \ public_key ssl mnesia inets odbc compiler erts \ @@ -457,13 +566,13 @@ dialyzer/erlang.plt: status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi dialyzer/deps.plt: - @mkdir -p dialyzer + @$(MKDIR_P) dialyzer @dialyzer --build_plt --output_plt dialyzer/deps.plt \ -o dialyzer/deps.log $(deps); \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi dialyzer/ejabberd.plt: - @mkdir -p dialyzer + @$(MKDIR_P) dialyzer @dialyzer --build_plt --output_plt dialyzer/ejabberd.plt \ -o dialyzer/ejabberd.log ebin; \ status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi @@ -486,6 +595,10 @@ dialyzer: erlang_plt deps_plt ejabberd_plt status=$$? ; if [ $$status -ne 2 ]; then exit $$status; else exit 0; fi endif +#. +#' test +# + test: @echo "************************** NOTICE ***************************************" @cat test/README @@ -493,9 +606,18 @@ test: @cd priv && ln -sf ../sql $(REBAR) $(SKIPDEPS) ct -.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean rel \ +#. +#' phony +# + +.PHONY: src edoc dialyzer Makefile TAGS clean clean-rel distclean prod rel \ install uninstall uninstall-binary uninstall-all translations deps test \ - quicktest erlang_plt deps_plt ejabberd_plt xref hooks options + all dev doap help install-rel relive scripts uninstall-rel update \ + erlang_plt deps_plt ejabberd_plt xref hooks options + +#. +#' help +# help: @echo "" @@ -508,10 +630,12 @@ help: @echo " distclean Clean completely the development files" @echo "" @echo " install Install ejabberd to /usr/local" + @echo " install-rel Install ejabberd to /usr/local (using release)" @echo " uninstall Uninstall ejabberd (buggy)" + @echo " uninstall-rel Uninstall ejabberd (using release)" @echo " uninstall-all Uninstall also configuration, logs, mnesia... (buggy)" @echo "" - @echo " rel Build a production release" + @echo " prod Build a production release" @echo " dev Build a development release" @echo " relive Start a live ejabberd in _build/relive/" @echo "" @@ -519,9 +643,13 @@ help: @echo " edoc Generate edoc documentation (unused)" @echo " options Generate ejabberd_option.erl" @echo " translations Extract translation files (requires --enable-tools)" - @echo " tags Generate tags file for text editors" + @echo " TAGS Generate tags file for text editors" @echo "" @echo " dialyzer Run Dialyzer static analyzer" @echo " hooks Run hooks validator" @echo " test Run Common Tests suite" @echo " xref Run cross reference analysis" + +#. +#' +# vim: foldmarker=#',#. foldmethod=marker: diff --git a/config/runtime.exs b/config/runtime.exs index b4e6dc5f1..fb2372ea6 100644 --- a/config/runtime.exs +++ b/config/runtime.exs @@ -8,6 +8,6 @@ end rootpath = System.get_env("RELEASE_ROOT", rootdefault) config :ejabberd, file: Path.join(rootpath, "conf/ejabberd.yml"), - log_path: Path.join(rootpath, 'logs/ejabberd.log') + log_path: Path.join(rootpath, "logs/ejabberd.log") config :mnesia, - dir: Path.join(rootpath, 'database/') + dir: Path.join(rootpath, "database/") diff --git a/configure.ac b/configure.ac index 33913d181..065047cb9 100644 --- a/configure.ac +++ b/configure.ac @@ -10,7 +10,9 @@ AC_CONFIG_MACRO_DIR([m4]) # Checks for programs. AC_PROG_MAKE_SET +AC_PROG_AWK AC_PROG_INSTALL +AC_PROG_MKDIR_P AC_PROG_SED if test "x$GCC" = "xyes"; then @@ -28,18 +30,35 @@ fi ]) AC_ARG_WITH(rebar, - AS_HELP_STRING([--with-rebar=bin],[use the rebar/rebar3/mix binary specified]), + AS_HELP_STRING([--with-rebar=bin],[use as build tool the rebar/rebar3/mix binary specified]), [if test "$withval" = "yes" -o "$withval" = "no" -o "X$with_rebar" = "X"; then - rebar="rebar" + rebar="rebar3" else rebar="$with_rebar" fi -], [rebar="rebar"]) +], [rebar="unconfigured"]) AC_PATH_TOOL(ERL, erl, , [${extra_erl_path}$PATH]) AC_PATH_TOOL(ERLC, erlc, , [${extra_erl_path}$PATH]) AC_PATH_TOOL(EPMD, epmd, , [${extra_erl_path}$PATH]) +AC_PATH_TOOL(REBAR3, rebar3, , [${extra_erl_path}$PATH]) +AC_PATH_TOOL(ELIXIR, elixir, , [${extra_erl_path}$PATH]) +AC_PATH_TOOL(IEX, iex, , [${extra_erl_path}$PATH]) +AC_PATH_TOOL(MIX, mix, , [${extra_erl_path}$PATH]) + +if test "$rebar" = unconfigured; then + if test "x$ELIXIR" = "x" -o "x$IEX" = "x" -o "x$MIX" = "x"; then + if test "x$REBAR3" = "x"; then + rebar="rebar3" + else + rebar=$REBAR3 + fi + else + rebar=$MIX + fi +fi + AC_ERLANG_NEED_ERL AC_ERLANG_NEED_ERLC @@ -84,7 +103,7 @@ AC_ARG_ENABLE(debug, esac],[if test "x$debug" = "x"; then debug=true; fi]) AC_ARG_ENABLE(elixir, -[AS_HELP_STRING([--enable-elixir],[enable Elixir support (default: no)])], +[AS_HELP_STRING([--enable-elixir],[enable Elixir support in Rebar3 (default: no)])], [case "${enableval}" in yes) elixir=true ;; no) elixir=false ;; @@ -237,7 +256,7 @@ AC_ARG_ENABLE(system_deps, esac],[if test "x$system_deps" = "x"; then system_deps=false; fi]) AC_ARG_ENABLE(tools, -[AS_HELP_STRING([--enable-tools],[build development tools (default: no)])], +[AS_HELP_STRING([--enable-tools],[build development tools: ejabberd-po, etop (default: no)])], [case "${enableval}" in yes) tools=true ;; no) tools=false ;; @@ -280,6 +299,8 @@ case "`uname`" in ;; esac +AC_MSG_RESULT([build tool to use (change using --with-rebar): $rebar]) + AC_SUBST(roster_gateway_workaround) AC_SUBST(new_sql_schema) AC_SUBST(full_xml) diff --git a/ejabberdctl.template b/ejabberdctl.template index 0e221f473..eb16e3839 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -15,8 +15,8 @@ SCRIPT_DIR="$(cd "$(dirname "$SCRIPT")" && pwd -P)" # shellcheck disable=SC2034 ERTS_VSN="{{erts_vsn}}" ERL="{{erl}}" -IEX="{{bindir}}/iex" EPMD="{{epmd}}" +IEX="{{iexpath}}" INSTALLUSER="{{installuser}}" # check the proper system user is used @@ -175,8 +175,8 @@ livewarning() echo "Please be extremely cautious with your actions," echo "and exit immediately if you are not completely sure." echo "" - echo "To exit this LIVE mode and stop ejabberd, press:" - echo " q(). and press the Enter key" + echo "To exit and detach this shell from ejabberd, press:" + echo " control+g and then q" echo "" echo "--------------------------------------------------------------------" echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" @@ -187,6 +187,39 @@ livewarning() fi } +check_etop_result() +{ + result=$? + if [ $result -eq 1 ] ; then + echo "" + echo "It seems there was some problem running 'ejabberdctl etop'." + echo "Is the error message something like this?" + echo " Failed to load module 'etop' because it cannot be found..." + echo "Then probably ejabberd was compiled with development tools disabled." + echo "To use 'etop', recompile ejabberd with: ./configure --enable-tools" + echo "" + exit $result + fi +} + +check_iex_result() +{ + result=$? + if [ $result -eq 127 ] ; then + echo "" + echo "It seems there was some problem finding 'iex' binary from Elixir." + echo "Probably ejabberd was compiled with Rebar3 and Elixir disabled, like:" + echo " ./configure" + echo "which is equivalent to:" + echo " ./configure --with-rebar=rebar3 --disable-elixir" + echo "To use 'iex', recompile ejabberd enabling Elixir or using Mix:" + echo " ./configure --enable-elixir" + echo " ./configure --with-rebar=mix" + echo "" + exit $result + fi +} + help() { echo "" @@ -310,15 +343,18 @@ case $1 in set_dist_client exec_erl "$(uid top)" -hidden -remsh "$ERLANG_NODE" -s etop \ -output text + check_etop_result ;; iexdebug) debugwarning set_dist_client exec_iex "$(uid debug)" --remsh "$ERLANG_NODE" + check_iex_result ;; iexlive) livewarning exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" + check_iex_result ;; ping) PEER=${2:-$ERLANG_NODE} diff --git a/lib/ejabberd/config/ejabberd_module.ex b/lib/ejabberd/config/ejabberd_module.ex index 6a74fe460..57fd8303c 100644 --- a/lib/ejabberd/config/ejabberd_module.ex +++ b/lib/ejabberd/config/ejabberd_module.ex @@ -60,7 +60,7 @@ defmodule Ejabberd.Config.EjabberdModule do defp fetch_and_store_repo_source_if_not_exists(path, repo) do unless File.exists?(path) do IO.puts "[info] Fetching: #{repo}" - :os.cmd('git clone #{repo} #{path}') + :os.cmd(~c"git clone #{repo} #{path}") end end diff --git a/lib/mod_presence_demo.ex b/lib/mod_presence_demo.ex index f41a53a31..c5be5bba5 100644 --- a/lib/mod_presence_demo.ex +++ b/lib/mod_presence_demo.ex @@ -2,19 +2,19 @@ defmodule ModPresenceDemo do use Ejabberd.Module def start(host, _opts) do - info('Starting ejabberd module Presence Demo') + info("Starting ejabberd module Presence Demo") Ejabberd.Hooks.add(:set_presence_hook, host, __MODULE__, :on_presence, 50) :ok end def stop(host) do - info('Stopping ejabberd module Presence Demo') + info("Stopping ejabberd module Presence Demo") Ejabberd.Hooks.delete(:set_presence_hook, host, __MODULE__, :on_presence, 50) :ok end def on_presence(user, _server, _resource, _packet) do - info('Receive presence for #{user}') + info("Receive presence for #{user}") :none end @@ -27,7 +27,7 @@ defmodule ModPresenceDemo do end def mod_doc() do - %{:desc => 'This is just a demonstration.'} + %{:desc => "This is just a demonstration."} end end diff --git a/mix.exs b/mix.exs index c1af5a18a..8227791b9 100644 --- a/mix.exs +++ b/mix.exs @@ -8,7 +8,7 @@ defmodule Ejabberd.MixProject do elixir: elixir_required_version(), elixirc_paths: ["lib"], compile_path: ".", - compilers: [:asn1] ++ Mix.compilers(), + compilers: [:asn1, :yecc] ++ Mix.compilers(), erlc_options: erlc_options(), erlc_paths: ["asn1", "src"], # Elixir tests are starting the part of ejabberd they need @@ -23,11 +23,11 @@ defmodule Ejabberd.MixProject do def version do case config(:vsn) do :false -> "0.0.0" # ./configure wasn't run: vars.config not created - '0.0' -> "0.0.0" # the full git repository wasn't downloaded - 'latest.0' -> "0.0.0" # running 'docker-ejabberd/ecs/build.sh latest' + ~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 @@ -40,14 +40,14 @@ defmodule Ejabberd.MixProject do def application do [mod: {:ejabberd_app, []}, - extra_applications: [:mix], - applications: [:idna, :inets, :kernel, :sasl, :ssl, :stdlib, + applications: [:idna, :inets, :kernel, :sasl, :ssl, :stdlib, :mix, :base64url, :fast_tls, :fast_xml, :fast_yaml, :jiffy, :jose, - :p1_utils, :stringprep, :syntax_tools, :yconf], + :p1_utils, :stringprep, :syntax_tools, :yconf] + ++ cond_apps(), included_applications: [:mnesia, :os_mon, :cache_tab, :eimp, :mqtree, :p1_acme, :p1_oauth2, :pkix, :xmpp] - ++ cond_apps()] + ++ cond_included_apps()] end defp if_version_above(ver, okResult) do @@ -68,20 +68,20 @@ defmodule Ejabberd.MixProject do defp erlc_options do # Use our own includes + includes from all dependencies - includes = ["include"] ++ deps_include(["fast_xml", "xmpp", "p1_utils"]) + includes = ["include", deps_include()] result = [{:d, :ELIXIR_ENABLED}] ++ cond_options() ++ Enum.map(includes, fn (path) -> {:i, path} end) ++ - if_version_above('20', [{:d, :DEPRECATED_GET_STACKTRACE}]) ++ - if_version_above('20', [{:d, :HAVE_URI_STRING}]) ++ - if_version_above('20', [{:d, :HAVE_ERL_ERROR}]) ++ - if_version_below('21', [{:d, :USE_OLD_HTTP_URI}]) ++ - if_version_below('22', [{:d, :LAGER}]) ++ - if_version_below('21', [{:d, :NO_CUSTOMIZE_HOSTNAME_CHECK}]) ++ - if_version_below('23', [{:d, :USE_OLD_CRYPTO_HMAC}]) ++ - if_version_below('23', [{:d, :USE_OLD_PG2}]) ++ - if_version_below('24', [{:d, :COMPILER_REPORTS_ONLY_LINES}]) ++ - if_version_below('24', [{:d, :SYSTOOLS_APP_DEF_WITHOUT_OPTIONAL}]) + 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}]) defines = for {:d, value} <- result, do: {:d, value} result ++ [{:d, :ALL_DEFS, defines}] end @@ -119,8 +119,8 @@ defmodule Ejabberd.MixProject do ++ cond_deps() end - defp deps_include(deps) do - base = if Mix.Project.umbrella?() do + defp deps_include() do + if Mix.Project.umbrella?() do "../../deps" else case Mix.Project.deps_paths()[:ejabberd] do @@ -128,7 +128,6 @@ defmodule Ejabberd.MixProject do _ -> ".." end end - Enum.map(deps, fn dep -> base<>"/#{dep}/include" end) end defp cond_deps do @@ -136,7 +135,7 @@ defmodule Ejabberd.MixProject do {config(:redis), {:eredis, "~> 1.2.0"}}, {config(:sip), {:esip, "~> 1.0"}}, {config(:zlib), {:ezlib, "~> 1.0"}}, - {if_version_below('22', true), {:lager, "~> 3.9.1"}}, + {if_version_below(~c"22", true), {:lager, "~> 3.9.1"}}, {config(:lua), {:luerl, "~> 1.0"}}, {config(:mysql), {:p1_mysql, git: "https://github.com/processone/p1_mysql.git", ref: "f685408b910c425b9905d4ddcdbedba717a5b48c"}}, {config(:pgsql), {:p1_pgsql, "~> 1.1"}}, @@ -146,10 +145,17 @@ defmodule Ejabberd.MixProject do end defp cond_apps do + for {:true, app} <- [{config(:stun), :stun}, + {config(:tools), :observer}, + {config(:tools), :runtime_tools}], do: + app + end + + defp cond_included_apps do for {:true, app} <- [{config(:pam), :epam}, {config(:lua), :luerl}, {config(:redis), :eredis}, - {if_version_below('22', true), :lager}, + {if_version_below(~c"22", true), :lager}, {config(:mysql), :p1_mysql}, {config(:sip), :esip}, {config(:odbc), :odbc}, @@ -172,9 +178,15 @@ defmodule Ejabberd.MixProject do end defp vars do - case :file.consult("vars.config") do + filepath = case Application.fetch_env(:ejabberd, :vars_config_path) do + :error -> + "vars.config" + {:ok, path} -> + path + end + case :file.consult(filepath) do {:ok,config} -> config - _ -> [zlib: true] + _ -> [stun: true, zlib: true] end end @@ -203,7 +215,7 @@ defmodule Ejabberd.MixProject do _ -> :ok end case Version.match?(System.version(), "< 1.11.4") - and :erlang.system_info(:otp_release) > '23' do + 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 @@ -239,6 +251,8 @@ defmodule Ejabberd.MixProject do config_dir: config(:config_dir), logs_dir: config(:logs_dir), spool_dir: config(:spool_dir), + vsn: config(:vsn), + iexpath: config(:iexpath), erl: config(:erl), epmd: config(:epmd), bindir: Path.join([config(:release_dir), "releases", version()]), @@ -253,7 +267,7 @@ defmodule Ejabberd.MixProject do execute = fn(command) -> case function_exported?(System, :shell, 1) do true -> - System.shell(command) + System.shell(command, into: IO.stream()) false -> :os.cmd(to_charlist(command)) end @@ -319,7 +333,7 @@ defmodule Ejabberd.MixProject do end case Mix.env() do - :dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh") + :dev -> execute.("REL_DIR_TEMP=$PWD/rel/overlays/ rel/setup-dev.sh mix") _ -> :ok end diff --git a/rebar b/rebar index b6f011846..0b6871e70 100755 Binary files a/rebar and b/rebar differ diff --git a/rebar.config b/rebar.config index bca63ad41..6a715b586 100644 --- a/rebar.config +++ b/rebar.config @@ -27,8 +27,6 @@ {eimp, ".*", {git, "https://github.com/processone/eimp", {tag, "1.0.22"}}}, {if_var_true, tools, {ejabberd_po, ".*", {git, "https://github.com/processone/ejabberd-po", {branch, "main"}}}}, - {if_var_true, elixir, - {elixir, ".*", {git, "https://github.com/elixir-lang/elixir", {tag, "v1.4.4"}}}}, {if_var_true, pam, {epam, ".*", {git, "https://github.com/processone/epam", {tag, "1.0.14"}}}}, {if_var_true, redis, @@ -69,9 +67,6 @@ {p1_pgsql, ".*", {git, "https://github.com/processone/p1_pgsql", {tag, "1.1.23"}}}}, {p1_utils, ".*", {git, "https://github.com/processone/p1_utils", {tag, "1.0.25"}}}, {pkix, ".*", {git, "https://github.com/processone/pkix", {tag, "1.0.9"}}}, - {if_not_rebar3, %% Needed because modules are not fully migrated to new structure and mix - {if_var_true, elixir, - {rebar_elixir_plugin, ".*", {git, "https://github.com/processone/rebar_elixir_plugin", "0.1.0"}}}}, {if_var_true, sqlite, {sqlite3, ".*", {git, "https://github.com/processone/erlang-sqlite3", {tag, "1.1.14"}}}}, {stringprep, ".*", {git, "https://github.com/processone/stringprep", {tag, "1.0.29"}}}, @@ -81,7 +76,7 @@ {yconf, ".*", {git, "https://github.com/processone/yconf", {tag, "1.0.15"}}} ]}. -{gitonly_deps, [elixir]}. +{gitonly_deps, [ejabberd_po]}. {if_var_true, latest_deps, {floating_deps, [cache_tab, @@ -146,23 +141,26 @@ {if_var_true, stun, {d, 'STUN'}}, {src_dirs, [src, {if_rebar3, sql}, - {if_var_true, tools, tools}, - {if_var_true, elixir, include}]}]}. + {if_var_true, tools, tools}]}]}. -{if_rebar3, {plugins, [rebar3_hex, {provider_asn1, "0.2.0"}]}}. +{if_rebar3, {plugins, [rebar3_hex, {provider_asn1, "0.2.0"}, + %% Protocol consolidation doesn't work correctly in upstream rebar_mix, see + %% https://github.com/Supersonido/rebar_mix/issues/27#issuecomment-894873335 + %% Let's use this fixed rebar_mix fork, see its PR: + %% https://github.com/Supersonido/rebar_mix/pull/31 + {if_var_true, elixir, {rebar_mix, ".*", + {git, "https://github.com/bsanyi/rebar_mix.git", + {branch, "consolidation_fix"}}} + }]}}. {if_rebar3, {project_plugins, [configure_deps]}}. {if_not_rebar3, {plugins, [ - deps_erl_opts, override_deps_versions2, override_opts, configure_deps, - {if_var_true, elixir, rebar_elixir_compiler}, - {if_var_true, elixir, rebar_exunit} + deps_erl_opts, override_deps_versions2, override_opts, configure_deps ]}}. {if_rebar3, {if_var_true, elixir, - {project_app_dirs, [".", "elixir/lib"]}}}. -{if_not_rebar3, {if_var_true, elixir, - {lib_dirs, ["deps/elixir/lib"]}}}. -{if_var_true, elixir, - {src_dirs, ["include"]}}. + {provider_hooks, [ + {post, [{compile, {mix, consolidate_protocols}}]} + ]}}}. {sub_dirs, ["rel"]}. @@ -255,6 +253,12 @@ {mkdir, "conf"}, {copy, "rel/files/erl", "erts-\{\{erts_vsn\}\}/bin/erl"}, {template, "ejabberdctl.template", "bin/ejabberdctl"}, + {copy, "_build/default/lib/ejabberd/ebin/Elixir.*", "lib/ejabberd-{{release_version}}/ebin/"}, + {copy, "{{base_dir}}/consolidated/*", "lib/ejabberd-{{release_version}}/ebin/"}, + {copy, "rel/overlays/iex", "releases/{{release_version}}/"}, + {if_var_true, elixir, + {template, "rel/overlays/elixir", "releases/{{release_version}}/elixir"} + }, {copy, "inetrc", "conf/inetrc"}, {copy, "tools/captcha*.sh", "lib/ejabberd-\{\{release_version\}\}/priv/bin/"}, {copy, "rel/files/install_upgrade.escript", "bin/install_upgrade.escript"}]} @@ -268,7 +272,7 @@ {overlay, [{copy, "sql/*", "lib/ejabberd-\{\{release_version\}\}/priv/sql/"}, {copy, "ejabberdctl.cfg.example", "conf/ejabberdctl.cfg"}, {copy, "ejabberd.yml.example", "conf/ejabberd.yml"}]}]}]}, - {dev, [{post_hooks, [{release, "rel/setup-dev.sh"}]}, + {dev, [{post_hooks, [{release, "rel/setup-dev.sh rebar3"}]}, {relx, [{debug_info, keep}, {dev_mode, true}, {include_erts, true}, diff --git a/rebar3 b/rebar3 index bf1935ce6..e903655b8 100755 Binary files a/rebar3 and b/rebar3 differ diff --git a/rel/reltool.config.script b/rel/reltool.config.script index b7ccdf9c5..fea4d6619 100644 --- a/rel/reltool.config.script +++ b/rel/reltool.config.script @@ -53,6 +53,8 @@ OTPApps = RequiredOTPApps ++ ConfiguredOTPApps, DepApps = lists:usort(lists:flatten(GetDeps(filename:join(TopDir, "rebar.config"), GetDeps))), +SysVer = erlang:system_info(otp_release), + Sys = [{lib_dirs, []}, {erts, [{mod_cond, derived}, {app_file, strip}]}, {app_file, strip}, @@ -70,13 +72,17 @@ Sys = [{lib_dirs, []}, {boot_rel, "ejabberd"}, {profile, embedded}, {incl_cond, exclude}, - {excl_archive_filters, [".*"]}, %% Do not archive built libs {excl_sys_filters, ["^bin/.*", "^erts.*/bin/(dialyzer|typer)", "^erts.*/(doc|info|include|lib|man|src)"]}, {excl_app_filters, ["\.gitignore"]}, {app, stdlib, [{incl_cond, include}]}, {app, kernel, [{incl_cond, include}]}, {app, ejabberd, [{incl_cond, include}, {lib_dir, ".."}]}] +++ if SysVer < "26" -> + [{excl_archive_filters, [".*"]}]; %% Do not archive built libs + true -> + [] + end ++ lists:map( fun(App) -> {app, App, [{incl_cond, include}, diff --git a/rel/setup-dev.sh b/rel/setup-dev.sh index d9d94a2d0..af3875cf0 100755 --- a/rel/setup-dev.sh +++ b/rel/setup-dev.sh @@ -23,5 +23,14 @@ sed -i "s|#' POLL|EJABBERD_BYPASS_WARNINGS=true\n\n#' POLL|g" ejabberdctl.cfg.ex echo "" echo "===> Some example ways to start this ejabberd dev:" -echo " _build/dev/rel/ejabberd/bin/ejabberd console" echo " _build/dev/rel/ejabberd/bin/ejabberdctl live" +case "$1" in + "rebar3") + echo " _build/dev/rel/ejabberd/bin/ejabberd console" + ;; + "mix") + echo " RELEASE_NODE=ejabberd@localhost _build/dev/rel/ejabberd/bin/ejabberd start" + ;; + "*") + ;; +esac diff --git a/src/ejabberd.app.src.script b/src/ejabberd.app.src.script index 4c8745146..83a639095 100644 --- a/src/ejabberd.app.src.script +++ b/src/ejabberd.app.src.script @@ -1,13 +1,21 @@ -Vars = case file:consult(filename:join([filename:dirname(SCRIPT), "..", "vars.config"])) of +{Vars, ElixirApps} = case file:consult(filename:join([filename:dirname(SCRIPT), "..", "vars.config"])) of {ok, Terms} -> Backends = [mssql, mysql, odbc, pgsql, redis, sqlite], EBs = lists:filter(fun(Backend) -> lists:member({Backend, true}, Terms) end, Backends), - [lists:keyfind(description, 1, Terms), + Elixirs = case lists:keyfind(elixir, 1, Terms) of + {elixir, true} -> [elixir, iex, logger, mix]; + _ -> [] + end, + Tools = case lists:keyfind(tools, 1, Terms) of + {tools, true} -> [observer, runtime_tools]; % for `ejabberdctl etop` + _ -> [] + end, + {[lists:keyfind(description, 1, Terms), lists:keyfind(vsn, 1, Terms), {env, [{enabled_backends, EBs}]} - ]; + ], Elixirs ++ Tools}; _Err -> - [] + {[], []} end, {application, ejabberd, @@ -27,7 +35,7 @@ Vars = case file:consult(filename:join([filename:dirname(SCRIPT), "..", "vars.co pkix, stringprep, yconf, - xmpp]}, + xmpp | ElixirApps]}, {mod, {ejabberd_app, []}}]}. %% Local Variables: diff --git a/src/ejabberd.erl b/src/ejabberd.erl index e90c8eb74..578a06d91 100644 --- a/src/ejabberd.erl +++ b/src/ejabberd.erl @@ -132,7 +132,7 @@ check_apps() -> fun() -> Apps = [ejabberd | [App || {App, _, _} <- application:which_applications(), - App /= ejabberd]], + App /= ejabberd, App /= hex]], ?DEBUG("Checking consistency of applications: ~ts", [misc:join_atoms(Apps, <<", ">>)]), misc:peach( diff --git a/src/ejabberd_logger.erl b/src/ejabberd_logger.erl index 736d6c20c..897a4352e 100644 --- a/src/ejabberd_logger.erl +++ b/src/ejabberd_logger.erl @@ -340,8 +340,20 @@ progress_filter(#{level:=info,msg:={report,#{label:={_,progress}}}} = Event, _) progress_filter(Event, _) -> Event. +-ifdef(ELIXIR_ENABLED). +console_template() -> + case (false /= code:is_loaded('Elixir.Logger')) + andalso + lists:keymember(default_formatter, 1, 'Elixir.Logger':module_info(exports)) of + true -> + [date, " ", time, " [", level, "] ", message, "\n"]; + false -> + [time, " [", level, "] " | msg()] + end. +-else. console_template() -> [time, " [", level, "] " | msg()]. +-endif. file_template() -> [time, " [", level, "] ", pid, diff --git a/src/ext_mod.erl b/src/ext_mod.erl index ddab4407c..922b4da65 100644 --- a/src/ext_mod.erl +++ b/src/ext_mod.erl @@ -603,8 +603,8 @@ compile(LibDir) -> Er = [compile_erlang_file(Bin, File, Options) || File <- filelib:wildcard(Src++"/*.erl")], Ex = [compile_elixir_file(Bin, File) - || File <- filelib:wildcard(Lib ++ "/*.ex")], - compile_result(Er++Ex). + || File <- filelib:wildcard(Lib ++ "/**/*.ex")], + compile_result(lists:flatten([Er, Ex])). compile_c_files(LibDir) -> case file:read_file_info(filename:join(LibDir, "c_src/Makefile")) of @@ -673,7 +673,7 @@ compile_elixir_file(Dest, File) when is_list(Dest) and is_list(File) -> compile_elixir_file(Dest, File) -> try 'Elixir.Kernel.ParallelCompiler':files_to_path([File], Dest, []) of - [Module] -> {ok, Module} + Modules when is_list(Modules) -> {ok, Modules} catch _ -> {error, {compilation_failed, File}} end. diff --git a/vars.config.in b/vars.config.in index 88cc581eb..d0b4a392a 100644 --- a/vars.config.in +++ b/vars.config.in @@ -55,6 +55,7 @@ {installuser, "@INSTALLUSER@"}. {erl, "{{erts_dir}}/bin/erl"}. {epmd, "{{erts_dir}}/bin/epmd"}. +{iexpath, "{{release_dir}}/releases/{{vsn}}/iex"}. {localstatedir, "{{release_dir}}/var"}. {libdir, "{{release_dir}}/lib"}. {docdir, "{{release_dir}}/doc"}.