From 59ef501a1909d29a2f567698341ec7e4b8c12ec8 Mon Sep 17 00:00:00 2001 From: Eugene Shamaev Date: Sun, 2 Apr 2017 17:56:50 +0300 Subject: [PATCH] waf: add support for building with UAVCAN --- Tools/ardupilotwaf/ap_library.py | 11 ++- Tools/ardupilotwaf/boards.py | 29 +++++++ .../configs/nuttx_px4fmu-common_apm.cmake | 2 - .../cmake/configs/nuttx_px4fmu-v2_apm.cmake | 6 -- .../cmake/configs/nuttx_px4fmu-v3_apm.cmake | 6 -- .../cmake/configs/nuttx_px4fmu-v4_apm.cmake | 6 -- Tools/ardupilotwaf/uavcangen.py | 75 +++++++++++++++++++ wscript | 17 ++++- 8 files changed, 129 insertions(+), 23 deletions(-) create mode 100644 Tools/ardupilotwaf/uavcangen.py diff --git a/Tools/ardupilotwaf/ap_library.py b/Tools/ardupilotwaf/ap_library.py index d4023cac74..3d90f49614 100644 --- a/Tools/ardupilotwaf/ap_library.py +++ b/Tools/ardupilotwaf/ap_library.py @@ -83,11 +83,18 @@ def ap_library(bld, library, vehicle): if common_tg and vehicle_tg: return - library_dir = bld.srcnode.find_dir('libraries/%s' % library) + if library.find('*') != -1: + # allow for wildcard patterns, used for submodules without direct waf support + library_dir = bld.srcnode.find_dir('.') + wildcard = library + else: + library_dir = bld.srcnode.find_dir('libraries/%s' % library) + wildcard = ap.SOURCE_EXTS + UTILITY_SOURCE_EXTS + if not library_dir: bld.fatal('ap_library: %s not found' % library) - src = library_dir.ant_glob(ap.SOURCE_EXTS + UTILITY_SOURCE_EXTS) + src = library_dir.ant_glob(wildcard) if not common_tg: kw = dict(bld.env.AP_LIBRARIES_OBJECTS_KW) diff --git a/Tools/ardupilotwaf/boards.py b/Tools/ardupilotwaf/boards.py index 1d40c9de69..f1a5585016 100644 --- a/Tools/ardupilotwaf/boards.py +++ b/Tools/ardupilotwaf/boards.py @@ -29,6 +29,9 @@ class BoardMeta(type): class Board: abstract = True + def __init__(self): + self.with_uavcan = False + def configure(self, cfg): cfg.env.TOOLCHAIN = self.toolchain cfg.load('toolchain') @@ -158,6 +161,26 @@ class Board: '-Wl,--gc-sections', ] + if self.with_uavcan: + env.AP_LIBRARIES += [ + 'AP_UAVCAN', + 'modules/uavcan/libuavcan/src/**/*.cpp' + ] + + env.CXXFLAGS += [ + '-Wno-error=cast-align', + ] + + env.DEFINES.update( + UAVCAN_CPP_VERSION = 'UAVCAN_CPP03', + UAVCAN_NO_ASSERTIONS = 1, + UAVCAN_NULLPTR = 'nullptr' + ) + + env.INCLUDES += [ + cfg.srcnode.find_dir('modules/uavcan/libuavcan/include').abspath() + ] + # We always want to use PRI format macros cfg.define('__STDC_FORMAT_MACROS', 1) @@ -420,6 +443,8 @@ class px4(Board): def __init__(self): # bootloader name: a file with that name will be used and installed # on ROMFS + super(px4, self).__init__() + self.bootloader_name = None # board name: it's the name of this board that's also used as path @@ -471,6 +496,7 @@ class px4(Board): 'PX4NuttX', 'uavcan', ] + env.ROMFS_EXCLUDE = self.ROMFS_EXCLUDE env.PX4_BOOTLOADER_NAME = self.bootloader_name @@ -506,6 +532,7 @@ class px4_v2(px4): self.board_name = 'px4fmu-v2' self.px4io_name = 'px4io-v2' self.romfs_exclude(['oreoled.bin']) + self.with_uavcan = True class px4_v3(px4): name = 'px4-v3' @@ -514,6 +541,7 @@ class px4_v3(px4): self.bootloader_name = 'px4fmuv2_bl.bin' self.board_name = 'px4fmu-v3' self.px4io_name = 'px4io-v2' + self.with_uavcan = True class px4_v4(px4): name = 'px4-v4' @@ -522,6 +550,7 @@ class px4_v4(px4): self.bootloader_name = 'px4fmuv4_bl.bin' self.board_name = 'px4fmu-v4' self.romfs_exclude(['oreoled.bin']) + self.with_uavcan = True class aerofc_v1(px4): name = 'aerofc-v1' diff --git a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-common_apm.cmake b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-common_apm.cmake index 34b8b47ade..547c53aeee 100644 --- a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-common_apm.cmake +++ b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-common_apm.cmake @@ -49,8 +49,6 @@ set(config_extra_libs ${APM_PROGRAM_LIB} ) -set(config_uavcan_num_ifaces 2) - add_custom_target(sercon) set_target_properties(sercon PROPERTIES MAIN "sercon" diff --git a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v2_apm.cmake b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v2_apm.cmake index 71971082c6..b808fa7098 100644 --- a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v2_apm.cmake +++ b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v2_apm.cmake @@ -4,12 +4,6 @@ list(APPEND config_module_list drivers/boards/px4fmu-v2 drivers/pwm_input drivers/px4io - modules/uavcan -) - -list(APPEND config_extra_libs - uavcan - uavcan_stm32_driver ) set(config_io_board diff --git a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v3_apm.cmake b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v3_apm.cmake index 993cacc6b1..57ecb0df6e 100644 --- a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v3_apm.cmake +++ b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v3_apm.cmake @@ -3,16 +3,10 @@ include(configs/nuttx_px4fmu-common_apm) list(APPEND config_module_list drivers/boards/px4fmu-v2 drivers/pwm_input - modules/uavcan drivers/px4io drivers/oreoled ) -list(APPEND config_extra_libs - uavcan - uavcan_stm32_driver -) - set(config_io_board px4io-v2 ) diff --git a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v4_apm.cmake b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v4_apm.cmake index 3a849aa77a..d52aed4be3 100644 --- a/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v4_apm.cmake +++ b/Tools/ardupilotwaf/px4/cmake/configs/nuttx_px4fmu-v4_apm.cmake @@ -3,11 +3,5 @@ include(configs/nuttx_px4fmu-common_apm) list(APPEND config_module_list drivers/boards/px4fmu-v4 drivers/pwm_input - modules/uavcan lib/rc ) - -list(APPEND config_extra_libs - uavcan - uavcan_stm32_driver -) diff --git a/Tools/ardupilotwaf/uavcangen.py b/Tools/ardupilotwaf/uavcangen.py new file mode 100644 index 0000000000..f2aa4f2b05 --- /dev/null +++ b/Tools/ardupilotwaf/uavcangen.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# encoding: utf-8 + +""" +generate DSDLC headers for uavcan +""" + +from waflib import Logs, Task, Utils, Node +from waflib.TaskGen import feature, before_method, extension +import os +import os.path +from xml.etree import ElementTree as et + +class uavcangen(Task.Task): + """generate uavcan header files""" + color = 'BLUE' + before = 'cxx c' + + def run(self): + python = self.env.get_flat('PYTHON') + out = self.env.get_flat('OUTPUT_DIR') + src = self.env.get_flat('SRC') + dsdlc = self.env.get_flat("DSDL_COMPILER") + input_dir = os.path.dirname(self.inputs[0].abspath()) + ret = self.exec_command('{} {} {} -O{}'.format( + python, dsdlc, input_dir, out)) + + if ret != 0: + # ignore if there was a signal to the interpreter rather + # than a real error in the script. Some environments use a + # signed and some an unsigned return for this + if ret > 128 or ret < 0: + Logs.warn('uavcangen crashed with code: {}'.format(ret)) + ret = 0 + else: + Logs.error('uavcangen returned {} error code'.format(ret)) + return ret + + def post_run(self): + super(uavcangen, self).post_run() + for header in self.generator.output_dir.ant_glob("*.hpp **/*.hpp", remove=False): + header.sig = header.cache_sig = self.cache_sig + +def options(opt): + opt.load('python') + +@feature('uavcangen') +@before_method('process_source') +def process_uavcangen(self): + if not hasattr(self, 'output_dir'): + self.bld.fatal('uavcangen: missing option output_dir') + + inputs = self.to_nodes(self.source) + outputs = [] + + self.source = [] + + if not isinstance(self.output_dir, Node.Node): + self.output_dir = self.bld.bldnode.find_or_declare(self.output_dir) + + task = self.create_task('uavcangen', inputs, outputs) + task.env['OUTPUT_DIR'] = self.output_dir.abspath() + + task.env.env = dict(os.environ) + +def configure(cfg): + """ + setup environment for uavcan header generator + """ + cfg.load('python') + cfg.check_python_version(minver=(2,7,0)) + + env = cfg.env + env.DSDL_COMPILER_DIR = cfg.srcnode.make_node('modules/uavcan/libuavcan/dsdl_compiler').abspath() + env.DSDL_COMPILER = env.DSDL_COMPILER_DIR + '/libuavcan_dsdlc' diff --git a/wscript b/wscript index 61de3e4828..4360fd2750 100644 --- a/wscript +++ b/wscript @@ -153,6 +153,7 @@ def configure(cfg): cfg.load('clang_compilation_database') cfg.load('waf_unit_test') cfg.load('mavgen') + cfg.load('uavcangen') cfg.env.SUBMODULE_UPDATE = cfg.options.submodule_update @@ -243,6 +244,17 @@ def _build_dynamic_sources(bld): ], ) + if bld.get_board().with_uavcan: + bld( + features='uavcangen', + source=bld.srcnode.ant_glob('modules/uavcan/dsdl/uavcan/**/*.uavcan'), + output_dir='modules/uavcan/libuavcan/include/dsdlc_generated', + name='uavcan', + export_includes=[ + bld.bldnode.make_node('modules/uavcan/libuavcan/include/dsdlc_generated').abspath(), + ] + ) + def write_version_header(tsk): bld = tsk.generator.bld return bld.write_version_header(tsk.outputs[0].abspath()) @@ -340,9 +352,12 @@ def build(bld): bld.load('ardupilotwaf') bld.env.AP_LIBRARIES_OBJECTS_KW.update( - use='mavlink', + use=['mavlink'], cxxflags=['-include', 'ap_config.h'], ) + + if bld.get_board().with_uavcan: + bld.env.AP_LIBRARIES_OBJECTS_KW['use'] += ['uavcan'] _build_cmd_tweaks(bld)