Build linphone-sdk and flexisip on Yocto

This pages describes how to build linphone-sdk and/or Flexisip on Yocto, on any hardware platform.
This is not a Yocto tutorial, and therefore this requires a little bit of first-hand Yocto experience.
A few leads and links are given for the installation of packages on the target machine, however it is mainly out of this wiki page's scope.

This setup has been tested with Yocto Kirkstone.

Set up your build system

Before jumping into building anything for your platform, you must ensure your host build system is correctly setup with the appropriate tools.

Install required packages

Install the required packages for the host development system. The Yocto Project documentation has a list of everything needed for each host type (Ubuntu, CentOS, etc.) as well as the matching install commands for them on this page.

The Yocto Project officially supports some host OS. Using one that is not officially supported can lead to build issues. We recommend using Debian 11.

Get the Yocto build system for your platform

The Yocto project Complete documentation set covers this in details, and is available on their official website here : Yocto Documentation Website. The Yocto Project Quick Start guide is particularly helpful for the execution of the following steps.

The main steps to setup the adequate Yocto build environment and layers for your platform are as follows:

  • Get Bitbake and the OpenEmbedded components (known as Poky)
    • poky
    • meta-openembedded
git clone -b kirkstone git://git.yoctoproject.org/poky
cd poky
git clone -b kirkstone git://git.openembedded.org/meta-openembedded
  • Initialize the build environment to setup Bitbake
source oe-init-build-env
  • Add the openembedded layers to the bblayers configuration file

Add the Linphone recipe

In order to build linphone-sdk and its dependencies with Yocto, the following steps must be completed :

  • Get the linphone-sdk recipes.
  • Add the layer to the bblayers configuration file
  • Add linphone-sdk to the image build
  • Accept the commercial license if building with ffmpeg or openh264 
  • Define environment variables to specify the version of Linphone SDK to build.

There are a few optional additional steps described here:

  • Change the packaging options
  • Disable video support
  • Add H264 support with openH264
  • Add mDNS support
  • Select the number of CPU cores used for the build
  • Add networking packages
  • Save disk space during builds
  • Add an ssh server

Get Linphone recipes

Clone the Linphone layers repository on the same level as the other metadata. In this example, all the metadata layers are cloned into the poky/ directory.

The feature/yocto-kirkstone branch provides the linphone-sdk for yocto-kirkstone

git clone https://gitlab.linphone.org/BC/public/meta-bc.git -b feature/yocto-kirkstone

Your metadata directory should now look like this:

[matthieu@linux-3 poky]$ ls
meta-bc   meta-openembedded   openembedded-core

[matthieu@linux-3 meta-bc]$ ls
classes   conf   docker   README.md   recipes-bc

[matthieu@linux-3 recipes-bc]$ ls
flexisip   linphone-sdk

[matthieu@linux-3 linphone-sdk]$ ls
linphone-sdk   python3-pystache

This repository also contains the bitbake recipes for Flexisip (SIP proxy server).

Add the linphone recipe to the layers

Modify the bblayers.conf file in the build/conf/ directory so that it looks like the following (you should just have to add the meta-bc line):

POKY_BBLAYERS_CONF_VERSION = "2"

BSPDIR := "${@os.path.abspath(os.path.dirname(d.getVar('FILE', True)) + '/../..')}"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  ${BSPDIR}/meta \
  ${BSPDIR}/meta-poky \
  ${BSPDIR}/meta-openembedded/meta-oe \
  ${BSPDIR}/meta-openembedded/meta-networking \
  ${BSPDIR}/meta-openembedded/meta-python \
  ${BSPDIR}/meta-openembedded/meta-multimedia \
  ${BSPDIR}/meta-yocto-bsp \
  ${BSPDIR}/meta-bc \
 "

Add linphone to the image build

Once Linphone is built you can add it to the final image in local.conf using the following lines:

IMAGE_INSTALL:append = " linphone-sdk"

Choose linphone-sdk version

Linphone-sdk can be built by Yocto as a stable version  or as HEAD of master branch, which sets the latest git revision for all submodules automatically. By default the stable version mode is selected but if you want to use the master/HEAD mode you need to define the LATEST_REVISIONS environment variable:

export LATEST_REVISIONS="1"

If you aim to build linphone-sdk specify version, you need to set both branch name and commit by defining the LINPHONE_SDK_REV and LINPHONE_SDK_BRANCH environment variables:

export LINPHONE_SDK_REV="cdc0d522dca3a52c083a90d08790891392513ba9"
export LINPHONE_SDK_BRANCH="master"

In all the cases, you need to define the BB_ENV_PASSTHROUGH_ADDITIONS environment variable so that the other environment variables you defined previously are passed to the build environment:

export BB_ENV_PASSTHROUGH_ADDITIONS="LINPHONE_SDK_REV LINPHONE_SDK_BRANCH PREFERED_LINPHONE_SDK_RECIPE_VERSION LATEST_REVISIONS"

Accept the commercial license if you include ffmpeg or openh264

The following step is relative to license issues, please be careful if you intend to build a commercial product.

This is useful for ffmpeg and openh264, otherwise the linphone build will fail. In the local.conf file under build/conf/, add the following line:

LICENSE_FLAGS_ACCEPTED = "commercial"

Change the packaging option

In the file local.conf, under build/conf/, make sure the PACKAGE_CLASSES is set to package_ipk:

PACKAGE_CLASSES ?= "package_ipk"

Add flexisip

If you want to add flexisip to the final image you can add the following line in local.conf:

IMAGE_INSTALL:append = " flexisip"

Disable the video options

If you don't need video support, you have two options. Either remove video support globally for the image you are building, or disable video support only in Linphone SDK.

To disable video globally, add the following line in your local.conf file:

DISTRO_FEATURES:remove = "x11 wayland"

To disable video only in Linphone SDK, add the following line in your local.conf file:

PACKAGECONFIG:remove:pn-linphone-sdk = "video"

Add H264 support with openH264

You can include H264 support by adding the following line to your local.conf file:

PACKAGECONFIG:append:pn-linphone-sdk = " h264"

Add mDNS support

By adding the following lines to your local.conf file, you will add support of mDNS in the Linphone SDK:

PACKAGECONFIG:append:pn-avahi = " libdns_sd"
PACKAGECONFIG:append:pn-linphone-sdk = " mdns"

If you want to add mDNS support to flexisip, add the following lines to your local.conf file:

PACKAGECONFIG:append:pn-avahi = " libdns_sd"
PACKAGECONFIG:append:pn-flexisip = " mdns"

Select number of CPU cores used for the build

In the local.conf file under build/conf/, add the following line:

BB_NUMBER_THREADS ?= "X"

X being the number of threads that you want to use (twice the number of CPU cores)

Add networking packages if necessary

If you want to add networking packages to the core images, for example you can add the following lines to local.conf:

CORE_IMAGE_EXTRA_INSTALL += "dhcpcd"
CORE_IMAGE_EXTRA_INSTALL += "init-ifupdown"

Save disk space during builds

You can save disk space during build by adding the following line to local.conf:

INHERIT += "rm_work"

Add ssh server if necessary

If you want to add an ssh server to the core images, you can modify the following line to local.conf:

EXTRA_IMAGE_FEATURES = "debug-tweaks ssh-server-openssh"

Build linphone-sdk, flexisip and the final image

Linphone-sdk and Flexisip must be built first before integrating them to the final image.

Build Linphone-sdk and/or flexisip

Now that you're environment is all set up, run the following commands to build the linphone-sdk and/or the Flexisip packages:

bitbake linphone-sdk
bitbake flexisip

Build the final image

Then you can build the image you want using the following example command, which will use the configuration you specified in local.conf:

bitbake core-image-minimal

By default the machine architecture for which Yocto builds the image is qemux86-64 but you can choose to build for any available emulated or hardware machine by specifying it in the local.conf file under the "Machine Selection" section.

Build for Wandboard Solo Freescale i.MX6 Cortex-A9

Example of a build for a specific hardware board with an ARMv7 architecture, which can help understand how to build for your own hardware.

In order to successfully build Linphone for the Wandboard Solo, the following steps must be followed:

  • Get the Wandboard specific layers of metadata
  • Add these layers to bblayers.conf
  • Change target machine to "wandboard"
  • Accept Freescale EULA
  • Clean and re-build the image
  • Unzip wic.gz and flash the image on sd card

Get the Wandboard specific layers of metadata

In order to support this specific architecture, you need to clone and checkout the corresponding branch of three layers of metadata:

  • meta-freescale
  • meta-freescale-distro
  • meta-freescale-3rdparty
git clone -b kirkstone https://github.com/Freescale/meta-freescale.git
git clone -b kirkstone https://github.com/Freescale/meta-freescale-distro.git
git clone -b kirkstone https://github.com/Freescale/meta-freescale-3rdparty.git

Add these layers to bblayers.conf

You can now add the layers to the bblayers.conf configuration file under /build/conf/, which should now be similar to this:

POKY_BBLAYERS_CONF_VERSION = "2"

BSPDIR := "${@os.path.abspath(os.path.dirname(d.getVar('FILE', True)) + '/../..')}"

BBPATH = "${TOPDIR}"
BBFILES ?= ""

BBLAYERS ?= " \
  ${BSPDIR}/meta \
  ${BSPDIR}/meta-poky \
  ${BSPDIR}/meta-openembedded/meta-oe \
  ${BSPDIR}/meta-openembedded/meta-networking \
  ${BSPDIR}/meta-openembedded/meta-python \
  ${BSPDIR}/meta-openembedded/meta-multimedia \
  ${BSPDIR}/meta-yocto-bsp \
  ${BSPDIR}/meta-freescale \
  ${BSPDIR}/meta-freescale-distro \
  ${BSPDIR}/meta-freescale-3rdparty \
  ${BSPDIR}/meta-bc \
 "

Change target machine to "wandboard"

In order to use the wandboard layers of metadata for the build you need to change to target machine in local.conf:

MACHINE = "wandboard"

Accept Freescale EULA

To accept the Freescale EULA you can add the following line to local.conf:

ACCEPT_FSL_EULA = "1"

Clean and re-build the image

Before building the Wandboard version of your image you may need to clean the linphone and image targets:

bitbake -c cleanall core-image-minimal
bitbake -c cleanall linphone-sdk

Then you can build the Wandboard image with bitbake:

bitbake -f linphone-sdk
bitbake -f core-image-minimal

Unzip wic.gz and flash the image on sd card

If your Wandboard build is successful, you can find the final images in /build/tmp/deploy/images/wandboard/. To retreive the .wic image you need to unzip the .wic.gz file with the following command:

gunzip -f core-image-minimal-wandboard.wic.gz

Then you can flash it on an sd card with the dd command. In this example the sd card device is called /dev/sdb.

The following step is critical, be sure to target the correct device before executing the "dd" command. The "lsblk" command is very useful to determine to correct device.

sudo dd if=core-image-minimal-wandboard.wic of=/dev/sdb bs=1024

Using linphone-sdk and flexisip binaries

Start linphone or flexisip binaries

All installed files from linphone and flexisip can be found in the directory /opt/belledonne-communications/

You can find and launch any executable present in /opt/belledonne-communications/bin/

For example /opt/belledonne-communications/bin/liblinphone_tester or /opt/belledonne-communications/bin/flexisip

Link against liblinphone in your own recipe

Since the installation prefix of linphone libraries is not the default system one, compiling and linking against these libraries can be tricky.

Here is an example recipe of a test program linking against liblinphone:

DESCRIPTION = "Example compilation of yocto program based on linphone"                                                                                                                                                                                                         

PR = "r0"                                                                                                                                                                                                                                                                      
LICENSE = "CLOSED"                                                                                                                                                                                                                                                             
S = "${WORKDIR}"                                                                                                                                                                                                                                                               

DEPENDS = "linphone-sdk"                                                                                                                                                                                                                                                       

LINPHONE_INSTALL_PATH = "/opt/belledonne-communications"                                                                                                                                                                                                                       

do_compile() {                                                                                                                                                                                                                                                                 
             ${CC} ${CFLAGS} ${LDFLAGS} -I ${STAGING_DIR_HOST}${LINPHONE_INSTALL_PATH}/include -c test.c -o test.o                                                                                                                                                                      
             ${CC} ${CFLAGS} ${LDFLAGS} -L${STAGING_DIR_HOST}${LINPHONE_INSTALL_PATH}/lib -llinphone -Wl,-rpath-link=${STAGING_DIR_HOST}${LINPHONE_INSTALL_PATH}/lib test.o -o test                                                                                                              
}                                                                                                                                                                                                                                                                              

do_install() {                                                                                                                                                                                                                                                                 
   install -m 0755 -d ${D}${bindir}                                                                                                                                                                                                                                           
   install -m 0755 ${S}/test ${D}${bindir}                                                                                                                                                                                                                               
}                                                                                                                                                                                                                                                                       

The STAGING_DIR_HOST points to the recipe-sysroot folder of your recipe which should contain all linphone-sdk related files (because the recipe DEPENDS on linphone-sdk).

The important option here is `-Wl,-rpath-link` which will make the compiler check for libraries at link time in the given directory.