mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-10-19 01:53:34 +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
|
||||||
lib*.so.*
|
lib*.so.*
|
||||||
*.a
|
*.a
|
||||||
*/build
|
build
|
||||||
.dep
|
.dep
|
||||||
__pycache__
|
__pycache__
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
# 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)
|
if(DEFINED CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Debug Release RelWithDebInfo MinSizeRel")
|
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE STRING "Debug Release RelWithDebInfo MinSizeRel")
|
||||||
@@ -31,9 +31,10 @@ endif ()
|
|||||||
# DSDL compiler invocation
|
# DSDL compiler invocation
|
||||||
# Probably output files should be saved into CMake output dir?
|
# 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_INPUTS "test/dsdl_test/root_ns_a" "test/dsdl_test/root_ns_b" "${CMAKE_SOURCE_DIR}/../dsdl/uavcan")
|
||||||
set(DSDLC_OUTPUT "include/dsdlc_generated")
|
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})
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||||
include_directories(${DSDLC_OUTPUT})
|
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_library(uavcan SHARED ${LIBUAVCAN_CXX_FILES})
|
||||||
add_dependencies(uavcan dsdlc)
|
add_dependencies(uavcan dsdlc)
|
||||||
|
|
||||||
install(TARGETS uavcan DESTINATION lib)
|
install(TARGETS uavcan DESTINATION lib)
|
||||||
install(DIRECTORY include/uavcan DESTINATION include)
|
install(DIRECTORY include/uavcan DESTINATION include)
|
||||||
install(DIRECTORY include/dsdlc_generated/uavcan DESTINATION include) # Merging generated .hpp with lib's .hpp
|
install(DIRECTORY include/dsdlc_generated/uavcan DESTINATION include) # Generated and lib's .hpp
|
||||||
install(DIRECTORY src/ DESTINATION src/uavcan)
|
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
|
# 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
|
# Tests run automatically upon successful build
|
||||||
# If failing tests need to be investigated with debugger, use 'make --ignore-errors'
|
# If failing tests need to be investigated with debugger, use 'make --ignore-errors'
|
||||||
add_custom_command(TARGET ${name} POST_BUILD
|
add_custom_command(TARGET ${name} POST_BUILD
|
||||||
COMMAND ./${name} > "${name}.log"
|
COMMAND ./${name} > "${name}.log"
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
if (DEBUG_BUILD)
|
if (DEBUG_BUILD)
|
||||||
@@ -109,9 +112,11 @@ if (DEBUG_BUILD)
|
|||||||
# Additional flavours of the library
|
# Additional flavours of the library
|
||||||
add_library(uavcan_cpp03 SHARED ${LIBUAVCAN_CXX_FILES})
|
add_library(uavcan_cpp03 SHARED ${LIBUAVCAN_CXX_FILES})
|
||||||
set_target_properties(uavcan_cpp03 PROPERTIES COMPILE_FLAGS ${cpp03_flags})
|
set_target_properties(uavcan_cpp03 PROPERTIES COMPILE_FLAGS ${cpp03_flags})
|
||||||
|
add_dependencies(uavcan_cpp03 dsdlc)
|
||||||
|
|
||||||
add_library(uavcan_optim SHARED ${LIBUAVCAN_CXX_FILES})
|
add_library(uavcan_optim SHARED ${LIBUAVCAN_CXX_FILES})
|
||||||
set_target_properties(uavcan_optim PROPERTIES COMPILE_FLAGS ${optim_flags})
|
set_target_properties(uavcan_optim PROPERTIES COMPILE_FLAGS ${optim_flags})
|
||||||
|
add_dependencies(uavcan_optim dsdlc)
|
||||||
|
|
||||||
# GTest executables
|
# GTest executables
|
||||||
find_package(GTest REQUIRED)
|
find_package(GTest REQUIRED)
|
||||||
|
|||||||
Executable → Regular
+28
-49
@@ -1,19 +1,11 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
#
|
#
|
||||||
# UAVCAN DSDL compiler for libuavcan
|
# UAVCAN DSDL compiler for libuavcan
|
||||||
#
|
#
|
||||||
# Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
|
# 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
|
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
|
from pyuavcan import dsdl
|
||||||
|
|
||||||
MAX_BITLEN_FOR_ENUM = 31
|
MAX_BITLEN_FOR_ENUM = 31
|
||||||
@@ -21,11 +13,27 @@ OUTPUT_FILE_EXTENSION = 'hpp'
|
|||||||
OUTPUT_FILE_PERMISSIONS = 0o444 # Read only for all
|
OUTPUT_FILE_PERMISSIONS = 0o444 # Read only for all
|
||||||
TEMPLATE_FILENAME = os.path.join(os.path.dirname(__file__), 'data_type_template.tmpl')
|
TEMPLATE_FILENAME = os.path.join(os.path.dirname(__file__), 'data_type_template.tmpl')
|
||||||
|
|
||||||
# -----------------
|
__all__ = ['run', 'logger', 'DsdlCompilerException']
|
||||||
|
|
||||||
class DsdlCompilerException(Exception):
|
class DsdlCompilerException(Exception):
|
||||||
pass
|
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):
|
def pretty_filename(filename):
|
||||||
a = os.path.abspath(filename)
|
a = os.path.abspath(filename)
|
||||||
r = os.path.relpath(filename)
|
r = os.path.relpath(filename)
|
||||||
@@ -43,20 +51,14 @@ def makedirs(path):
|
|||||||
raise
|
raise
|
||||||
|
|
||||||
def die(text):
|
def die(text):
|
||||||
print(text, file=sys.stderr)
|
raise DsdlCompilerException(str(text))
|
||||||
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)
|
|
||||||
|
|
||||||
def run_parser(source_dirs, search_dirs):
|
def run_parser(source_dirs, search_dirs):
|
||||||
try:
|
try:
|
||||||
types = dsdl.parse_namespaces(source_dirs, search_dirs)
|
types = dsdl.parse_namespaces(source_dirs, search_dirs)
|
||||||
except dsdl.DsdlException as ex:
|
except dsdl.DsdlException as ex:
|
||||||
logging.info('Parser failure', exc_info=True)
|
logger.info('Parser failure', exc_info=True)
|
||||||
die(str(ex))
|
die(ex)
|
||||||
return types
|
return types
|
||||||
|
|
||||||
def run_generator(types, dest_dir):
|
def run_generator(types, dest_dir):
|
||||||
@@ -64,13 +66,13 @@ def run_generator(types, dest_dir):
|
|||||||
dest_dir = os.path.abspath(dest_dir) # Removing '..'
|
dest_dir = os.path.abspath(dest_dir) # Removing '..'
|
||||||
makedirs(dest_dir)
|
makedirs(dest_dir)
|
||||||
for t in types:
|
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))
|
filename = os.path.join(dest_dir, type_output_filename(t))
|
||||||
text = generate_one_type(t)
|
text = generate_one_type(t)
|
||||||
write_generated_data(filename, text)
|
write_generated_data(filename, text)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logging.info('Generator failure', exc_info=True)
|
logger.info('Generator failure', exc_info=True)
|
||||||
die(str(ex))
|
die(ex)
|
||||||
|
|
||||||
def write_generated_data(filename, data):
|
def write_generated_data(filename, data):
|
||||||
dirname = os.path.dirname(filename)
|
dirname = os.path.dirname(filename)
|
||||||
@@ -81,12 +83,12 @@ def write_generated_data(filename, data):
|
|||||||
with open(filename) as f:
|
with open(filename) as f:
|
||||||
existing_data = f.read()
|
existing_data = f.read()
|
||||||
if data == existing_data:
|
if data == existing_data:
|
||||||
logging.info('Up to date [%s]', pretty_filename(filename))
|
logger.info('Up to date [%s]', pretty_filename(filename))
|
||||||
return
|
return
|
||||||
logging.info('Rewriting [%s]', pretty_filename(filename))
|
logger.info('Rewriting [%s]', pretty_filename(filename))
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
else:
|
else:
|
||||||
logging.info('Creating [%s]', pretty_filename(filename))
|
logger.info('Creating [%s]', pretty_filename(filename))
|
||||||
|
|
||||||
# Full rewrite
|
# Full rewrite
|
||||||
with open(filename, 'w') as f:
|
with open(filename, 'w') as f:
|
||||||
@@ -94,7 +96,7 @@ def write_generated_data(filename, data):
|
|||||||
try:
|
try:
|
||||||
os.chmod(filename, OUTPUT_FILE_PERMISSIONS)
|
os.chmod(filename, OUTPUT_FILE_PERMISSIONS)
|
||||||
except (OSError, IOError) as ex:
|
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):
|
def type_to_cpp_type(t):
|
||||||
if t.category == t.CATEGORY_PRIMITIVE:
|
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\n', '\n\n').replace('\n\n\n', '\n\n')
|
||||||
text = text.replace('{\n\n ', '{\n ')
|
text = text.replace('{\n\n ', '{\n ')
|
||||||
return text
|
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