Skip to content

Migrating from open62541

Replace the NodeSet compiler scripts shipped with open62541 with ncc, while keeping your model inputs and the generated filenames and symbols your application uses. For example:

Before

python /path/to/open62541/tools/nodeset_compiler/nodeset_compiler.py \
    -e Opc.Ua.NodeSet2.xml -x MyModel.xml \
    generated/namespace_mymodel_generated

After

ncc c MyModel.xml -e Opc.Ua.NodeSet2.xml \
    --shortname namespace_mymodel_generated -o generated

Both commands produce namespace_mymodel_generated.c/.h and an initializer named namespace_mymodel_generated. Replace the example paths with your existing inputs and output basename. Install the compiler with python -m pip install o6-ncc; generation does not require an installed open62541 SDK. Building the generated C still requires your SDK and C toolchain.

Choose the replacement command or CMake function

Existing tool or workflow ncc replacement command or CMake function
nodeset_compiler.py Terminal command: ncc c
generate_datatypes.py Terminal command: ncc c datatypes
generate_nodeid_header.py Terminal command: ncc c nodeids
generate_bsd.py Terminal command: ncc c bsd
Separate CMake generation helpers CMake helper functions: ncc_generate_nodeset, ncc_generate_datatypes, ncc_generate_nodeid_header
Coordinated generation of all model artifacts ncc c model; CMake helper function: ncc_generate_model

cncc is an alias for ncc c, including its subcommands. The examples below use separate commands so you can preserve your application's names and build steps.

Replace address-space generation

Replace nodeset_compiler.py while keeping the generated filenames and initializer:

Before

python /path/to/open62541/tools/nodeset_compiler/nodeset_compiler.py \
    -e Opc.Ua.NodeSet2.xml -x MyModel.xml \
    generated/namespace_mymodel_generated

After

ncc c MyModel.xml -e Opc.Ua.NodeSet2.xml \
    --shortname namespace_mymodel_generated -o generated
Upstream argument ncc argument
-x MyModel.xml MyModel.xml; supply multiple targets as positional inputs
Positional generated/namespace_mymodel_generated --shortname namespace_mymodel_generated -o generated
-e Dependency.xml Same; repeat for every dependency
--bsd MyTypes.bsd, -t UA_TYPES_MYMODEL Same; preserve array order
-b blacklist.txt, -i ignore.txt, -v Same
--internal-headers Accepted; SDK headers are selected at C compile time

Keep all dependency XMLs in -e, including transitive dependencies, and load their initializers before the dependent model. See the command reference for output naming and the generated API.

Replace address-space generation while keeping existing datatype tables

Supply your existing datatype arrays and BSD definitions to keep using the upstream-generated datatype .c and .h files:

ncc c MyModel.xml -e Opc.Ua.NodeSet2.xml --bsd MyTypes.bsd \
    -t UA_TYPES_MYMODEL --shortname namespace_mymodel_generated -o generated

No metadata or table regeneration is required; preserve array order, output basename and runtime namespace assumptions. See external datatype tables.

Replace datatype generation while keeping filenames and symbols

Replace generate_datatypes.py, keeping the output basename to preserve types_mymodel_generated.c/.h and UA_TYPES_MYMODEL:

Before

python /path/to/open62541/tools/generate_datatypes.py \
    -t MyTypes.bsd -c NodeIds.csv --no-builtin generated/types_mymodel

After

ncc c datatypes -t MyTypes.bsd -c NodeIds.csv --no-builtin \
    --namespaceMap 2:urn:my:model generated/types_mymodel
  • Replace 2:urn:my:model with the namespace index needed by your standalone consumer and the BSD's TargetNamespace; supply one mapping per custom namespace, matching any namespace-qualified CSV IDs.
  • Keep the generated .ncc.json beside the table files and regenerate them together; it enables namespace resolution by URI during initialization. If the tables are outside the address-space output directory, pass --types-metadata /path/to/types_mymodel_generated.ncc.json.

See datatype options for imports, selections and opaque mappings.

Replace NodeId header generation while keeping macro names

Replace generate_nodeid_header.py, preserving the header basename and case-sensitive namespace prefix:

Before

python /path/to/open62541/tools/generate_nodeid_header.py NodeIds.csv generated/ids NS0

After

ncc c nodeids NodeIds.csv --prefix NS0 -o generated/ids.h

Include .h in the output path. This preserves constants such as UA_NS0ID_MYVARIABLE; ncc c model instead uses NCC_<NAME>_ID_... names. See NodeId constants for CSV formats.

Replace BSD extraction while keeping your datatype generator

Replace generate_bsd.py and continue passing the extracted BSD file to your existing datatype generator:

Before

python /path/to/open62541/tools/generate_bsd.py -x MyModel.xml generated/MyTypes.bsd

After

ncc c bsd MyModel.xml -o generated/MyTypes.bsd

The decoded bytes are preserved; exactly one distinct embedded dictionary is required. XML <Definition> elements alone do not provide BSD layouts. See extraction behavior.

Load the ncc CMake helper

Add this after project(...) to load Ncc.cmake (CMake 3.20 or newer):

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")

Replace CMake generation calls while keeping existing targets

Replace ua_generate_nodeset while preserving filenames, the initializer, the generator target name and existing datatype tables:

Before, using open62541Macros.cmake

ua_generate_nodeset(NAME mymodel FILE MyModel.xml
    DEPENDS_NS Opc.Ua.NodeSet2.xml FILES_BSD MyTypes.bsd
    TYPES_ARRAY UA_TYPES_MYMODEL OUTPUT_DIR "${CMAKE_BINARY_DIR}/generated")

After, using Ncc.cmake

ncc_generate_nodeset(TARGET open62541-generator-ns-mymodel
    NAME namespace_mymodel_generated FILES MyModel.xml
    EXISTING Opc.Ua.NodeSet2.xml BSD MyTypes.bsd TYPES_ARRAY UA_TYPES_MYMODEL
    OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/generated")
Upstream helper ncc helper Argument changes
ua_generate_nodeset ncc_generate_nodeset NAME mymodel → NAME namespace_mymodel_generated; FILE → FILES, DEPENDS_NS → EXISTING, FILES_BSD → BSD; combine DEPENDS_TYPES and TYPES_ARRAY in order as TYPES_ARRAY.
ua_generate_datatypes ncc_generate_datatypes Keep NAME; FILES_BSD → BSD, FILE_CSV → CSV, FILE_XML → XML, FILES_SELECTED → SELECTED_TYPES; add NAMESPACE_MAP for custom namespaces and NO_BUILTIN to retain upstream's default.
ua_generate_nodeid_header ncc_generate_nodeid_header Keep NAME; FILE_CSV → CSV, ID_PREFIX → PREFIX.
  • Replace OUTPUT_DIR with OUTPUT_DIRECTORY and set TARGET explicitly.
  • Read NCC_SOURCES, NCC_HEADERS, NCC_OUTPUTS and NCC_INCLUDE_DIRS with get_target_property instead of upstream's exported variables.
  • DEPENDS_TARGETS orders generation; supply dependency XML, arrays and metadata explicitly. Use DEPENDS for file dependencies.

These helpers need no SDK or C compiler. See independent CMake generation for linking the outputs, or model integration to adopt ncc_generate_model, its combined artifact naming and SDK-linked static library.

Check your migrated application

Rebuild with the same SDK and inputs, then check filenames, includes, symbols, namespace and datatype identities, and initial values. XML initial values require UA_ENABLE_XML_ENCODING; an initializer returning Good does not verify them.

The tested baseline is open62541 revision 3bea2f6a7b655e7c48841fe78668edd540997bfc on Linux, with separate headers and amalgamation using reduced NS0. Coverage is custom-model generation, excluding SDK-internal/NS0 generation and AUTOLOAD integration. See runtime requirements.