Browse Source

cosmetic improvements; make ns0 generation an advanced build option

Julius Pfrommer 8 years ago
parent
commit
587a9284c7
2 changed files with 117 additions and 125 deletions
  1. 5 4
      CMakeLists.txt
  2. 112 121
      tools/pyUANamespace/generate_open62541CCode.py

+ 5 - 4
CMakeLists.txt

@@ -53,11 +53,12 @@ endif()
 option(UA_ENABLE_TYPENAMES "Add the type and member names to the UA_DataType structure" OFF)
 mark_as_advanced(UA_ENABLE_TYPENAMES)
 
-option(UA_ENABLE_GENERATE_NAMESPACE0 "Generate and load UA XML Namespace 0 definition" OFF)
-
 option(UA_ENABLE_EMBEDDED_LIBC "Use a custom implementation of some libc functions that might be missing on embedded targets (e.g. string handling)." OFF)
 mark_as_advanced(UA_ENABLE_EMBEDDED_LIBC)
 
+option(UA_ENABLE_GENERATE_NAMESPACE0 "Generate and load UA XML Namespace 0 definition (experimental)" OFF)
+mark_as_advanced(UA_ENABLE_GENERATE_NAMESPACE0)
+
 option(UA_ENABLE_EXTERNAL_NAMESPACES "Enable namespace handling by an external component (experimental)" OFF)
 mark_as_advanced(UA_ENABLE_EXTERNAL_NAMESPACES)
 
@@ -72,15 +73,15 @@ endif()
 
 # Build Targets
 option(UA_BUILD_EXAMPLES "Build example servers and clients" OFF)
-option(UA_BUILD_EXAMPLES_NODESET_COMPILER "Generate an OPC UA information model from a nodeset XML (experimental)" OFF)
 option(UA_BUILD_UNIT_TESTS "Build the unit tests" OFF)
 option(UA_BUILD_DOCUMENTATION "Generate doxygen/sphinx documentation" OFF)
+option(UA_BUILD_EXAMPLES_NODESET_COMPILER "Generate an OPC UA information model from a nodeset XML (experimental)" OFF)
 
 # Advanced Build Targets
 option(UA_BUILD_SELFSIGNED_CERTIFICATE "Generate self-signed certificate" OFF)
 mark_as_advanced(UA_BUILD_SELFSIGNED_CERTIFICATE)
 
-# Building shared libs (dll, so)
+# Building shared libs (dll, so). This option is written into ua_config.h.
 set(UA_DYNAMIC_LINKING OFF)
 if(BUILD_SHARED_LIBS)
   set(UA_DYNAMIC_LINKING ON)

+ 112 - 121
tools/pyUANamespace/generate_open62541CCode.py

@@ -62,124 +62,115 @@ parser.add_argument('-s','--suppress',
 
 parser.add_argument('-v','--verbose', action='count', help='Make the script more verbose. Can be applied up to 4 times')
 
-
-
-if __name__ == '__main__':
-  args = parser.parse_args()
-
-  level = logging.CRITICAL
-  verbosity = 0
-  if args.verbose:
-    verbosity = int(args.verbose)
-  if (verbosity==1):
-    level = logging.ERROR
-  elif (verbosity==2):
-    level = logging.WARNING
-  elif (verbosity==3):
-    level = logging.INFO
-  elif (verbosity>=4):
-    level = logging.DEBUG
-  logging.basicConfig(level=level)
-  logger.setLevel(logging.INFO)
-
-  # Creating the header is tendious. We can skip the entire process if
-  # the header exists.
-  #if path.exists(argv[-1]+".c") or path.exists(argv[-1]+".h"):
-  #  log(None, "File " + str(argv[-1]) + " does already exists.", LOG_LEVEL_INFO)
-  #  log(None, "Header generation will be skipped. Delete the header and rerun this script if necessary.", LOG_LEVEL_INFO)
-  #  exit(0)
-
-  # Open the output file
-  outfileh = open(args.outputFile+".h", r"w+")
-  outfilec = open(args.outputFile+".c", r"w+")
-
-  # Create a new namespace
-  # Note that the name is actually completely symbolic, it has no other
-  # function but to distinguish this specific class.
-  # A namespace class acts as a container for nodes. The nodes may belong
-  # to any number of different OPC-UA namespaces.
-  ns = opcua_namespace("open62541")
-
-  # Clean up the XML files by removing duplicate namespaces and unwanted prefixes
-  preProc = open62541_XMLPreprocessor()
-  for xmlfile in args.infiles:
-    logger.info("Preprocessing " + str(xmlfile.name))
-    preProc.addDocument(xmlfile.name)
-  preProc.preprocessAll()
-
-  for xmlfile in preProc.getPreProcessedFiles():
-    logger.info("Parsing " + str(xmlfile))
-    ns.parseXML(xmlfile)
-
-  # We need to notify the open62541 server of the namespaces used to be able to use i.e. ns=3
-  namespaceArrayNames = preProc.getUsedNamespaceArrayNames()
-  for key in namespaceArrayNames:
-    ns.addNamespace(key, namespaceArrayNames[key])
-
-  # Remove any temp files - they are not needed after the AST is created
-  # Removed for debugging
-  preProc.removePreprocessedFiles()
-
-  # Remove blacklisted nodes from the namespace
-  # Doing this now ensures that unlinkable pointers will be cleanly removed
-  # during sanitation.
-  for blacklist in args.blacklistFiles:
-    for line in blacklist.readlines():
-      line = line.replace(" ","")
-      id = line.replace("\n","")
-      if ns.getNodeByIDString(id) == None:
-        logger.info("Can't blacklist node, namespace does currently not contain a node with id " + str(id))
-      else:
-        ns.removeNodeById(line)
-    blacklist.close()
-
-  # Link the references in the namespace
-  logger.info("Linking namespace nodes and references")
-  ns.linkOpenPointers()
-
-  # Remove nodes that are not printable or contain parsing errors, such as
-  # unresolvable or no references or invalid NodeIDs
-  ns.sanitize()
-
-  # Parse Datatypes in order to find out what the XML keyed values actually
-  # represent.
-  # Ex. <rpm>123</rpm> is not encodable
-  #     only after parsing the datatypes, it is known that
-  #     rpm is encoded as a double
-  logger.info("Building datatype encoding rules")
-  ns.buildEncodingRules()
-
-  # Allocate/Parse the data values. In order to do this, we must have run
-  # buidEncodingRules.
-  logger.info("Allocating variables")
-  ns.allocateVariables()
-
-  # Users may have manually defined some nodes in their code already (such as serverStatus).
-  # To prevent those nodes from being reprinted, we will simply mark them as already
-  # converted to C-Code. That way, they will still be reffered to by other nodes, but
-  # they will not be created themselves.
-  ignoreNodes = []
-  for ignore in args.ignoreFiles:
-    for line in ignore.readlines():
-      line = line.replace(" ","")
-      id = line.replace("\n","")
-      if ns.getNodeByIDString(id) == None:
-        logger.warn("Can't ignore node, Namespace does currently not contain a node with id " + str(id))
-      else:
-        ignoreNodes.append(ns.getNodeByIDString(id))
-    ignore.close()
-
-  # Create the C Code
-  logger.info("Generating Header")
-  # Returns a tuple of (["Header","lines"],["Code","lines","generated"])
-  from os.path import basename
-  generatedCode=ns.printOpen62541Header(ignoreNodes, args.suppressedAttributes, outfilename=basename(args.outputFile))
-  for line in generatedCode[0]:
-    outfileh.write(line+"\n")
-  for line in generatedCode[1]:
-    outfilec.write(line+"\n")
-
-  outfilec.close()
-  outfileh.close()
-
-  exit(0)
+args = parser.parse_args()
+
+level = logging.CRITICAL
+verbosity = 0
+if args.verbose:
+  verbosity = int(args.verbose)
+if (verbosity==1):
+  level = logging.ERROR
+elif (verbosity==2):
+  level = logging.WARNING
+elif (verbosity==3):
+  level = logging.INFO
+elif (verbosity>=4):
+  level = logging.DEBUG
+logging.basicConfig(level=level)
+logger.setLevel(logging.INFO)
+
+# Creating the header is tendious. We can skip the entire process if
+# the header exists.
+#if path.exists(argv[-1]+".c") or path.exists(argv[-1]+".h"):
+#  log(None, "File " + str(argv[-1]) + " does already exists.", LOG_LEVEL_INFO)
+#  log(None, "Header generation will be skipped. Delete the header and rerun this script if necessary.", LOG_LEVEL_INFO)
+#  exit(0)
+
+# Open the output file
+outfileh = open(args.outputFile+".h", r"w+")
+outfilec = open(args.outputFile+".c", r"w+")
+
+# Create a new namespace. Note that the namespace name is not significant.
+ns = opcua_namespace("open62541")
+
+# Clean up the XML files by removing duplicate namespaces and unwanted prefixes
+preProc = open62541_XMLPreprocessor()
+for xmlfile in args.infiles:
+  logger.info("Preprocessing " + str(xmlfile.name))
+  preProc.addDocument(xmlfile.name)
+preProc.preprocessAll()
+
+# Parse the XML files
+for xmlfile in preProc.getPreProcessedFiles():
+  logger.info("Parsing " + str(xmlfile))
+  ns.parseXML(xmlfile)
+
+# We need to notify the open62541 server of the namespaces used to be able to use i.e. ns=3
+namespaceArrayNames = preProc.getUsedNamespaceArrayNames()
+for key in namespaceArrayNames:
+  ns.addNamespace(key, namespaceArrayNames[key])
+
+# Remove any temp files - they are not needed after the AST is created
+preProc.removePreprocessedFiles()
+
+# Remove blacklisted nodes from the namespace
+# Doing this now ensures that unlinkable pointers will be cleanly removed
+# during sanitation.
+for blacklist in args.blacklistFiles:
+  for line in blacklist.readlines():
+    line = line.replace(" ","")
+    id = line.replace("\n","")
+    if ns.getNodeByIDString(id) == None:
+      logger.info("Can't blacklist node, namespace does currently not contain a node with id " + str(id))
+    else:
+      ns.removeNodeById(line)
+  blacklist.close()
+
+# Link the references in the namespace
+logger.info("Linking namespace nodes and references")
+ns.linkOpenPointers()
+
+# Remove nodes that are not printable or contain parsing errors, such as
+# unresolvable or no references or invalid NodeIDs
+ns.sanitize()
+
+# Parse Datatypes in order to find out what the XML keyed values actually
+# represent.
+# Ex. <rpm>123</rpm> is not encodable
+#     only after parsing the datatypes, it is known that
+#     rpm is encoded as a double
+logger.info("Building datatype encoding rules")
+ns.buildEncodingRules()
+
+# Allocate/Parse the data values. In order to do this, we must have run
+# buidEncodingRules.
+logger.info("Allocating variables")
+ns.allocateVariables()
+
+# Users may have manually defined some nodes in their code already (such as serverStatus).
+# To prevent those nodes from being reprinted, we will simply mark them as already
+# converted to C-Code. That way, they will still be reffered to by other nodes, but
+# they will not be created themselves.
+ignoreNodes = []
+for ignore in args.ignoreFiles:
+  for line in ignore.readlines():
+    line = line.replace(" ","")
+    id = line.replace("\n","")
+    if ns.getNodeByIDString(id) == None:
+      logger.warn("Can't ignore node, Namespace does currently not contain a node with id " + str(id))
+    else:
+      ignoreNodes.append(ns.getNodeByIDString(id))
+  ignore.close()
+
+# Create the C Code
+logger.info("Generating Header")
+# Returns a tuple of (["Header","lines"],["Code","lines","generated"])
+from os.path import basename
+generatedCode = ns.printOpen62541Header(ignoreNodes, args.suppressedAttributes, outfilename=basename(args.outputFile))
+for line in generatedCode[0]:
+  outfileh.write(line+"\n")
+for line in generatedCode[1]:
+  outfilec.write(line+"\n")
+
+outfilec.close()
+outfileh.close()