diff --git a/configure b/configure index 6f0a273e3b9813e83383faa538b4db4b635cb4b0..d701af6d49373720a8264d9e4369e54d7885b5af 100755 --- a/configure +++ b/configure @@ -1157,6 +1157,7 @@ PJPROJECT_INCLUDE PJPROJECT_LIB PBX_PJPROJECT PJPROJECT_DIR +PJPROJECT_BUNDLED_OOT PJPROJECT_BUNDLED PJPROJECT_CONFIGURE_OPTS JANSSON_INCLUDE @@ -1210,6 +1211,7 @@ DOWNLOAD_TIMEOUT DOWNLOAD_TO_STDOUT DOWNLOAD FETCH +REALPATH NM PATCH TAR @@ -7607,6 +7609,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= @@ -9973,6 +10017,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)) @@ -10000,11 +10052,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 @@ -10017,7 +10078,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 @@ -10083,6 +10148,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; } @@ -23048,8 +23114,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" @@ -23089,7 +23155,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 @@ -23110,7 +23176,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 diff --git a/configure.ac b/configure.ac index 9bae41361fa1946844ed75912215145b82ecb98d..b175ef024e202e63f548e52133b79dbb919b2aa2 100644 --- a/configure.ac +++ b/configure.ac @@ -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 index 0000000000000000000000000000000000000000..976c0f5a935e21c973b5d35e9c25c005ce6920bc --- /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 ff1f53766f15878a5d22e0b469a1a91279632f2c..8ffa9cab19310ed17d4f9cb9968c4207f65b461e 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -609,6 +609,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 210ac76d6eeca1e7ab0ec22c1008f49177f80e49..77bc974d84f300024e5c01f3307aa50121595bd9 100644 --- a/makeopts.in +++ b/makeopts.in @@ -228,6 +228,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@ diff --git a/res/res_pjproject.c b/res/res_pjproject.c index 4047acae39105c9b60f302429ac08466ffcf69bb..9bd053b8b180ef1d35a110cfc70c60d657381778 100644 --- a/res/res_pjproject.c +++ b/res/res_pjproject.c @@ -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; diff --git a/third-party/Makefile b/third-party/Makefile index 7b2afdac32a0504c76ba3b8cc2f4d99f2dfb8d8c..e87e26f32690b6650859a9fe9db4656e3f6846bd 100644 --- a/third-party/Makefile +++ b/third-party/Makefile @@ -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): diff --git a/third-party/Makefile.rules b/third-party/Makefile.rules index f02ddb1f824a865e7ce82a02a79a0875152f0b29..9e4925ec62d145031f6a779492066e320553034c 100644 --- a/third-party/Makefile.rules +++ b/third-party/Makefile.rules @@ -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 diff --git a/third-party/apply_patches b/third-party/apply_patches index 23323fbef2e815233b645e9defff11e852c1b991..3c0a6bc76e70e7a341934da82aa5189967d7425b 100755 --- a/third-party/apply_patches +++ b/third-party/apply_patches @@ -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 diff --git a/third-party/jansson/Makefile b/third-party/jansson/Makefile index 8c9da1a46897fc6b101a631cc94da04098c05333..f24a1c6a6db9864ae493364075e7cd20d80585e3 100644 --- a/third-party/jansson/Makefile +++ b/third-party/jansson/Makefile @@ -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 diff --git a/third-party/pjproject/.gitignore b/third-party/pjproject/.gitignore index 6904ebfb641b7bef2c91e150eb824a2f794ea73a..f0a2b2aebbe3134406f383253d6efa15d2280480 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 96a64915556a60b1524ed68e006e7b0c3d3056b3..612c116bd9f31cd253cd6d2b8c32cc0e2107f2a9 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 @@ 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) @@ -92,31 +93,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/ @@ -128,7 +126,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)) @@ -144,24 +142,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 @@ -170,21 +217,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 @@ -210,19 +258,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) || : diff --git a/third-party/pjproject/Makefile.rules b/third-party/pjproject/Makefile.rules index e76a753e58610c541c7b65fc21b86381f08578e9..b92a4cba88cd445a23be332400f640c2b159bbca 100644 --- a/third-party/pjproject/Makefile.rules +++ b/third-party/pjproject/Makefile.rules @@ -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 index 0000000000000000000000000000000000000000..0ce57ecf2c97788b76e82fa0a173febdda7b245b --- /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@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. + + + diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4 index f67ef577e259aac47e11fa0508da162eefc0d82a..2f266252da9c3735b507b73577a651d99e249288 100644 --- a/third-party/pjproject/configure.m4 +++ b/third-party/pjproject/configure.m4 @@ -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 index 0000000000000000000000000000000000000000..fb221ea2a19b315083aa2fdfb2cd28d5c3471fad --- /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