Build and Installation
- Note
- The most up-to-date information on building and installing PJLIB should be found in the website, under "Getting Started" document. More over, the new PJLIB build system is now based on autoconf, so some of the information here might not be relevant anymore (although most still are, since the autoconf script still use the old Makefile system as the backend).
Visual Studio
The PJLIB Visual Studio workspace supports the building of PJLIB for Win32 target. Although currently only the Visual Studio 6 Workspace is actively maintained, developers with later version of Visual Studio can easily imports VS6 workspace into their IDE.
To start building PJLIB projects with Visual Studio 6 or later, open the workspace file in the corresponding build
directory. You have several choices on which dsw file to open:
$PJPROJECT/pjlib/build/pjlib.dsw
$PJPROJECT/pjsip/build/pjsip.dsw
..etc
The easiest way is to open pjsip_apps.dsw
file in $PJPROJECT/pjsip-apps/build
directory, and build pjsua project or the samples project. However this will not build the complete projects. For example, the PJLIB test is not included in this workspace. To build the complete projects, you must open and build each dsw file in build
directory in each subprojects. For example, to open the complete PJLIB workspace, open pjlib.dsw
in $PJPROJECT/pjlib/build
directory.
Create config_site.h
The file $PJPROJECT/pjlib/include/pj/config_site.h
is supposed to contain configuration that is specific to your site/target. This file is not part of PJLIB, so you must create it yourself. Normally you just need to create a blank file.
The reason why it's not included in PJLIB is so that you would not accidently overwrite your site configuration.
If you fail to do this, Visual C will complain with error like:
"fatal error C1083: Cannot open include file: 'pj/config_site.h': No such file
or directory".
Build the Projects
Just hit the build button!
Make System
For other targets, PJLIB provides a rather comprehensive build system that uses GNU make (and only GNU make will work). Currently, the build system supports building * PJLIB for these targets:
- i386/Win32/mingw
- i386/Linux
- i386/Linux (kernel)
- alpha/linux
- sparc/SunOS
- etc..
Requirements
In order to use the make
based build system, you MUST have:
- GNU make
The Makefiles heavily utilize GNU make commands which most likely are not available in other make
system.
- bash shell is recommended.
Specificly, there is a command "echo -n"
which may not work in other shells. This command is used when generating dependencies (make dep
) and it's located in $PJPROJECT/build/rules.mak
.
- ar, ranlib from GNU binutils
In your system has different ar
or ranlib
(e.g. they may have been installed as gar
and granlib
), then either you create the relevant symbolic links, or modify $PJPROJECT/build/cc-gcc.mak
and rename ar
and ranlib
to the appropriate names.
- gcc to generate dependency.
Currently the build system uses "gcc -MM"
to generate build dependencies. If gcc
is not desired to generate dependency, then either you don't run make dep
, or edit $PJPROJECT/build/rules.mak
to calculate dependency using your prefered method. (And let me know when you do so so that I can update the file. :) )
Building the Project
Generally, steps required to build the PJLIB are:
$ cd /home/user/pjproject
$ ./configure
$ touch pjlib/include/pj/config_site.h
$ make dep
$ make
The above process will build all static libraries and all applications.
- Note
- the
configure
script is not a proper autoconf script, but rather a simple shell script to detect current host. This script currently does not support cross-compilation.
-
For Linux kernel target, there are additional steps required, which will be explained in section Linux Kernel Target.
Cross Compilation
For cross compilation, you will need to edit the build.mak
file in $PJPROJECT
root directory manually. Please see README-configure file in the root directory for more information.
For Linux kernel target, you are also required to declare the following variables in this file:
KERNEL_DIR:
full path of kernel source tree.
KERNEL_ARCH:
kernel ARCH options (e.g. "ARCH=um"), or leave blank for default.
PJPROJECT_DIR:
full path of PJPROJECT source tree.
Apart from these, there are also additional steps required to build Linux kernel target, which will be explained in Linux Kernel Target.
Files in "build" Directory
The *.mak
files in $PJPROJECT/build
directory are used to specify the configuration for the specified compiler, target machine target operating system, and host options. These files will be executed (included) by make during building process, depending on the values specified in $PJPROJECT/build.mak file.
Normally you don't need to edit these files, except when you're porting PJLIB to new target.
Below are the description of some files in this directory:
rules.mak
: contains generic rules always included during make.
cc-gcc.mak
: rules when gcc is used for compiler.
cc-vc.mak
: rules when MSVC compiler is used.
host-mingw.mak
: rules for building in mingw host.
host-unix.mak
: rules for building in Unix/Posix host.
host-win32.mak
: rules for building in Win32 command console (only valid when VC is used).
m-i386.mak
: rules when target machine is an i386 processor.
m-m68k.mak
: rules when target machine is an m68k processor.
os-linux.mak
: rules when target OS is Linux.
os-linux-kernel.mak
: rules when PJLIB is to be build as part of Linux kernel.
os-win32.mak
: rules when target OS is Win32.
Create config_site.h
The file $PJPROJECT/pjlib/include/pj/config_site.h
is supposed to contain configuration that is specific to your site/target. This file is not part of PJLIB, so you must create it yourself.
The reason why it's not included in PJLIB is so that you would not accidently overwrite your site configuration.
Invoking make
Normally, make is invoked in build
directory under each project. For example, to build PJLIB, you would invoke make in $PJPROJECT/pjlib/build
directory like below:
$ cd pjlib/build
$ make
Alternatively you may invoke make
in $PJPROJECT
directory, to build all projects under that directory (e.g. PJLIB, PJSIP, etc.).
Linux Kernel Target
- Note
- BUILDING APPLICATIONS IN LINUX KERNEL MODE IS A VERY DANGEROUS BUSINESS. YOU MAY CRASH THE WHOLE OF YOUR SYSTEM, CORRUPT YOUR HARDISK, ETC. PJLIB KERNEL MODULES ARE STILL IN EXPERIMENTAL PHASE. DO NOT RUN IT IN PRODUCTION SYSTEMS OR OTHER SYSTEMS WHERE RISK OF LOSS OF DATA IS NOT ACCEPTABLE. YOU HAVE BEEN WARNED.
-
User Mode Linux (UML) provides excellent way to experiment with Linux kernel without risking the stability of the host system. See http://user-mode-linux.sourceforge.net for details.
-
I only use UML to experiment with PJLIB kernel modules. I wouldn't be so foolish to use my host Linux machine to experiment with this.
-
You have been warned.
For building PJLIB for Linux kernel target, there are additional steps required. In general, the additional tasks are:
- Declare some more variables in
build.mak
file (this has been explained in Cross Compilation above).
- Perform these two small modifications in kernel source tree.
There are two small modification need to be applied to the kernel tree.
1. Edit Makefile
in kernel root source tree.
Add the following lines at the end of the Makefile
in your $KERNEL_SRC
dir:
script:
$(SCRIPT)
- Note
- Remember to replace spaces with tab in the Makefile.
The modification above is needed to capture kernel's $CFLAGS
and $CFLAGS_MODULE
which will be used for PJLIB's compilation.
2. Add Additional Exports.
We need the kernel to export some more symbols for our use. So we declare the additional symbols to be exported in extra-exports.c
file, and add a this file to be compiled into the kernel:
- Copy the file <tt>extra-exports.c</tt> from <tt>pjlib/src/pj</tt>
directory to <tt>$KERNEL_SRC/kernel/</tt> directory.
- Edit <tt>Makefile</tt> in that directory, and add this line
somewhere after the declaration of that variable:
obj-y += extra-exports.o
To illustrate what have been done in your kernel source tree, below is screenshot of my kernel source tree after the modification.
[root@vpc-linux linux-2.6.7]# pwd
/usr/src/linux-2.6.7
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# tail Makefile
endif # skip-makefile
FORCE:
.PHONY: script
script:
$(SCRIPT)
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# head kernel/extra-exports.c
#include <linux/module.h>
#include <linux/syscalls.h>
EXPORT_SYMBOL(sys_select);
EXPORT_SYMBOL(sys_epoll_create);
EXPORT_SYMBOL(sys_epoll_ctl);
EXPORT_SYMBOL(sys_epoll_wait);
EXPORT_SYMBOL(sys_socket);
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]#
[root@vpc-linux linux-2.6.7]# head -15 kernel/Makefile
#
# Makefile for the linux kernel.
#
obj-y = sched.o fork.o exec_domain.o panic.o printk.o profile.o \
exit.o itimer.o time.o softirq.o resource.o \
sysctl.o capability.o ptrace.o timer.o user.o \
signal.o sys.o kmod.o workqueue.o pid.o \
rcupdate.o intermodule.o extable.o params.o posix-timers.o \
kthread.o
obj-y += extra-exports.o
obj-$(CONFIG_FUTEX) += futex.o
obj-$(CONFIG_GENERIC_ISA_DMA) += dma.o
[root@vpc-linux linux-2.6.7]#
Then you must rebuild the kernel. If you fail to do this, you won't be able to insmod pjlib.
- Note
- You will see a lots of warning messages during pjlib-test compilation. The warning messages complain about unresolved symbols which are defined in pjlib module. You can safely ignore these warnings. However, you can not ignore warnings about non-pjlib unresolved symbols.
Makefile Explained
The Makefile for each project (e.g. PJLIB, PJSIP, etc) should be very similar in the contents. The Makefile is located under build
directory in each project subdir.
PJLIB Makefile.
Below is PJLIB's Makefile:
include ../../build.mak
include ../../version.mak
include $(PJDIR)/build/common.mak
export LIBDIR := ../lib
export BINDIR := ../bin
RULES_MAK := $(PJDIR)/build/rules.mak
export PJLIB_LIB := libpj-$(TARGET_NAME)$(LIBEXT)
ifeq ($(PJ_SHARED_LIBRARIES),)
else
export PJLIB_SONAME := libpj.$(SHLIB_SUFFIX)
export PJLIB_SHLIB := $(PJLIB_SONAME).$(PJ_VERSION_MAJOR)
endif
###############################################################################
# Gather all flags.
#
export _CFLAGS := $(CC_CFLAGS) $(OS_CFLAGS) $(HOST_CFLAGS) $(M_CFLAGS) \
$(CFLAGS) $(CC_INC)../include
export _CXXFLAGS:= $(_CFLAGS) $(CC_CXXFLAGS) $(OS_CXXFLAGS) $(M_CXXFLAGS) \
$(HOST_CXXFLAGS) $(CXXFLAGS)
export _LDFLAGS := $(CC_LDFLAGS) $(OS_LDFLAGS) $(M_LDFLAGS) $(HOST_LDFLAGS) \
$(APP_LDFLAGS) $(LDFLAGS)
###############################################################################
# Defines for building PJLIB library
#
export PJLIB_SRCDIR = ../src/pj
export PJLIB_OBJS += $(OS_OBJS) $(M_OBJS) $(CC_OBJS) $(HOST_OBJS) \
activesock.o array.o config.o ctype.o errno.o except.o fifobuf.o \
guid.o hash.o ip_helper_generic.o list.o lock.o log.o os_time_common.o \
os_info.o pool.o pool_buf.o pool_caching.o pool_dbg.o rand.o \
rbtree.o sock_common.o sock_qos_common.o \
ssl_sock_common.o ssl_sock_ossl.o ssl_sock_gtls.o ssl_sock_dump.o \
ssl_sock_darwin.o string.o timer.o types.o
export PJLIB_CFLAGS += $(_CFLAGS)
export PJLIB_CXXFLAGS += $(_CXXFLAGS)
export PJLIB_LDFLAGS += $(_LDFLAGS)
###############################################################################
# Defines for building test application
#
export TEST_SRCDIR = ../src/pjlib-test
export TEST_OBJS += activesock.o atomic.o echo_clt.o errno.o exception.o \
fifobuf.o file.o hash_test.o ioq_perf.o ioq_udp.o \
ioq_stress_test.o ioq_unreg.o ioq_tcp.o \
list.o mutex.o os.o pool.o pool_perf.o rand.o rbtree.o \
select.o sleep.o sock.o sock_perf.o ssl_sock.o \
string.o test.o thread.o timer.o timestamp.o \
udp_echo_srv_sync.o udp_echo_srv_ioqueue.o \
util.o
export TEST_CFLAGS += $(_CFLAGS)
export TEST_CXXFLAGS += $(_CXXFLAGS)
export TEST_LDFLAGS += $(PJLIB_LDLIB) $(_LDFLAGS)
ifeq ($(EXCLUDE_APP),0)
export TEST_EXE := pjlib-test-$(TARGET_NAME)$(HOST_EXE)
endif
export CC_OUT CC AR RANLIB HOST_MV HOST_RM HOST_RMDIR HOST_MKDIR OBJEXT LD LDOUT
###############################################################################
# Main entry
#
# $(TARGET) is defined in os-$(OS_NAME).mak file in current directory.
#
all: $(TARGETS) $(TARGETS_EXE)
lib: $(TARGETS)
doc:
cd .. && rm -rf docs/$(PJ_VERSION) && doxygen docs/doxygen.cfg
@if [ -n "$(WWWDIR)" ] && ! [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html" ] ; then \
echo "Creating docs/$(PJ_VERSION)/pjlib/docs/html" ; \
mkdir -p $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html ; \
fi
@if [ -n "$(WWWDIR)" ] && [ -d "$(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html" ] ; then \
echo "Copying docs/$(PJ_VERSION) to $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html.." ; \
cp -v -a ../docs/$(PJ_VERSION)/html/* $(WWWDIR)/docs/$(PJ_VERSION)/pjlib/docs/html/ ; \
fi
print:
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib print_lib
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test print_bin
depend: ../include/pj/config_site.h
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib depend
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test depend
echo '$(BINDIR)/$(TEST_EXE): $(LIBDIR)/$(PJLIB_LIB)' >> .pjlib-test-$(TARGET_NAME).depend
.PHONY: all dep depend clean realclean distclean
.PHONY: $(TARGETS)
.PHONY: $(PJLIB_LIB) $(PJLIB_SONAME)
.PHONY: $(TEST_EXE)
dep: depend
pjlib: $(PJLIB_LIB)
$(PJLIB_LIB): ../include/pj/config_site.h
$(PJLIB_SONAME): $(PJLIB_LIB)
$(PJLIB_LIB) $(PJLIB_SONAME):
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
../include/pj/config_site.h:
touch ../include/pj/config_site.h
pjlib-test: $(TEST_EXE)
$(TEST_EXE): $(PJLIB_LIB) $(PJLIB_SONAME)
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test $(subst /,$(HOST_PSEP),$(BINDIR)/$@)
.PHONY: pjlib.ko
pjlib.ko:
echo Making $@
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
.PHONY: pjlib-test.ko
pjlib-test.ko:
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test $(subst /,$(HOST_PSEP),$(LIBDIR)/$@)
clean:
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib clean
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test clean
realclean:
$(subst @@,$(subst /,$(HOST_PSEP),.pjlib-$(TARGET_NAME).depend),$(HOST_RMR))
$(subst @@,$(subst /,$(HOST_PSEP),.pjlib-test-$(TARGET_NAME).depend),$(HOST_RMR))
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib realclean
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test realclean
distclean: realclean
gcov-report:
$(MAKE) -f $(RULES_MAK) APP=PJLIB app=pjlib gcov-report
$(MAKE) -f $(RULES_MAK) APP=TEST app=pjlib-test gcov-report
PJLIB os-linux.mak.
Below is file os-linux.mak
file in $PJPROJECT/pjlib/build
directory, which is OS specific configuration file for Linux target that is specific for PJLIB project. For global OS specific configuration, please see $PJPROJECT/build/os-*.mak
.
#
# OS specific configuration for Linux OS target.
#
#
# PJLIB_OBJS specified here are object files to be included in PJLIB
# (the library) for this specific operating system. Object files common
# to all operating systems should go in Makefile instead.
#
export PJLIB_OBJS += addr_resolv_sock.o file_access_unistd.o \
file_io_ansi.o guid_simple.o \
log_writer_stdout.o os_core_unix.o \
os_error_unix.o os_time_unix.o \
os_timestamp_common.o os_timestamp_posix.o \
pool_policy_malloc.o sock_bsd.o sock_select.o
ifeq (epoll,$(LINUX_POLL))
export PJLIB_OBJS += ioqueue_epoll.o
else
export PJLIB_OBJS += ioqueue_select.o
endif
export PJLIB_OBJS += sock_qos_bsd.o
#
# TEST_OBJS are operating system specific object files to be included in
# the test application.
#
export TEST_OBJS += main.o
#
# Additional LDFLAGS for pjlib-test
#
export TEST_LDFLAGS += -lm
#
# TARGETS are make targets in the Makefile, to be executed for this given
# operating system.
#
export TARGETS = $(PJLIB_LIB) $(PJLIB_SONAME) $(TEST_EXE)