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.
This commit is contained in:
Caio Marcelo de Oliveira Filho 2015-11-26 12:34:24 -02:00 committed by Andrew Tridgell
parent 8456cb4532
commit 6856950bd3
2 changed files with 151 additions and 126 deletions

View File

@ -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()))

144
wscript
View File

@ -8,6 +8,7 @@ import sys
sys.path.insert(0, 'Tools/ardupilotwaf/') sys.path.insert(0, 'Tools/ardupilotwaf/')
import ardupilotwaf import ardupilotwaf
import boards
import waflib import waflib
# TODO: implement a command 'waf help' that shows the basic tasks a # 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 # contain the board extension so make it less convenient, maybe hook
# to support automatic filling this extension? # 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): def options(opt):
boards_names = boards.get_boards_names()
opt.load('compiler_cxx compiler_c waf_unit_test') opt.load('compiler_cxx compiler_c waf_unit_test')
opt.add_option('--board', opt.add_option('--board',
action='store', action='store',
choices=BOARDS_NAMES, choices=boards_names,
default='sitl', 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 = opt.add_option_group('Check options')
g.add_option('--check-verbose', g.add_option('--check-verbose',
@ -182,15 +70,19 @@ def configure(cfg):
cfg.msg('Setting board to', cfg.options.board) cfg.msg('Setting board to', cfg.options.board)
cfg.env.BOARD = 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 # Always prepend so that arguments passed in the command line get
# priority. Board configuration gets priority over the project # the priority.
# configuration. for k in board_dict:
for k in board.keys(): val = board_dict[k]
cfg.env.prepend_value(k, board[k]) # Dictionaries (like 'DEFINES') are converted to lists to
for k in PROJECT_CONFIG.keys(): # conform to waf conventions.
cfg.env.prepend_value(k, PROJECT_CONFIG[k]) 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.env.prepend_value('INCLUDES', [
cfg.srcnode.abspath() + '/libraries/' cfg.srcnode.abspath() + '/libraries/'
@ -211,7 +103,7 @@ def collect_dirs_to_recurse(bld, globs, **kw):
return dirs return dirs
def list_boards(ctx): def list_boards(ctx):
print(*BOARDS_NAMES) print(*boards.get_boards_names())
def build(bld): def build(bld):
# NOTE: Static library with vehicle set to UNKNOWN, shared by all # NOTE: Static library with vehicle set to UNKNOWN, shared by all