WARNING: The online documentation has moved to https://docs.pjsip.org.

Visit the new documentation at https://docs.pjsip.org:

BLOG | DOCUMENTATION | GITHUB

Home --> Documentations --> PJLIB Reference

Building, and Installing PJLIB

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)

 


PJLIB Open Source, high performance, small footprint, and very very portable framework
Copyright (C) 2006-2009 Teluu Inc.