diff --git a/examples/companion_radio/CompanionHelpPacked.cpp b/examples/companion_radio/CompanionHelpPacked.cpp index ee21aad31..c5e7a1f41 100644 --- a/examples/companion_radio/CompanionHelpPacked.cpp +++ b/examples/companion_radio/CompanionHelpPacked.cpp @@ -1,8 +1,10 @@ +// This is the only selected Companion source compiled as C++17. Include the +// same feature/board context as MyMesh before testing board aliases: RAK3401 +// defines its RAK_4631 compatibility macro in the variant header. +#include "MyMesh.h" + #if defined(RAK_4631) && defined(COMPANION_RADIO_FULL) \ || (defined(STM32_PLATFORM) && defined(STM32WLxx)) -// This is the only selected Companion source compiled as C++17. Include the -// same feature/board context as MyMesh before expanding the single help source. -#include "MyMesh.h" #include "CompanionHelpWriter.h" #if !defined(STM32_PLATFORM) || COMPANION_FEATURE_TEXT_TERMINAL diff --git a/test/test_companion_help_build_policy.py b/test/test_companion_help_build_policy.py index 33472319c..c529f8d18 100644 --- a/test/test_companion_help_build_policy.py +++ b/test/test_companion_help_build_policy.py @@ -2,6 +2,11 @@ from pathlib import Path import copy import importlib.util +import os +import re +import shutil +import subprocess +import tempfile import unittest ROOT=Path(__file__).resolve().parents[1] spec=importlib.util.spec_from_file_location('help_language_policy',ROOT/'scripts/nrf52_flash_trim.py');m=importlib.util.module_from_spec(spec);spec.loader.exec_module(m) @@ -31,6 +36,45 @@ class HelpBuildPolicy(unittest.TestCase): self.assertEqual(result,('compiled17',node));self.assertEqual(dict(env),before) self.assertEqual(env.overrides['CXXFLAGS'],['-fno-exceptions','-fno-rtti','-std=gnu++17']) self.assertEqual(env.overrides['CCFLAGS'],['-Os','-flto']);self.assertEqual(env['CPPDEFINES'],before['CPPDEFINES']) + def test_producer_resolves_header_board_alias_before_feature_gate(self): + compiler=os.environ.get('CXX') or shutil.which('g++') or shutil.which('clang++') + if not compiler: + self.skipTest('host C++ preprocessor required') + directory=ROOT/'examples/companion_radio' + producer=(directory/'CompanionHelpPacked.cpp').read_text() + # RAK3401's variant header defines RAK_4631 only after Arduino/MyMesh is + # included. A command-line definition would hide the linker's regression. + board_context='''#pragma once +#if defined(TEST_RAK3401_VARIANT) +#define RAK_4631 1 +#endif +#if defined(TEST_STM32WL_VARIANT) +#define STM32WLxx 1 +#endif +''' + profiles=( + ('rak3401_full',('NRF52_PLATFORM','TEST_RAK3401_VARIANT','COMPANION_RADIO_FULL'),True), + ('rak3401_usb',('NRF52_PLATFORM','TEST_RAK3401_VARIANT'),False), + ('other_nrf52_full',('NRF52_PLATFORM','COMPANION_RADIO_FULL'),False), + ('rak4631_full',('NRF52_PLATFORM','RAK_4631','COMPANION_RADIO_FULL'),True), + ('stm32wl_terminal',('STM32_PLATFORM','STM32WLxx','COMPANION_FEATURE_TEXT_TERMINAL=1'),True), + ('stm32wl_header_alias',('STM32_PLATFORM','TEST_STM32WL_VARIANT','COMPANION_FEATURE_TEXT_TERMINAL=1'),True), + ('stm32wl_no_terminal',('STM32_PLATFORM','STM32WLxx','COMPANION_FEATURE_TEXT_TERMINAL=0'),False), + ) + with tempfile.TemporaryDirectory(prefix='companion-help-gate-') as folder: + work=Path(folder) + (work/'MyMesh.h').write_text(board_context,encoding='ascii') + source=work/'CompanionHelpPacked.cpp' + source.write_text(producer,encoding='ascii') + for name,defines,selected in profiles: + with self.subTest(profile=name): + result=subprocess.run([compiler,'-E','-P','-std=c++17', + *['-D'+value for value in defines],'-I'+str(directory),str(source)], + capture_output=True,text=True) + self.assertEqual(result.returncode,0,result.stdout+result.stderr) + definition=re.search(r'size_t\s+writePackedCompanionHelp\s*\([^)]*\)\s*\{',result.stdout) + self.assertEqual(definition is not None,selected, + 'packed help producer and caller must see the same header-defined board aliases') def test_producer_uses_same_feature_context_and_single_help_source(self): cpp=(ROOT/'examples/companion_radio/CompanionHelpPacked.cpp').read_text();mesh=(ROOT/'examples/companion_radio/MyMesh.cpp').read_text() self.assertLess(cpp.index('#include "MyMesh.h"'),cpp.index('#include "CompanionHelp.inc"'))