Building the Low-Level OPC UA Client Library

Two options for the low-level client library are supported:

These options are alternative - you only need one.

The choice is completely transparent on the IOC. Neither your databases nor the startup script need any change when you switch between the options.

Choose your option, then follow the appropriate instructions that provide all the details:

Option A: open62541 Client SDK

The open62541 Client SDK option was added later, in 2024. The client library is not as complete and robust as the UASDK, we have seen the API change over recent years.

However, as the open62541 project is getting more mature and stable, an increasing number of Device Support users have switched to this option.

Status

Despite of being relatively new, this option is gaining popularity and getting more and more hours of production use.

Please contact the authors Dirk Zimoch and Ralph Lange for details.

Prerequisites

  • open62541 SDK / C library (v1.2 and v1.3 series have been tested; their system packages should also work. open62541 v1.4 changed the header file structure and does not work yet.)

  • Cmake (3.x) if you’re building open62541 from sources.

  • For OPC UA security support (authentication/encryption), we suggest using the openssl plugin for open62541. For that to work, you need openssl on your system - both when compiling the client library and when generating any binaries (IOCs). On Linux, the name of the package you have to install depends on the distribution: development packages are called openssl-devel on RedHat/CentOS/Fedora and libssl-dev on Debian/Ubuntu, runtime packages are called openssl on RedHat/CentOS/Fedora and libssl on Debian/Ubuntu, respectively. See below for Windows instructions. In your CONFIG_SITE.local file (see below), enable the OPC UA Security option.

Building Open62541

Note

The open62541 project is focused on the server implementation of OPC UA. The client functionality is fully supported, complete and usable, but it does not get the attention that the server parts get.

Caution

Do not use the download link on the open62541 web site. Use their GitHub Release Page instead.

On Linux

  • Unpack the open62541 distribution. Create a build directory on the top level and cd into it. We’ll go with the usual convention of calling it build .

  • The cmake build of Open62541 creates a static library by default. This type of library is needed for the EMBED type of Device Support build (see below).

    To create shared libraries, build the Open62541 library setting the cmake option BUILD_SHARED_LIBS=ON.

    cmake .. -DBUILD_SHARED_LIBS=ON [...]
    

    You can create both types by running two builds with different configurations in the same build directory. Remove the CMakeCache between the builds to get clean configurations.

  • Open62541 supports multiple low-level libraries to implement OPC UA Security. The most widely used option (that also keeps things simple by staying in line with the UA SDK client) is based on openssl. We suggest to select that by setting the cmake option UA_ENABLE_ENCRYPTION=OPENSSL.

  • Given all the above, for a Linux build, a reasonable option setting would be:

    cmake .. -DBUILD_SHARED_LIBS=ON \
             -DCMAKE_BUILD_TYPE=RelWithDebInfo \
             -DUA_ENABLE_ENCRYPTION=OPENSSL
    

    to create a shared library, and

    cmake .. -DBUILD_SHARED_LIBS=OFF \
             -DCMAKE_BUILD_TYPE=RelWithDebInfo \
             -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=OFF \
             -DUA_ENABLE_ENCRYPTION=OPENSSL
    

    to create the static variant.

    There are a lot of other options available, but most of them affect only the server part and are not relevant for use of the client.

    For Open62541 version 1.2, set UA_ENABLE_ENCRYPTION_OPENSSL=ON instead of the OPENSSL setting shown above. You may also have to explicitly set the open62541 version string in file CMakeLists.txt, as the auto-detection doesn’t work when you’re not working under git.

  • The default installation location is below /usr/local. Normally, this is a system location, so that the deploy mode setting (see below) would be SYSTEM. If you want to install into a different location, set the option CMAKE_INSTALL_PREFIX=/other/location. In that case, the deploy mode setting (see below) would be PROVIDED and the library location needs to be set. The same is true if you want to use the Open62541 library in its build location (not recommended). The library location (set in CONFIG_SITE.local) would be $(OPEN62541)/build/bin or $(OPEN62541)/build/bin/Release or something different, depending on your installation, OS and choice of build directory name.

  • After running cmake, run make followed by make install. Installation into a system location will need root permission.

On Windows

See the EPICS Windows Installation How-To for an overview and introduction to the different compilation options under Windows.

Using MSYS2/MinGW

  • Install the necessary tools and dependencies using the pacman system package manager. You will need mingw-w64-x86_64-cmake, mingw-w64-x86_64-libxml2 and mingw-w64-x86_64-openssl.

  • Unpack the open62541 distribution. Create a build directory on the top level and cd into it. We’ll go with the usual convention of calling it build .

  • A reasonable option setting for running cmake would look similar to the Linux variant:

    cmake .. -G "MinGW Makefiles" \
             -DBUILD_SHARED_LIBS=ON \
             -DCMAKE_BUILD_TYPE=RelWithDebInfo \
             -DUA_ENABLE_ENCRYPTION=OPENSSL
    
  • Run mingw32-make followed by mingw32-make install.

Using MSVC

  • Get the necessary prerequisites and install them: Python version 3 can be found here. libml2 and iconv binaries for Windows can be found here or here. Install them in an appropriate location. You might have to rename .dll.a DLL export stubs to .lib to work properly with the EPICS build system. openssl can be found here. The installer makes sure that MSVC finds it (without explicit configuration).

  • Unpack the open62541 distribution. Create a build directory on the top level and cd into it. We’ll go with the usual convention of calling it build .

  • A reasonable option setting for running cmake would look like this:

    cmake .. -DBUILD_SHARED_LIBS=ON \
             -DCMAKE_BUILD_TYPE=RelWithDebInfo \
             -DUA_ENABLE_ENCRYPTION=OPENSSL
    

    plus -DCMAKE_INSTALL_PREFIX=/other/location if you want to select where things are installed.

    The cmake configuration seems to have a bug (seen on 1.3.6) that always selects Release for the path of the library to install. The easiest fix is to replace that string with the appropriate path (Debug) in two places in the block between lines 35 and 55 of the file cmake_install.cmake.

  • Run cmake --build . followed by cmake --install . to build and install the library.

Configure the Device Support Module

Inside the configure subdirectory or one level above the TOP location, create a file RELEASE.local that sets EPICS_BASE to the absolute path of your EPICS installation.

Inside the configure subdirectory or one level above the TOP location, create a file CONFIG_SITE.local that sets the absolute path of your Open62541 installation as well as its build and deploy features if necessary. You also need to configure the locations of the other dependencies that you installed.

# Path to the Open62541 C++ installation
OPEN62541 = /other/location

# How the Open62541 shared libraries are deployed
#   SYSTEM = shared libs are in a system location
#   PROVIDED = shared libs are in $(OPEN62541_SHRLIB_DIR)
#   INSTALL = shared libs are installed (copied) into this module
#   EMBED = link Open62541 code statically into libopcua,
#           the Open62541 libraries are not required on target system
OPEN62541_DEPLOY_MODE = PROVIDED
OPEN62541_LIB_DIR = $(OPEN62541)/lib
OPEN62541_SHRLIB_DIR = $(OPEN62541_LIB_DIR)
# How the Open62541 libraries were built
OPEN62541_USE_CRYPTO = YES
OPEN62541_USE_XMLPARSER = YES

This open62541 related configuration is only needed in the Device Support module. During the build, it creates a CONFIG_OPCUA file that is automatically included by all downstream (IOC-generating) modules and applications. This ensures that the configuration is always consistent.

Windows Specifics

All paths in EPICS build configuration files must use Windows “short names” where needed, e.g.

OPEN62541 = C:/PROGRA~2/open62541-1.3.6-MinGW/

If you’re using MSYS2/MinGW64, you need to set the location of the MinGW64 installation in a CONFIG_SITE file, e.g.

# Location of MSYS2/MinGW64
MSYSTEM_PREFIX = C:/msys64/mingw64

When using MSVC, you need to add the settings for the dependencies that you installed in non-system locations:

# Prerequisites: libxml2 iconv
LIBXML2 = C:/dependency/location/libxml2-2.9.3
ICONV = C:/dependency/location/iconv-1.14

As always on Windows, the build environment as well as the runtime environment (for any IOC) need to have the locations of all DLLs in the PATH to be able to run binaries (also applies to the unit tests). You will need to add the appropriate locations for EPICS Base, the opcua module, the open62541 library and all other dependencies you installed. Alternatively, you can put copies of all needed DLLs into the location of the binaries. (Remember that make distclean will remove those copies.)

Caution

Over time, Windows systems will have a large number of possibly different DLLs with the same names and/or versions being used concurrently on the system - a situation that is hard to maintain and known as DLL Hell.

If you want your IOC binaries to be deployable without depending on specific DLLs being present on the target system, consider linking your IOCs statically. (Note that static builds are not available when using the evaluation bundles.)

Known issues

n/a

Credits

The adaption of the open62541 client library has been done by Dirk Zimoch (PSI) with help from Carsten Winkler (HZB/BESSY II). Additional EPICS build system magic by Ralph Lange (ITER).

Option B: Unified Automation C++ Client SDK

The Unified Automation SDK (UASDK) was the first and original low-level client used in the OPC UA Device Support. It is a very stable and complete “gold-standard” implementation.

Unified Automation offers a freely available evaluation bundle (binary), which offers full functionality with a running time limited to one hour.

Status

Support for this low-level client is stable, with some expected development still to be happening.

Please contact the authors Dirk Zimoch and Ralph Lange for details.

Prerequisites

  • Unified Automation C++ Based OPC UA Client SDK (1.5/1.6/1.7 are supported, as well as their evaluation bundles).

  • Windows and Linux builds are supported.

  • The evaluation binary bundles by Unified Automation (free download) are supported. However, the EVAL bundle contains a shared library (DLL), namely the stack component, see below, so only shared builds of the Device Support will work.

On Linux

  • For OPC UA security support (authentication/encryption), you need libcrypto on your system - both when compiling the SDK and when generating any binaries (IOCs). The name of the package you have to install depends on the Linux distribution: openssl-devel on RedHat/CentOS/Fedora, libssl-dev on Debian/Ubuntu.

  • The UA Client SDK sets BUILD_SHARED_LIBS=OFF as default. To create shared SDK libraries, build the SDK using

    ./buildSdk.sh -s ON
    

    In many versions of the SDK, the buildSdk.sh build script does not apply the -s ON setting to the stack component. To fix this and create a complete shared library set of the SDK, apply the following patch (shown for 1.5.5):

    --- buildSdk.sh
    +++ buildSdk.sh
    @@ -95,7 +95,7 @@
         cd $UASDKDIR/build$config || { echo "cd $UASDKDIR/build$config failed."; exit 1; }
         # create the Makefile using CMake
         # Just create only the SDK Makefiles
    -    cmake "$TOOLCHAIN" "$OPTION" -DBUILD_EXAMPLES=off -DBUILD_UACLIENTCPP_APP=off -DBUILD_UASERVERCPP_APP=off -DENABLE_GCC_FORTIFY_SOURCE=off -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX $UASDKDIR
    +    cmake "$TOOLCHAIN" "$OPTION" -DBUILD_EXAMPLES=off -DBUILD_UACLIENTCPP_APP=off -DBUILD_UASERVERCPP_APP=off -DENABLE_GCC_FORTIFY_SOURCE=off -DCMAKE_BUILD_TYPE=$config -DBUILD_SHARED_LIBS=$BUILD_SHARED_LIBS -DBUILD_SHARED_STACK=$BUILD_SHARED_LIBS -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX $UASDKDIR
         # build
         make "$JOBS" || { echo "make failed."; exit 1; }
         # install
    

    You can build the shared and the static versions of the SDK in the same location (there are no artifact conflicts). This allows full flexibility for the Device Support module and your IOC applications, i.e., static and shared builds.

On Windows

  • Extract the SDK to a known location, e.g., /opt/unifiedautomation/UaSdkCppBundle or C:\Program Files\UnifiedAutomation\UaSdkCppBundle. This is where the Makefile variable UASDK should point to (see below).

  • Binary libraries (DLLs and headers) of matching versions for openssl and libxml2 are provided under the third-party directory of the SDK bundle.

Configure the Device Support Module

Inside the configure subdirectory or one level above the TOP location, create a file RELEASE.local that sets EPICS_BASE to the absolute path of your EPICS installation.

Inside the configure subdirectory or one level above the TOP location, create a file CONFIG_SITE.local that sets the absolute path of your SDK installation as well as the SDK build and deploy features if necessary.

# Path to the Unified Automation OPC UA C++ SDK
UASDK = /usr/local/opcua/uasdkcppclient-v1.5.3-346/sdk

# How the Unified Automation SDK shared libraries are deployed
#   SYSTEM = shared libs are in a system location
#   PROVIDED = shared libs are in $(UASDK_SHRLIB_DIR)
#   INSTALL = shared libs are installed (copied) into this module
#   EMBED = link SDK code statically into libopcua,
#           SDK libraries are not required on target system
UASDK_DEPLOY_MODE = PROVIDED
UASDK_LIB_DIR = $(UASDK)/lib
UASDK_SHRLIB_DIR = $(UASDK_LIB_DIR)
# How the Unified Automation SDK libraries were built
UASDK_USE_CRYPTO = YES
UASDK_USE_XMLPARSER = YES

This SDK related configuration is only needed in the Device Support module. During the build, it creates a CONFIG_OPCUA file that is automatically included by all downstream (IOC-generating) modules and applications. This ensures that the configuration is always consistent.

Caution

When using the evaluation bundle of the SDK, only regular (shared) builds are supported. Do not set STATIC_BUILD = YES in your configuration.

Windows Specifics

Windows builds should use UASDK_DEPLOY_MODE = PROVIDED and set UASDK to the location of the Unified Automation bundle.

All paths in EPICS build configuration files must use Windows “short names” where needed, e.g.

UASDK = C:/PROGRA~2/UnifiedAutomation/UaSdkCppBundleEval

In your CONFIG_SITE.local, you also need to define the locations of the supplied third-party dependencies.

# Prerequisites: libxml2 openssl
LIBXML2 = $(UASDK)/third-party/win64/vs2015/libxml2
OPENSSL = $(UASDK)/third-party/win64/vs2015/openssl

Caution

Different versions of the Unified Automation bundle have these libraries in different folders, under different names. Check configure/CONFIG_SITE.Common.win32-x86 and adapt the settings to your situation.

If you do not have Administrator rights or if you want to unpack multiple versions of the UA SDK bundle, UniExtract2 is your friend.

Caution

The evaluation bundle only contains binary libraries to be used with the MSVC compilers. MinGW can not be used with the libraries from the bundle, as the C++ name mangling is different.

As always on Windows, the build environment as well as the runtime environment (for any IOC) need to have the locations of all DLLs in the PATH to be able to run binaries (also applies to the unit tests). You will need to add the appropriate locations for EPICS Base, the opcua module, the UASDK library and all other dependencies you installed. Alternatively, you can put copies of all needed DLLs into the location of the binaries. (Remember that make distclean will remove those copies.)

Caution

Over time, Windows systems will have a large number of possibly different DLLs with the same names and/or versions being used concurrently on the system - a situation that is hard to maintain and known as DLL Hell.

If you want your IOC binaries to be deployable without depending on specific DLLs being present on the target system, consider linking your IOCs statically. (Note that static builds are not available when using the evaluation bundles.)

On newer Windows systems, the Windows system version of the openssl DLLs are not compatible with the UA SDK bundled versions (see below). Copy the vendor-supplied DLLs next to the binaries to avoid a mismatch.

Known issues

Reported by Shi Li (ASIPP): The C++ SDK version 1.7.1 has a bug that shows as monitored items not getting updates anymore after the server has disconnected and reconnected. A reboot of the IOC restores good behavior until the server disconnects again. Updating the C++ SDK to version 1.7.2 resolves the issue.

Credits

This option is based on extensive prototype work by Bernhard Kuner (HZB/BESSY). Support for Windows builds with help from Carsten Winkler (HZB/BESSY).