You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
310 lines
9.9 KiB
310 lines
9.9 KiB
#!/usr/bin/env python |
|
# encoding: utf-8 |
|
|
|
""" |
|
Waf tool for PX4 build |
|
""" |
|
|
|
from waflib import Logs, Task, Utils |
|
from waflib.TaskGen import after_method, before_method, feature |
|
|
|
import os |
|
import sys |
|
|
|
_dynamic_env_data = {} |
|
def _load_dynamic_env_data(bld): |
|
bldnode = bld.bldnode.make_node('modules/PX4Firmware') |
|
for name in ('cxx_flags', 'include_dirs', 'definitions'): |
|
_dynamic_env_data[name] = bldnode.find_node(name).read().split(';') |
|
|
|
@feature('px4_ap_stlib', 'px4_ap_program') |
|
@before_method('process_source') |
|
def px4_dynamic_env(self): |
|
# The generated files from configuration possibly don't exist if it's just |
|
# a list command (TODO: figure out a better way to address that). |
|
if self.bld.cmd == 'list': |
|
return |
|
|
|
if not _dynamic_env_data: |
|
_load_dynamic_env_data(self.bld) |
|
|
|
self.env.append_value('INCLUDES', _dynamic_env_data['include_dirs']) |
|
self.env.prepend_value('CXXFLAGS', _dynamic_env_data['cxx_flags']) |
|
self.env.prepend_value('CXXFLAGS', _dynamic_env_data['definitions']) |
|
|
|
# Single static library |
|
# NOTE: This only works only for local static libraries dependencies - fake |
|
# libraries aren't supported yet |
|
@feature('px4_ap_program') |
|
@after_method('apply_link') |
|
@before_method('process_use') |
|
def px4_import_objects_from_use(self): |
|
queue = Utils.to_list(getattr(self, 'use', [])) |
|
names = set() |
|
|
|
while queue: |
|
name = queue.pop(0) |
|
if name in names: |
|
continue |
|
names.add(name) |
|
|
|
try: |
|
tg = self.bld.get_tgen_by_name(name) |
|
except Errors.WafError: |
|
continue |
|
|
|
tg.post() |
|
for t in getattr(tg, 'compiled_tasks', []): |
|
self.link_task.set_inputs(t.outputs) |
|
|
|
queue.extend(Utils.to_list(getattr(tg, 'use', []))) |
|
|
|
class px4_copy_lib(Task.Task): |
|
run_str = '${CP} ${SRC} ${PX4_AP_PROGRAM_LIB}' |
|
color = 'CYAN' |
|
|
|
def runnable_status(self): |
|
status = super(px4_copy_lib, self).runnable_status() |
|
if status != Task.SKIP_ME: |
|
return status |
|
|
|
pseudo_target = self.get_pseudo_target() |
|
try: |
|
if pseudo_target.sig != self.inputs[0].sig: |
|
status = Task.RUN_ME |
|
except AttributeError: |
|
status = Task.RUN_ME |
|
|
|
return status |
|
|
|
def get_pseudo_target(self): |
|
if hasattr(self, 'pseudo_target'): |
|
return self.pseudo_target |
|
|
|
bldnode = self.generator.bld.bldnode |
|
self.pseudo_target = bldnode.make_node(self.env.PX4_AP_PROGRAM_LIB) |
|
return self.pseudo_target |
|
|
|
def keyword(self): |
|
return 'PX4: Copying program library' |
|
|
|
def post_run(self): |
|
super(px4_copy_lib, self).post_run() |
|
pseudo_target = self.get_pseudo_target() |
|
pseudo_target.sig = pseudo_target.cache_sig = self.inputs[0].sig |
|
|
|
class px4_copy(Task.Task): |
|
run_str = '${CP} ${SRC} ${TGT}' |
|
color = 'CYAN' |
|
|
|
def keyword(self): |
|
return "PX4: Copying %s to" % self.inputs[0].name |
|
|
|
def __str__(self): |
|
return self.outputs[0].path_from(self.generator.bld.bldnode) |
|
|
|
class px4_add_git_hashes(Task.Task): |
|
run_str = '${PYTHON} ${PX4_ADD_GIT_HASHES} --ardupilot ${PX4_APM_ROOT} --px4 ${PX4_ROOT} --nuttx ${PX4_NUTTX_ROOT} --uavcan ${PX4_UAVCAN_ROOT} ${SRC} ${TGT}' |
|
color = 'CYAN' |
|
|
|
def keyword(self): |
|
return "PX4: Copying firmware and adding git hashes" |
|
|
|
def __str__(self): |
|
return self.outputs[0].path_from(self.outputs[0].ctx.launch_node()) |
|
|
|
def _update_firmware_sig(fw_task, firmware): |
|
original_post_run = fw_task.post_run |
|
def post_run(): |
|
original_post_run() |
|
firmware.sig = firmware.cache_sig = Utils.h_file(firmware.abspath()) |
|
fw_task.post_run = post_run |
|
|
|
_cp_px4io = None |
|
_firmware_semaphorish_tasks = [] |
|
_upload_task = [] |
|
|
|
@feature('px4_ap_program') |
|
@after_method('process_source') |
|
def px4_firmware(self): |
|
global _cp_px4io, _firmware_semaphorish_tasks, _upload_task |
|
version = self.env.get_flat('PX4_VERSION') |
|
|
|
if self.env.PX4_USE_PX4IO and not _cp_px4io: |
|
px4io_task = self.create_cmake_build_task('px4', 'fw_io') |
|
px4io = px4io_task.config_taskgen.get_cmake_bldnode().make_node( |
|
'src/modules/px4iofirmware/px4io-v%s.bin' % version, |
|
) |
|
px4io_task.set_outputs(px4io) |
|
|
|
romfs = self.bld.bldnode.make_node(self.env.PX4_ROMFS_BLD) |
|
romfs_px4io = romfs.make_node('px4io/px4io.bin') |
|
romfs_px4io.parent.mkdir() |
|
_cp_px4io = self.create_task('px4_copy', px4io, romfs_px4io) |
|
_cp_px4io.keyword = lambda: 'PX4: Copying PX4IO to ROMFS' |
|
|
|
cp_lib = self.create_task('px4_copy_lib', self.link_task.outputs) |
|
# we need to synchronize because the path PX4_AP_PROGRAM_LIB is used by all |
|
# ap_programs |
|
if _firmware_semaphorish_tasks: |
|
for t in _firmware_semaphorish_tasks: |
|
cp_lib.set_run_after(t) |
|
_firmware_semaphorish_tasks = [] |
|
|
|
fw_task = self.create_cmake_build_task( |
|
'px4', |
|
'build_firmware_px4fmu-v%s' % version, |
|
) |
|
fw_task.set_run_after(cp_lib) |
|
if self.env.PX4_USE_PX4IO and _cp_px4io.generator is self: |
|
fw_task.set_run_after(_cp_px4io) |
|
|
|
firmware = fw_task.config_taskgen.cmake_bld.make_node( |
|
'src/firmware/nuttx/nuttx-px4fmu-v%s-apm.px4' % version, |
|
) |
|
_update_firmware_sig(fw_task, firmware) |
|
|
|
fw_dest = self.bld.bldnode.make_node( |
|
os.path.join(self.program_dir, '%s.px4' % self.program_name) |
|
) |
|
git_hashes = self.create_task('px4_add_git_hashes', firmware, fw_dest) |
|
git_hashes.set_run_after(fw_task) |
|
_firmware_semaphorish_tasks.append(git_hashes) |
|
|
|
if self.bld.options.upload: |
|
if _upload_task: |
|
Logs.warn('PX4: upload for %s ignored' % self.name) |
|
return |
|
_upload_task = self.create_cmake_build_task('px4', 'upload') |
|
_upload_task.set_run_after(fw_task) |
|
_firmware_semaphorish_tasks.append(_upload_task) |
|
|
|
def _px4_taskgen(bld, **kw): |
|
if 'cls_keyword' in kw and not callable(kw['cls_keyword']): |
|
cls_keyword = str(kw['cls_keyword']) |
|
kw['cls_keyword'] = lambda tsk: 'PX4: ' + cls_keyword |
|
|
|
if 'cls_str' in kw and not callable(kw['cls_str']): |
|
cls_str = str(kw['cls_str']) |
|
kw['cls_str'] = lambda tsk: cls_str |
|
|
|
kw['color'] = 'CYAN' |
|
|
|
return bld(**kw) |
|
|
|
@feature('_px4_romfs') |
|
def _process_romfs(self): |
|
bld = self.bld |
|
file_list = ( |
|
'firmware/oreoled.bin', |
|
'init.d/rc.APM', |
|
'init.d/rc.error', |
|
'init.d/rcS', |
|
(bld.env.PX4_BOOTLOADER, 'bootloader/fmu_bl.bin'), |
|
) |
|
|
|
romfs_src = bld.srcnode.find_dir(bld.env.PX4_ROMFS_SRC) |
|
romfs_bld = bld.bldnode.make_node(bld.env.PX4_ROMFS_BLD) |
|
|
|
for item in file_list: |
|
if isinstance(item, str): |
|
src = romfs_src.make_node(item) |
|
dst = romfs_bld.make_node(item) |
|
else: |
|
src = bld.srcnode.make_node(item[0]) |
|
dst = romfs_bld.make_node(item[1]) |
|
|
|
dst.parent.mkdir() |
|
self.create_task('px4_copy', src, dst) |
|
|
|
def configure(cfg): |
|
cfg.load('cmake') |
|
cfg.find_program('cp') |
|
|
|
bldnode = cfg.bldnode.make_node(cfg.variant) |
|
env = cfg.env |
|
|
|
env.AP_PROGRAM_FEATURES += ['px4_ap_program'] |
|
env.AP_STLIB_FEATURES += ['px4_ap_stlib'] |
|
|
|
def srcpath(path): |
|
return cfg.srcnode.make_node(path).abspath() |
|
|
|
def bldpath(path): |
|
return bldnode.make_node(path).abspath() |
|
|
|
if env.PX4_VERSION == '1': |
|
bootloader_name = 'px4fmu_bl.bin' |
|
else: |
|
bootloader_name = 'px4fmuv%s_bl.bin' % env.get_flat('PX4_VERSION') |
|
|
|
# TODO: we should move stuff from mk/PX4 to Tools/ardupilotwaf/px4 after |
|
# stop using the make-based build system |
|
env.PX4_ROMFS_SRC = 'mk/PX4/ROMFS' |
|
env.PX4_ROMFS_BLD = 'px4-extra-files/ROMFS' |
|
env.PX4_BOOTLOADER = 'mk/PX4/bootloader/%s' % bootloader_name |
|
|
|
program_lib_name = cfg.env.cxxstlib_PATTERN % 'ap_program' |
|
env.PX4_AP_PROGRAM_LIB = os.path.join('px4-extra-files', program_lib_name) |
|
|
|
env.PX4_ADD_GIT_HASHES = srcpath('Tools/scripts/add_git_hashes.py') |
|
env.PX4_APM_ROOT = srcpath('') |
|
env.PX4_ROOT = srcpath('modules/PX4Firmware') |
|
env.PX4_NUTTX_ROOT = srcpath('modules/PX4NuttX') |
|
env.PX4_UAVCAN_ROOT = srcpath('modules/uavcan') |
|
|
|
env.PX4_CMAKE_VARS = dict( |
|
CONFIG='nuttx_px4fmu-v%s_apm' % env.get_flat('PX4_VERSION'), |
|
CMAKE_MODULE_PATH=srcpath('Tools/ardupilotwaf/px4/cmake'), |
|
UAVCAN_LIBUAVCAN_PATH=env.PX4_UAVCAN_ROOT, |
|
NUTTX_SRC=env.PX4_NUTTX_ROOT, |
|
PX4_NUTTX_ROMFS=bldpath(env.PX4_ROMFS_BLD), |
|
APM_PROGRAM_LIB=bldpath(env.PX4_AP_PROGRAM_LIB), |
|
ARDUPILOT_BUILD='YES', |
|
EXTRA_CXX_FLAGS=' '.join(( |
|
# NOTE: these "-Wno-error=*" flags should be removed as we update |
|
# the submodule |
|
'-Wno-error=double-promotion', |
|
'-Wno-error=reorder', |
|
# NOTE: *Temporarily* using this definition so that both |
|
# PX4Firmware build systems (cmake and legacy make-based) can live |
|
# together |
|
'-DCMAKE_BUILD', |
|
'-DARDUPILOT_BUILD', |
|
'-I%s' % bldpath('libraries/GCS_MAVLink'), |
|
'-Wl,--gc-sections', |
|
)), |
|
EXTRA_C_FLAGS=' '.join(( |
|
# NOTE: *Temporarily* using this definition so that both |
|
# PX4Firmware build systems (cmake and legacy make-based) can live |
|
# together |
|
'-DCMAKE_BUILD', |
|
)), |
|
) |
|
|
|
def build(bld): |
|
version = bld.env.get_flat('PX4_VERSION') |
|
px4 = bld( |
|
features='cmake_configure', |
|
name='px4', |
|
cmake_src=bld.srcnode.find_dir('modules/PX4Firmware'), |
|
cmake_vars=bld.env.PX4_CMAKE_VARS, |
|
group='dynamic_sources', |
|
) |
|
|
|
px4.cmake_build( |
|
'msg_gen', |
|
group='dynamic_sources', |
|
cmake_output_patterns='src/modules/uORB/topics/*.h', |
|
) |
|
px4.cmake_build( |
|
'prebuild_targets', |
|
group='dynamic_sources', |
|
cmake_output_patterns='px4fmu-v%s/NuttX/nuttx-export/**/*.h' % version, |
|
) |
|
|
|
bld( |
|
name='px4_romfs_static_files', |
|
group='dynamic_sources', |
|
features='_px4_romfs', |
|
)
|
|
|