Skip to content

Step 1: Setup open62541 on Linux & build first server

Last updated on September 14, 2020

open62541 setup using the source code on Linux and build the executable of a minimal open62541 server

This Post is part of the OPC UA Information Model Tutorial.

open62541 Documentation

This setup guide is based on the official documentation of open62541. It augments and comments the official documentation whenever necessary:

A printable version of the online documentation can be downloaded from for offline use.

Get Source Code

To get the source code and install open62541 from source, use the following steps:

git clone ~/open62541
cd ~/open62541
git submodule update --init --recursive

Build the library


You first need to install all required dependencies and then use cmake or ccmake to configure the build environment:

sudo apt-get install git build-essential gcc pkg-config cmake python

# enable additional features
sudo apt-get install cmake-curses-gui # for the ccmake graphical interface
sudo apt-get install libmbedtls-dev # for encryption support
sudo apt-get install check libsubunit-dev # for unit tests
sudo apt-get install python-sphinx graphviz # for documentation generation
sudo apt-get install python-sphinx-rtd-theme # documentation style

mkdir ~/open62541/build && cd ~/open62541/build
ccmake ..
Home Directory

Note that the following steps use /home/user/install (or /home/ubuntu/install) as the installation path. Make sure that you change it to your username. You can also use the following value instead: $HOME/install.

In the newly opened window press c and then configure the following values. When you are done, press c followed by g :

  • configure a custom install path to /home/user/install
    • avoid polluting Debian’s system paths with custom libraries
  • Set the build type to RelWithDebInfo
    • This will create a library which is optimized for Release, but still includes debugging info for additional error investigations
  • Enable the Full Namespace Zero
    • To build your own information models based on the official OPC UA Specification you most probably need the complete Namespace Zero

Note: ccmake configures cmake which in turn configures make. Consequently, setting options in ccmake is equivalent to setting build flags in cmake.

For more information, visit

Example: cmake -DCMAKE_INSTALL_PREFIX=/home/user/install -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUA_NAMESPACE_ZERO=Full ..

Build the library. This will take a few minutes. Transfer the build artefacts to the custom install folder ~/install by calling make install. This is required for building your own custom server based on the installed sources.

cd ~/open62541/build
make -j
make install

Building the server executable using gcc

Create a new directory for your own code ~/myServer. Then copy the tutorial code to your own file:

mkdir ~/myServer
cp ~/open62541/examples/tutorial_server_firststeps.c ~/myServer/myServer.c

Now we can build this custom server code by adding the custom installation directory to the gcc command, and by adding additional required libraries

  • adding our custom installation paths as include path -I$HOME/install/include
  • adding our custom library paths -L$HOME/install/lib
  • adding the open62541 library -lopen62541
  • adding -lmbedtls -lmbedx509 -lmbedcrypto for crypto
cd ~/myServer
gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib myServer.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer

Detailed explanation of the custom build command (optional)

You can skip this section if you don’t care why we deviate from the official documentation with above build command.

The official documentation is using the amalgamated build. This is still outdated as it is recommended to use the non-amalgamated version. If you follow the official documentation closely, the build command

gcc -std=c99 open62541.c myServer.c -o myServer

will also fail with

gcc -std=c99 open62541.c myServer.c -o myServer
myServer.c:1:10: fatal error: open62541/plugin/log_stdout.h: No such file or directory
 #include <open62541/plugin/log_stdout.h>
compilation terminated.

gcc fails with the first include in myServer.c It seems, like it’s missing the custom install path from its includes. That was to be expected. Verify the assumption and query gcc’s include paths


# user@debian:~/open62541/build$
gcc -xc -E -v -
#include "..." search starts here:
#include <...> search starts here:
End of search list.

The custom install path /home/user/install is missing. This is a case of a missing -I (include) option to the gcc command. With -I/home/user/install the directory is added to gcc’s search path. This can be verifyed as follows

# user@debian:~/open62541/build$
gcc -I/home/user/inst -xc -E -v -
#include "..." search starts here:
#include <...> search starts here:
End of search list.


gcc -std=c99 -I/home/user/install/include open62541.c myServer.c -o myServer

Progress! All header files are successfully located, but the linker fails

# user@debian:~/open62541/build$
gcc -std=c99 -I/home/user/inst/include open62541.c myServer.c -o myServer
/usr/bin/ld: /tmp/ccgaXZyP.o: in function `mbedtls_pk_get_len':
open62541.c:(.text+0x2c37): undefined reference to `mbedtls_pk_get_bitlen'
/usr/bin/ld: /tmp/ccgaXZyP.o: in function `reloadCertificates':
open62541.c:(.text+0x355d92): undefined reference to `mbedtls_x509_crt_free'
/usr/bin/ld: open62541.c:(.text+0x355da5): undefined reference to `mbedtls_x509_crt_init'
/usr/bin/ld: open62541.c:(.text+0x355dfb): undefined reference to `mbedtls_x509_crt_parse_path'
/usr/bin/ld: open62541.c:(.text+0x355e49): undefined reference to `mbedtls_strerror'
/usr/bin/ld: open62541.c:(.text+0x355efb): undefined reference to `mbedtls_x509_crl_free'
/usr/bin/ld: open62541.c:(.text+0x355f10): undefined reference to `mbedtls_x509_crl_init'
/usr/bin/ld: open62541.c:(.text+0x355f8e): undefined reference to `mbedtls_x509_crl_parse_file'
/usr/bin/ld: open62541.c:(.text+0x3560b3): undefined reference to `mbedtls_x509_crt_free'
/usr/bin/ld: open62541.c:(.text+0x3560c8): undefined reference to `mbedtls_x509_crt_init'
/usr/bin/ld: open62541.c:(.text+0x356123): undefined reference to `mbedtls_x509_crt_parse_path'
/usr/bin/ld: /tmp/ccgaXZyP.o: in function `certificateVerification_verify':
open62541.c:(.text+0x356282): undefined reference to `mbedtls_x509_crt_init'
/usr/bin/ld: open62541.c:(.text+0x3562a9): undefined reference to `mbedtls_x509_crt_parse'
/usr/bin/ld: open62541.c:(.text+0x356331): undefined reference to `mbedtls_x509_crt_verify_with_profile'
/usr/bin/ld: open62541.c:(.text+0x356425): undefined reference to `mbedtls_x509_crt_verify_with_profile'

Is the mbedTLS library missing? Make sure it’s installed on Debian.

# user@debian:~/open62541/build$
sudo apt-cache search mbedtls
[sudo] password for user:
libmbedtls-dev - lightweight crypto and SSL/TLS library - development files
libmbedtls-doc - lightweight crypto and SSL/TLS library - documentation
libmbedtls12 - lightweight crypto and SSL/TLS library - tls library
libshadowsocks-libev-dev - lightweight and secure socks5 proxy (development files)
libshadowsocks-libev2 - lightweight and secure socks5 proxy (shared library)
shadowsocks-libev - lightweight and secure socks5 proxy

Let’s install them

# user@debian:~/open62541/build$
sudo apt install libmbedtls-dev libmbedtls12
Reading package lists... Done
Building dependency tree
Reading state information... Done
libmbedtls-dev is already the newest version (2.16.0-1).
libmbedtls12 is already the newest version (2.16.0-1).
libmbedtls12 set to manually installed.
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

The output indicates that mbedTLS is already installed. Pass the library files to the linker with the -l flag. Do not confuse it with -L , which is used for folders.

gcc -std=c99 -I/home/user/install/include open62541.c myServer.c -lmbedtls -lmbedx509 -lmbedcrypto -o myServer

Compilation completes successfully.

Execute the test server

# user@debian:~/myServer$

Published inopen62541


  1. audupi audupi

    Hi Stephen!

    Thank you for documenting open62541! It is a lot of help in understanding the concepts! Great job!

    However, I am unable to execute the sample server.
    There are variations in custom install path
    in ccmake -> /home/user/install
    in image -> home/ubuntu/install
    in the launch command -> $HOME/install/include

    is this on purpose?

    Upon executing the sample server, errors are
    -> open62541/plugin/log_stdout.h: No such file or directory when following the instructions
    -> open62541.h: No such file or directory when trying to include “open62541.h” as header

    Kindly request your input!

    • Benedict Simlinger Benedict Simlinger

      Hi audupi,

      you are correct, the username displayed in the image image is inconsistent with the rest of the documentation. This documentation consistently uses user as username, while the image uses ubuntu as username.
      The image should show /home/user/install.

      Be sure to replace user (or ubuntu in the image) with the actual username you’re using on your Linux computer!

      $HOME is a well-known Linux variable for your current user’s home directory. It’s equivalent to typing ~ in your terminal. Let us assume that your username on your Linux computer is audupi. Therefore all following paths will point to the same directory:

      If you are not familiar with Linux, I recommend to use /home/audupi/install. It’s the least error-prone way to describe the path.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.