fbt: improvements (#3217)
* fbt: changed cdefines & lib handling for external apps; added extra checks for app manifest fields; moved around AppsC generator * fbt: commandline fixes for spaces in paths * fbt: fixed stringification for FAP_VERSION * fbt: Removed excessive quoting for gdb * docs: update for cdefines; fbt: typo fix * fbt: enforcing at least 2 components in app version= Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									457aa5331f
								
							
						
					
					
						commit
						98d5718ec9
					
				
							
								
								
									
										36
									
								
								SConstruct
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								SConstruct
									
									
									
									
									
								
							| @ -172,17 +172,19 @@ Alias("fap_dist", fap_dist) | |||||||
| 
 | 
 | ||||||
| fap_deploy = distenv.PhonyTarget( | fap_deploy = distenv.PhonyTarget( | ||||||
|     "fap_deploy", |     "fap_deploy", | ||||||
|     [ |     Action( | ||||||
|         [ |         [ | ||||||
|             "${PYTHON3}", |             [ | ||||||
|             "${FBT_SCRIPT_DIR}/storage.py", |                 "${PYTHON3}", | ||||||
|             "-p", |                 "${FBT_SCRIPT_DIR}/storage.py", | ||||||
|             "${FLIP_PORT}", |                 "-p", | ||||||
|             "send", |                 "${FLIP_PORT}", | ||||||
|             "${SOURCE}", |                 "send", | ||||||
|             "/ext/apps", |                 "${SOURCE}", | ||||||
|  |                 "/ext/apps", | ||||||
|  |             ] | ||||||
|         ] |         ] | ||||||
|     ], |     ), | ||||||
|     source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")), |     source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")), | ||||||
| ) | ) | ||||||
| Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"]) | Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"]) | ||||||
| @ -261,7 +263,7 @@ distenv.PhonyTarget( | |||||||
| distenv.PhonyTarget( | distenv.PhonyTarget( | ||||||
|     "debug_other_blackmagic", |     "debug_other_blackmagic", | ||||||
|     "${GDBPYCOM}", |     "${GDBPYCOM}", | ||||||
|     GDBOPTS="${GDBOPTS_BASE}  ${GDBOPTS_BLACKMAGIC}", |     GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}", | ||||||
|     GDBREMOTE="${BLACKMAGIC_ADDR}", |     GDBREMOTE="${BLACKMAGIC_ADDR}", | ||||||
|     GDBPYOPTS=debug_other_opts, |     GDBPYOPTS=debug_other_opts, | ||||||
| ) | ) | ||||||
| @ -276,13 +278,13 @@ distenv.PhonyTarget( | |||||||
| # Linter | # Linter | ||||||
| distenv.PhonyTarget( | distenv.PhonyTarget( | ||||||
|     "lint", |     "lint", | ||||||
|     "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}", |     [["${PYTHON3}", "${FBT_SCRIPT_DIR}/lint.py", "check", "${LINT_SOURCES}"]], | ||||||
|     LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]], |     LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| distenv.PhonyTarget( | distenv.PhonyTarget( | ||||||
|     "format", |     "format", | ||||||
|     "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}", |     [["${PYTHON3}", "${FBT_SCRIPT_DIR}/lint.py", "format", "${LINT_SOURCES}"]], | ||||||
|     LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]], |     LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -323,10 +325,14 @@ distenv.PhonyTarget( | |||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # Start Flipper CLI via PySerial's miniterm | # Start Flipper CLI via PySerial's miniterm | ||||||
| distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}") | distenv.PhonyTarget( | ||||||
|  |     "cli", [["${PYTHON3}", "${FBT_SCRIPT_DIR}/serial_cli.py", "-p", "${FLIP_PORT}"]] | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| # Update WiFi devboard firmware | # Update WiFi devboard firmware | ||||||
| distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py") | distenv.PhonyTarget( | ||||||
|  |     "devboard_flash", [["${PYTHON3}", "${FBT_SCRIPT_DIR}/wifi_board.py"]] | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Find blackmagic probe | # Find blackmagic probe | ||||||
| @ -361,5 +367,5 @@ distenv.Alias("vscode_dist", vscode_dist) | |||||||
| # Configure shell with build tools | # Configure shell with build tools | ||||||
| distenv.PhonyTarget( | distenv.PhonyTarget( | ||||||
|     "env", |     "env", | ||||||
|     "@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)", |     "@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)", | ||||||
| ) | ) | ||||||
|  | |||||||
| @ -4,7 +4,6 @@ App( | |||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     targets=["f7"], |     targets=["f7"], | ||||||
|     entry_point="accessor_app", |     entry_point="accessor_app", | ||||||
|     cdefines=["APP_ACCESSOR"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=4 * 1024, |     stack_size=4 * 1024, | ||||||
|     order=40, |     order=40, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Battery Test", |     name="Battery Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="battery_test_app", |     entry_point="battery_test_app", | ||||||
|     cdefines=["APP_BATTERY_TEST"], |  | ||||||
|     requires=[ |     requires=[ | ||||||
|         "gui", |         "gui", | ||||||
|         "power", |         "power", | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Blink Test", |     name="Blink Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="blink_test_app", |     entry_point="blink_test_app", | ||||||
|     cdefines=["APP_BLINK"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=10, |     order=10, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="CCID Debug", |     name="CCID Debug", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="ccid_test_app", |     entry_point="ccid_test_app", | ||||||
|     cdefines=["CCID_TEST"], |  | ||||||
|     requires=[ |     requires=[ | ||||||
|         "gui", |         "gui", | ||||||
|     ], |     ], | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Crash Test", |     name="Crash Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="crash_test_app", |     entry_point="crash_test_app", | ||||||
|     cdefines=["APP_CRASH_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     fap_category="Debug", |     fap_category="Debug", | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Display Test", |     name="Display Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="display_test_app", |     entry_point="display_test_app", | ||||||
|     cdefines=["APP_DISPLAY_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     fap_libs=["misc"], |     fap_libs=["misc"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="File Browser Test", |     name="File Browser Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="file_browser_app", |     entry_point="file_browser_app", | ||||||
|     cdefines=["APP_FILE_BROWSER_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=2 * 1024, |     stack_size=2 * 1024, | ||||||
|     order=150, |     order=150, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Keypad Test", |     name="Keypad Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="keypad_test_app", |     entry_point="keypad_test_app", | ||||||
|     cdefines=["APP_KEYPAD_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=30, |     order=30, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Locale Test", |     name="Locale Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="locale_test_app", |     entry_point="locale_test_app", | ||||||
|     cdefines=["APP_LOCALE"], |  | ||||||
|     requires=["gui", "locale"], |     requires=["gui", "locale"], | ||||||
|     stack_size=2 * 1024, |     stack_size=2 * 1024, | ||||||
|     order=70, |     order=70, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Text Box Test", |     name="Text Box Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="text_box_test_app", |     entry_point="text_box_test_app", | ||||||
|     cdefines=["APP_TEXT_BOX_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=140, |     order=140, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="UART Echo", |     name="UART Echo", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="uart_echo_app", |     entry_point="uart_echo_app", | ||||||
|     cdefines=["APP_UART_ECHO"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=2 * 1024, |     stack_size=2 * 1024, | ||||||
|     order=70, |     order=70, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="USB Mouse Demo", |     name="USB Mouse Demo", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="usb_mouse_app", |     entry_point="usb_mouse_app", | ||||||
|     cdefines=["APP_USB_MOUSE"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=60, |     order=60, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="USB Test", |     name="USB Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="usb_test_app", |     entry_point="usb_test_app", | ||||||
|     cdefines=["APP_USB_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=50, |     order=50, | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ App( | |||||||
|     name="Vibro Test", |     name="Vibro Test", | ||||||
|     apptype=FlipperAppType.DEBUG, |     apptype=FlipperAppType.DEBUG, | ||||||
|     entry_point="vibro_test_app", |     entry_point="vibro_test_app", | ||||||
|     cdefines=["APP_VIBRO_TEST"], |  | ||||||
|     requires=["gui"], |     requires=["gui"], | ||||||
|     stack_size=1 * 1024, |     stack_size=1 * 1024, | ||||||
|     order=20, |     order=20, | ||||||
|  | |||||||
| @ -32,7 +32,7 @@ Only two parameters are mandatory: **_appid_** and **_apptype_**. Others are opt | |||||||
| - **name**: name displayed in menus. | - **name**: name displayed in menus. | ||||||
| - **entry_point**: C function to be used as the application's entry point. Note that C++ function names are mangled, so you need to wrap them in `extern "C"` to use them as entry points. | - **entry_point**: C function to be used as the application's entry point. Note that C++ function names are mangled, so you need to wrap them in `extern "C"` to use them as entry points. | ||||||
| - **flags**: internal flags for system apps. Do not use. | - **flags**: internal flags for system apps. Do not use. | ||||||
| - **cdefines**: C preprocessor definitions to declare globally for other apps when the current application is included in the active build configuration. | - **cdefines**: C preprocessor definitions to declare globally for other apps when the current application is included in the active build configuration. **For external applications**: specified definitions are used when building the application itself. | ||||||
| - **requires**: list of application IDs to include in the build configuration when the current application is referenced in the list of applications to build. | - **requires**: list of application IDs to include in the build configuration when the current application is referenced in the list of applications to build. | ||||||
| - **conflicts**: list of application IDs with which the current application conflicts. If any of them is found in the constructed application list, **`fbt`** will abort the firmware build process. | - **conflicts**: list of application IDs with which the current application conflicts. If any of them is found in the constructed application list, **`fbt`** will abort the firmware build process. | ||||||
| - **provides**: functionally identical to **_requires_** field. | - **provides**: functionally identical to **_requires_** field. | ||||||
|  | |||||||
| @ -219,7 +219,7 @@ AddPostAction(fwelf, fwenv["APPBUILD_DUMP"]) | |||||||
| AddPostAction( | AddPostAction( | ||||||
|     fwelf, |     fwelf, | ||||||
|     Action( |     Action( | ||||||
|         '${PYTHON3} "${BIN_SIZE_SCRIPT}" elf ${TARGET}', |         [["${PYTHON3}", "${BIN_SIZE_SCRIPT}", "elf", "${TARGET}"]], | ||||||
|         "Firmware size", |         "Firmware size", | ||||||
|     ), |     ), | ||||||
| ) | ) | ||||||
| @ -229,7 +229,7 @@ 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( | AddPostAction( | ||||||
|     fwbin, |     fwbin, | ||||||
|     Action('@${PYTHON3} "${BIN_SIZE_SCRIPT}" bin ${TARGET}'), |     Action([["@${PYTHON3}", "${BIN_SIZE_SCRIPT}", "bin", "${TARGET}"]]), | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") | fwdfu = fwenv["FW_DFU"] = fwenv.DFUBuilder("${FIRMWARE_BUILD_CFG}") | ||||||
|  | |||||||
| @ -33,6 +33,8 @@ class FlipperAppType(Enum): | |||||||
| @dataclass | @dataclass | ||||||
| class FlipperApplication: | class FlipperApplication: | ||||||
|     APP_ID_REGEX: ClassVar[re.Pattern] = re.compile(r"^[a-z0-9_]+$") |     APP_ID_REGEX: ClassVar[re.Pattern] = re.compile(r"^[a-z0-9_]+$") | ||||||
|  |     PRIVATE_FIELD_PREFIX: ClassVar[str] = "_" | ||||||
|  |     APP_MANIFEST_DEFAULT_NAME: ClassVar[str] = "application.fam" | ||||||
| 
 | 
 | ||||||
|     @dataclass |     @dataclass | ||||||
|     class ExternallyBuiltFile: |     class ExternallyBuiltFile: | ||||||
| @ -48,8 +50,6 @@ class FlipperApplication: | |||||||
|         cdefines: List[str] = field(default_factory=list) |         cdefines: List[str] = field(default_factory=list) | ||||||
|         cincludes: List[str] = field(default_factory=list) |         cincludes: List[str] = field(default_factory=list) | ||||||
| 
 | 
 | ||||||
|     PRIVATE_FIELD_PREFIX = "_" |  | ||||||
| 
 |  | ||||||
|     appid: str |     appid: str | ||||||
|     apptype: FlipperAppType |     apptype: FlipperAppType | ||||||
|     name: Optional[str] = "" |     name: Optional[str] = "" | ||||||
| @ -117,8 +117,10 @@ class FlipperApplication: | |||||||
|                 self.fap_version = tuple(int(v) for v in self.fap_version.split(".")) |                 self.fap_version = tuple(int(v) for v in self.fap_version.split(".")) | ||||||
|             except ValueError: |             except ValueError: | ||||||
|                 raise FlipperManifestException( |                 raise FlipperManifestException( | ||||||
|                     f"Invalid version string '{self.fap_version}'. Must be in the form 'major.minor'" |                     f"Invalid version '{self.fap_version}'. Must be in the form 'major.minor'" | ||||||
|                 ) |                 ) | ||||||
|  |             if len(self.fap_version) < 2: | ||||||
|  |                 raise ValueError("Not enough version components") | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class AppManager: | class AppManager: | ||||||
| @ -155,11 +157,20 @@ class AppManager: | |||||||
|                 raise FlipperManifestException( |                 raise FlipperManifestException( | ||||||
|                     f"App {kw.get('appid')} cannot have fal_embedded set" |                     f"App {kw.get('appid')} cannot have fal_embedded set" | ||||||
|                 ) |                 ) | ||||||
|         # Harmless - cdefines for external apps are meaningless | 
 | ||||||
|         # if apptype == FlipperAppType.EXTERNAL and kw.get("cdefines"): |         if apptype in AppBuildset.dist_app_types: | ||||||
|         #     raise FlipperManifestException( |             # For distributing .fap's resources, there's "fap_file_assets" | ||||||
|         #         f"External app {kw.get('appid')} must not have 'cdefines' in manifest" |             for app_property in ("resources",): | ||||||
|         #     ) |                 if kw.get(app_property): | ||||||
|  |                     raise FlipperManifestException( | ||||||
|  |                         f"App {kw.get('appid')} of type {apptype} cannot have '{app_property}' in manifest" | ||||||
|  |                     ) | ||||||
|  |         else: | ||||||
|  |             for app_property in ("fap_extbuild", "fap_private_libs", "fap_icon_assets"): | ||||||
|  |                 if kw.get(app_property): | ||||||
|  |                     raise FlipperManifestException( | ||||||
|  |                         f"App {kw.get('appid')} of type {apptype} must not have '{app_property}' in manifest" | ||||||
|  |                     ) | ||||||
| 
 | 
 | ||||||
|     def load_manifest(self, app_manifest_path: str, app_dir_node: object): |     def load_manifest(self, app_manifest_path: str, app_dir_node: object): | ||||||
|         if not os.path.exists(app_manifest_path): |         if not os.path.exists(app_manifest_path): | ||||||
| @ -241,12 +252,21 @@ class AppBuildset: | |||||||
|         FlipperAppType.STARTUP, |         FlipperAppType.STARTUP, | ||||||
|     ) |     ) | ||||||
|     EXTERNAL_APP_TYPES_MAP = { |     EXTERNAL_APP_TYPES_MAP = { | ||||||
|  |         # AppType -> bool: true if always deploy, false if obey app set | ||||||
|         FlipperAppType.EXTERNAL: True, |         FlipperAppType.EXTERNAL: True, | ||||||
|         FlipperAppType.PLUGIN: True, |         FlipperAppType.PLUGIN: True, | ||||||
|         FlipperAppType.DEBUG: True, |         FlipperAppType.DEBUG: True, | ||||||
|         FlipperAppType.MENUEXTERNAL: False, |         FlipperAppType.MENUEXTERNAL: False, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     @classmethod | ||||||
|  |     @property | ||||||
|  |     def dist_app_types(cls): | ||||||
|  |         """Applications that are installed on SD card""" | ||||||
|  |         return list( | ||||||
|  |             entry[0] for entry in cls.EXTERNAL_APP_TYPES_MAP.items() if entry[1] | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def print_writer(message): |     def print_writer(message): | ||||||
|         print(message) |         print(message) | ||||||
| @ -432,96 +452,3 @@ class AppBuildset: | |||||||
|                 for source_type in app.sources |                 for source_type in app.sources | ||||||
|             ) |             ) | ||||||
|         ) |         ) | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class ApplicationsCGenerator: |  | ||||||
|     APP_TYPE_MAP = { |  | ||||||
|         FlipperAppType.SERVICE: ("FlipperInternalApplication", "FLIPPER_SERVICES"), |  | ||||||
|         FlipperAppType.SYSTEM: ("FlipperInternalApplication", "FLIPPER_SYSTEM_APPS"), |  | ||||||
|         FlipperAppType.APP: ("FlipperInternalApplication", "FLIPPER_APPS"), |  | ||||||
|         FlipperAppType.DEBUG: ("FlipperInternalApplication", "FLIPPER_DEBUG_APPS"), |  | ||||||
|         FlipperAppType.SETTINGS: ( |  | ||||||
|             "FlipperInternalApplication", |  | ||||||
|             "FLIPPER_SETTINGS_APPS", |  | ||||||
|         ), |  | ||||||
|         FlipperAppType.STARTUP: ( |  | ||||||
|             "FlipperInternalOnStartHook", |  | ||||||
|             "FLIPPER_ON_SYSTEM_START", |  | ||||||
|         ), |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     APP_EXTERNAL_TYPE = ( |  | ||||||
|         "FlipperExternalApplication", |  | ||||||
|         "FLIPPER_EXTERNAL_APPS", |  | ||||||
|     ) |  | ||||||
| 
 |  | ||||||
|     def __init__(self, buildset: AppBuildset, autorun_app: str = ""): |  | ||||||
|         self.buildset = buildset |  | ||||||
|         self.autorun = autorun_app |  | ||||||
| 
 |  | ||||||
|     def get_app_ep_forward(self, app: FlipperApplication): |  | ||||||
|         if app.apptype == FlipperAppType.STARTUP: |  | ||||||
|             return f"extern void {app.entry_point}();" |  | ||||||
|         return f"extern int32_t {app.entry_point}(void* p);" |  | ||||||
| 
 |  | ||||||
|     def get_app_descr(self, app: FlipperApplication): |  | ||||||
|         if app.apptype == FlipperAppType.STARTUP: |  | ||||||
|             return app.entry_point |  | ||||||
|         return f""" |  | ||||||
|     {{.app = {app.entry_point}, |  | ||||||
|      .name = "{app.name}", |  | ||||||
|      .appid = "{app.appid}",  |  | ||||||
|      .stack_size = {app.stack_size}, |  | ||||||
|      .icon = {f"&{app.icon}" if app.icon else "NULL"}, |  | ||||||
|      .flags = {'|'.join(f"FlipperInternalApplicationFlag{flag}" for flag in app.flags)} }}""" |  | ||||||
| 
 |  | ||||||
|     def get_external_app_descr(self, app: FlipperApplication): |  | ||||||
|         app_path = "/ext/apps" |  | ||||||
|         if app.fap_category: |  | ||||||
|             app_path += f"/{app.fap_category}" |  | ||||||
|         app_path += f"/{app.appid}.fap" |  | ||||||
|         return f""" |  | ||||||
|     {{ |  | ||||||
|      .name = "{app.name}", |  | ||||||
|      .icon = {f"&{app.icon}" if app.icon else "NULL"}, |  | ||||||
|      .path = "{app_path}" }}""" |  | ||||||
| 
 |  | ||||||
|     def generate(self): |  | ||||||
|         contents = [ |  | ||||||
|             '#include "applications.h"', |  | ||||||
|             "#include <assets_icons.h>", |  | ||||||
|             f'const char* FLIPPER_AUTORUN_APP_NAME = "{self.autorun}";', |  | ||||||
|         ] |  | ||||||
|         for apptype in self.APP_TYPE_MAP: |  | ||||||
|             contents.extend( |  | ||||||
|                 map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) |  | ||||||
|             ) |  | ||||||
|             entry_type, entry_block = self.APP_TYPE_MAP[apptype] |  | ||||||
|             contents.append(f"const {entry_type} {entry_block}[] = {{") |  | ||||||
|             contents.append( |  | ||||||
|                 ",\n".join( |  | ||||||
|                     map(self.get_app_descr, self.buildset.get_apps_of_type(apptype)) |  | ||||||
|                 ) |  | ||||||
|             ) |  | ||||||
|             contents.append("};") |  | ||||||
|             contents.append( |  | ||||||
|                 f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});" |  | ||||||
|             ) |  | ||||||
| 
 |  | ||||||
|         archive_app = self.buildset.get_apps_of_type(FlipperAppType.ARCHIVE) |  | ||||||
|         if archive_app: |  | ||||||
|             contents.extend( |  | ||||||
|                 [ |  | ||||||
|                     self.get_app_ep_forward(archive_app[0]), |  | ||||||
|                     f"const FlipperInternalApplication FLIPPER_ARCHIVE = {self.get_app_descr(archive_app[0])};", |  | ||||||
|                 ] |  | ||||||
|             ) |  | ||||||
| 
 |  | ||||||
|         entry_type, entry_block = self.APP_EXTERNAL_TYPE |  | ||||||
|         external_apps = self.buildset.get_apps_of_type(FlipperAppType.MENUEXTERNAL) |  | ||||||
|         contents.append(f"const {entry_type} {entry_block}[] = {{") |  | ||||||
|         contents.append(",\n".join(map(self.get_external_app_descr, external_apps))) |  | ||||||
|         contents.append("};") |  | ||||||
|         contents.append(f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});") |  | ||||||
| 
 |  | ||||||
|         return "\n".join(contents) |  | ||||||
|  | |||||||
| @ -1,25 +1,118 @@ | |||||||
| from ansi.color import fg | from ansi.color import fg | ||||||
| from fbt.appmanifest import ( | from fbt.appmanifest import ( | ||||||
|     ApplicationsCGenerator, |  | ||||||
|     AppManager, |     AppManager, | ||||||
|  |     AppBuildset, | ||||||
|  |     FlipperApplication, | ||||||
|     FlipperAppType, |     FlipperAppType, | ||||||
|     FlipperManifestException, |     FlipperManifestException, | ||||||
| ) | ) | ||||||
| from SCons.Action import Action | from SCons.Action import Action | ||||||
| from SCons.Builder import Builder | from SCons.Builder import Builder | ||||||
| from SCons.Errors import StopError | from SCons.Errors import StopError | ||||||
| from SCons.Warnings import WarningOnByDefault, warn |  | ||||||
| from SCons.Script import GetOption | from SCons.Script import GetOption | ||||||
|  | from SCons.Warnings import WarningOnByDefault, warn | ||||||
| 
 | 
 | ||||||
| # Adding objects for application management to env | # Adding objects for application management to env | ||||||
| #  AppManager env["APPMGR"] - loads all manifests; manages list of known apps | #  AppManager env["APPMGR"] - loads all manifests; manages list of known apps | ||||||
| #  AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config | #  AppBuildset env["APPBUILD"] - contains subset of apps, filtered for current config | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class ApplicationsCGenerator: | ||||||
|  |     APP_TYPE_MAP = { | ||||||
|  |         FlipperAppType.SERVICE: ("FlipperInternalApplication", "FLIPPER_SERVICES"), | ||||||
|  |         FlipperAppType.SYSTEM: ("FlipperInternalApplication", "FLIPPER_SYSTEM_APPS"), | ||||||
|  |         FlipperAppType.APP: ("FlipperInternalApplication", "FLIPPER_APPS"), | ||||||
|  |         FlipperAppType.DEBUG: ("FlipperInternalApplication", "FLIPPER_DEBUG_APPS"), | ||||||
|  |         FlipperAppType.SETTINGS: ( | ||||||
|  |             "FlipperInternalApplication", | ||||||
|  |             "FLIPPER_SETTINGS_APPS", | ||||||
|  |         ), | ||||||
|  |         FlipperAppType.STARTUP: ( | ||||||
|  |             "FlipperInternalOnStartHook", | ||||||
|  |             "FLIPPER_ON_SYSTEM_START", | ||||||
|  |         ), | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     APP_EXTERNAL_TYPE = ( | ||||||
|  |         "FlipperExternalApplication", | ||||||
|  |         "FLIPPER_EXTERNAL_APPS", | ||||||
|  |     ) | ||||||
|  | 
 | ||||||
|  |     def __init__(self, buildset: AppBuildset, autorun_app: str = ""): | ||||||
|  |         self.buildset = buildset | ||||||
|  |         self.autorun = autorun_app | ||||||
|  | 
 | ||||||
|  |     def get_app_ep_forward(self, app: FlipperApplication): | ||||||
|  |         if app.apptype == FlipperAppType.STARTUP: | ||||||
|  |             return f"extern void {app.entry_point}();" | ||||||
|  |         return f"extern int32_t {app.entry_point}(void* p);" | ||||||
|  | 
 | ||||||
|  |     def get_app_descr(self, app: FlipperApplication): | ||||||
|  |         if app.apptype == FlipperAppType.STARTUP: | ||||||
|  |             return app.entry_point | ||||||
|  |         return f""" | ||||||
|  |     {{.app = {app.entry_point}, | ||||||
|  |      .name = "{app.name}", | ||||||
|  |      .appid = "{app.appid}",  | ||||||
|  |      .stack_size = {app.stack_size}, | ||||||
|  |      .icon = {f"&{app.icon}" if app.icon else "NULL"}, | ||||||
|  |      .flags = {'|'.join(f"FlipperInternalApplicationFlag{flag}" for flag in app.flags)} }}""" | ||||||
|  | 
 | ||||||
|  |     def get_external_app_descr(self, app: FlipperApplication): | ||||||
|  |         app_path = "/ext/apps" | ||||||
|  |         if app.fap_category: | ||||||
|  |             app_path += f"/{app.fap_category}" | ||||||
|  |         app_path += f"/{app.appid}.fap" | ||||||
|  |         return f""" | ||||||
|  |     {{ | ||||||
|  |      .name = "{app.name}", | ||||||
|  |      .icon = {f"&{app.icon}" if app.icon else "NULL"}, | ||||||
|  |      .path = "{app_path}" }}""" | ||||||
|  | 
 | ||||||
|  |     def generate(self): | ||||||
|  |         contents = [ | ||||||
|  |             '#include "applications.h"', | ||||||
|  |             "#include <assets_icons.h>", | ||||||
|  |             f'const char* FLIPPER_AUTORUN_APP_NAME = "{self.autorun}";', | ||||||
|  |         ] | ||||||
|  |         for apptype in self.APP_TYPE_MAP: | ||||||
|  |             contents.extend( | ||||||
|  |                 map(self.get_app_ep_forward, self.buildset.get_apps_of_type(apptype)) | ||||||
|  |             ) | ||||||
|  |             entry_type, entry_block = self.APP_TYPE_MAP[apptype] | ||||||
|  |             contents.append(f"const {entry_type} {entry_block}[] = {{") | ||||||
|  |             contents.append( | ||||||
|  |                 ",\n".join( | ||||||
|  |                     map(self.get_app_descr, self.buildset.get_apps_of_type(apptype)) | ||||||
|  |                 ) | ||||||
|  |             ) | ||||||
|  |             contents.append("};") | ||||||
|  |             contents.append( | ||||||
|  |                 f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});" | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |         archive_app = self.buildset.get_apps_of_type(FlipperAppType.ARCHIVE) | ||||||
|  |         if archive_app: | ||||||
|  |             contents.extend( | ||||||
|  |                 [ | ||||||
|  |                     self.get_app_ep_forward(archive_app[0]), | ||||||
|  |                     f"const FlipperInternalApplication FLIPPER_ARCHIVE = {self.get_app_descr(archive_app[0])};", | ||||||
|  |                 ] | ||||||
|  |             ) | ||||||
|  | 
 | ||||||
|  |         entry_type, entry_block = self.APP_EXTERNAL_TYPE | ||||||
|  |         external_apps = self.buildset.get_apps_of_type(FlipperAppType.MENUEXTERNAL) | ||||||
|  |         contents.append(f"const {entry_type} {entry_block}[] = {{") | ||||||
|  |         contents.append(",\n".join(map(self.get_external_app_descr, external_apps))) | ||||||
|  |         contents.append("};") | ||||||
|  |         contents.append(f"const size_t {entry_block}_COUNT = COUNT_OF({entry_block});") | ||||||
|  | 
 | ||||||
|  |         return "\n".join(contents) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| def LoadAppManifest(env, entry): | def LoadAppManifest(env, entry): | ||||||
|     try: |     try: | ||||||
|         APP_MANIFEST_NAME = "application.fam" |         manifest_glob = entry.glob(FlipperApplication.APP_MANIFEST_DEFAULT_NAME) | ||||||
|         manifest_glob = entry.glob(APP_MANIFEST_NAME) |  | ||||||
|         if len(manifest_glob) == 0: |         if len(manifest_glob) == 0: | ||||||
|             try: |             try: | ||||||
|                 disk_node = next(filter(lambda d: d.exists(), entry.get_all_rdirs())) |                 disk_node = next(filter(lambda d: d.exists(), entry.get_all_rdirs())) | ||||||
| @ -27,7 +120,7 @@ def LoadAppManifest(env, entry): | |||||||
|                 disk_node = entry |                 disk_node = entry | ||||||
| 
 | 
 | ||||||
|             raise FlipperManifestException( |             raise FlipperManifestException( | ||||||
|                 f"App folder '{disk_node.abspath}': missing manifest ({APP_MANIFEST_NAME})" |                 f"App folder '{disk_node.abspath}': missing manifest ({FlipperApplication.APP_MANIFEST_DEFAULT_NAME})" | ||||||
|             ) |             ) | ||||||
| 
 | 
 | ||||||
|         app_manifest_file_path = manifest_glob[0].rfile().abspath |         app_manifest_file_path = manifest_glob[0].rfile().abspath | ||||||
|  | |||||||
| @ -58,7 +58,8 @@ class AppBuilder: | |||||||
|         ) |         ) | ||||||
|         self.app_env.Append( |         self.app_env.Append( | ||||||
|             CPPDEFINES=[ |             CPPDEFINES=[ | ||||||
|                 ("FAP_VERSION", f'"{".".join(map(str, self.app.fap_version))}"') |                 ("FAP_VERSION", f'\\"{".".join(map(str, self.app.fap_version))}\\"'), | ||||||
|  |                 *self.app.cdefines, | ||||||
|             ], |             ], | ||||||
|         ) |         ) | ||||||
|         self.app_env.VariantDir(self.app_work_dir, self.app._appdir, duplicate=False) |         self.app_env.VariantDir(self.app_work_dir, self.app._appdir, duplicate=False) | ||||||
| @ -143,8 +144,8 @@ class AppBuilder: | |||||||
|             self.app._assets_dirs = [self.app._appdir.Dir(self.app.fap_file_assets)] |             self.app._assets_dirs = [self.app._appdir.Dir(self.app.fap_file_assets)] | ||||||
| 
 | 
 | ||||||
|         self.app_env.Append( |         self.app_env.Append( | ||||||
|             LIBS=[*self.app.fap_libs, *self.private_libs], |             LIBS=[*self.app.fap_libs, *self.private_libs, *self.app.fap_libs], | ||||||
|             CPPPATH=[self.app_work_dir, self.app._appdir], |             CPPPATH=[self.app_env.Dir(self.app_work_dir), self.app._appdir], | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         app_sources = self.app_env.GatherSources( |         app_sources = self.app_env.GatherSources( | ||||||
| @ -472,7 +473,19 @@ def AddAppLaunchTarget(env, appname, launch_target_name): | |||||||
|     components = _gather_app_components(env, appname) |     components = _gather_app_components(env, appname) | ||||||
|     target = env.PhonyTarget( |     target = env.PhonyTarget( | ||||||
|         launch_target_name, |         launch_target_name, | ||||||
|         '${PYTHON3} "${APP_RUN_SCRIPT}" -p ${FLIP_PORT} ${EXTRA_ARGS} -s ${SOURCES} -t ${FLIPPER_FILE_TARGETS}', |         [ | ||||||
|  |             [ | ||||||
|  |                 "${PYTHON3}", | ||||||
|  |                 "${APP_RUN_SCRIPT}", | ||||||
|  |                 "-p", | ||||||
|  |                 "${FLIP_PORT}", | ||||||
|  |                 "${EXTRA_ARGS}", | ||||||
|  |                 "-s", | ||||||
|  |                 "${SOURCES}", | ||||||
|  |                 "-t", | ||||||
|  |                 "${FLIPPER_FILE_TARGETS}", | ||||||
|  |             ] | ||||||
|  |         ], | ||||||
|         source=components.deploy_sources.values(), |         source=components.deploy_sources.values(), | ||||||
|         FLIPPER_FILE_TARGETS=components.deploy_sources.keys(), |         FLIPPER_FILE_TARGETS=components.deploy_sources.keys(), | ||||||
|         EXTRA_ARGS=components.extra_launch_args, |         EXTRA_ARGS=components.extra_launch_args, | ||||||
|  | |||||||
| @ -285,7 +285,20 @@ def generate(env, **kw): | |||||||
|                         "$SDK_AMALGAMATE_HEADER_COMSTR", |                         "$SDK_AMALGAMATE_HEADER_COMSTR", | ||||||
|                     ), |                     ), | ||||||
|                     Action( |                     Action( | ||||||
|                         "$CC -o $TARGET -E -P $CCFLAGS $_CCCOMCOM $SDK_PP_FLAGS -MMD ${TARGET}.c", |                         [ | ||||||
|  |                             [ | ||||||
|  |                                 "$CC", | ||||||
|  |                                 "-o", | ||||||
|  |                                 "$TARGET", | ||||||
|  |                                 "-E", | ||||||
|  |                                 "-P", | ||||||
|  |                                 "$CCFLAGS", | ||||||
|  |                                 "$_CCCOMCOM", | ||||||
|  |                                 "$SDK_PP_FLAGS", | ||||||
|  |                                 "-MMD", | ||||||
|  |                                 "${TARGET}.c", | ||||||
|  |                             ] | ||||||
|  |                         ], | ||||||
|                         "$SDK_AMALGAMATE_PP_COMSTR", |                         "$SDK_AMALGAMATE_PP_COMSTR", | ||||||
|                     ), |                     ), | ||||||
|                 ], |                 ], | ||||||
|  | |||||||
| @ -19,10 +19,22 @@ def generate(env): | |||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "VersionBuilder": Builder( |             "VersionBuilder": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     '${PYTHON3} "${VERSION_SCRIPT}" generate ' |                     [ | ||||||
|                     "-t ${TARGET_HW} -fw-origin ${FIRMWARE_ORIGIN} " |                         [ | ||||||
|                     '-o ${TARGET.dir.posix} --dir "${ROOT_DIR}"', |                             "${PYTHON3}", | ||||||
|                     "${VERSIONCOMSTR}", |                             "${VERSION_SCRIPT}", | ||||||
|  |                             "generate", | ||||||
|  |                             "-t", | ||||||
|  |                             "${TARGET_HW}", | ||||||
|  |                             "--fw-origin", | ||||||
|  |                             "${FIRMWARE_ORIGIN}", | ||||||
|  |                             "-o", | ||||||
|  |                             "${TARGET.dir.posix}", | ||||||
|  |                             "--dir", | ||||||
|  |                             "${ROOT_DIR}", | ||||||
|  |                             "${VERSIONCOMSTR}", | ||||||
|  |                         ] | ||||||
|  |                     ] | ||||||
|                 ), |                 ), | ||||||
|                 emitter=_version_emitter, |                 emitter=_version_emitter, | ||||||
|             ), |             ), | ||||||
|  | |||||||
| @ -25,7 +25,7 @@ def generate(env): | |||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "HEXBuilder": Builder( |             "HEXBuilder": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     '${OBJCOPY} -O ihex "${SOURCE}" "${TARGET}"', |                     [["${OBJCOPY}", "-O", "ihex", "${SOURCE}", "${TARGET}"]], | ||||||
|                     "${HEXCOMSTR}", |                     "${HEXCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".hex", |                 suffix=".hex", | ||||||
| @ -33,7 +33,7 @@ def generate(env): | |||||||
|             ), |             ), | ||||||
|             "BINBuilder": Builder( |             "BINBuilder": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     '${OBJCOPY} -O binary -S "${SOURCE}" "${TARGET}"', |                     [["${OBJCOPY}", "-O", "binary", "-S", "${SOURCE}", "${TARGET}"]], | ||||||
|                     "${BINCOMSTR}", |                     "${BINCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".bin", |                 suffix=".bin", | ||||||
| @ -41,7 +41,20 @@ def generate(env): | |||||||
|             ), |             ), | ||||||
|             "DFUBuilder": Builder( |             "DFUBuilder": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     '${PYTHON3} "${BIN2DFU}" -i "${SOURCE}" -o "${TARGET}" -a ${IMAGE_BASE_ADDRESS} -l "Flipper Zero F${TARGET_HW}"', |                     [ | ||||||
|  |                         [ | ||||||
|  |                             "${PYTHON3}", | ||||||
|  |                             "${BIN2DFU}", | ||||||
|  |                             "-i", | ||||||
|  |                             "${SOURCE}", | ||||||
|  |                             "-o", | ||||||
|  |                             "${TARGET}", | ||||||
|  |                             "-a", | ||||||
|  |                             "${IMAGE_BASE_ADDRESS}", | ||||||
|  |                             "-l", | ||||||
|  |                             "Flipper Zero F${TARGET_HW}", | ||||||
|  |                         ] | ||||||
|  |                     ], | ||||||
|                     "${DFUCOMSTR}", |                     "${DFUCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".dfu", |                 suffix=".dfu", | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| from SCons.Builder import Builder | from SCons.Builder import Builder | ||||||
| from SCons.Defaults import Touch | from SCons.Defaults import Touch | ||||||
|  | from SCons.Action import Action | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def generate(env): | def generate(env): | ||||||
| @ -9,13 +10,21 @@ def generate(env): | |||||||
|             "-auto", |             "-auto", | ||||||
|             "-exit", |             "-exit", | ||||||
|         ], |         ], | ||||||
|         JFLASHCOM="${JFLASH} -openprj${JFLASHPROJECT} -open${SOURCE},${JFLASHADDR} ${JFLASHFLAGS}", |  | ||||||
|     ) |     ) | ||||||
|     env.Append( |     env.Append( | ||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "JFlash": Builder( |             "JFlash": Builder( | ||||||
|                 action=[ |                 action=[ | ||||||
|                     "${JFLASHCOM}", |                     Action( | ||||||
|  |                         [ | ||||||
|  |                             [ | ||||||
|  |                                 "${JFLASH}", | ||||||
|  |                                 "-openprj${JFLASHPROJECT}", | ||||||
|  |                                 "-open${SOURCE},${JFLASHADDR}", | ||||||
|  |                                 "${JFLASHFLAGS}", | ||||||
|  |                             ] | ||||||
|  |                         ] | ||||||
|  |                     ), | ||||||
|                     Touch("${TARGET}"), |                     Touch("${TARGET}"), | ||||||
|                 ], |                 ], | ||||||
|             ), |             ), | ||||||
|  | |||||||
| @ -6,13 +6,12 @@ def generate(env): | |||||||
|     env.SetDefault( |     env.SetDefault( | ||||||
|         OBJDUMP="objdump", |         OBJDUMP="objdump", | ||||||
|         OBJDUMPFLAGS=[], |         OBJDUMPFLAGS=[], | ||||||
|         OBJDUMPCOM="$OBJDUMP $OBJDUMPFLAGS -S $SOURCES > $TARGET", |  | ||||||
|     ) |     ) | ||||||
|     env.Append( |     env.Append( | ||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "ObjDump": Builder( |             "ObjDump": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     "${OBJDUMPCOM}", |                     [["$OBJDUMP", "$OBJDUMPFLAGS", "-S", "$SOURCES", ">", "$TARGET"]], | ||||||
|                     "${OBJDUMPCOMSTR}", |                     "${OBJDUMPCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".lst", |                 suffix=".lst", | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ from SCons.Defaults import Touch | |||||||
| 
 | 
 | ||||||
| __OPENOCD_BIN = "openocd" | __OPENOCD_BIN = "openocd" | ||||||
| 
 | 
 | ||||||
|  | # TODO: FL-3663: rework argument passing to lists | ||||||
| _oocd_action = Action( | _oocd_action = Action( | ||||||
|     "${OPENOCD} ${OPENOCD_OPTS} ${OPENOCD_COMMAND}", |     "${OPENOCD} ${OPENOCD_OPTS} ${OPENOCD_COMMAND}", | ||||||
|     "${OPENOCDCOMSTR}", |     "${OPENOCDCOMSTR}", | ||||||
|  | |||||||
| @ -79,7 +79,17 @@ def generate(env): | |||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "PVSCheck": Builder( |             "PVSCheck": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     '${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"', |                     [ | ||||||
|  |                         [ | ||||||
|  |                             "${PVSCHECKBIN}", | ||||||
|  |                             "analyze", | ||||||
|  |                             "${PVSOPTIONS}", | ||||||
|  |                             "-f", | ||||||
|  |                             "${SOURCE}", | ||||||
|  |                             "-o", | ||||||
|  |                             "${TARGET}", | ||||||
|  |                         ] | ||||||
|  |                     ], | ||||||
|                     "${PVSCHECKCOMSTR}", |                     "${PVSCHECKCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".log", |                 suffix=".log", | ||||||
| @ -92,7 +102,17 @@ def generate(env): | |||||||
|                         # PlogConverter.exe and plog-converter have different behavior |                         # PlogConverter.exe and plog-converter have different behavior | ||||||
|                         Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None, |                         Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None, | ||||||
|                         Action(_set_browser_action, None), |                         Action(_set_browser_action, None), | ||||||
|                         '${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"', |                         Action( | ||||||
|  |                             [ | ||||||
|  |                                 [ | ||||||
|  |                                     "${PVSCONVBIN}", | ||||||
|  |                                     "${PVSCONVOPTIONS}", | ||||||
|  |                                     "${SOURCE}", | ||||||
|  |                                     "-o", | ||||||
|  |                                     "${REPORT_DIR}", | ||||||
|  |                                 ] | ||||||
|  |                             ] | ||||||
|  |                         ), | ||||||
|                     ], |                     ], | ||||||
|                     "${PVSCONVCOMSTR}", |                     "${PVSCONVCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|  | |||||||
| @ -6,13 +6,12 @@ def generate(env): | |||||||
|     env.SetDefault( |     env.SetDefault( | ||||||
|         STRIP="strip", |         STRIP="strip", | ||||||
|         STRIPFLAGS=[], |         STRIPFLAGS=[], | ||||||
|         STRIPCOM="$STRIP $STRIPFLAGS $SOURCES -o $TARGET", |  | ||||||
|     ) |     ) | ||||||
|     env.Append( |     env.Append( | ||||||
|         BUILDERS={ |         BUILDERS={ | ||||||
|             "ELFStripper": Builder( |             "ELFStripper": Builder( | ||||||
|                 action=Action( |                 action=Action( | ||||||
|                     "${STRIPCOM}", |                     [["$STRIP", "$STRIPFLAGS", "$SOURCES", "-o", "$TARGET"]], | ||||||
|                     "${STRIPCOMSTR}", |                     "${STRIPCOMSTR}", | ||||||
|                 ), |                 ), | ||||||
|                 suffix=".elf", |                 suffix=".elf", | ||||||
|  | |||||||
| @ -325,24 +325,26 @@ else: | |||||||
| 
 | 
 | ||||||
| appenv.PhonyTarget( | appenv.PhonyTarget( | ||||||
|     "cli", |     "cli", | ||||||
|     '${PYTHON3} "${FBT_SCRIPT_DIR}/serial_cli.py" -p ${FLIP_PORT}', |     [["${PYTHON3}", "${FBT_SCRIPT_DIR}/serial_cli.py", "-p", "${FLIP_PORT}"]], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # Update WiFi devboard firmware | # Update WiFi devboard firmware | ||||||
| dist_env.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py") | dist_env.PhonyTarget( | ||||||
|  |     "devboard_flash", [["${PYTHON3}", "${FBT_SCRIPT_DIR}/wifi_board.py"]] | ||||||
|  | ) | ||||||
| 
 | 
 | ||||||
| # Linter | # Linter | ||||||
| 
 | 
 | ||||||
| dist_env.PhonyTarget( | dist_env.PhonyTarget( | ||||||
|     "lint", |     "lint", | ||||||
|     "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}", |     [["${PYTHON3}", "${FBT_SCRIPT_DIR}/lint.py", "check", "${LINT_SOURCES}"]], | ||||||
|     source=original_app_dir.File(".clang-format"), |     source=original_app_dir.File(".clang-format"), | ||||||
|     LINT_SOURCES=[original_app_dir], |     LINT_SOURCES=[original_app_dir], | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| dist_env.PhonyTarget( | dist_env.PhonyTarget( | ||||||
|     "format", |     "format", | ||||||
|     "${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}", |     [["${PYTHON3}", "${FBT_SCRIPT_DIR}/lint.py", "format", "${LINT_SOURCES}"]], | ||||||
|     source=original_app_dir.File(".clang-format"), |     source=original_app_dir.File(".clang-format"), | ||||||
|     LINT_SOURCES=[original_app_dir], |     LINT_SOURCES=[original_app_dir], | ||||||
| ) | ) | ||||||
| @ -455,7 +457,17 @@ if dolphin_src_dir.exists(): | |||||||
|     ) |     ) | ||||||
|     dist_env.PhonyTarget( |     dist_env.PhonyTarget( | ||||||
|         "dolphin_ext", |         "dolphin_ext", | ||||||
|         '${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py -p ${FLIP_PORT} send "${SOURCE}" /ext/dolphin', |         [ | ||||||
|  |             [ | ||||||
|  |                 "${PYTHON3}", | ||||||
|  |                 "${FBT_SCRIPT_DIR}/storage.py", | ||||||
|  |                 "-p", | ||||||
|  |                 "${FLIP_PORT}", | ||||||
|  |                 "send", | ||||||
|  |                 "${SOURCE}", | ||||||
|  |                 "/ext/dolphin", | ||||||
|  |             ] | ||||||
|  |         ], | ||||||
|         source=ufbt_build_dir.Dir("dolphin"), |         source=ufbt_build_dir.Dir("dolphin"), | ||||||
|     ) |     ) | ||||||
| else: | else: | ||||||
| @ -467,7 +479,7 @@ else: | |||||||
| 
 | 
 | ||||||
| dist_env.PhonyTarget( | dist_env.PhonyTarget( | ||||||
|     "env", |     "env", | ||||||
|     "@echo $( ${FBT_SCRIPT_DIR}/toolchain/fbtenv.sh $)", |     "@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)", | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| dist_env.PostConfigureUfbtEnvionment() | dist_env.PostConfigureUfbtEnvionment() | ||||||
|  | |||||||
| @ -101,7 +101,7 @@ class Main(App): | |||||||
|             required=True, |             required=True, | ||||||
|         ) |         ) | ||||||
|         self.parser_generate.add_argument( |         self.parser_generate.add_argument( | ||||||
|             "-fw-origin", |             "--fw-origin", | ||||||
|             dest="firmware_origin", |             dest="firmware_origin", | ||||||
|             type=str, |             type=str, | ||||||
|             help="firmware origin", |             help="firmware origin", | ||||||
|  | |||||||
| @ -27,6 +27,8 @@ variables_to_forward = [ | |||||||
|     "PYTHONNOUSERSITE", |     "PYTHONNOUSERSITE", | ||||||
|     "TMP", |     "TMP", | ||||||
|     "TEMP", |     "TEMP", | ||||||
|  |     # ccache | ||||||
|  |     "CCACHE_DISABLE", | ||||||
|     # Colors for tools |     # Colors for tools | ||||||
|     "TERM", |     "TERM", | ||||||
| ] | ] | ||||||
| @ -62,7 +64,7 @@ coreenv = VAR_ENV.Clone( | |||||||
|     # Setting up temp file parameters - to overcome command line length limits |     # Setting up temp file parameters - to overcome command line length limits | ||||||
|     TEMPFILEARGESCFUNC=tempfile_arg_esc_func, |     TEMPFILEARGESCFUNC=tempfile_arg_esc_func, | ||||||
|     ROOT_DIR=Dir("#"), |     ROOT_DIR=Dir("#"), | ||||||
|     FBT_SCRIPT_DIR="${ROOT_DIR}/scripts", |     FBT_SCRIPT_DIR=Dir("#/scripts"), | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| # If DIST_SUFFIX is set in environment, is has precedence (set by CI) | # If DIST_SUFFIX is set in environment, is has precedence (set by CI) | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 hedger
						hedger