[Asterisk-code-review] bundled_pjproject: Make it easier to hack (asterisk[18])

George Joseph asteriskteam at digium.com
Fri Jan 7 08:44:29 CST 2022


George Joseph has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/17836 )


Change subject: bundled_pjproject:  Make it easier to hack
......................................................................

bundled_pjproject:  Make it easier to hack

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
---
M configure
M configure.ac
A doc/CHANGES-staging/bundled-pjproject-build.txt
M include/asterisk/autoconfig.h.in
M makeopts.in
M res/res_pjproject.c
M third-party/Makefile
M third-party/Makefile.rules
M third-party/apply_patches
M third-party/jansson/Makefile
M third-party/pjproject/.gitignore
M third-party/pjproject/Makefile
M third-party/pjproject/Makefile.rules
A third-party/pjproject/README-hacking.md
M third-party/pjproject/configure.m4
A third-party/pjproject/dependency_utils
16 files changed, 546 insertions(+), 65 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/36/17836/1

diff --git a/configure b/configure
index e227e22..e7ec180 100755
--- a/configure
+++ b/configure
@@ -1188,6 +1188,7 @@
 PJPROJECT_LIB
 PBX_PJPROJECT
 PJPROJECT_DIR
+PJPROJECT_BUNDLED_OOT
 PJPROJECT_BUNDLED
 PJPROJECT_CONFIGURE_OPTS
 JANSSON_INCLUDE
@@ -1241,6 +1242,7 @@
 DOWNLOAD_TO_STDOUT
 DOWNLOAD
 FETCH
+REALPATH
 NM
 PATCH
 TAR
@@ -7698,6 +7700,48 @@
 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=
@@ -10064,6 +10108,14 @@
 		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))
@@ -10091,11 +10143,20 @@
 			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
@@ -10108,7 +10169,11 @@
 		{ $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
 
@@ -10174,6 +10239,7 @@
 
 
 
+
 		{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
 $as_echo "yes" >&6; }
 
@@ -23863,8 +23929,8 @@
    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"
@@ -23904,7 +23970,7 @@
 
 
 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
@@ -23925,7 +23991,7 @@
 
 
 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
diff --git a/configure.ac b/configure.ac
index 6071ef4..355e2e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -285,6 +285,8 @@
 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
index 0000000..976c0f5
--- /dev/null
+++ b/doc/CHANGES-staging/bundled-pjproject-build.txt
@@ -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.
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index af6df9d..4f04d4b 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -627,6 +627,9 @@
 /* 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
 
diff --git a/makeopts.in b/makeopts.in
index 61d6437..e5730bf 100644
--- a/makeopts.in
+++ b/makeopts.in
@@ -236,6 +236,7 @@
 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@
diff --git a/res/res_pjproject.c b/res/res_pjproject.c
index 4047aca..9bd053b 100644
--- a/res/res_pjproject.c
+++ b/res/res_pjproject.c
@@ -489,7 +489,7 @@
 	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 @@
 	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;
diff --git a/third-party/Makefile b/third-party/Makefile
index 7b2afda..e87e26f 100644
--- a/third-party/Makefile
+++ b/third-party/Makefile
@@ -11,9 +11,8 @@
 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):
diff --git a/third-party/Makefile.rules b/third-party/Makefile.rules
index f02ddb1..9e4925e 100644
--- a/third-party/Makefile.rules
+++ b/third-party/Makefile.rules
@@ -13,6 +13,9 @@
 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 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
diff --git a/third-party/apply_patches b/third-party/apply_patches
index 23323fb..3c0a6bc 100755
--- a/third-party/apply_patches
+++ b/third-party/apply_patches
@@ -6,6 +6,7 @@
 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 @@
 	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
diff --git a/third-party/jansson/Makefile b/third-party/jansson/Makefile
index 8c9da1a..f24a1c6 100644
--- a/third-party/jansson/Makefile
+++ b/third-party/jansson/Makefile
@@ -96,7 +96,7 @@
 
 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
diff --git a/third-party/pjproject/.gitignore b/third-party/pjproject/.gitignore
index 6904ebf..f0a2b2a 100644
--- a/third-party/pjproject/.gitignore
+++ b/third-party/pjproject/.gitignore
@@ -1,5 +1,6 @@
-source/
+source
 **.bz2
 build.mak
 pjproject.symbols
 .rebuild_needed
+.makedeps
diff --git a/third-party/pjproject/Makefile b/third-party/pjproject/Makefile
index 96a6491..612c116 100644
--- a/third-party/pjproject/Makefile
+++ b/third-party/pjproject/Makefile
@@ -3,6 +3,7 @@
 .NOTPARALLEL:
 
 include ../versions.mak
+
 export PJDIR := $(shell pwd -P)/source
 
 SPECIAL_TARGETS :=
@@ -40,21 +41,21 @@
     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)
@@ -92,31 +93,28 @@
 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 $<
-	- at 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"
 	- at 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/
 
@@ -128,7 +126,7 @@
 	$(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))
 
@@ -144,25 +142,74 @@
 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
 
-# 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)
+# 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))
 
-# 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)
-
+# Create the dependency order we need
 $(PJLIB_UTIL_LIB_FILES): $(PJLIB_LIB_FILES)
 $(PJSIP_LIB_FILES): $(PJLIB_UTIL_LIB_FILES)
 
+# 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
+
+# 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
+
+.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
 	$(CMD_PREFIX) $(NM) -Pog $(ALL_LIB_FILES) | $(SED) -n -E -e "s/.+: ([_]?[pP][jJ][^ ]+) .+/\1/gp" | sort -u > pjproject.symbols
@@ -170,21 +217,22 @@
 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
@@ -210,19 +258,33 @@
 	$(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
+	+-$(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:
+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) || :
diff --git a/third-party/pjproject/Makefile.rules b/third-party/pjproject/Makefile.rules
index e76a753..b92a4cb 100644
--- a/third-party/pjproject/Makefile.rules
+++ b/third-party/pjproject/Makefile.rules
@@ -37,7 +37,7 @@
 	--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
index 0000000..0ce57ec
--- /dev/null
+++ b/third-party/pjproject/README-hacking.md
@@ -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 at 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 at 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.
+
+
+
diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4
index f67ef57..2f26625 100644
--- a/third-party/pjproject/configure.m4
+++ b/third-party/pjproject/configure.m4
@@ -47,6 +47,14 @@
 		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 @@
 			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_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_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
index 0000000..fb221ea
--- /dev/null
+++ b/third-party/pjproject/dependency_utils
@@ -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

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/17836
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 18
Gerrit-Change-Id: Idb1251040affdab31d27cd272dda68676da9b268
Gerrit-Change-Number: 17836
Gerrit-PatchSet: 1
Gerrit-Owner: George Joseph <gjoseph at digium.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220107/3b22b431/attachment-0001.html>


More information about the asterisk-code-review mailing list