Skip to content

Step 1: Setup open62541 on Linux & build first server

Last updated on February 2, 2021


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

If you’re building the FULL namespace 0 (as recommended by this guide) be prepared to see the following output

cd ~/myServer
gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib myServer.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
/home/ubuntu/open62541/build/src_generated/open62541/namespace0_generated.c: In function ‘namespace0_generated’:
/home/ubuntu/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) {
       |               ^

This is just a note that your server was built without some debugging information. As long as you do not intend to debug open62541 itself, this note has no relevance for you. The server executable myServer was build successfully and is ready to run!

Note

For production use, build the server in RELEASE mode.

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

20 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!

  8. Klemens Klemens

    Hi Benedict,
    I try it again and again, but on my raspberry Pi it ends up with the following error after round about 2hours, with the gcc command. To you have any Idea or workaround? Or do I need an Raspberry with more Ram? I have now 2GB Ram…

    gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib myServer.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
    /home/user/open62541/build/src_generated/open62541/namespace0_generated.c: In function ‘namespace0_generated’:
    /home/user/open62541/build/src_generated/open62541/namespace0_generated.c:117159:15: note: variable tracking size limit exceeded with -fvar-tracking-assignments, retrying without
    UA_StatusCode namespace0_generated(UA_Server *server) {
    ^
    gcc: fatal error: Killed signal terminated program lto1
    compilation terminated.
    lto-wrapper: fatal error: gcc returned 1 exit status
    compilation terminated.
    /usr/bin/ld: error: lto-wrapper failed
    collect2: error: ld returned 1 exit status

  9. Klemens Klemens

    Hi Benedict,

    Thanks for your answer,
    Here some Updates
    Before I start with your example, I build the firststep server like kalycite[4] and thats works. After I read this source in your answer I´m wondering how I do this and check the ccmake settings…
    I change your example without the change from namespace_zero to full.
    Now I can build the server on the raspberry

    after that I try to build the server on my mac and on a vm with debian
    both ends with this error:

    gcc -std=c99 -I$HOME/install/include -L$HOME/install/lib myServer.c -lopen62541 -lmbedtls -lmbedx509 -lmbedcrypto -o myServer
    /home/parallels/open62541/build/src_generated/open62541/namespace0_generated.c: In function ‘namespace0_generated’:
    /home/parallels/open62541/build/src_generated/open62541/namespace0_generated.c:117159:15: note: variable tracking size limit exceeded with -fvar-tracking-assignments, retrying without
    UA_StatusCode namespace0_generated(UA_Server *server) {

    but it works also if I don´t change the namespace-zero settings…

    Whats kind of problems came in, when I work without the full namespace_zero?

    Maybe you need to know what I need?!:
    My Goal is to build some opc ua servers for a fischertechnik demonstrator. The servers should work together and then I have an edge device with an opc ua client / server for the HMI and Communication outside the local net.

    • Benedict Simlinger Benedict Simlinger

      Hi,

      1) You need to understand what NAMESPACE_ZERO does [1]. Namespace 0 is anything in namespace “http://opcfoundation.org/UA/” [3] That’s where the OPC Foundation defines standard server nodes and all basic node types you may want to use in your model. If you follow the instructions from Kalycito [2] NAMESPACE_ZERO is REDUCED by default. Depending on your needs, this may be sufficient. You may move ahead with REDUCED (although there is no need too; see my second point in this comment), but be prepared to revisit that decision later on.

      2) Again, the message “variable tracking size limit exceeded with -fvar-tracking-assignments, retrying without” is NOT an error. It’s a NOTE, as the message says. The executable myServer will still be compiled successfully, just without var-tracking-assignments (which is only required for debugging anyway). There will be an executable myServer in your directory that you can run. I have already explained what this messages means and how you can deal with it, if it bothers you.

      [1] https://open62541.org/doc/current/building.html#select-build-artefacts
      [2] https://www.kalycito.com/running-opcua-on-raspberry-pi/
      [3] https://reference.opcfoundation.org/v104/Core/docs/Part3/8.2.2/

  10. Klemens Klemens

    Hello Benedict,
    Thanks for your feedback and
    sorry about the late reply.
    Have now put the Raspberry back on again. Everything rebuilt and the gcc command executed with the -flto = 1 command. Now the whole thing can be built and executed with namespace Zero Full. However, it takes a good hour to build. A lecturer gave me the tip with crosscompiling that I would look at that next. Because the existing Raspberrys in the demonstrator are older and slower. Do you have experience with that I have to pay attention to what?

    I am currently writing all of my results in a small manual, open62541 on raspberry for dummies 😉 I can make these available to you. In case you have to give tips to beginners like me 😉

    • Benedict Simlinger Benedict Simlinger

      Hi,

      happy to hear that -flto=1 did the trick, congratulations on your success and thanks for reporting back your results.

      Regarding cross-compiling:
      1) Before setting up a cross-compiler try to do as much work as possible on your development computer or some spare computer/laptop

      2) Setting up a cross-compiler requires some trial-and-error in my experience. I recommend you try following the instructions given by Stefan [1], who is also owner of this blog. Depending on your time budget setting up a cross-compiler toolchain might be not worth the effort.

      3) Thanks to ‘make’, the build process will be faster if you’re rebuilding the code a second time with minor changes. How much time does a rebuild take?

      Regarding your manual:
      That’s very kind of you! I’ll contact you by mail to work something out.

      Cheers!

      [1] https://stackoverflow.com/questions/19162072/how-to-install-the-raspberry-pi-cross-compiler-on-my-linux-host-machine/58559140#58559140

  11. Klemens Klemens

    Hello Benedict,

    I’m already two steps further along with the crosscompiler, but it’s more likely to be a paid add-on for Visual Studio. I am currently testing VisualGDB here.

    Then I had now also tried whether the whole compiles faster when I build it again. Unfortunately, nothing changes here, of course in relation to the make -j command, but not with the gcc command… that would have surprised me, the gcc command has no temporary files, which would make it faster. However, I am still a beginner and can also be completely wrong here.

    Greetings Klemens

    • Benedict Simlinger Benedict Simlinger

      Hi Klemens,

      good to see you making progress & thanks for sharing!

      @ paid add-on for VS / VisalGDB:
      Hm, I am not exactly sure what code you’re working on / debugging right now but to me it looks like VisualGDB reproduces many features in Visual Studio that you would find for free in any common Linux IDE. But whatever floats your boat, I don’t know your skills, preferences, setup, … 🙂

      @ faster re-compiles:
      You’re right. I had ‘make’ in mind. For a single gcc call it won’t help.

      Cheers!

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.