diff options
Diffstat (limited to 'build-aux/measurestack/app_main.py')
-rw-r--r-- | build-aux/measurestack/app_main.py | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/build-aux/measurestack/app_main.py b/build-aux/measurestack/app_main.py new file mode 100644 index 0000000..7573146 --- /dev/null +++ b/build-aux/measurestack/app_main.py @@ -0,0 +1,132 @@ +# build-aux/measurestack/app_main.py - Application-specific wrapper around analyze.py +# +# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com> +# SPDX-License-Identifier: AGPL-3.0-or-later + +import os.path +import typing + +from . import analyze, app_output, app_plugins, util +from .analyze import BaseName, QName + +# pylint: disable=unused-variable +__all__ = [ + "main", +] + + +def main( + *, + arg_pico_platform: str, + arg_base_dir: str, + arg_ci_fnames: typing.Collection[str], + arg_c_fnames: typing.Collection[str], +) -> None: + + plugins: list[util.Plugin] = [] + + # sbc-harness #################################################### + + libobj_plugin = app_plugins.LibObjPlugin(arg_c_fnames) + lib9p_plugin = app_plugins.Lib9PPlugin(arg_base_dir, arg_c_fnames, libobj_plugin) + + def sbc_is_thread(name: QName) -> int: + if str(name).endswith("_cr") and name.base() != BaseName("lib9p_srv_read_cr"): + if "9p" in str(name.base()) or "lib9p/tests/test_server/main.c:" in str( + name + ): + return lib9p_plugin.thread_count(name) + return 1 + if name.base() == ( + BaseName("_entry_point") + if arg_pico_platform == "rp2040" + else BaseName("main") + ): + return 1 + return 0 + + plugins += [ + app_plugins.CmdPlugin(), + libobj_plugin, + app_plugins.PicoFmtPlugin(arg_pico_platform), + app_plugins.LibHWPlugin(arg_pico_platform, libobj_plugin), + app_plugins.LibCRPlugin(), + app_plugins.LibCRIPCPlugin(), + lib9p_plugin, + app_plugins.LibMiscPlugin(), + ] + + # pico-sdk ####################################################### + + if arg_pico_platform == "rp2040": + + def get_init_array() -> typing.Collection[QName]: + ret: list[QName] = [] + for plugin in plugins: + ret.extend(plugin.init_array()) + return ret + + plugins += [ + app_plugins.PicoSDKPlugin( + get_init_array=get_init_array, + ), + app_plugins.TinyUSBDevicePlugin(arg_c_fnames), + app_plugins.NewlibPlugin(), + app_plugins.LibGCCPlugin(), + ] + + # Tie it all together ############################################ + + def thread_filter(name: QName) -> tuple[int, bool]: + return sbc_is_thread(name), True + + def intrhandler_filter(name: QName) -> tuple[int, bool]: + for plugin in plugins: + if plugin.is_intrhandler(name): + return 1, True + return 0, False + + def misc_filter(name: QName) -> tuple[int, bool]: + if name in [ + QName("__assert_msg_fail"), + QName("__lm_printf"), + QName("__lm_light_printf"), + QName("fmt_vfctprintf"), + QName("fmt_vsnprintf"), + ]: + return 1, False + return 0, False + + extra_includes: list[BaseName] = [] + for plugin in plugins: + extra_includes.extend(plugin.extra_includes()) + + def extra_filter(name: QName) -> tuple[int, bool]: + nonlocal extra_includes + if name.base() in extra_includes: + return 1, True + return 0, False + + def _str_location_xform(loc: str) -> str: + if not loc.startswith("/"): + return loc + parts = loc.split(":", 1) + parts[0] = "./" + os.path.relpath(parts[0], arg_base_dir) + return ":".join(parts) + + def location_xform(_loc: QName) -> str: + return _str_location_xform(str(_loc)) + + result = analyze.analyze( + ci_fnames=arg_ci_fnames, + app_func_filters={ + "Threads": thread_filter, + "Interrupt handlers": intrhandler_filter, + "Misc": misc_filter, + "Extra": extra_filter, + }, + app=util.PluginApplication(_str_location_xform, plugins), + cfg_max_call_depth=100, + ) + + app_output.print_c(result, location_xform) |