mirror of https://github.com/asterisk/asterisk
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: Idb1251040affdab31d27cd272dda68676da9b268pull/24/head
parent
0d62735f99
commit
bc59b66de3
@ -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.
|
@ -1,5 +1,6 @@
|
||||
source/
|
||||
source
|
||||
**.bz2
|
||||
build.mak
|
||||
pjproject.symbols
|
||||
.rebuild_needed
|
||||
.makedeps
|
||||
|
@ -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.
|
||||
|
||||
|
||||
|
@ -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
|
Loading…
Reference in new issue