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.
Generate and link a model¶
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.
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:
--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.