mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-14 03:53:35 +08:00
Rewritten CMake installation directives, added setup.py for libuavcan_dsdl_compiler. uavcan_dsdlc should be lifted from libuavcan to a separate subproject in order to add support for other programming languages
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
lib*.so
|
||||
lib*.so.*
|
||||
*.a
|
||||
*/build
|
||||
build
|
||||
.dep
|
||||
__pycache__
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
|
||||
if(DEFINED CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Debug Release RelWithDebInfo MinSizeRel")
|
||||
@@ -31,9 +31,10 @@ endif ()
|
||||
# DSDL compiler invocation
|
||||
# Probably output files should be saved into CMake output dir?
|
||||
#
|
||||
execute_process(COMMAND ./setup.py build WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dsdl_compiler)
|
||||
set(DSDLC_INPUTS "test/dsdl_test/root_ns_a" "test/dsdl_test/root_ns_b" "${CMAKE_SOURCE_DIR}/../dsdl/uavcan")
|
||||
set(DSDLC_OUTPUT "include/dsdlc_generated")
|
||||
add_custom_target(dsdlc dsdl_compiler/dsdlc.py ${DSDLC_INPUTS} -O${DSDLC_OUTPUT}
|
||||
add_custom_target(dsdlc dsdl_compiler/uavcan_dsdlc ${DSDLC_INPUTS} -O${DSDLC_OUTPUT}
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
include_directories(${DSDLC_OUTPUT})
|
||||
|
||||
@@ -64,10 +65,12 @@ file(GLOB_RECURSE LIBUAVCAN_CXX_FILES RELATIVE ${CMAKE_SOURCE_DIR} "src/*.cpp")
|
||||
add_library(uavcan SHARED ${LIBUAVCAN_CXX_FILES})
|
||||
add_dependencies(uavcan dsdlc)
|
||||
|
||||
install(TARGETS uavcan DESTINATION lib)
|
||||
install(DIRECTORY include/uavcan DESTINATION include)
|
||||
install(DIRECTORY include/dsdlc_generated/uavcan DESTINATION include) # Merging generated .hpp with lib's .hpp
|
||||
install(DIRECTORY src/ DESTINATION src/uavcan)
|
||||
install(TARGETS uavcan DESTINATION lib)
|
||||
install(DIRECTORY include/uavcan DESTINATION include)
|
||||
install(DIRECTORY include/dsdlc_generated/uavcan DESTINATION include) # Generated and lib's .hpp
|
||||
install(DIRECTORY src DESTINATION src/uavcan)
|
||||
install(DIRECTORY ../dsdl DESTINATION share/uavcan) # TODO: move to top-level CMake script
|
||||
install(CODE "execute_process(COMMAND ./setup.py install WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/dsdl_compiler)")
|
||||
|
||||
#
|
||||
# Tests and static analysis - only for debug builds
|
||||
@@ -91,8 +94,8 @@ function(add_libuavcan_test name library flags) # Adds GTest executable and crea
|
||||
# Tests run automatically upon successful build
|
||||
# If failing tests need to be investigated with debugger, use 'make --ignore-errors'
|
||||
add_custom_command(TARGET ${name} POST_BUILD
|
||||
COMMAND ./${name} > "${name}.log"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
COMMAND ./${name} > "${name}.log"
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
endfunction()
|
||||
|
||||
if (DEBUG_BUILD)
|
||||
@@ -109,9 +112,11 @@ if (DEBUG_BUILD)
|
||||
# Additional flavours of the library
|
||||
add_library(uavcan_cpp03 SHARED ${LIBUAVCAN_CXX_FILES})
|
||||
set_target_properties(uavcan_cpp03 PROPERTIES COMPILE_FLAGS ${cpp03_flags})
|
||||
add_dependencies(uavcan_cpp03 dsdlc)
|
||||
|
||||
add_library(uavcan_optim SHARED ${LIBUAVCAN_CXX_FILES})
|
||||
set_target_properties(uavcan_optim PROPERTIES COMPILE_FLAGS ${optim_flags})
|
||||
add_dependencies(uavcan_optim dsdlc)
|
||||
|
||||
# GTest executables
|
||||
find_package(GTest REQUIRED)
|
||||
|
||||
Executable → Regular
+28
-49
@@ -1,19 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# UAVCAN DSDL compiler for libuavcan
|
||||
#
|
||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
#
|
||||
|
||||
import sys, os, argparse, logging, errno
|
||||
import sys, os, logging, errno
|
||||
from mako.template import Template
|
||||
|
||||
RUNNING_FROM_SRC_DIR = os.path.abspath(__file__).endswith(os.path.join('libuavcan', 'dsdl_compiler', 'dsdlc.py'))
|
||||
if RUNNING_FROM_SRC_DIR:
|
||||
print('Running from the source directory')
|
||||
scriptdir = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(os.path.join(scriptdir, '..', '..', 'pyuavcan'))
|
||||
|
||||
from pyuavcan import dsdl
|
||||
|
||||
MAX_BITLEN_FOR_ENUM = 31
|
||||
@@ -21,11 +13,27 @@ OUTPUT_FILE_EXTENSION = 'hpp'
|
||||
OUTPUT_FILE_PERMISSIONS = 0o444 # Read only for all
|
||||
TEMPLATE_FILENAME = os.path.join(os.path.dirname(__file__), 'data_type_template.tmpl')
|
||||
|
||||
# -----------------
|
||||
__all__ = ['run', 'logger', 'DsdlCompilerException']
|
||||
|
||||
class DsdlCompilerException(Exception):
|
||||
pass
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def run(source_dirs, include_dirs, output_dir):
|
||||
assert isinstance(source_dirs, list)
|
||||
assert isinstance(include_dirs, list)
|
||||
assert isinstance(output_dir, str)
|
||||
|
||||
types = run_parser(source_dirs, include_dirs + source_dirs)
|
||||
if not types:
|
||||
die('No type definitions were found')
|
||||
|
||||
logger.info('%d types total', len(types))
|
||||
run_generator(types, output_dir)
|
||||
|
||||
# -----------------
|
||||
|
||||
def pretty_filename(filename):
|
||||
a = os.path.abspath(filename)
|
||||
r = os.path.relpath(filename)
|
||||
@@ -43,20 +51,14 @@ def makedirs(path):
|
||||
raise
|
||||
|
||||
def die(text):
|
||||
print(text, file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
def configure_logging(verbosity):
|
||||
fmt = '%(message)s'
|
||||
level = { 0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG }.get(verbosity or 0, logging.DEBUG)
|
||||
logging.basicConfig(stream=sys.stderr, level=level, format=fmt)
|
||||
raise DsdlCompilerException(str(text))
|
||||
|
||||
def run_parser(source_dirs, search_dirs):
|
||||
try:
|
||||
types = dsdl.parse_namespaces(source_dirs, search_dirs)
|
||||
except dsdl.DsdlException as ex:
|
||||
logging.info('Parser failure', exc_info=True)
|
||||
die(str(ex))
|
||||
logger.info('Parser failure', exc_info=True)
|
||||
die(ex)
|
||||
return types
|
||||
|
||||
def run_generator(types, dest_dir):
|
||||
@@ -64,13 +66,13 @@ def run_generator(types, dest_dir):
|
||||
dest_dir = os.path.abspath(dest_dir) # Removing '..'
|
||||
makedirs(dest_dir)
|
||||
for t in types:
|
||||
logging.info('Generating type %s', t.full_name)
|
||||
logger.info('Generating type %s', t.full_name)
|
||||
filename = os.path.join(dest_dir, type_output_filename(t))
|
||||
text = generate_one_type(t)
|
||||
write_generated_data(filename, text)
|
||||
except Exception as ex:
|
||||
logging.info('Generator failure', exc_info=True)
|
||||
die(str(ex))
|
||||
logger.info('Generator failure', exc_info=True)
|
||||
die(ex)
|
||||
|
||||
def write_generated_data(filename, data):
|
||||
dirname = os.path.dirname(filename)
|
||||
@@ -81,12 +83,12 @@ def write_generated_data(filename, data):
|
||||
with open(filename) as f:
|
||||
existing_data = f.read()
|
||||
if data == existing_data:
|
||||
logging.info('Up to date [%s]', pretty_filename(filename))
|
||||
logger.info('Up to date [%s]', pretty_filename(filename))
|
||||
return
|
||||
logging.info('Rewriting [%s]', pretty_filename(filename))
|
||||
logger.info('Rewriting [%s]', pretty_filename(filename))
|
||||
os.remove(filename)
|
||||
else:
|
||||
logging.info('Creating [%s]', pretty_filename(filename))
|
||||
logger.info('Creating [%s]', pretty_filename(filename))
|
||||
|
||||
# Full rewrite
|
||||
with open(filename, 'w') as f:
|
||||
@@ -94,7 +96,7 @@ def write_generated_data(filename, data):
|
||||
try:
|
||||
os.chmod(filename, OUTPUT_FILE_PERMISSIONS)
|
||||
except (OSError, IOError) as ex:
|
||||
logging.warning('Failed to set permissions for %s: %s', pretty_filename(filename), ex)
|
||||
logger.warning('Failed to set permissions for %s: %s', pretty_filename(filename), ex)
|
||||
|
||||
def type_to_cpp_type(t):
|
||||
if t.category == t.CATEGORY_PRIMITIVE:
|
||||
@@ -192,26 +194,3 @@ def generate_one_type(t):
|
||||
text = text.replace('\n\n\n\n', '\n\n').replace('\n\n\n', '\n\n')
|
||||
text = text.replace('{\n\n ', '{\n ')
|
||||
return text
|
||||
|
||||
# -----------------
|
||||
|
||||
DESCRIPTION = '''UAVCAN DSDL compiler. Takes an input directory that contains an hierarchy of DSDL
|
||||
definitions and converts it into compatible hierarchy of C++ types for libuavcan.'''
|
||||
|
||||
DEFAULT_OUTDIR = './dsdlc_generated'
|
||||
|
||||
argparser = argparse.ArgumentParser(description=DESCRIPTION)
|
||||
argparser.add_argument('source_dir', nargs='+', help='source directory with DSDL definitions')
|
||||
argparser.add_argument('--verbose', '-v', action='count', help='verbosity level (-v, -vv)')
|
||||
argparser.add_argument('--outdir', '-O', default=DEFAULT_OUTDIR, help='output directory, default %s' % DEFAULT_OUTDIR)
|
||||
argparser.add_argument('--incdir', '-I', default=[], action='append', help='nested type namespaces')
|
||||
args = argparser.parse_args()
|
||||
|
||||
configure_logging(args.verbose)
|
||||
|
||||
types = run_parser(args.source_dir, args.incdir + args.source_dir)
|
||||
if not types:
|
||||
die('No type definitions were found')
|
||||
logging.info('%d types total', len(types))
|
||||
|
||||
run_generator(types, args.outdir)
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from distutils.core import setup
|
||||
|
||||
args = dict(
|
||||
name='uavcan_dsdlc',
|
||||
version='0.1',
|
||||
description='UAVCAN DSDL compiler for libuavcan',
|
||||
packages=['libuavcan_dsdl_compiler'],
|
||||
package_data={'libuavcan_dsdl_compiler': ['data_type_template.tmpl']},
|
||||
scripts=['uavcan_dsdlc'],
|
||||
requires=['mako', 'pyuavcan'],
|
||||
author='Pavel Kirienko',
|
||||
author_email='pavel.kirienko@gmail.com',
|
||||
url='http://uavcan.org',
|
||||
license='MIT'
|
||||
)
|
||||
|
||||
setup(**args)
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# UAVCAN DSDL compiler
|
||||
# Probably it will be extended in future to add support for different programming languages.
|
||||
#
|
||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
||||
#
|
||||
|
||||
import os, sys, logging, argparse
|
||||
|
||||
def configure_logging(verbosity):
|
||||
fmt = '%(message)s'
|
||||
level = { 0: logging.WARNING, 1: logging.INFO, 2: logging.DEBUG }.get(verbosity or 0, logging.DEBUG)
|
||||
logging.basicConfig(stream=sys.stderr, level=level, format=fmt)
|
||||
|
||||
def die(text):
|
||||
print(text, file=sys.stderr)
|
||||
exit(1)
|
||||
|
||||
RUNNING_FROM_SRC_DIR = os.path.abspath(__file__).endswith(os.path.join('libuavcan', 'dsdl_compiler', 'uavcan_dsdlc'))
|
||||
if RUNNING_FROM_SRC_DIR:
|
||||
print('Running from the source directory')
|
||||
scriptdir = os.path.dirname(os.path.abspath(__file__))
|
||||
sys.path.append(os.path.join(scriptdir, '..', '..', 'pyuavcan'))
|
||||
sys.path.append(os.path.join(scriptdir))
|
||||
|
||||
DEFAULT_OUTDIR = './dsdlc_generated'
|
||||
|
||||
DESCRIPTION = '''UAVCAN DSDL compiler. Takes an input directory that contains an hierarchy of DSDL
|
||||
definitions and converts it into compatible hierarchy of C++ types for libuavcan.'''
|
||||
|
||||
argparser = argparse.ArgumentParser(description=DESCRIPTION)
|
||||
argparser.add_argument('source_dir', nargs='+', help='source directory with DSDL definitions')
|
||||
argparser.add_argument('--verbose', '-v', action='count', help='verbosity level (-v, -vv)')
|
||||
argparser.add_argument('--outdir', '-O', default=DEFAULT_OUTDIR, help='output directory, default %s' % DEFAULT_OUTDIR)
|
||||
argparser.add_argument('--incdir', '-I', default=[], action='append', help='nested type namespaces')
|
||||
args = argparser.parse_args()
|
||||
|
||||
configure_logging(args.verbose)
|
||||
|
||||
from libuavcan_dsdl_compiler import run as dsdlc_run
|
||||
try:
|
||||
# TODO: collect include dirs from environment variable UAVCAN_DSDL_INCLUDE
|
||||
dsdlc_run(args.source_dir, args.incdir, args.outdir)
|
||||
except Exception as ex:
|
||||
logging.error('Compiler failure', exc_info=True)
|
||||
die(str(ex))
|
||||
Reference in New Issue
Block a user