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: https://open62541.org/doc/current/

A printable version of the online documentation can be downloaded from https://open62541.org/doc/open62541-current.pdf for offline use.

Get Source Code

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

git clone https://github.com/open62541/open62541.git ~/open62541
cd ~/open62541
git submodule update --init --recursive

Build the library

Note

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

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 https://cmake.org/runningcmake/

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

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

source: https://stackoverflow.com/questions/4980819/what-are-the-gcc-default-include-directories

# user@debian:~/open62541/build$
gcc -xc -E -v -
[...]
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
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:
 /home/user/inst
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

Retry

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$
./myServer

Published inopen62541

12 Comments

  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!

      Note:
      $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:
      $HOME/install
      ~/install
      /home/audupi/install

      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.

  2. audupi audupi

    Hi there!

    Can we have two compiled versions of open62541 installed in the same machine?

    Version1, following the same procedure as above and building it in /build.
    (/home/open62541/build)

    Version2, is a ‘single file release’ version which generates open62541.c & open62541.h in /build_sfr.
    (/home/open62541/build_sfr)

    Will this lead to any issues in finding the correct “open62541 package” in CMake when building new opcua servers ?

    Thanks in advance.

    • Benedict Simlinger Benedict Simlinger

      Hi Audupi,

      you should be able to have them side-by-side. I have not tested that myself though.

      In case you run into any CMake issues I suggest you find help at the appropriate places (forums, IRC channels, stackoverflow, …)

      Good luck!

      PS:
      A remark towards your question:

      Will this lead to any issues in finding the correct “open62541 package” in CMake when building new opcua servers ?

      You will most likely not get an answer to this this hypothetical question from anyone, because

      1) it shows that you have not bothered to try it yourself (and that may be considered lazy)

      2) you are forcing anyone who wants to help you to make probably incorrect assumptions about your setup thus wasting a lot of time of others

      In general, better questions will give you better feedback/help. Try it and then ask about specific error messages (and give sufficient background information).

  3. Alex Alex

    Hi there,

    Very nice tutorial, I like appreciate the detailed explanations and the explicit note why they are interesting.
    I assume the build prerequisite are copied from the open62541 description.

    Those two commands did not work for me:
    sudo apt-get install python-sphinx graphviz # for documentation generation
    sudo apt-get install python-sphinx-rtd-theme # documentation style

    The python-sphinx documentation states that the package is python3-sphinx now.

    Building the Server leads to this message for me:
    /home/alex/open62541/build/src_generated/open62541/namespace0_generated.c: In function ‘namespace0_generated’:
    /home/alex/open62541/build/src_generated/open62541/namespace0_generated.c:117159:15: note: variable tracking size limit exceeded with ‘-fvar-tracking-assignments’, retrying without
    117159 | UA_StatusCode namespace0_generated(UA_Server *server) {
    | ^

    I am working on a fresh setup Ubuntu VM, so I don’t expect any version issues from that side.

    Cheers and merry christmas,
    Alex

  4. Klemens Klemens

    Hey Opc Rocker,
    I try to learn OPC UA but I have on my raspberry a problem with the gcc command….

    so when I try the steps, without the “Detailed explanation of the custom build command (optional)”
    I get this erros:
    root@raspberrypi:~/myServer# gcc -std=c99 -I/home/MYUSER/install/include myServer.c -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
    /usr/bin/ld: /tmp/cc643rFr.o: in function `UA_ServerConfig_setMinimal’:
    myServer.c:(.text+0xb0): undefined reference to `UA_ServerConfig_setMinimalCustomBuffer’
    /usr/bin/ld: /tmp/cc643rFr.o: in function `stopHandler’:
    myServer.c:(.text+0x138): undefined reference to `UA_Log_Stdout’
    /usr/bin/ld: /tmp/cc643rFr.o: in function `main’:
    myServer.c:(.text+0x168): undefined reference to `UA_Server_new’
    /usr/bin/ld: myServer.c:(.text+0x174): undefined reference to `UA_Server_getConfig’
    /usr/bin/ld: myServer.c:(.text+0x18c): undefined reference to `UA_Server_run’
    /usr/bin/ld: myServer.c:(.text+0x198): undefined reference to `UA_Server_delete’
    collect2: error: ld returned 1 exit status

    with details instruction it ends that it don´t find the open62541.h file.

    I think but don´t know that I have a problem with the ccmake options.
    There is after editing the setup a flag error (after click c on the keyboard)
    but the make install command after ccmake works without error

    Can you help me with my beginner questions ?

    Thank you 🙂

    • Benedict Simlinger Benedict Simlinger

      Hi,

      I noticed that you’re missing open62541.c in your command, which seems to be taken from the “detailed” section.
      Compare your commands with the given instructions carefully.

      Good luck!

  5. Klemens Klemens

    Hi Benedict,
    Thanks for the fast answer 🙂
    yes but I don´t find the open62541.c file in my filesystem were can I get this file?

    Tomorrow I will try it again, maybe it was only a small mistake on my side…

  6. Klemens Klemens

    Hi there,
    Today I try it again and again it ends up with an #include error
    first try it was again as root
    second try as myuser

    myuser@raspberrypi:~/opcUaServer $ sudo gcc -std=c99 -Ihome/myuser/install/include -Lhome/myuser/install/lib opcUaServer.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o opcUaServer
    opcUaServer.c:23:10: fatal error: open62541/plugin/log_stdout.h: No such file or directory
    #include

    in the inlcude path the files are there and the user has permission to that files…

    I try also with the ccmake to build also the examples and start directly the simpleServer. Thats works fine.

    Have you any idea what I making wrong?

    Thank you

    regards Klemens

  7. Klemens Klemens

    sorry I´m just a stupid student 😉

    sometimes the small things make big problems

    I write home/…. but path starts with /home/…

    sorry for wasting your time

    • Benedict Simlinger Benedict Simlinger

      Hi Klemens,

      I am glad you got it up and running. As I said Compare your commands with the given instructions carefully. 😉 No time wasted on my time.

      Good luck!

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.