fbt: support for LOADER_AUTOSTART; post-build size stats (#1594)
* fbt: restored LOADER_AUTOSTART support * scripts: added fwsize.py wrapper for size command; fbt: changed size post-build stats to fwsize.py call * fbt: removed size wrapper * fbt: added stats for binary flash size in pages * fbt: hint on build options details * scripts: fixed fwsize.py for *nix
This commit is contained in:
		
							parent
							
								
									9e452d2b26
								
							
						
					
					
						commit
						e1ffb4ac4d
					
				| @ -18,6 +18,8 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
| typedef void (*FlipperOnStartHook)(void); | typedef void (*FlipperOnStartHook)(void); | ||||||
| 
 | 
 | ||||||
|  | extern const char* FLIPPER_AUTORUN_APP_NAME; | ||||||
|  | 
 | ||||||
| /* Services list
 | /* Services list
 | ||||||
|  * Spawned on startup |  * Spawned on startup | ||||||
|  */ |  */ | ||||||
|  | |||||||
| @ -466,9 +466,9 @@ int32_t loader_srv(void* p) { | |||||||
| 
 | 
 | ||||||
|     furi_record_create(RECORD_LOADER, loader_instance); |     furi_record_create(RECORD_LOADER, loader_instance); | ||||||
| 
 | 
 | ||||||
| #ifdef LOADER_AUTOSTART |     if(FLIPPER_AUTORUN_APP_NAME && strlen(FLIPPER_AUTORUN_APP_NAME)) { | ||||||
|     loader_start(loader_instance, LOADER_AUTOSTART, NULL); |         loader_start(loader_instance, FLIPPER_AUTORUN_APP_NAME, NULL); | ||||||
| #endif |     } | ||||||
| 
 | 
 | ||||||
|     while(1) { |     while(1) { | ||||||
|         uint32_t flags = |         uint32_t flags = | ||||||
|  | |||||||
| @ -1,5 +1,7 @@ | |||||||
| import posixpath | import posixpath | ||||||
| 
 | 
 | ||||||
|  | # For more details on these options, run 'fbt -h' | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| # Default hardware target | # Default hardware target | ||||||
| TARGET_HW = 7 | TARGET_HW = 7 | ||||||
| @ -59,6 +61,9 @@ SVD_FILE = "debug/STM32WB55_CM4.svd" | |||||||
| # Look for blackmagic probe on serial ports and local network | # Look for blackmagic probe on serial ports and local network | ||||||
| BLACKMAGIC = "auto" | BLACKMAGIC = "auto" | ||||||
| 
 | 
 | ||||||
|  | # Application to start on boot | ||||||
|  | LOADER_AUTOSTART = "" | ||||||
|  | 
 | ||||||
| FIRMWARE_APPS = { | FIRMWARE_APPS = { | ||||||
|     "default": [ |     "default": [ | ||||||
|         "crypto_start", |         "crypto_start", | ||||||
|  | |||||||
| @ -139,7 +139,7 @@ fwenv.AppendUnique( | |||||||
| # Depends on virtual value-only node, so it only gets rebuilt when set of apps changes | # Depends on virtual value-only node, so it only gets rebuilt when set of apps changes | ||||||
| apps_c = fwenv.ApplicationsC( | apps_c = fwenv.ApplicationsC( | ||||||
|     "applications/applications.c", |     "applications/applications.c", | ||||||
|     Value(fwenv["APPS"]), |     [Value(fwenv["APPS"]), Value(fwenv["LOADER_AUTOSTART"])], | ||||||
| ) | ) | ||||||
| # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed | # Adding dependency on manifest files so apps.c is rebuilt when any manifest is changed | ||||||
| fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) | fwenv.Depends(apps_c, fwenv.GlobRecursive("*.fam", "#/applications")) | ||||||
| @ -210,11 +210,19 @@ fwelf = fwenv["FW_ELF"] = fwenv.Program( | |||||||
| Depends(fwelf, lib_targets) | Depends(fwelf, lib_targets) | ||||||
| # Output extra details after building firmware | # Output extra details after building firmware | ||||||
| AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) | AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) | ||||||
| AddPostAction(fwelf, Action("@$SIZECOM")) | AddPostAction( | ||||||
|  |     fwelf, | ||||||
|  |     Action('${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" elf ${TARGET}', "Firmware size"), | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| # Produce extra firmware files | # Produce extra firmware files | ||||||
| fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") | fwhex = fwenv["FW_HEX"] = fwenv.HEXBuilder("${FIRMWARE_BUILD_CFG}") | ||||||
| fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") | fwbin = fwenv["FW_BIN"] = fwenv.BINBuilder("${FIRMWARE_BUILD_CFG}") | ||||||
|  | AddPostAction( | ||||||
|  |     fwbin, | ||||||
|  |     Action('@${PYTHON3} "${ROOT_DIR}/scripts/fwsize.py" bin ${TARGET}'), | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") | fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") | ||||||
| Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu) | Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_dfu", fwdfu) | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										52
									
								
								scripts/fwsize.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								scripts/fwsize.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,52 @@ | |||||||
|  | #!/usr/bin/env python3 | ||||||
|  | 
 | ||||||
|  | from flipper.app import App | ||||||
|  | import subprocess | ||||||
|  | import os | ||||||
|  | import math | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Main(App): | ||||||
|  |     def init(self): | ||||||
|  |         self.subparsers = self.parser.add_subparsers(help="sub-command help") | ||||||
|  | 
 | ||||||
|  |         self.parser_elfsize = self.subparsers.add_parser("elf", help="Dump elf stats") | ||||||
|  |         self.parser_elfsize.add_argument("elfname", action="store") | ||||||
|  |         self.parser_elfsize.set_defaults(func=self.process_elf) | ||||||
|  | 
 | ||||||
|  |         self.parser_binsize = self.subparsers.add_parser("bin", help="Dump bin stats") | ||||||
|  |         self.parser_binsize.add_argument("binname", action="store") | ||||||
|  |         self.parser_binsize.set_defaults(func=self.process_bin) | ||||||
|  | 
 | ||||||
|  |     def process_elf(self): | ||||||
|  |         all_sizes = subprocess.check_output( | ||||||
|  |             ["arm-none-eabi-size", "-A", self.args.elfname], shell=False | ||||||
|  |         ) | ||||||
|  |         all_sizes = all_sizes.splitlines() | ||||||
|  | 
 | ||||||
|  |         sections_to_keep = (".text", ".rodata", ".data", ".bss", ".free_flash") | ||||||
|  |         for line in all_sizes: | ||||||
|  |             line = line.decode("utf-8") | ||||||
|  |             parts = line.split() | ||||||
|  |             if len(parts) != 3: | ||||||
|  |                 continue | ||||||
|  |             section, size, _ = parts | ||||||
|  |             if section not in sections_to_keep: | ||||||
|  |                 continue | ||||||
|  |             print(f"{section:<11} {size:>8} ({(int(size)/1024):6.2f} K)") | ||||||
|  | 
 | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  |     def process_bin(self): | ||||||
|  |         PAGE_SIZE = 4096 | ||||||
|  |         binsize = os.path.getsize(self.args.binname) | ||||||
|  |         pages = math.ceil(binsize / PAGE_SIZE) | ||||||
|  |         last_page_state = (binsize % PAGE_SIZE) * 100 / PAGE_SIZE | ||||||
|  |         print( | ||||||
|  |             f"{os.path.basename(self.args.binname):<11}: {pages:>4} flash pages (last page {last_page_state:.02f}% full)" | ||||||
|  |         ) | ||||||
|  |         return 0 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | if __name__ == "__main__": | ||||||
|  |     Main()() | ||||||
| @ -174,6 +174,12 @@ vars.Add( | |||||||
|     default="update_default", |     default="update_default", | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | vars.Add( | ||||||
|  |     "LOADER_AUTOSTART", | ||||||
|  |     help="Application name to automatically run on Flipper boot", | ||||||
|  |     default="", | ||||||
|  | ) | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| vars.Add( | vars.Add( | ||||||
|     "FIRMWARE_APPS", |     "FIRMWARE_APPS", | ||||||
|  | |||||||
| @ -200,8 +200,9 @@ class ApplicationsCGenerator: | |||||||
|         FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"), |         FlipperAppType.STARTUP: ("FlipperOnStartHook", "FLIPPER_ON_SYSTEM_START"), | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     def __init__(self, buildset: AppBuildset): |     def __init__(self, buildset: AppBuildset, autorun_app: str = ""): | ||||||
|         self.buildset = buildset |         self.buildset = buildset | ||||||
|  |         self.autorun = autorun_app | ||||||
| 
 | 
 | ||||||
|     def get_app_ep_forward(self, app: FlipperApplication): |     def get_app_ep_forward(self, app: FlipperApplication): | ||||||
|         if app.apptype == FlipperAppType.STARTUP: |         if app.apptype == FlipperAppType.STARTUP: | ||||||
| @ -219,7 +220,11 @@ class ApplicationsCGenerator: | |||||||
|      .flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}""" |      .flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}""" | ||||||
| 
 | 
 | ||||||
|     def generate(self): |     def generate(self): | ||||||
|         contents = ['#include "applications.h"', "#include <assets_icons.h>"] |         contents = [ | ||||||
|  |             '#include "applications.h"', | ||||||
|  |             "#include <assets_icons.h>", | ||||||
|  |             f'const char* FLIPPER_AUTORUN_APP_NAME = "{self.autorun}";', | ||||||
|  |         ] | ||||||
|         for apptype in self.APP_TYPE_MAP: |         for apptype in self.APP_TYPE_MAP: | ||||||
|             contents.extend( |             contents.extend( | ||||||
|                 map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) |                 map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) | ||||||
|  | |||||||
| @ -7,7 +7,6 @@ from SCons.Tool import gnulink | |||||||
| import strip | import strip | ||||||
| import gdb | import gdb | ||||||
| import objdump | import objdump | ||||||
| import size |  | ||||||
| 
 | 
 | ||||||
| from SCons.Action import _subproc | from SCons.Action import _subproc | ||||||
| import subprocess | import subprocess | ||||||
| @ -38,7 +37,7 @@ def _get_tool_version(env, tool): | |||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def generate(env, **kw): | def generate(env, **kw): | ||||||
|     for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump, size): |     for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump): | ||||||
|         orig_tool.generate(env) |         orig_tool.generate(env) | ||||||
|     env.SetDefault( |     env.SetDefault( | ||||||
|         TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"), |         TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"), | ||||||
| @ -57,7 +56,6 @@ def generate(env, **kw): | |||||||
|             "GDB", |             "GDB", | ||||||
|             "GDBPY", |             "GDBPY", | ||||||
|             "OBJDUMP", |             "OBJDUMP", | ||||||
|             "SIZE", |  | ||||||
|         ], |         ], | ||||||
|     ) |     ) | ||||||
|     # Call CC to check version |     # Call CC to check version | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ def DumpApplicationConfig(target, source, env): | |||||||
| def build_apps_c(target, source, env): | def build_apps_c(target, source, env): | ||||||
|     target_file_name = target[0].path |     target_file_name = target[0].path | ||||||
| 
 | 
 | ||||||
|     gen = ApplicationsCGenerator(env["APPBUILD"]) |     gen = ApplicationsCGenerator(env["APPBUILD"], env.subst("$LOADER_AUTOSTART")) | ||||||
|     with open(target_file_name, "w") as file: |     with open(target_file_name, "w") as file: | ||||||
|         file.write(gen.generate()) |         file.write(gen.generate()) | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,24 +0,0 @@ | |||||||
| from SCons.Builder import Builder |  | ||||||
| from SCons.Action import Action |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def generate(env): |  | ||||||
|     env.SetDefault( |  | ||||||
|         SIZE="size", |  | ||||||
|         SIZEFLAGS=[], |  | ||||||
|         SIZECOM="$SIZE $SIZEFLAGS $TARGETS", |  | ||||||
|     ) |  | ||||||
|     env.Append( |  | ||||||
|         BUILDERS={ |  | ||||||
|             "ELFSize": Builder( |  | ||||||
|                 action=Action( |  | ||||||
|                     "${SIZECOM}", |  | ||||||
|                     "${SIZECOMSTR}", |  | ||||||
|                 ), |  | ||||||
|             ), |  | ||||||
|         } |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def exists(env): |  | ||||||
|     return True |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 hedger
						hedger