Przeglądaj źródła

NodesetCompiler: Add ua_generate_datatypes CMake macro

This macro simplyfies the usage of the generate_datatypes.py script
Stefan Profanter 6 lat temu
rodzic
commit
0840848622

+ 17 - 48
CMakeLists.txt

@@ -674,57 +674,26 @@ if(NOT EXISTS "${UA_FILE_NS0}")
     message(FATAL_ERROR "File ${UA_FILE_NS0} not found. You probably need to initialize the git submodule for deps/ua-nodeset.")
 endif()
 
-set(SELECTED_TYPES_TMP "")
-foreach(f ${UA_FILE_DATATYPES})
-    set(SELECTED_TYPES_TMP ${SELECTED_TYPES_TMP} "--selected-types=${f}")
-endforeach()
-
 # standard-defined data types
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_handling.h
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_encoding_binary.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                           --type-csv=${UA_FILE_NODEIDS}
-                           ${SELECTED_TYPES_TMP}
-                           --type-bsd=${UA_FILE_TYPES_BSD}
-                           ${PROJECT_BINARY_DIR}/src_generated/ua_types
-                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
-                           ${UA_FILE_NODEIDS}
-                           ${UA_FILE_TYPES_BSD}
-                           ${UA_FILE_DATATYPES})
-# we need a custom target to avoid that the generator is called concurrently and thus overwriting files while the other thread is compiling
-add_custom_target(open62541-generator-types DEPENDS
-                  ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.c
-                  ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated.h
-                  ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_handling.h
-                  ${PROJECT_BINARY_DIR}/src_generated/ua_types_generated_encoding_binary.h)
+ua_generate_datatypes(
+    BUILTIN
+    NAME "ua_types"
+    TARGET_SUFFIX "types"
+    NAMESPACE_IDX 0
+    FILE_CSV "${UA_FILE_NODEIDS}"
+    FILES_BSD "${UA_FILE_TYPES_BSD}"
+    FILES_SELECTED ${UA_FILE_DATATYPES}
+)
 
 # transport data types
-add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_handling.h
-                          ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_encoding_binary.h
-                   PRE_BUILD
-                   COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                           --namespace=1
-                           --selected-types=${PROJECT_SOURCE_DIR}/tools/schema/datatypes_transport.txt
-                           --type-bsd=${UA_FILE_TYPES_BSD}
-                           --type-bsd=${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd
-                           --no-builtin
-                           ${PROJECT_BINARY_DIR}/src_generated/ua_transport
-                   DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/generate_datatypes.py
-                           ${PROJECT_SOURCE_DIR}/tools/schema/datatypes_transport.txt
-                           ${UA_FILE_TYPES_BSD}
-                           ${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd)
-
-# we need a custom target to avoid that the generator is called concurrently and thus overwriting files while the other thread is compiling
-add_custom_target(open62541-generator-transport DEPENDS
-        ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.c
-        ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated.h
-        ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_handling.h
-        ${PROJECT_BINARY_DIR}/src_generated/ua_transport_generated_encoding_binary.h)
+ua_generate_datatypes(
+    NAME "ua_transport"
+    TARGET_SUFFIX "transport"
+    NAMESPACE_IDX 1
+    FILE_CSV "${UA_FILE_NODEIDS}"
+    FILES_BSD "${UA_FILE_TYPES_BSD}" "${PROJECT_SOURCE_DIR}/tools/schema/Custom.Opc.Ua.Transport.bsd"
+    FILES_SELECTED "${PROJECT_SOURCE_DIR}/tools/schema/datatypes_transport.txt"
+)
 
 # statuscode explanation
 add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_statuscodes.h

+ 12 - 11
doc/nodeset_compiler.rst

@@ -376,17 +376,18 @@ Combination of multiple nodesets
 
 In previous section you have seen how you can use the nodeset compiler with one single nodeset which depends on the default nodeset (NS0) ``Opc.Ua.NodeSet2.xml``. The nodeset compiler also supports nodesets which depend on more than one nodeset. We will show this use-case with the PLCopen nodeset. The PLCopen nodeset ``Opc.Ua.Plc.NodeSet2.xml`` depends on the DI nodeset ``Opc.Ua.Di.NodeSet2.xml`` which then depends on NS0. This example is also shown in ``examples/nodeset/CMakeLists.txt``.
 
-This DI nodeset makes use of some additional data types in ``deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd``. Since we also need these types within the generated code, we first need to compile the types into C code. The generated code is mainly a definition of the binary representation of the types required for encoding and decoding. The generation can be done using the ``tools/generate_datatypes.py`` script::
-
-    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-    --namespace=2
-    --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-    --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd
-    --no-builtin
-    ${PROJECT_BINARY_DIR}/src_generated/ua_types_di
-
-The ``namespace`` parameter indicates the namespace index of the generated node IDs for the type definitions. Currently we need to rely that the namespace is also added at this position in the final server. There is no automatic inferring yet (pull requests are warmly welcome).
-The CSV and BSD files contain the metadata and definition for the types. The ``--no-builtin`` argument tells the script to skip internal datatypes which are always included in the stack. The last parameter is the output file and at the same time the name of the types array: ``UA_TYPES_DI``.
+This DI nodeset makes use of some additional data types in ``deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd``. Since we also need these types within the generated code, we first need to compile the types into C code. The generated code is mainly a definition of the binary representation of the types required for encoding and decoding. The generation can be done using the ``ua_generate_datatypes`` CMake function, which uses the ``tools/generate_datatypes.py`` script::
+
+    ua_generate_datatypes(
+        NAME "ua_types_di"
+        TARGET_SUFFIX "types-di"
+        NAMESPACE_IDX 2
+        FILE_CSV "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv"
+        FILES_BSD "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd"
+    )
+
+The ``NAMESPACE_IDX`` parameter indicates the namespace index of the generated node IDs for the type definitions. Currently we need to rely that the namespace is also added at this position in the final server. There is no automatic inferring yet (pull requests are warmly welcome).
+The CSV and BSD files contain the metadata and definition for the types. ``TARGET_SUFFIX`` is used to create a new target with the name ``open62541-generator-TARGET_SUFFIX``.
 
 Now you can compile the DI nodeset XML using the following command::
 

+ 8 - 16
examples/nodeset/CMakeLists.txt

@@ -48,22 +48,14 @@ endif()
 if(UA_NAMESPACE_ZERO STREQUAL "FULL")
 
     # Generate types for DI namespace
-    set(UA_TYPES_OUT "ua_types_di")
-    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c
-                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.h
-                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_handling.h
-                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated_encoding_binary.h
-                       PRE_BUILD
-                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       --namespace=2
-                       --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                       --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd
-                       --no-builtin
-                       ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}
-                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd)
-    add_custom_target(open62541-generator-types-di DEPENDS ${PROJECT_BINARY_DIR}/src_generated/${UA_TYPES_OUT}_generated.c)
+    ua_generate_datatypes(
+        NAME "ua_types_di"
+        TARGET_SUFFIX "types-di"
+        NAMESPACE_IDX 2
+        FILE_CSV "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv"
+        FILES_BSD "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd"
+    )
+
 
     # generate DI namespace
     add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/ua_namespace_di.c

+ 16 - 32
tests/nodeset-compiler/CMakeLists.txt

@@ -35,40 +35,24 @@ add_test_valgrind(nodeset_objecttype ${TESTS_BINARY_DIR}/check_nodeset_objecttyp
 if(UA_NAMESPACE_ZERO STREQUAL "FULL")
 
     # Generate types for DI namespace
-    set(UA_TYPES_OUT "ua_types_di")
-    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.c
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.h
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated_handling.h
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated_encoding_binary.h
-                       PRE_BUILD
-                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       --namespace=2
-                       --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                       --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd
-                       --no-builtin
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}
-                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd)
-    add_custom_target(open62541-generator-tests-types-di DEPENDS ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.c)
+    ua_generate_datatypes(
+        NAME "ua_types_di"
+        TARGET_SUFFIX "tests-types-di"
+        NAMESPACE_IDX 2
+        OUTPUT_DIR "${PROJECT_BINARY_DIR}/src_generated/tests"
+        FILE_CSV "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/OpcUaDiModel.csv"
+        FILES_BSD "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/DI/Opc.Ua.Di.Types.bsd"
+    )
 
     # Generate types for ADI namespace
-    set(UA_TYPES_OUT "ua_types_adi")
-    add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.c
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.h
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated_handling.h
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated_encoding_binary.h
-                       PRE_BUILD
-                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       --namespace=3
-                       --type-csv=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
-                       --type-bsd=${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd
-                       --no-builtin
-                       ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}
-                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv
-                       ${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd)
-    add_custom_target(open62541-generator-tests-types-adi DEPENDS ${PROJECT_BINARY_DIR}/src_generated/tests/${UA_TYPES_OUT}_generated.c)
+    ua_generate_datatypes(
+        NAME "ua_types_adi"
+        TARGET_SUFFIX "tests-types-adi"
+        NAMESPACE_IDX 3
+        OUTPUT_DIR "${PROJECT_BINARY_DIR}/src_generated/tests"
+        FILE_CSV "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/OpcUaAdiModel.csv"
+        FILES_BSD "${PROJECT_SOURCE_DIR}/deps/ua-nodeset/ADI/Opc.Ua.Adi.Types.bsd"
+    )
 
     # generate DI namespace
     add_custom_command(OUTPUT ${PROJECT_BINARY_DIR}/src_generated/tests/ua_namespace_di.c

+ 112 - 0
tools/cmake/macros.cmake

@@ -53,3 +53,115 @@ FUNCTION(ua_architecture_append_to_library)
         set_property(GLOBAL APPEND PROPERTY UA_ARCHITECTURE_APPEND_TO_LIBRARY ${ARG})
     ENDFOREACH(ARG)
 ENDFUNCTION(ua_architecture_append_to_library)
+
+
+# --------------- Generate Datatypes ---------------------
+#
+# Generates Datatype definition based on the .csv and .bsd files of a nodeset.
+# The result of the generation will be C Code which can be compiled with the rest of the stack.
+# Some nodesets come with custom datatypes. These datatype structures first need to be
+# generated so that the nodeset can use these types.
+#
+# The resulting files will be put into OUTPUT_DIR with the names:
+# - NAME_generated.c
+# - NAME_generated.h
+# - NAME_generated_encoding_binary.h
+# - NAME_generated_handling.h
+#
+# The cmake resulting cmake target will be named like this:
+#   open62541-generator-${TARGET_SUFFIX}
+#
+# The following arguments are accepted:
+#   Options:
+#
+#   [BUILTIN]       Optional argument. If given, then builtin types will be generated.
+#
+#   Arguments taking one value:
+#
+#   NAME            Full name of the generated files, e.g. ua_types_di
+#   TARGET_SUFFIX   Suffix for the resulting target. e.g. types-di
+#   NAMESPACE_IDX   Namespace index of the nodeset, when it is loaded into the server. This index
+#                   is used for the node ids withing the types array and is currently not determined automatically.
+#                   Make sure that it matches the namespace index in the server.
+#   [OUTPUT_DIR]    Optional target directory for the generated files. Default is '${PROJECT_BINARY_DIR}/src_generated'
+#   FILE_CSV        Path to the .csv file containing the node ids, e.g. 'OpcUaDiModel.csv'
+#
+#   Arguments taking multiple values:
+#
+#   FILES_BSD        Path to the .bsd file containing the type definitions, e.g. 'Opc.Ua.Di.Types.bsd'. Multiple files can be
+#                   passed which will all combined to one resulting code.
+#   [FILES_SELECTED] Optional path to a simple text file which contains a list of types which should be included in the generation.
+#                   The file should contain one type per line. Multiple files can be passed to this argument.
+#
+#
+function(ua_generate_datatypes)
+    set(options BUILTIN)
+    set(oneValueArgs NAME TARGET_SUFFIX NAMESPACE_IDX OUTPUT_DIR FILE_CSV)
+    set(multiValueArgs FILES_BSD FILES_SELECTED)
+    cmake_parse_arguments(PARSE_ARGV 0 UA_GEN_DT "${options}" "${oneValueArgs}"
+                          "${multiValueArgs}")
+
+
+    # ------ Argument checking -----
+    if(NOT DEFINED UA_GEN_DT_NAMESPACE_IDX AND NOT "${UA_GEN_DT_NAMESPACE_IDX}" STREQUAL "0")
+        message(FATAL_ERROR "ua_generate_datatype function requires a value for the NAMESPACE_IDX argument")
+    endif()
+    if(NOT UA_GEN_DT_NAME OR "${UA_GEN_DT_NAME}" STREQUAL "")
+        message(FATAL_ERROR "ua_generate_datatype function requires a value for the NAME argument")
+    endif()
+    if(NOT UA_GEN_DT_TARGET_SUFFIX OR "${UA_GEN_DT_TARGET_SUFFIX}" STREQUAL "")
+        message(FATAL_ERROR "ua_generate_datatype function requires a value for the TARGET_SUFFIX argument")
+    endif()
+    if(NOT UA_GEN_DT_FILE_CSV OR "${UA_GEN_DT_FILE_CSV}" STREQUAL "")
+        message(FATAL_ERROR "ua_generate_datatype function requires a value for the FILE_CSV argument")
+    endif()
+    if(NOT UA_GEN_DT_FILES_BSD OR "${UA_GEN_DT_FILES_BSD}" STREQUAL "")
+        message(FATAL_ERROR "ua_generate_datatype function requires a value for the FILES_BSD argument")
+    endif()
+
+    # Set default value for output dir
+    if(NOT UA_GEN_DT_OUTPUT_DIR)
+        set(UA_GEN_DT_OUTPUT_DIR ${PROJECT_BINARY_DIR}/src_generated)
+    endif()
+
+    # ------ Add custom command and target -----
+
+    set(UA_GEN_DT_NO_BUILTIN "--no-builtin")
+    if (UA_GEN_DT_BUILTIN)
+        set(UA_GEN_DT_NO_BUILTIN "")
+    endif()
+
+
+    set(SELECTED_TYPES_TMP "")
+    foreach(f ${UA_GEN_DT_FILES_SELECTED})
+        set(SELECTED_TYPES_TMP ${SELECTED_TYPES_TMP} "--selected-types=${f}")
+    endforeach()
+
+    set(BSD_FILES_TMP "")
+    foreach(f ${UA_GEN_DT_FILES_BSD})
+        set(BSD_FILES_TMP ${BSD_FILES_TMP} "--type-bsd=${f}")
+    endforeach()
+
+    add_custom_command(OUTPUT ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated.c
+                       ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated.h
+                       ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated_handling.h
+                       ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated_encoding_binary.h
+                       PRE_BUILD
+                       COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       --namespace=${UA_GEN_DT_NAMESPACE_IDX}
+                       ${SELECTED_TYPES_TMP}
+                       ${BSD_FILES_TMP}
+                       --type-csv=${UA_GEN_DT_FILE_CSV}
+                       ${UA_GEN_DT_NO_BUILTIN}
+                       ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}
+                       DEPENDS ${PROJECT_SOURCE_DIR}/tools/generate_datatypes.py
+                       ${UA_GEN_DT_FILES_BSD}
+                       ${UA_GEN_DT_FILE_CSV}
+                       ${UA_GEN_DT_FILES_SELECTED})
+    add_custom_target(open62541-generator-${UA_GEN_DT_TARGET_SUFFIX} DEPENDS
+                      ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated.c
+                      ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated.h
+                      ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated_handling.h
+                      ${UA_GEN_DT_OUTPUT_DIR}/${UA_GEN_DT_NAME}_generated_encoding_binary.h
+                      )
+endfunction()