Tools/px_generate_uorb_topic*: combine the src & header generators into one script

This commit is contained in:
Beat Küng
2016-05-06 16:42:35 +02:00
committed by Lorenz Meier
parent 093eece29b
commit 6e7c605279
4 changed files with 71 additions and 229 deletions
@@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
############################################################################# #############################################################################
# #
# Copyright (C) 2013-2015 PX4 Development Team. All rights reserved. # Copyright (C) 2013-2016 PX4 Development Team. All rights reserved.
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions # modification, are permitted provided that the following conditions
@@ -33,8 +33,8 @@
############################################################################# #############################################################################
""" """
px_generate_uorb_topic_headers.py px_generate_uorb_topics.py
Generates c/cpp header files for uorb topics from .msg (ROS syntax) Generates c/cpp header/source files for uorb topics from .msg (ROS syntax)
message files message files
""" """
from __future__ import print_function from __future__ import print_function
@@ -69,14 +69,15 @@ On Windows please run:
''') ''')
exit(1) exit(1)
__author__ = "Thomas Gubler" __author__ = "Sergey Belash, Thomas Gubler, Beat Kueng"
__copyright__ = "Copyright (C) 2013-2014 PX4 Development Team." __copyright__ = "Copyright (C) 2013-2016 PX4 Development Team."
__license__ = "BSD" __license__ = "BSD"
__email__ = "thomasgubler@gmail.com" __email__ = "thomasgubler@gmail.com"
TEMPLATE_FILE = 'msg.h.template' TEMPLATE_FILE = ['msg.h.template', 'msg.cpp.template']
OUTPUT_FILE_EXT = '.h' TOPICS_LIST_TEMPLATE_FILE = 'uORBTopics.cpp.template'
OUTPUT_FILE_EXT = ['.h', '.cpp']
INCL_DEFAULT = ['std_msgs:./msg/std_msgs'] INCL_DEFAULT = ['std_msgs:./msg/std_msgs']
PACKAGE = 'px4' PACKAGE = 'px4'
TOPICS_TOKEN = '# TOPICS ' TOPICS_TOKEN = '# TOPICS '
@@ -97,10 +98,16 @@ def get_multi_topics(filename):
ofile.close() ofile.close()
return result return result
def get_msgs_list(msgdir):
"""
Makes list of msg files in the given directory
"""
return [fn for fn in os.listdir(msgdir) if fn.endswith(".msg")]
def generate_header_from_file(filename, outputdir, templatedir, includepath):
def generate_output_from_file(format_idx, filename, outputdir, templatedir, includepath):
""" """
Converts a single .msg file to a uorb header file Converts a single .msg file to an uorb header/source file
""" """
msg_context = genmsg.msg_loader.MsgContext.create_default() msg_context = genmsg.msg_loader.MsgContext.create_default()
full_type_name = genmsg.gentools.compute_full_type_name(PACKAGE, os.path.basename(filename)) full_type_name = genmsg.gentools.compute_full_type_name(PACKAGE, os.path.basename(filename))
@@ -127,28 +134,34 @@ def generate_header_from_file(filename, outputdir, templatedir, includepath):
if not os.path.isdir(outputdir): if not os.path.isdir(outputdir):
os.makedirs(outputdir) os.makedirs(outputdir)
template_file = os.path.join(templatedir, TEMPLATE_FILE) template_file = os.path.join(templatedir, TEMPLATE_FILE[format_idx])
output_file = os.path.join(outputdir, spec.short_name + OUTPUT_FILE_EXT) output_file = os.path.join(outputdir, spec.short_name +
OUTPUT_FILE_EXT[format_idx])
if os.path.isfile(output_file): return generate_by_template(output_file, template_file, em_globals)
return False
def generate_by_template(output_file, template_file, em_globals):
"""
Invokes empy intepreter to geneate output_file by the
given template_file and predefined em_globals dict
"""
ofile = open(output_file, 'w') ofile = open(output_file, 'w')
# todo, reuse interpreter # todo, reuse interpreter
interpreter = em.Interpreter(output=ofile, globals=em_globals, options={em.RAW_OPT:True,em.BUFFERED_OPT:True}) interpreter = em.Interpreter(output=ofile, globals=em_globals, options={em.RAW_OPT:True,em.BUFFERED_OPT:True})
if not os.path.isfile(template_file): if not os.path.isfile(template_file):
ofile.close() ofile.close()
os.remove(output_file) os.remove(output_file)
raise RuntimeError("Template file %s not found in template dir %s" % (template_file, templatedir)) raise RuntimeError("Template file %s not found" % (template_file))
interpreter.file(open(template_file)) #todo try interpreter.file(open(template_file)) #todo try
interpreter.shutdown() interpreter.shutdown()
ofile.close() ofile.close()
return True return True
def convert_dir(inputdir, outputdir, templatedir): def convert_dir(format_idx, inputdir, outputdir, templatedir):
""" """
Converts all .msg files in inputdir to uORB header files Converts all .msg files in inputdir to uORB header/source files
""" """
# Find the most recent modification time in input dir # Find the most recent modification time in input dir
@@ -185,7 +198,7 @@ def convert_dir(inputdir, outputdir, templatedir):
if not os.path.isfile(fn): if not os.path.isfile(fn):
continue continue
generate_header_from_file(fn, outputdir, templatedir, includepath) generate_output_from_file(format_idx, fn, outputdir, templatedir, includepath)
return True return True
@@ -223,19 +236,32 @@ def copy_changed(inputdir, outputdir, prefix='', quiet=False):
print("{0}: unchanged".format(input_file)) print("{0}: unchanged".format(input_file))
def convert_dir_save(inputdir, outputdir, templatedir, temporarydir, prefix, quiet=False): def convert_dir_save(format_idx, inputdir, outputdir, templatedir, temporarydir, prefix, quiet=False):
""" """
Converts all .msg files in inputdir to uORB header files Converts all .msg files in inputdir to uORB header files
Unchanged existing files are not overwritten. Unchanged existing files are not overwritten.
""" """
# Create new headers in temporary output directory # Create new headers in temporary output directory
convert_dir(inputdir, temporarydir, templatedir) convert_dir(format_idx, inputdir, temporarydir, templatedir)
if generate_idx == 1:
generate_topics_list_file(inputdir, temporarydir, templatedir)
# Copy changed headers from temporary dir to output dir # Copy changed headers from temporary dir to output dir
copy_changed(temporarydir, outputdir, prefix, quiet) copy_changed(temporarydir, outputdir, prefix, quiet)
def generate_topics_list_file(msgdir, outputdir, templatedir):
# generate cpp file with topics list
tl_globals = {"msgs" : get_msgs_list(msgdir)}
tl_template_file = os.path.join(templatedir, TOPICS_LIST_TEMPLATE_FILE)
tl_out_file = os.path.join(outputdir, TOPICS_LIST_TEMPLATE_FILE.replace(".template", ""))
generate_by_template(tl_out_file, tl_template_file, tl_globals)
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='Convert msg files to uorb headers') description='Convert msg files to uorb headers/sources')
parser.add_argument('--headers', help='Generate header files',
action='store_true')
parser.add_argument('--sources', help='Generate source files',
action='store_true')
parser.add_argument('-d', dest='dir', help='directory with msg files') parser.add_argument('-d', dest='dir', help='directory with msg files')
parser.add_argument('-f', dest='file', parser.add_argument('-f', dest='file',
help="files to convert (use only without -d)", help="files to convert (use only without -d)",
@@ -254,11 +280,22 @@ if __name__ == "__main__":
' name when converting directories') ' name when converting directories')
args = parser.parse_args() args = parser.parse_args()
if args.headers:
generate_idx = 0
elif args.sources:
generate_idx = 1
else:
print('Error: either --headers or --sources must be specified')
exit(-1)
if args.file is not None: if args.file is not None:
for f in args.file: for f in args.file:
generate_header_from_file(f, args.outputdir, args.templatedir, INCL_DEFAULT) generate_output_from_file(generate_idx, f, args.outputdir, args.templatedir, INCL_DEFAULT)
if generate_idx == 1:
generate_topics_list_file(args.dir, args.outputdir, args.templatedir)
elif args.dir is not None: elif args.dir is not None:
convert_dir_save( convert_dir_save(
generate_idx,
args.dir, args.dir,
args.outputdir, args.outputdir,
args.templatedir, args.templatedir,
-199
View File
@@ -1,199 +0,0 @@
#!/usr/bin/env python
#############################################################################
#
# Copyright (C) 2013-2015 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
#############################################################################
"""
px_generate_uorb_topic_sources.py
Generates cpp source files for uorb topics from .msg (ROS syntax)
message files
"""
from __future__ import print_function
import os
import shutil
import filecmp
import argparse
import sys
px4_tools_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(px4_tools_dir + "/genmsg/src")
sys.path.append(px4_tools_dir + "/gencpp/src")
try:
import em
import genmsg.template_tools
except ImportError as e:
print("python import error: ", e)
print('''
Required python packages not installed.
On a Debian/Ubuntu system please run:
sudo apt-get install python-empy
sudo pip install catkin_pkg
On MacOS please run:
sudo pip install empy catkin_pkg
On Windows please run:
easy_install empy catkin_pkg
''')
exit(1)
__author__ = "Sergey Belash, Thomas Gubler"
__copyright__ = "Copyright (C) 2013-2014 PX4 Development Team."
__license__ = "BSD"
__email__ = "againagainst@gmail.com, thomasgubler@gmail.com"
TOPIC_TEMPLATE_FILE = 'msg.cpp.template'
TOPICS_LIST_TEMPLATE_FILE = 'uORBTopics.cpp.template'
OUTPUT_FILE_EXT = '.cpp'
INCL_DEFAULT = ['std_msgs:./msg/std_msgs']
PACKAGE = 'px4'
TOPICS_TOKEN = '# TOPICS '
def get_multi_topics(filename):
"""
Get TOPICS names from a "# TOPICS" line
"""
ofile = open(filename, 'r')
text = ofile.read()
result = []
for each_line in text.split('\n'):
if each_line.startswith (TOPICS_TOKEN):
topic_names_str = each_line.strip()
topic_names_str = topic_names_str.replace(TOPICS_TOKEN, "")
result.extend(topic_names_str.split(" "))
ofile.close()
return result
def get_msgs_list(msgdir):
"""
Makes list of msg files in the given directory
"""
return [fn for fn in os.listdir(msgdir) if fn.endswith(".msg")]
def generate_source_from_file(filename, outputdir, template_file, includepath, quiet=False):
"""
Converts a single .msg file to a uorb source file
"""
# print("Generating sources from {0}".format(filename))
msg_context = genmsg.msg_loader.MsgContext.create_default()
full_type_name = genmsg.gentools.compute_full_type_name(PACKAGE, os.path.basename(filename))
spec = genmsg.msg_loader.load_msg_from_file(msg_context, filename, full_type_name)
topics = get_multi_topics(filename)
if includepath:
search_path = genmsg.command_line.includepath_to_dict(includepath)
else:
search_path = {}
if len(topics) == 0:
topics.append(spec.short_name)
em_globals = {
"file_name_in": filename,
"search_path": search_path,
"spec": spec,
"topics": topics
}
output_file = os.path.join(outputdir, spec.short_name + OUTPUT_FILE_EXT)
if os.path.isfile(output_file):
return False
generate_by_template(output_file, template_file, em_globals)
if not quiet:
print("{0}: new source file".format(output_file))
return True
def generate_by_template(output_file, template_file, em_globals):
"""
Invokes empy intepreter to geneate output_file by the
given template_file and predefined em_globals dict
"""
ofile = open(output_file, 'w')
# todo, reuse interpreter
interpreter = em.Interpreter(output=ofile, globals=em_globals, options={em.RAW_OPT:True,em.BUFFERED_OPT:True})
if not os.path.isfile(template_file):
ofile.close()
os.remove(output_file)
raise RuntimeError("Template file %s not found" % (template_file))
interpreter.file(open(template_file)) #todo try
interpreter.shutdown()
ofile.close()
def convert_dir(msgdir, outputdir, templatedir, quiet=False):
"""
Converts all .msg files in msgdir to uORB sources
"""
# Make sure output directory exists:
if not os.path.isdir(outputdir):
os.makedirs(outputdir)
template_file = os.path.join(templatedir, TOPIC_TEMPLATE_FILE)
includepath = INCL_DEFAULT + [':'.join([PACKAGE, msgdir])]
for f in os.listdir(msgdir):
# Ignore hidden files
if f.startswith("."):
continue
fn = os.path.join(msgdir, f)
# Only look at actual files
if not os.path.isfile(fn):
continue
generate_source_from_file(fn, outputdir, template_file, includepath, quiet)
# generate cpp file with topics list
tl_globals = {"msgs" : get_msgs_list(msgdir)}
tl_template_file = os.path.join(templatedir, TOPICS_LIST_TEMPLATE_FILE)
tl_out_file = os.path.join(outputdir, TOPICS_LIST_TEMPLATE_FILE.replace(".template", ""))
generate_by_template(tl_out_file, tl_template_file, tl_globals)
return True
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Convert msg files to uorb sources')
parser.add_argument('-d', dest='dir', help='directory with msg files')
parser.add_argument('-f', dest='file', help="files to convert (use only without -d)", nargs="+")
parser.add_argument('-e', dest='templatedir', help='directory with template files',)
parser.add_argument('-o', dest='outputdir', help='output directory for source files')
parser.add_argument('-q', dest='quiet', default=False, action='store_true',
help='string added as prefix to the output file '
' name when converting directories')
args = parser.parse_args()
if args.file is not None:
for f in args.file:
generate_source_from_file(f, args.outputdir, args.templatedir, args.quiet)
elif args.dir is not None:
convert_dir(args.dir, args.outputdir, args.templatedir, args.quiet)
+9 -5
View File
@@ -380,12 +380,13 @@ function(px4_generate_messages)
endforeach() endforeach()
add_custom_command(OUTPUT ${msg_files_out} add_custom_command(OUTPUT ${msg_files_out}
COMMAND ${PYTHON_EXECUTABLE} COMMAND ${PYTHON_EXECUTABLE}
Tools/px_generate_uorb_topic_headers.py Tools/px_generate_uorb_topic_files.py
--headers
${QUIET} ${QUIET}
-d msg -d msg
-o ${msg_out_path} -o ${msg_out_path}
-e msg/templates/uorb -e msg/templates/uorb
-t ${CMAKE_BINARY_DIR}/topics_temporary -t ${CMAKE_BINARY_DIR}/topics_temporary_header
DEPENDS ${DEPENDS} ${MSG_FILES} DEPENDS ${DEPENDS} ${MSG_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating uORB topic headers" COMMENT "Generating uORB topic headers"
@@ -400,11 +401,13 @@ function(px4_generate_messages)
endforeach() endforeach()
add_custom_command(OUTPUT ${msg_source_files_out} add_custom_command(OUTPUT ${msg_source_files_out}
COMMAND ${PYTHON_EXECUTABLE} COMMAND ${PYTHON_EXECUTABLE}
Tools/px_generate_uorb_topic_sources.py Tools/px_generate_uorb_topic_files.py
--sources
${QUIET} ${QUIET}
-d msg -d msg
-e msg/templates/uorb
-o ${msg_source_out_path} -o ${msg_source_out_path}
-e msg/templates/uorb
-t ${CMAKE_BINARY_DIR}/topics_temporary_sources
DEPENDS ${DEPENDS} ${MSG_FILES} DEPENDS ${DEPENDS} ${MSG_FILES}
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMENT "Generating uORB topic sources" COMMENT "Generating uORB topic sources"
@@ -421,7 +424,8 @@ function(px4_generate_messages)
endforeach() endforeach()
add_custom_command(OUTPUT ${msg_multi_files_out} add_custom_command(OUTPUT ${msg_multi_files_out}
COMMAND ${PYTHON_EXECUTABLE} COMMAND ${PYTHON_EXECUTABLE}
Tools/px_generate_uorb_topic_headers.py Tools/px_generate_uorb_topic_files.py
--headers
${QUIET} ${QUIET}
-d msg -d msg
-o ${msg_multi_out_path} -o ${msg_multi_out_path}
+2 -2
View File
@@ -147,8 +147,8 @@ set(MULTIPLATFORM_HEADER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/platforms/ros/px4_m
set(MULTIPLATFORM_TEMPLATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/msg/templates/px4/ros) set(MULTIPLATFORM_TEMPLATE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/msg/templates/px4/ros)
set(TOPICHEADER_TEMP_DIR ${CMAKE_BINARY_DIR}/topics_temporary) set(TOPICHEADER_TEMP_DIR ${CMAKE_BINARY_DIR}/topics_temporary)
set(MULTIPLATFORM_PREFIX px4_) set(MULTIPLATFORM_PREFIX px4_)
add_custom_target(multiplatform_message_headers ALL ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Tools/px_generate_uorb_topic_headers.py add_custom_target(multiplatform_message_headers ALL ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/Tools/px_generate_uorb_topic_files.py
-d ${CMAKE_CURRENT_SOURCE_DIR}/msg -o ${MULTIPLATFORM_HEADER_DIR} -e ${MULTIPLATFORM_TEMPLATE_DIR} --headers -d ${CMAKE_CURRENT_SOURCE_DIR}/msg -o ${MULTIPLATFORM_HEADER_DIR} -e ${MULTIPLATFORM_TEMPLATE_DIR}
-t ${TOPICHEADER_TEMP_DIR} -p ${MULTIPLATFORM_PREFIX}) -t ${TOPICHEADER_TEMP_DIR} -p ${MULTIPLATFORM_PREFIX})
## Declare a cpp library ## Declare a cpp library