From 6856950bd304c606b662d62c2c67e76cd515afe5 Mon Sep 17 00:00:00 2001 From: Caio Marcelo de Oliveira Filho Date: Thu, 26 Nov 2015 12:34:24 -0200 Subject: [PATCH] waf: use ConfigSet for board environments Instead of a dictionary of dictionaries, have a dictionary of ConfigSets. Using ConfigSet have two benefits: (1) allow easily copying values from other, (2) have syntax for specifying the keys directly as attributes. With this change now it's easier to specify minlure without repetition. New boards can override a value, append or prepend depending on the need. DEFINES attribute is treated as a dictionary instead of a list, so that's easier to override values (at expense of ordering). When reading the board environment, the code converts back to a list. The board configuration is now stored in a separate file, there's also a function to get the boards names. --- Tools/ardupilotwaf/boards.py | 133 ++++++++++++++++++++++++++++++++ wscript | 144 +++++------------------------------ 2 files changed, 151 insertions(+), 126 deletions(-) create mode 100644 Tools/ardupilotwaf/boards.py diff --git a/Tools/ardupilotwaf/boards.py b/Tools/ardupilotwaf/boards.py new file mode 100644 index 0000000000..6fa3008eb3 --- /dev/null +++ b/Tools/ardupilotwaf/boards.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python +# encoding: utf-8 + +import sys + +import waflib + +BOARDS = {} + +PROJECT_ENV = waflib.ConfigSet.ConfigSet() + +def define_board(func, name, parent_name=None): + if parent_name is None: + parent = PROJECT_ENV + elif parent_name not in BOARDS: + print("Undefined parent board '%s' for '%s'" % (parent_name, name)) + sys.exit(1) + else: + parent = BOARDS[parent_name] + + env = parent.derive().detach() + if name in BOARDS: + print("Multiple definitions of " + name) + sys.exit(1) + BOARDS[name] = env + func(env) + +# Use a dictionary instead of the convetional list for definitions to +# make easy to override them. Convert back to list before consumption. +PROJECT_ENV.DEFINES = {} + +PROJECT_ENV.CFLAGS += [ + '-ffunction-sections', + '-fdata-sections', + '-fsigned-char', + + '-Wformat', + '-Wall', + '-Wshadow', + '-Wpointer-arith', + '-Wcast-align', + '-Wno-unused-parameter', + '-Wno-missing-field-initializers', +] + +PROJECT_ENV.CXXFLAGS += [ + '-std=gnu++11', + + '-fdata-sections', + '-ffunction-sections', + '-fno-exceptions', + '-fsigned-char', + + '-Wformat', + '-Wall', + '-Wshadow', + '-Wpointer-arith', + '-Wcast-align', + '-Wno-unused-parameter', + '-Wno-missing-field-initializers', + '-Wno-reorder', + '-Werror=format-security', + '-Werror=array-bounds', + '-Wfatal-errors', + '-Werror=unused-but-set-variable', + '-Werror=uninitialized', + '-Werror=init-self', + '-Wno-missing-field-initializers', +] + +PROJECT_ENV.LINKFLAGS += [ + '-Wl,--gc-sections', +] + +# NOTE: Keeping all the board definitions together so we can easily +# identify opportunities to simplify common flags. In the future might +# be worthy to keep board definitions in files of their own. + +def sitl(env): + env.DEFINES.update( + CONFIG_HAL_BOARD = 'HAL_BOARD_SITL', + CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_NONE', + ) + + env.CXXFLAGS += [ + '-O3', + ] + + env.LIB += [ + 'm', + 'pthread', + ] + + env.AP_LIBRARIES += [ + 'AP_HAL_SITL', + 'SITL', + ] + +define_board(sitl, 'sitl') + + +def linux(env): + env.DEFINES.update( + CONFIG_HAL_BOARD = 'HAL_BOARD_LINUX', + CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_LINUX_NONE', + ) + + env.CXXFLAGS += [ + '-O3', + ] + + env.LIB += [ + 'm', + 'pthread', + 'rt', + ] + + env.AP_LIBRARIES = [ + 'AP_HAL_Linux', + ] + +define_board(linux, 'linux') + + +def minlure(env): + env.DEFINES.update( + CONFIG_HAL_BOARD_SUBTYPE = 'HAL_BOARD_SUBTYPE_LINUX_MINLURE', + ) + +define_board(minlure, 'minlure', 'linux') + +def get_boards_names(): + return sorted(list(BOARDS.keys())) diff --git a/wscript b/wscript index fe8adca026..93b623f3a3 100644 --- a/wscript +++ b/wscript @@ -8,6 +8,7 @@ import sys sys.path.insert(0, 'Tools/ardupilotwaf/') import ardupilotwaf +import boards import waflib # TODO: implement a command 'waf help' that shows the basic tasks a @@ -33,128 +34,15 @@ import waflib # contain the board extension so make it less convenient, maybe hook # to support automatic filling this extension? -PROJECT_CONFIG = dict( - CFLAGS=[ - '-ffunction-sections', - '-fdata-sections', - '-fsigned-char', - - '-Wformat', - '-Wall', - '-Wshadow', - '-Wpointer-arith', - '-Wcast-align', - '-Wno-unused-parameter', - '-Wno-missing-field-initializers', - ], - - CXXFLAGS=[ - '-std=gnu++11', - - '-fdata-sections', - '-ffunction-sections', - '-fno-exceptions', - '-fsigned-char', - - '-Wformat', - '-Wall', - '-Wshadow', - '-Wpointer-arith', - '-Wcast-align', - '-Wno-unused-parameter', - '-Wno-missing-field-initializers', - '-Wno-reorder', - '-Werror=format-security', - '-Werror=array-bounds', - '-Wfatal-errors', - '-Werror=unused-but-set-variable', - '-Werror=uninitialized', - '-Werror=init-self', - '-Wno-missing-field-initializers', - ], - - LINKFLAGS=[ - '-Wl,--gc-sections', - ], -) - -# NOTE: Keeping all the board definitions together so we can easily -# identify opportunities to simplify how it works. In the future might -# be worthy to keep board definitions in files of their own. -BOARDS = { - 'sitl': dict( - DEFINES=[ - 'CONFIG_HAL_BOARD=HAL_BOARD_SITL', - 'CONFIG_HAL_BOARD_SUBTYPE=HAL_BOARD_SUBTYPE_NONE', - ], - - CXXFLAGS=[ - '-O3' - ], - - LIB=[ - 'm', - 'pthread', - ], - - AP_LIBRARIES=[ - 'AP_HAL_SITL', - 'SITL', - ], - ), - - 'linux': dict( - DEFINES=[ - 'CONFIG_HAL_BOARD=HAL_BOARD_LINUX', - 'CONFIG_HAL_BOARD_SUBTYPE=HAL_BOARD_SUBTYPE_LINUX_NONE', - ], - - CXXFLAGS=[ - '-O3' - ], - - LIB=[ - 'm', - 'pthread', - 'rt', - ], - - AP_LIBRARIES=[ - 'AP_HAL_Linux', - ], - ), - - 'minlure': dict( - DEFINES=[ - 'CONFIG_HAL_BOARD=HAL_BOARD_LINUX', - 'CONFIG_HAL_BOARD_SUBTYPE=HAL_BOARD_SUBTYPE_LINUX_MINLURE', - ], - - CXXFLAGS=[ - '-O3' - ], - - LIB=[ - 'm', - 'pthread', - 'rt', - ], - - AP_LIBRARIES=[ - 'AP_HAL_Linux', - ], - ), -} - -BOARDS_NAMES = sorted(list(BOARDS.keys())) - def options(opt): + boards_names = boards.get_boards_names() + opt.load('compiler_cxx compiler_c waf_unit_test') opt.add_option('--board', action='store', - choices=BOARDS_NAMES, + choices=boards_names, default='sitl', - help='Target board to build, choices are %s' % BOARDS_NAMES) + help='Target board to build, choices are %s' % boards_names) g = opt.add_option_group('Check options') g.add_option('--check-verbose', @@ -182,15 +70,19 @@ def configure(cfg): cfg.msg('Setting board to', cfg.options.board) cfg.env.BOARD = cfg.options.board - board = BOARDS[cfg.env.BOARD] + board_dict = boards.BOARDS[cfg.env.BOARD].get_merged_dict() - # Always prepend so that arguments passed in the command line get the - # priority. Board configuration gets priority over the project - # configuration. - for k in board.keys(): - cfg.env.prepend_value(k, board[k]) - for k in PROJECT_CONFIG.keys(): - cfg.env.prepend_value(k, PROJECT_CONFIG[k]) + # Always prepend so that arguments passed in the command line get + # the priority. + for k in board_dict: + val = board_dict[k] + # Dictionaries (like 'DEFINES') are converted to lists to + # conform to waf conventions. + if isinstance(val, dict): + for item in val.items(): + cfg.env.prepend_value(k, '%s=%s' % item) + else: + cfg.env.prepend_value(k, val) cfg.env.prepend_value('INCLUDES', [ cfg.srcnode.abspath() + '/libraries/' @@ -211,7 +103,7 @@ def collect_dirs_to_recurse(bld, globs, **kw): return dirs def list_boards(ctx): - print(*BOARDS_NAMES) + print(*boards.get_boards_names()) def build(bld): # NOTE: Static library with vehicle set to UNKNOWN, shared by all