]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
bundled_pjproject: Make it easier to hack
authorGeorge Joseph <gjoseph@digium.com>
Tue, 30 Nov 2021 22:35:27 +0000 (15:35 -0700)
committerFriendly Automation <jenkins2@gerrit.asterisk.org>
Fri, 7 Jan 2022 15:57:43 +0000 (09:57 -0600)
There are times when you need to troubleshoot issues with bundled
pjproject or add new features that need to be pushed upstream
but...

* The source directory created by extracting the pjproject tarball
  is not scanned for code changes so you have to keep forcing
  rebuilds.
* The source directory isn't a git repo so you can't easily create
  patches, do git bisects, etc.
* Accidentally doing a make distclean will ruin your day by wiping
  out the source directory, and your changes.
* etc.

This commit makes that easier.
See third-party/pjproject/README-hacking.md for the details.

ASTERISK-29824

Change-Id: Idb1251040affdab31d27cd272dda68676da9b268

16 files changed:
configure
configure.ac
doc/CHANGES-staging/bundled-pjproject-build.txt [new file with mode: 0644]
include/asterisk/autoconfig.h.in
makeopts.in
res/res_pjproject.c
third-party/Makefile
third-party/Makefile.rules
third-party/apply_patches
third-party/jansson/Makefile
third-party/pjproject/.gitignore
third-party/pjproject/Makefile
third-party/pjproject/Makefile.rules
third-party/pjproject/README-hacking.md [new file with mode: 0644]
third-party/pjproject/configure.m4
third-party/pjproject/dependency_utils [new file with mode: 0755]

index b8fbd7cf010dbfc3345784bbf7bf7780f28c712a..2a94585c78d91b615f010310c0ab88be3d09c0b5 100755 (executable)
--- a/configure
+++ b/configure
@@ -1180,6 +1180,7 @@ PJPROJECT_INCLUDE
 PJPROJECT_LIB
 PBX_PJPROJECT
 PJPROJECT_DIR
+PJPROJECT_BUNDLED_OOT
 PJPROJECT_BUNDLED
 PJPROJECT_CONFIGURE_OPTS
 JANSSON_INCLUDE
@@ -1233,6 +1234,7 @@ DOWNLOAD_TIMEOUT
 DOWNLOAD_TO_STDOUT
 DOWNLOAD
 FETCH
+REALPATH
 NM
 PATCH
 TAR
@@ -7690,6 +7692,48 @@ $as_echo "no" >&6; }
 fi
 
 
+# Extract the first word of "realpath", so it can be a program name with args.
+set dummy realpath; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_REALPATH+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  case $REALPATH in
+  [\\/]* | ?:[\\/]*)
+  ac_cv_path_REALPATH="$REALPATH" # Let the user override the test with a path.
+  ;;
+  *)
+  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+  IFS=$as_save_IFS
+  test -z "$as_dir" && as_dir=.
+    for ac_exec_ext in '' $ac_executable_extensions; do
+  if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+    ac_cv_path_REALPATH="$as_dir/$ac_word$ac_exec_ext"
+    $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+    break 2
+  fi
+done
+  done
+IFS=$as_save_IFS
+
+  test -z "$ac_cv_path_REALPATH" && ac_cv_path_REALPATH=":"
+  ;;
+esac
+fi
+REALPATH=$ac_cv_path_REALPATH
+if test -n "$REALPATH"; then
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: $REALPATH" >&5
+$as_echo "$REALPATH" >&6; }
+else
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
 
 DOWNLOAD=":"
 DOWNLOAD_TO_STDOUT=
@@ -10056,6 +10100,14 @@ $as_echo "configuring" >&6; }
                if test "${GREP}" = ":" ; then
                        as_fn_error $? "grep is required to build bundled pjproject" "$LINENO" 5
                fi
+               if test "${FIND}" = ":" ; then
+                       as_fn_error $? "find is required to build bundled pjproject" "$LINENO" 5
+               fi
+               if test "x${AST_DEVMODE}" != "x" ; then
+                       if test "${REALPATH}" = ":" ; then
+                               as_fn_error $? "realpath is required to build bundled pjproject in dev mode" "$LINENO" 5
+                       fi
+               fi
 
 
                this_host=$(./config.sub $(./config.guess))
@@ -10083,11 +10135,20 @@ $as_echo "configuring" >&6; }
                        esac
                fi
 
-               export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP
+               # Determine if we're doing an out-of-tree build...
+
+               if test -L ${PJPROJECT_DIR}/source -o -d ${PJPROJECT_DIR}/source/.git ; then
+                       $as_echo "#define HAVE_PJPROJECT_BUNDLED_OOT 1" >>confdefs.h
+
+                       PJPROJECT_BUNDLED_OOT=yes
+               fi
+
+               export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP FIND REALPATH
                export NOISY_BUILD AST_DEVMODE
                ${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
                        PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
                        EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
+                       PJPROJECT_BUNDLED_OOT="${PJPROJECT_BUNDLED_OOT}" \
                        configure
                if test $? -ne 0 ; then
                        { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5
@@ -10100,7 +10161,11 @@ $as_echo "$as_me: Unable to configure ${PJPROJECT_DIR}" >&6;}
                { $as_echo "$as_me:${as_lineno-$LINENO}: checking for bundled pjproject" >&5
 $as_echo_n "checking for bundled pjproject... " >&6; }
 
-               PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" echo_cflags)
+               PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
+                       PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
+                       EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
+                       PJPROJECT_BUNDLED_OOT="${PJPROJECT_BUNDLED_OOT}" \
+                       echo_cflags)
                PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE"
                PBX_PJPROJECT=1
 
@@ -10166,6 +10231,7 @@ $as_echo "#define HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK 1" >>confdefs.h
 
 
 
+
                { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
@@ -23831,8 +23897,8 @@ rm -f core conftest.err conftest.$ac_objext \
    if test "x${PBX_NETSNMP}" != "x1" -a "${USE_NETSNMP}" != "no"; then
 
 pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for netsnmp-agent" >&5
-$as_echo_n "checking for netsnmp-agent... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for NETSNMP" >&5
+$as_echo_n "checking for NETSNMP... " >&6; }
 
 if test -n "$NETSNMP_CFLAGS"; then
     pkg_cv_NETSNMP_CFLAGS="$NETSNMP_CFLAGS"
@@ -23872,7 +23938,7 @@ fi
 
 
 if test $pkg_failed = yes; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -23893,7 +23959,7 @@ fi
 
 
 elif test $pkg_failed = untried; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+       { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
 $as_echo "no" >&6; }
 
             PBX_NETSNMP=0
index 53e9565ce4f7e60244f37c7326bd2306173f2918..8675ad6f244e2681df76a3f271b60973e87b4d0d 100644 (file)
@@ -285,6 +285,8 @@ AC_PATH_PROG([TAR], [tar], :)
 AC_PATH_PROG([PATCH], [patch], :)
 AC_PATH_PROG([SED], [sed], :)
 AC_PATH_PROG([NM], [nm], :)
+AC_PATH_PROG([REALPATH], [realpath], :)
+
 
 DOWNLOAD=":"
 DOWNLOAD_TO_STDOUT=
diff --git a/doc/CHANGES-staging/bundled-pjproject-build.txt b/doc/CHANGES-staging/bundled-pjproject-build.txt
new file mode 100644 (file)
index 0000000..976c0f5
--- /dev/null
@@ -0,0 +1,8 @@
+Subject: Core
+
+Bundled PJProject Build
+
+The build process has been updated to make pjproject troubleshooting
+and development easier. See third-party/pjproject/README-hacking.md or
+https://wiki.asterisk.org/wiki/display/AST/Bundled+PJProject
+for more info.
index 92675441b11a2c4a16f2fda6e58588206b1cdf1f..6240b592066ac1587e1e423ffa410f3240a1e050 100644 (file)
 /* Define if your system has PJPROJECT_BUNDLED */
 #undef HAVE_PJPROJECT_BUNDLED
 
+/* Define if doing a bundled pjproject out-of-tree build. */
+#undef HAVE_PJPROJECT_BUNDLED_OOT
+
 /* Define to 1 if on_valid_pair callback is present. */
 #undef HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK
 
index 61d64376102855c421085c6fadaa444292fa6d01..e5730bfcfa40d49abdfd4e9921df9240e7cc9332 100644 (file)
@@ -236,6 +236,7 @@ PGSQL_INCLUDE=@PGSQL_INCLUDE@
 PGSQL_LIB=@PGSQL_LIB@
 
 PJPROJECT_BUNDLED=@PJPROJECT_BUNDLED@
+PJPROJECT_BUNDLED_OOT=@PJPROJECT_BUNDLED_OOT@
 PJPROJECT_INCLUDE=@PJPROJECT_INCLUDE@
 PJPROJECT_LIB=@PJPROJECT_LIB@
 PJPROJECT_DIR=@PJPROJECT_DIR@
index 4047acae39105c9b60f302429ac08466ffcf69bb..9bd053b8b180ef1d35a110cfc70c60d657381778 100644 (file)
@@ -489,7 +489,7 @@ int ast_sockaddr_to_pj_sockaddr(const struct ast_sockaddr *addr, pj_sockaddr *pj
        if (addr->ss.ss_family == AF_INET) {
                struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
                pjaddr->ipv4.sin_family = pj_AF_INET();
-#ifdef HAVE_PJPROJECT_BUNDLED
+#if defined(HAVE_PJPROJECT_BUNDLED) && !defined(HAVE_PJPROJECT_BUNDLED_OOT)
                pjaddr->ipv4.sin_addr = sin->sin_addr;
 #else
                pjaddr->ipv4.sin_addr.s_addr = sin->sin_addr.s_addr;
@@ -514,7 +514,7 @@ int ast_sockaddr_from_pj_sockaddr(struct ast_sockaddr *addr, const pj_sockaddr *
        if (pjaddr->addr.sa_family == pj_AF_INET()) {
                struct sockaddr_in *sin = (struct sockaddr_in *) &addr->ss;
                sin->sin_family = AF_INET;
-#ifdef HAVE_PJPROJECT_BUNDLED
+#if defined(HAVE_PJPROJECT_BUNDLED) && !defined(HAVE_PJPROJECT_BUNDLED_OOT)
                sin->sin_addr = pjaddr->ipv4.sin_addr;
 #else
                sin->sin_addr.s_addr = pjaddr->ipv4.sin_addr.s_addr;
index 7b2afdac32a0504c76ba3b8cc2f4d99f2dfb8d8c..e87e26f32690b6650859a9fe9db4656e3f6846bd 100644 (file)
@@ -11,9 +11,8 @@ TP_INSTALL_SUBDIRS := pjproject jansson
 override MAKECMDGOALS?=all
 
 MAKECMDGOALS:=$(subst dist-clean,distclean,$(MAKECMDGOALS))
-MAKECMDGOALS:=$(subst tpclean,clean,$(MAKECMDGOALS))
 
-all distclean dist-clean install uninstall tpclean : $(TP_SUBDIRS)
+all distclean dist-clean install uninstall clean : $(TP_SUBDIRS)
 install uninstall: $(TP_INSTALL_SUBDIRS)
 
 $(TP_SUBDIRS):
index f02ddb1f824a865e7ce82a02a79a0875152f0b29..9e4925ec62d145031f6a779492066e320553034c 100644 (file)
@@ -13,6 +13,9 @@ QUIET_CONFIGURE=
 REALLY_QUIET=
 endif
 
+# The following exports are set during a configure but if
+# it hasn't been run yet, we'll set some defaults
+# to be able to still allow clean and distclean to run
 export SUBMAKE
 export ECHO_PREFIX
 export CMD_PREFIX
@@ -24,12 +27,16 @@ export DESTDIR
 export ASTDATADIR
 export TAR
 export PATCH
-export SED
+export SED ?= sed
 export NM
 export MD5
 export CAT
 export CUT
-export GREP
+export GREP ?= grep
+export FIND ?= find
+export REALPATH ?= realpath
+export BASENAME ?= basename
+export DIRNAME ?= dirname
 export DOWNLOAD
 export DOWNLOAD_TO_STDOUT
 export DOWNLOAD_TIMEOUT
index 23323fbef2e815233b645e9defff11e852c1b991..3c0a6bc76e70e7a341934da82aa5189967d7425b 100755 (executable)
@@ -6,6 +6,7 @@ if [ "$1" = "-q" ] ; then
 fi
 
 PATCH=${PATCH:-patch}
+FIND=${FIND:-find}
 
 patchdir=${1:?You must supply a patches directory}
 sourcedir=${2?:You must supply a source directory}
@@ -20,12 +21,13 @@ if [ ! -d "$sourcedir" ] ; then
        exit 1
 fi
 
-if [ ! "$(ls -A $patchdir/*.patch 2>/dev/null)" ] ; then
+patches=$(${FIND} "$patchdir" -name "*.patch")
+if [ x"$patches" = x"" ] ; then
        echo "No patches in $patchdir"  >&2
        exit 0
 fi
 
-for patchfile in "$patchdir"/*.patch ; do
+for patchfile in ${patches} ; do
        [ -z $quiet ] && echo "Applying patch $(basename $patchfile)"
        ${PATCH} -d "$sourcedir" -p1 -s -i "$patchfile" || exit 1
 done
index 8c9da1a46897fc6b101a631cc94da04098c05333..f24a1c6a6db9864ae493364075e7cd20d80585e3 100644 (file)
@@ -96,7 +96,7 @@ uninstall:
 
 clean:
        $(ECHO_PREFIX) Cleaning
-       +-$(CMD_PREFIX) test -d source dest && $(SUBMAKE) -C source clean || :
+       +-$(CMD_PREFIX) test -d source && $(SUBMAKE) -C source clean $(REALLY_QUIET) || :
 
 distclean:
        $(ECHO_PREFIX) Distcleaning
index 6904ebfb641b7bef2c91e150eb824a2f794ea73a..f0a2b2aebbe3134406f383253d6efa15d2280480 100644 (file)
@@ -1,5 +1,6 @@
-source/
+source
 **.bz2
 build.mak
 pjproject.symbols
 .rebuild_needed
+.makedeps
index 65852bc9779bcff663e9879e3572fea8344bebd3..158725e3a820e8bf2a6e5339be2b32f445c35d55 100644 (file)
@@ -3,6 +3,7 @@
 .NOTPARALLEL:
 
 include ../versions.mak
+
 export PJDIR := $(shell pwd -P)/source
 
 SPECIAL_TARGETS :=
@@ -40,21 +41,21 @@ ifeq ($(SPECIAL_TARGETS),)
     endif
 
     ifeq ($(PJPROJECT_BUNDLED),yes)
+        all: _all
+        install: _install
+
         ifneq ($(wildcard ../../menuselect.makeopts),)
             include ../../menuselect.makeopts
         else
             $(warning ASTTOPDIR/menuselect hasn't been run yet.  Can't find debug options.)
         endif
                include ../../Makefile.rules
-               include ../Makefile.rules
+        include ../Makefile.rules
                include Makefile.rules
 
-        all: _all
-        install: _install
-
-        include source/user.mak
-        include source/version.mak
-        include source/build.mak
+        -include source/user.mak
+        -include source/version.mak
+        -include source/build.mak
         CF := $(filter-out -W%,$(CC_CFLAGS))
         CF := $(filter-out -I%,$(CF))
         ifeq ($(AST_DEVMODE),yes)
@@ -82,31 +83,28 @@ export CFLAGS += $(CF) $(OPENSSL_INCLUDE)
 export LDFLAGS += $(CC_LDFLAGS) $(OPENSSL_LIB)
 
 ECHO_PREFIX := $(ECHO_PREFIX) echo '[pjproject] '
+ECHO_PREFIX_NONL := $(ECHO_PREFIX) echo -n '[pjproject] '
 SHELL_ECHO_PREFIX := echo '[pjproject] '
 
 _all: $(TARGETS)
 
-.DELETE_ON_ERROR:
-
 $(DOWNLOAD_DIR)/$(TARBALL_FILE): ../versions.mak
        $(CMD_PREFIX) ($(TARBALL_EXISTS) && $(TARBALL_VERIFY) && touch $@) || (rm -rf $@ ;\
        $(TARBALL_DOWNLOAD)) || (rm -rf $@ ;\
        $(SHELL_ECHO_PREFIX) Retrying download ; $(TARBALL_DOWNLOAD))
 
 source/.unpacked: $(DOWNLOAD_DIR)/$(TARBALL_FILE)
-       $(CMD_PREFIX) $(TARBALL_VERIFY) || (rm -rf $@ ;\
-       $(SHELL_ECHO_PREFIX) Retrying download ; $(TARBALL_DOWNLOAD))
-       $(ECHO_PREFIX) Unpacking $<
-       -@rm -rf source pjproject-*/ >/dev/null 2>&1
-       $(CMD_PREFIX) $(TAR) -xjf $<
-       @mv pjproject-$(PJPROJECT_VERSION) source
+       $(CMD_PREFIX) \
+               $(TARBALL_VERIFY) || (rm -rf $@ ; $(SHELL_ECHO_PREFIX) Retrying download ; $(TARBALL_DOWNLOAD)) ;\
+               $(SHELL_ECHO_PREFIX) Unpacking $< ;\
+               rm -rf source pjproject-*/ $(REALLY_QUIET) || : ;\
+               $(TAR) -xjf $< ;\
+               mv pjproject-$(PJPROJECT_VERSION) source
        $(ECHO_PREFIX) Applying patches "$(realpath patches)" "$(realpath .)/source"
        $(CMD_PREFIX) ../apply_patches $(QUIET_CONFIGURE) "$(realpath patches)" "$(realpath .)/source"
        -@touch source/.unpacked
 
-source/version.mak: source/.unpacked
-
-source/user.mak: source/.unpacked patches/user.mak
+source/user.mak: $(if $(PJPROJECT_BUNDLED_OOT),,source/.unpacked) patches/user.mak
        $(ECHO_PREFIX) Applying user.mak
        $(CMD_PREFIX) cp -f patches/user.mak source/
 
@@ -118,7 +116,7 @@ source/pjlib/include/pj/%.h: patches/%.h
        $(ECHO_PREFIX) Rebuilding
        $(CMD_PREFIX) $(MAKE) clean $(REALLY_QUIET)
 
-source/build.mak: Makefile.rules source/version.mak source/user.mak $(addprefix source/pjlib/include/pj/,$(notdir $(wildcard patches/*.h))) .rebuild_needed
+source/build.mak: Makefile.rules source/user.mak $(if $(PJPROJECT_BUNDLED_OOT),,.rebuild_needed)
        $(ECHO_PREFIX) Configuring with $(PJPROJECT_CONFIG_OPTS) 
        $(CMD_PREFIX) (cd source ; ./aconfigure $(QUIET_CONFIGURE) $(PJPROJECT_CONFIG_OPTS))
 
@@ -134,24 +132,73 @@ configure: source/build.mak
 echo_cflags: source/build.mak
        @echo $(filter-out -O% -g%,$(PJ_CFLAGS))
 
-libpj%.a: source/build.mak
-       $(ECHO_PREFIX) Compiling lib $(@F)
-       $(CMD_PREFIX) $(MAKE) -C $(dir $(shell dirname $@))/build $(@F) $(REALLY_QUIET)
+# The dependency_utils script needs TARGET_NAME in the environment
+export TARGET_NAME
+
+# PJ_LIB_FILES is set by the pjproject build.mak and contains the libs we
+# need, but not in the order they need to be built.  We need to compile
+# pjlib, then pjlib-util, then the rest so we separate them out and create
+# the dependencies.  First though, we shorten all file paths by making them
+# relative to the current directory.
+SHORTENED_PJ_LIB_FILES = $(subst $(CURDIR)/,,$(PJ_LIB_FILES))
+# Now separate them
+PJLIB_LIB_FILES = $(filter %/libpj-$(TARGET_NAME).a,$(SHORTENED_PJ_LIB_FILES))
+PJLIB_UTIL_LIB_FILES = $(filter %/libpjlib-util-$(TARGET_NAME).a,$(SHORTENED_PJ_LIB_FILES))
+RESAMPLE_LIB_FILE = $(filter %/libresample-$(TARGET_NAME).a,$(SHORTENED_PJ_LIB_FILES))
+# The rest.
+PJSIP_LIB_FILES = $(filter-out $(PJLIB_LIB_FILES) $(PJLIB_UTIL_LIB_FILES) $(RESAMPLE_LIB_FILE),$(SHORTENED_PJ_LIB_FILES))
+
+# Create the dependency order we need
+$(PJLIB_UTIL_LIB_FILES): $(PJLIB_LIB_FILES)
+$(PJSIP_LIB_FILES): $(PJLIB_UTIL_LIB_FILES)
 
-# pjsua needs resample and g711 to successfully run the testsuite
-libresample%.a: source/build.mak
-       $(ECHO_PREFIX) Compiling lib $(@F)
-       $(CMD_PREFIX) $(MAKE) -C $(dir $(shell dirname $@))/build/resample all $(REALLY_QUIET)
+# and here's the full list
+ALL_LIB_FILES = $(PJLIB_LIB_FILES) $(PJLIB_UTIL_LIB_FILES) $(PJSIP_LIB_FILES) $(RESAMPLE_LIB_FILE)
+
+# Assuming that since you're doing an out-of-tree build you're modifying
+# the pjproject source files, we need to create dependencies between
+# the libraries and their respective source files.  Pjproject does
+# create dependency files if you run 'make dep' but those files include
+# the system include files and the paths are relative to the lib's
+# "build" directory.  Neither really works for us.
+# So...
+# We create our own "astdep" files with dependency paths relative
+# to "this" directory and strip out all the system includes.
+# The dependency_utils script does all the heavy lifting.
+#
+# REMINDER: None of this gets invoked unless you're doing an out-of-tree
+# pjproject build.
+
+ifdef PJPROJECT_BUNDLED_OOT
+    ALL_PJDEP_FILES = $(shell TARGET_NAME=$(TARGET_NAME) ./dependency_utils getpjdepname $(ALL_LIB_FILES))
+    ALL_ASTDEP_FILES = $(ALL_PJDEP_FILES:.depend=.astdep)
+
+    $(ALL_PJDEP_FILES): build.mak
+               $(ECHO_PREFIX) Generating pjproject dependency file $(@F)
+               $(CMD_PREFIX) $(MAKE) -C $(@D) dep $(REALLY_QUIET)
+
+    $(ALL_ASTDEP_FILES): %.astdep: %.depend
+               $(ECHO_PREFIX) Generating asterisk dependency file $(@F)
+               $(CMD_PREFIX) ./dependency_utils gendepfile $<
+    ifeq ($(SPECIAL_TARGETS),)
+        ifneq ($(ALL_ASTDEP_FILES),)
+            include $(ALL_ASTDEP_FILES)
+            depends: $(ALL_ASTDEP_FILES)
+        endif
+    endif
+endif
 
-# We need to compile pjlib, then pjlib-util, then the rest
-# so we separate them out and create the dependencies
-PJLIB_LIB_FILES = $(foreach lib,$(PJ_LIB_FILES),$(if $(findstring libpj-,$(lib)),$(lib),))
-PJLIB_UTIL_LIB_FILES = $(foreach lib,$(PJ_LIB_FILES),$(if $(findstring libpjlib-util,$(lib)),$(lib),))
-PJSIP_LIB_FILES = $(filter-out $(PJLIB_LIB_FILES) $(PJLIB_UTIL_LIB_FILES) $(APP_THIRD_PARTY_LIB_FILES),$(PJ_LIB_FILES))
-ALL_LIB_FILES = $(PJLIB_LIB_FILES) $(PJLIB_UTIL_LIB_FILES) $(PJSIP_LIB_FILES)
+# resample's a little odd in that it's build directory is one directory
+# level down from the other libraries.  We set the RESAMPLE_OPTS
+# variable for it then let the ALL_LIB_FILE build rules take over.
+$(RESAMPLE_LIB_FILE): RESAMPLE_OPTS=/resample all
 
-$(PJLIB_UTIL_LIB_FILES): $(PJLIB_LIB_FILES)
-$(PJSIP_LIB_FILES): $(PJLIB_UTIL_LIB_FILES)
+.PRECIOUS: $(ALL_LIB_FILES)
+
+$(ALL_LIB_FILES): BUILD_DIR=$(dir $(@D))
+$(ALL_LIB_FILES): source/build.mak source/pjlib/include/pj/config_site.h
+       $(ECHO_PREFIX) Compiling $(@F)
+       $(CMD_PREFIX) ( $(MAKE) -C $(BUILD_DIR)build$(if $(RESAMPLE_OPTS),$(RESAMPLE_OPTS), $(@F)) >/dev/null ) $(if $(PJPROJECT_BUNDLED_OOT),2>&1 | ($(GREP) -E -v "^(r - output|ar:)" || : ),$(REALLY_QUIET))
 
 pjproject.symbols: $(ALL_LIB_FILES)
        $(ECHO_PREFIX) Generating symbols
@@ -160,21 +207,22 @@ pjproject.symbols: $(ALL_LIB_FILES)
 source/pjsip-apps/src/asterisk_malloc_debug.c: patches/asterisk_malloc_debug.c
        $(ECHO_PREFIX) Copying $< to $@
        $(CMD_PREFIX) cp -f $< $@
-       $(CMD_PREFIX) mkdir source/pjsip-apps/lib/
+       -$(CMD_PREFIX) mkdir source/pjsip-apps/lib/ $(REALLY_QUIET)
 
-source/pjsip-apps/lib/asterisk_malloc_debug.o: source/pjsip-apps/src/asterisk_malloc_debug.c .rebuild_needed
+source/pjsip-apps/lib/asterisk_malloc_debug.o: source/pjsip-apps/src/asterisk_malloc_debug.c | source/pjlib/include/pj/config_site.h source/pjlib/include/pj/asterisk_malloc_debug.h
        $(ECHO_PREFIX) Compiling asterisk debug malloc stubs
        $(CMD_PREFIX) $(CC) -fPIC  $(PJ_CFLAGS) -c $< -o $@
 
 source/pjsip-apps/lib/libasterisk_malloc_debug.a: source/pjsip-apps/lib/asterisk_malloc_debug.o
        $(ECHO_PREFIX) Creating archive $(@F)
-       $(CMD_PREFIX) ar qs $@ $< >/dev/null 2>&1
+       $(CMD_PREFIX) ar qs $@ $< $(REALLY_QUIET)
 
 $(apps): APP = $(filter pj%,$(subst -, ,$(notdir $@)))
 $(apps): LDFLAGS += $(MALLOC_DEBUG_LDFLAGS)
-$(apps): $(MALLOC_DEBUG_LIBS) pjproject.symbols $(APP_THIRD_PARTY_LIB_FILES)
+$(apps): $(MALLOC_DEBUG_LIBS) pjproject.symbols
        $(ECHO_PREFIX) Compiling $(APP)
-       $(CMD_PREFIX) +$(MAKE) -C source/pjsip-apps/build $(filter pj%,$(subst -, ,$(notdir $@))) $(REALLY_QUIET)
+       $(CMD_PREFIX) +$(MAKE) -C source/pjsip-apps/build $(APP) $(REALLY_QUIET)
+       $(CMD_PREFIX) touch $@
 
 source/pjsip-apps/src/python/_pjsua.o: source/pjsip-apps/src/python/_pjsua.c $(apps)
        $(ECHO_PREFIX) Compiling python bindings
@@ -200,19 +248,33 @@ ifneq ($(findstring _pjsua.so,$(TARGETS)),)
        $(CMD_PREFIX) $(INSTALL) -m 644 source/pjsip-apps/src/python/pjsua.py "$(DESTDIR)$(ASTDATADIR)/third-party/pjproject/"
 endif
 
+all: _all
+
 uninstall:
        $(ECHO_PREFIX) Uninstalling apps and python bindings
        $(CMD_PREFIX) rm -rf "$(DESTDIR)$(ASTDATADIR)/third-party/pjproject"
 
 clean:
        $(ECHO_PREFIX) Cleaning
-       +-$(CMD_PREFIX) test -d source && ($(SUBMAKE) -C source clean || : ;\
-               rm -rf source/pjsip-apps/bin/* || : ;\
-               find source -name *.a | xargs rm -rf  ;\
-               find source -name *.o | xargs rm -rf  ;\
-               find source -name *.so  | xargs rm -rf ; ) || :
-       -$(CMD_PREFIX) rm -rf pjproject.symbols
-
-distclean:
+       +-$(CMD_PREFIX) {\
+               if [ -d source ] ; then  \
+                       $(SUBMAKE) -C source clean ;\
+                       rm -rf source/pjsip-apps/bin/* ;\
+                       $(FIND) source/ '(' -name *.a -or -name *.o -or -name *.so ')' -delete ;\
+               fi ;\
+               rm -rf pjproject.symbols ;\
+               } $(REALLY_QUIET) || :
+
+distclean: clean
        $(ECHO_PREFIX) Distcleaning
-       -$(CMD_PREFIX) rm -rf source pjproject.symbols pjproject-*.tar.bz2 build.mak .rebuild_needed
+       +-$(CMD_PREFIX) {\
+               rm -rf build.mak .rebuild_needed ;\
+               if [ "x$(PJPROJECT_BUNDLED_OOT)" = "x" -a ! -d source/.git ] ; then \
+                       rm -rf source pjproject-*.tar.bz2 ;\
+               else \
+                       $(SUBMAKE) -C source distclean ;\
+                       rm -rf source/build.mak source/user.mak ;\
+                       $(FIND) source/ -name '*asterisk_malloc_debug*' -delete ;\
+                       $(FIND) source/ '(' -name '.*.depend' -or -name '.*.astdep' ')' -delete ;\
+               fi \
+               } $(REALLY_QUIET) || :
index e76a753e58610c541c7b65fc21b86381f08578e9..b92a4cba88cd445a23be332400f640c2b159bbca 100644 (file)
@@ -37,7 +37,7 @@ PJPROJECT_CONFIG_OPTS = $(PJPROJECT_CONFIGURE_OPTS) --prefix=/opt/pjproject \
        --disable-ipp \
        --disable-libwebrtc \
        --without-external-pa \
-       --without-external-srtp
+       --with-external-srtp
 
 ifneq ($(AST_DEVMODE),yes)
     PJPROJECT_CONFIG_OPTS += --disable-resample --disable-g711-codec
diff --git a/third-party/pjproject/README-hacking.md b/third-party/pjproject/README-hacking.md
new file mode 100644 (file)
index 0000000..0ce57ec
--- /dev/null
@@ -0,0 +1,213 @@
+# Hacking on PJProject
+
+## Intro
+There are times when you need to troubleshoot issues with bundled pjproject
+or add new features that need to be pushed upstream but...
+
+* The source directory created by extracting the pjproject tarball is not
+scanned for code changes so you have to keep forcing rebuilds.
+* The source directory isn't a git repo so you can't easily create patches,
+do git bisects, etc.
+* Accidentally doing a make distclean will ruin your day by wiping out the
+source directory, and your changes.
+* etc.
+
+Well No More!
+
+You can now replace the `source` directory that's normally created
+by the Makefile extracting the tarball, with a symlink to a "real" pjproject
+git clone.  The Makefile will now detect that `source` is a real pjproject
+repo and enable some advanced behaviors (and disable others).
+
+## Setup
+
+Let's assume you have an Asterisk development environment like so:
+
+```plain
+~/dev/asterisk/
+  asterisk/
+    .git/
+    addons/
+    ...
+    third-party/
+      jansson/
+      pjproject/
+```
+
+### Cloning pjproject
+
+Start by cloning a pjproject repository next to your asterisk repository.
+The source of the clone depends on whether you anticipate pushing changes
+back upstream or not.  If you already have a good pjproject repository clone,
+read this section anyway but you probably won't have to do anything.
+
+* For pushing upstream: (Community Contributors)
+    * Make sure you have the proper ssh keys added to your github account
+    so you can push changes.
+    * Navigate to https://github.com/pjsip/pjproject
+    * Click the "Fork" button to create a fork under your own username.
+
+Back on your own machine...
+
+```plain
+$ cd ~/dev/asterisk
+$ git clone git@github.com:<yourusername>/pjproject
+```
+
+* For pushing upstream: (Asterisk Core Team Developers)
+Asterisk Core Team Developers should clone the fork we have in our own
+Asterisk github organization.
+
+```plain
+$ cd ~/dev/asterisk
+$ git clone git@github.com:asterisk/pjproject
+```
+
+Regardless of how you got your repo, you'll need to create an "upstream"
+remote that points to the original pjproject repo.
+
+```plain
+$ cd pjproject
+$ git remote add upstream https://github.com/pjsip/pjproject
+```
+
+If you're just troubleshooting and don't plan on pushing changes upstream,
+you can just clone directly from the upstream pjproject repo.
+
+```plain
+$ cd ~/dev/asterisk
+$ git clone https://github.com/pjsip/pjproject
+```
+
+Your directory structure should now look something like:
+
+```plain
+~/dev/asterisk/
+  asterisk/
+    .git/
+    addons/
+    ...
+    third-party/
+      jansson/
+      pjproject/
+  pjproject/
+    .git
+    pjlib/
+    ...
+```
+
+### Adjusting Asterisk
+Start with a "distcleaned" asterisk work tree then in the
+asterisk/third-party/pjproject directory, create a symlink to the pjproject
+clone you just created.
+
+```plain
+$ cd ~/dev/asterisk/asterisk/
+$ make distclean
+$ cd third-party/pjproject
+$ ln -s ../../../pjproject source
+```
+The "source" directory is now a relative symlink to your pjproject
+clone so your directory structure should now look something like:
+
+```plain
+~/dev/asterisk/
+  asterisk/
+    .git/
+    addons/
+    ...
+    third-party/
+      jansson/
+      pjproject/
+        source -> ../../../pjproject
+  pjproject/
+    .git
+    pjlib/
+    ...
+```
+
+### Adjust pjproject git ignores.
+One final step is required to keep your pjproject repo from being dirtied
+by the build process.  Add the following lines to your pjproject (not asterisk)
+repo's .git/info/exclude file...
+
+```plain
+**/*.astdep
+**/*asterisk_malloc_debug*
+**/_pjsua.o
+**/_pjsua.so
+```
+Don't add these to the top-level .gitignore file!  If you do, they'll become
+part of any change you submit upstream.
+
+## Usage
+
+Just run `./configure` and `make` as you would for any other asterisk build.
+When you make changes to pjproject source files, they'll be automatically
+recompiled the next time you build asterisk.
+
+You can do git operations in the pjproject repo while it's still symlinked
+into the asterisk source.  Assuming you made the proper changes to
+pjproject's .git/info/exclude file, a commit in the pjproject repo _should_ contain
+only the changes you made.
+
+You can run `make` commands directly in third-party/pjproject  The only
+requirement is that an asterisk top-level `configure` had to have been
+run at least once.
+
+You can always revert to standard bundled pjproject by running an asterisk
+top-level `make distclean`, removing the third-party/pjproject/source
+symlink, and re-running a top-level `configure`.  That will download and
+extract the pjproject tarball to the `third-party/pjproject/source`
+directory as usual.
+
+### Notes
+
+While your pjproject repo is symlinked into the asterisk source tree,
+you should not run `configure` directly in the pjproject repo.  You won't get
+the proper options applied to be compatible with Asterisk.  You can run
+`make` though.
+
+Although asterisk_malloc_debug and site_config.h are applied to the pjproject
+repo, No patches from the `third-party/pjproject/patches` directory are
+applied.  Since you're probably working off the pjproject master branch,
+the patches aren't needed.  Also, applying the patches would contaminate
+the pjproject repo and you wouldn't be able to do a clean commit there.
+
+You'll see compile and/or link warnings you wouldn't see with a normal
+bundled build.
+
+
+## How it works
+
+When an asterisk top-level `configure` is run, `third-party/pjproject/configure.m4 `
+checks whether `third-party/pjproject/source` is a symlink or is a git
+repository.  If neither are true, the build isn't considered "out-of-tree"
+and the normal pjproject bundled process occurs.
+If either is true, it sets `PJPROJECT_BUNDLED_OOT=yes` for the Makefiles.
+
+When a `make` is done, either from top-level asterisk or from the
+third-party/pjproject directory, it checks `PJPROJECT_BUNDLED_OOT`
+and if set to yes it...
+
+    * Alters the behavior of `clean` and `distclean` to just run
+    pjproject's `clean` or `distclean` targets and to NOT remove the
+    `source` directory or symlink as it would normally do.
+
+    * Generates `astdep` dependency files in the pjproject source tree
+    if they don't already exist.  These are git-ignored by the edit
+    to pjproject's `.git/info/exclude` done above.  You'll
+    see new progress messages during the make as the astdep files are
+    built.
+
+    * Copies asterisk_malloc_debug.c, asterisk_malloc_debug.h and
+    config_site.h from the patches directory into the pjproject source
+    tree.  These are also git-ignored by the edit to pjproject's
+    `.git/info/exclude` file.
+
+    * Compiles only the out-of-date source files into their respective
+    libpj libraries.  That in turn triggers the asterisk top-level
+    make to re-link main/libasteriskpj.so.
+
+
+
index f67ef577e259aac47e11fa0508da162eefc0d82a..2f266252da9c3735b507b73577a651d99e249288 100644 (file)
@@ -47,6 +47,14 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
                if test "${GREP}" = ":" ; then
                        AC_MSG_ERROR(grep is required to build bundled pjproject)
                fi
+               if test "${FIND}" = ":" ; then
+                       AC_MSG_ERROR(find is required to build bundled pjproject)
+               fi
+               if test "x${AST_DEVMODE}" != "x" ; then
+                       if test "${REALPATH}" = ":" ; then
+                               AC_MSG_ERROR(realpath is required to build bundled pjproject in dev mode)
+                       fi
+               fi
 
                AC_ARG_VAR([PJPROJECT_CONFIGURE_OPTS],[Additional configure options to pass to bundled pjproject])
                this_host=$(./config.sub $(./config.guess))
@@ -74,11 +82,19 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
                        esac
                fi
 
-               export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP
+               # Determine if we're doing an out-of-tree build...
+               AH_TEMPLATE(m4_bpatsubst([[HAVE_PJPROJECT_BUNDLED_OOT]], [(.*)]), [Define if doing a bundled pjproject out-of-tree build.])
+               if test -L ${PJPROJECT_DIR}/source -o -d ${PJPROJECT_DIR}/source/.git ; then
+                       AC_DEFINE([HAVE_PJPROJECT_BUNDLED_OOT], 1)
+                       PJPROJECT_BUNDLED_OOT=yes
+               fi
+
+               export TAR PATCH SED NM EXTERNALS_CACHE_DIR AST_DOWNLOAD_CACHE DOWNLOAD_TO_STDOUT DOWNLOAD_TIMEOUT DOWNLOAD MD5 CAT CUT GREP FIND REALPATH
                export NOISY_BUILD AST_DEVMODE
                ${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
                        PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
                        EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
+                       PJPROJECT_BUNDLED_OOT="${PJPROJECT_BUNDLED_OOT}" \
                        configure
                if test $? -ne 0 ; then
                        AC_MSG_RESULT(failed)
@@ -88,7 +104,11 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
 
                AC_MSG_CHECKING(for bundled pjproject)
 
-               PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" echo_cflags)
+               PJPROJECT_INCLUDE=$(${GNU_MAKE} --quiet --no-print-directory -C ${PJPROJECT_DIR} \
+                       PJPROJECT_CONFIGURE_OPTS="$PJPROJECT_CONFIGURE_OPTS" \
+                       EXTERNALS_CACHE_DIR="${EXTERNALS_CACHE_DIR:-${AST_DOWNLOAD_CACHE}}" \
+                       PJPROJECT_BUNDLED_OOT="${PJPROJECT_BUNDLED_OOT}" \
+                       echo_cflags)
                PJPROJECT_CFLAGS="$PJPROJECT_INCLUDE"
                PBX_PJPROJECT=1
 
@@ -113,6 +133,7 @@ AC_DEFUN([_PJPROJECT_CONFIGURE],
                AC_DEFINE([HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK], 1, [Define if your system has the on_valid_pair pjnath callback.])
 
                AC_SUBST([PJPROJECT_BUNDLED])
+               AC_SUBST([PJPROJECT_BUNDLED_OOT])
                AC_SUBST([PJPROJECT_DIR])
                AC_SUBST([PBX_PJPROJECT])
                AC_SUBST([PJPROJECT_LIB])
diff --git a/third-party/pjproject/dependency_utils b/third-party/pjproject/dependency_utils
new file mode 100755 (executable)
index 0000000..fb221ea
--- /dev/null
@@ -0,0 +1,96 @@
+#!/bin/sh
+
+[ "x${SED}" = "x" ] && SED=sed
+[ "x${GREP}" = "x" ] && GREP=grep
+[ "x${REALPATH}" = "x" ] && REALPATH=realpath
+[ "x${DIRNAME}" = "x" ] && DIRNAME=dirname
+[ "x${BASENAME}" = "x" ] && BASENAME=basename
+[ "x${GREP}" = "x" ] && GREP=grep
+if [ "x${TARGET_NAME}" = "x" ] ; then
+       if [ ! -f build.mak ] ; then
+               exit 0;
+       fi
+       TARGET_NAME=$(${SED} -n -r -e "s/export\s+TARGET_NAME\s*:=\s*(.*)/\1/gp" build.mak)
+fi
+
+getlibname() {
+       dep="$1"
+       libdir=$(${DIRNAME} $(${DIRNAME} "${dep}"))/lib
+       depname=$(${BASENAME} "${dep}")
+       depprefix="${depname%%-${TARGET_NAME}.depend}"
+       case ${depprefix} in
+               .pjlib)
+                       libfile=libpj
+                       ;;
+               .pjsua-lib)
+                       libfile=libpjsua
+                       ;;
+               .*)
+                       libfile=lib${depprefix#.*}
+                       ;;
+       esac
+       echo "${libdir}/${libfile}-${TARGET_NAME}.a"
+}
+
+gendepfile() {
+       pjdf="$1"
+       astdf="${pjdf%*.depend}.astdep"
+       dirname=$(${DIRNAME} "${astdf}")
+       lines=$(grep -E -o -- "[.][.]/[^ ]+" "${pjdf}" | sort -u | wc -l)
+       libname=$(getlibname "${pjdf}")
+       backslash="\\"
+       echo "${libname}: ${backslash}" >"${astdf}"
+       for dep in $(grep -E -o -- "[.][.]/[^ ]+" "${pjdf}" | sort -u) ; do
+               ( echo "${dep}" | grep -Eq "(test|/bin/)" ; ) && continue
+               newdep=$( cd "${dirname}" ; ${REALPATH} -L --relative-to=../../ "${dep}" ; )
+               lines=$(( ${lines} - 1 ))
+               if [ ${lines} -eq 0 ] ; then
+                       echo "source/${newdep}" >>"${astdf}"
+               else
+                       echo "source/${newdep} ${backslash}" >>"${astdf}"
+               fi
+       done
+       echo >>"${astdf}"
+}
+
+getpjdepname () {
+       lib="$1"
+       builddir=$(${DIRNAME} $(${DIRNAME} "${lib}"))/build
+       libname=$(${BASENAME} "${lib}")
+       libprefix="${libname%%-${TARGET_NAME}.a}"
+       nolib=$(echo "${libprefix}" | ${SED} -r -e "s@^lib@@g")
+       case ${nolib} in
+               pj)
+                       depfile=.pjlib
+                       ;;
+               pjsua)
+                       depfile=.pjsua-lib
+                       ;;
+               resample)
+                       depfile=resample/.libresample
+                       ;;
+               *)
+                       depfile=.${nolib}
+                       ;;
+       esac
+       echo "${builddir}/${depfile}-${TARGET_NAME}.depend"
+}
+
+case $1 in
+       getpjdepname)
+               shift
+               for lib in $@ ; do getpjdepname "${lib}" ; done
+               ;;
+       gendepfile)
+               shift
+               for dep in $@ ; do gendepfile "${dep}" ; done
+               ;;
+       getlibname)
+               shift
+               for dep in $@ ; do getlibname "${dep}" ; done
+               ;;
+       *)
+               echo Invalid command
+               exit 1
+               ;;
+esac