mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-19 23:28:32 -04:00
06a515645e
A (possible) bug in CMake makes it not to relink firmware_nuttx sometimes when
the following sequence of events happen with very short period of time in
between them:
1) cmake target build_firmware_px4fmu-v2 just finishes
2) px4-extra-files/libap_program.a is replaced with the next library
3) cmake target build_firmware_px4fmu-v2 is run
It's unfortunate to have to reconfigure PX4Firmware with a different path
because of the overhead added.
That problem was found with CMake 3.5.2 and is reproducible with the following
bash script (with git HEAD at ae3cb05
'HAL_PX4: disable "Overtime in task"
msg'):
```
modules/waf/waf-light configure --board px4-v2
modules/waf/waf-light build --targets bin/arduplane,bin/arducopter-quad
fails=0
total=0
while true; do
cp build/px4-v2/bin/libarducopter-quad.a \
build/px4-v2/px4-extra-files/libap_program.a
cmake --build build/px4-v2/modules/PX4Firmware \
--target build_firmware_px4fmu-v2 &> /dev/null
h1=$(sha256sum build/px4-v2/modules/PX4Firmware/src/firmware/nuttx/firmware_nuttx \
| cut -d" " -f1)
cp build/px4-v2/bin/libarduplane.a build/px4-v2/px4-extra-files/libap_program.a
cmake --build build/px4-v2/modules/PX4Firmware \
--target build_firmware_px4fmu-v2 &> /dev/null
h2=$(sha256sum build/px4-v2/modules/PX4Firmware/src/firmware/nuttx/firmware_nuttx \
| cut -d" " -f1)
[[ $h1 == $h2 ]] && ((fails++))
((total++))
printf "\r%d/%d" $fails $total
done
```
273 lines
8.7 KiB
Python
273 lines
8.7 KiB
Python
#!/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(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.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'
|
|
|
|
px4 = self.bld.cmake('px4')
|
|
px4.vars['APM_PROGRAM_LIB'] = self.link_task.outputs[0].abspath()
|
|
|
|
fw_task = self.create_cmake_build_task(
|
|
'px4',
|
|
'build_firmware_px4fmu-v%s' % version,
|
|
)
|
|
|
|
# we need to synchronize in order to avoid the output expected by the
|
|
# previous ap_program being overwritten before used
|
|
for t in _firmware_semaphorish_tasks:
|
|
fw_task.set_run_after(t)
|
|
_firmware_semaphorish_tasks = []
|
|
|
|
if self.env.PX4_USE_PX4IO and _cp_px4io.generator is self:
|
|
fw_task.set_run_after(_cp_px4io)
|
|
|
|
firmware = px4.bldnode.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
|
|
|
|
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),
|
|
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'),
|
|
'-I%s' % bldpath('libraries/GCS_MAVLink/include/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.cmake(
|
|
name='px4',
|
|
cmake_src=bld.srcnode.find_dir('modules/PX4Firmware'),
|
|
cmake_vars=bld.env.PX4_CMAKE_VARS,
|
|
)
|
|
|
|
px4.build(
|
|
'msg_gen',
|
|
group='dynamic_sources',
|
|
cmake_output_patterns='src/modules/uORB/topics/*.h',
|
|
)
|
|
px4.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',
|
|
)
|