Skip to content

CMake integration

ncc_generate_model generates your model, compiles it into a library, and supplies its headers and link dependencies to your application. It regenerates the code when inputs change.

With ncc and a compatible open62541 SDK installed, add this to CMakeLists.txt. Replace MyModel.xml, Opc.Ua.NodeSet2.xml and server.c with your files:

cmake_minimum_required(VERSION 3.20)
project(my_server C)
find_package(open62541 CONFIG REQUIRED)

# Find and load the ncc helper.
find_program(NCC_EXECUTABLE ncc REQUIRED)
execute_process(COMMAND "${NCC_EXECUTABLE}" c --cmake-dir
    OUTPUT_VARIABLE ncc_cmake OUTPUT_STRIP_TRAILING_WHITESPACE
    COMMAND_ERROR_IS_FATAL ANY)
include("${ncc_cmake}/Ncc.cmake")

# Generate the model and link it to your application.
ncc_generate_model(TARGET model NAME mymodel
    FILES MyModel.xml
    EXISTING Opc.Ua.NodeSet2.xml)

add_executable(server server.c)
target_link_libraries(server PRIVATE model)

In server.c, include mymodel.h and call mymodel(server) after creating the server. Check for UA_STATUSCODE_GOOD before starting it; see the initialization example.

cmake -S . -B build
cmake --build build

Generated files go into build/ncc/model/. Include paths and linking are handled by the model target.

If CMake cannot find ncc or open62541

Add -DNCC_EXECUTABLE=/path/to/ncc or -DCMAKE_PREFIX_PATH=/path/to/open62541 to the configure command.

Custom datatypes

Add CSV and BSD to the model declaration:

ncc_generate_model(TARGET model NAME mymodel
    FILES MyModel.xml EXISTING Opc.Ua.NodeSet2.xml
    CSV MyModel.NodeIds.csv BSD MyModel.Types.bsd)

Omit BSD if the XML contains an embedded dictionary. XML <Definition> elements alone do not supply C layouts. See datatype generation.

Dependency models

Declare the dependency first, then refer to its target:

ncc_generate_model(TARGET model_base NAME base
    FILES Base.xml EXISTING Opc.Ua.NodeSet2.xml)
ncc_generate_model(TARGET model NAME mymodel
    FILES MyModel.xml DEPENDS_TARGETS model_base)

DEPENDS_TARGETS carries dependency XML, arrays, metadata and link libraries. Your application must still call base(server) before mymodel(server) and check both results.

If a datatype uses a dependency's custom type, also add IMPORT_BSD "UA_TYPES_BASE#Base.Types.bsd" to the dependent model.

Arguments

Argument Meaning
TARGET Required library target to create.
NAME Required initializer and output name; must remain distinct after lowercasing.
FILES Required target XML paths, combined into one model.
EXISTING Dependency XML paths, without SHORTNAME= prefixes.
BSD, CSV Type dictionaries and NodeId CSV files.
IMPORT_BSD TYPE_ARRAY#path.bsd imports.
DEPENDS_TARGETS Previously declared model targets.
TYPES_ARRAY, TYPES_METADATA External datatype arrays and metadata; link their sources or libraries separately.
BLACKLIST, IGNORE Node-filter files.
SELECTED_TYPES, OPAQUE_MAP Datatype selection and opaque mapping files.
NAMESPACE_MAP INDEX:URI mappings for standalone datatype use.
OUTPUT_DIRECTORY Defaults to ncc/<TARGET> under the current binary directory.
GEN_DOC Also generate datatype RST documentation.

Relative inputs use the current source directory; relative outputs use the current binary directory. The helper runs ncc c model. Changed inputs or settings and deleted outputs trigger generation; failures stop the build. Keep each target's output files exclusive to that target.

SDK headers

Separate headers and amalgamation (open62541.h) are supported. Header selection is automatic with C compilers that support __has_include.

Older compilers default to separate headers. To select amalgamation, apply this to each generated model or datatype library:

target_compile_definitions(model PUBLIC NCC_USE_AMALGAMATION)

--internal-headers is a compatibility no-op.

Supported runtime configuration

Preserve XML initial values

Enable UA_ENABLE_XML_ENCODING in open62541. Otherwise, values may be absent or replaced by defaults even when initialization returns Good.

Model feature Requirement
Dependencies Load their nodes before the dependent model. Richer models may require full NS0.
Methods Enable UA_ENABLE_METHODCALLS and supply application callbacks.
Custom datatype registries One server per registry; repeated initialization and sharing between servers with different namespace orders are unsupported.

Tested with open62541 revision 3bea2f6a7b655e7c48841fe78668edd540997bfc, separate headers and amalgamation, and reduced NS0. Check your model's values as well as startup status. Automatic model injection, NS0 stack-build replacement and Graphviz generation are outside this workflow.

Independent artifact generation

Use these helpers when generation and compilation need separate targets, such as when migrating an existing build. They require no SDK or C compiler; use ncc_generate_model above for a library you can link directly.

Generate files

Load Ncc.cmake as above, then declare the generation targets:

ncc_generate_datatypes(TARGET custom_types NAME types_custom
    BSD Custom.Types.bsd CSV Custom.NodeIds.csv
    NAMESPACE_MAP 2:urn:my:custom NO_BUILTIN)
ncc_generate_nodeid_header(TARGET custom_ids NAME custom_nodeids
    CSV Custom.NodeIds.csv PREFIX CUSTOM)
get_target_property(type_dir custom_types NCC_INCLUDE_DIRS)
ncc_generate_nodeset(TARGET custom_nodes NAME namespace_custom_generated
    FILES Custom.xml EXISTING Opc.Ua.NodeSet2.xml
    BSD Custom.Types.bsd TYPES_ARRAY UA_TYPES_CUSTOM
    TYPES_METADATA "${type_dir}/types_custom_generated.ncc.json"
    DEPENDS_TARGETS custom_types)
add_custom_target(generate_all ALL DEPENDS custom_types custom_ids custom_nodes)

Replace the input paths and namespace mapping with your model's values. Each helper requires TARGET and NAME; outputs default to ncc/<TARGET> under the current binary directory. Run cmake --build build, or build an individual target with --target custom_types.

Here, DEPENDS_TARGETS only orders generation. Supply dependency XML, arrays, metadata and imports explicitly; use DEPENDS for extra tracked files. To reuse upstream tables, omit TYPES_METADATA and track their C and header files with DEPENDS.

Helper Additional options
ncc_generate_datatypes XML, IMPORT_BSD, SELECTED_TYPES, OPAQUE_MAP, INTERNAL, GEN_DOC.
ncc_generate_nodeset BLACKLIST, IGNORE, INTERNAL_HEADERS, VERBOSE.
ncc_generate_nodeid_header One CSV and a case-sensitive PREFIX; emits <NAME>.h with UA_<PREFIX>ID_<SYMBOL> constants.

Compile the generated files

Continuing the example above:

find_package(open62541 CONFIG REQUIRED)
get_target_property(type_sources custom_types NCC_SOURCES)
get_target_property(node_sources custom_nodes NCC_SOURCES)
get_target_property(node_dir custom_nodes NCC_INCLUDE_DIRS)
get_target_property(id_dir custom_ids NCC_INCLUDE_DIRS)
add_executable(server server.c ${type_sources} ${node_sources})
add_dependencies(server custom_types custom_nodes custom_ids)
target_include_directories(server PRIVATE "${type_dir}" "${node_dir}" "${id_dir}")
target_link_libraries(server PRIVATE open62541::open62541)

Independent targets generate files; they are not libraries. Each exposes absolute paths through these properties:

Property Content
NCC_SOURCES Generated C files; empty for NodeId headers.
NCC_HEADERS Public headers.
NCC_OUTPUTS All outputs, including metadata and optional documentation.
NCC_INCLUDE_DIRS Generated include directory.

For pre-existing tables, add their C files or library and include path instead of type_sources and type_dir.