[FL-3437] fbt: build target for faps (#2888)

* fbt: added build target for faps. Usage: ./fbt build APPSRC=<appid>
* Updated docs & vscode config
* Code cleanup
This commit is contained in:
hedger 2023-07-18 13:39:30 +04:00 committed by GitHub
parent 9bb04832a8
commit 309f65e401
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 73 additions and 33 deletions

View File

@ -4,13 +4,13 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "[Release] Build", "label": "[Release] Build Firmware",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0" "command": "./fbt COMPACT=1 DEBUG=0"
}, },
{ {
"label": "[Debug] Build", "label": "[Debug] Build Firmware",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt" "command": "./fbt"
@ -123,17 +123,29 @@
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist" "command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
}, },
{
"label": "[Debug] Build App",
"group": "build",
"type": "shell",
"command": "./fbt build APPSRC=${relativeFileDirname}"
},
{
"label": "[Release] Build App",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
},
{ {
"label": "[Debug] Launch App on Flipper", "label": "[Debug] Launch App on Flipper",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt launch_app APPSRC=${relativeFileDirname}" "command": "./fbt launch APPSRC=${relativeFileDirname}"
}, },
{ {
"label": "[Release] Launch App on Flipper", "label": "[Release] Launch App on Flipper",
"group": "build", "group": "build",
"type": "shell", "type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}" "command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
}, },
{ {
"label": "[Debug] Launch App on Flipper with Serial Console", "label": "[Debug] Launch App on Flipper with Serial Console",

View File

@ -18,7 +18,7 @@ Before launching the application, connect the sensor to Flipper's external GPIO
In order to launch this demo, follow the steps below: In order to launch this demo, follow the steps below:
1. Make sure your Flipper has an SD card installed. 1. Make sure your Flipper has an SD card installed.
2. Connect your Flipper to the computer via a USB cable. 2. Connect your Flipper to the computer via a USB cable.
3. Run `./fbt launch_app APPSRC=example_thermo` in your terminal emulator of choice. 3. Run `./fbt launch APPSRC=example_thermo` in your terminal emulator of choice.
## Changing the data pin ## Changing the data pin
It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below: It is possible to use other GPIO pin as a 1-Wire data pin. In order to change it, set the `THERMO_GPIO_PIN` macro to any of the options listed below:

View File

@ -13,7 +13,8 @@ FAPs are created and developed the same way as internal applications that are pa
To build your application as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest, and set its _apptype_ to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details. To build your application as a FAP, create a folder with your app's source code in `applications_user`, then write its code the way you'd do when creating a regular built-in application. Then configure its `application.fam` manifest, and set its _apptype_ to FlipperAppType.EXTERNAL. See [Application Manifests](./AppManifests.md#application-definition) for more details.
- To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest. - To build your application, run `./fbt fap_{APPID}`, where APPID is your application's ID in its manifest.
- To build your app and upload it over USB to run on Flipper, use `./fbt launch_app APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu). - To build your app and upload it over USB to run on Flipper, use `./fbt launch APPSRC=applications_user/path/to/app`. This command is configured in the default [VS Code profile](../.vscode/ReadMe.md) as a "Launch App on Flipper" build action (Ctrl+Shift+B menu).
- To build an app without uploading it to Flipper, use `./fbt build APPSRC=applications_user/path/to/app`. This command is also availabe in VSCode configuration as "Build App".
- To build all FAPs, run `./fbt faps` or `./fbt fap_dist`. - To build all FAPs, run `./fbt faps` or `./fbt fap_dist`.
## FAP assets ## FAP assets

View File

@ -328,10 +328,7 @@ class AppBuildset:
sdk_headers.extend( sdk_headers.extend(
[ [
src._appdir.File(header) src._appdir.File(header)
for src in [ for src in [app, *app._plugins]
app,
*(plugin for plugin in app._plugins),
]
for header in src.sdk_headers for header in src.sdk_headers
] ]
) )

View File

@ -3,7 +3,7 @@ import os
import pathlib import pathlib
import shutil import shutil
from dataclasses import dataclass, field from dataclasses import dataclass, field
from typing import Optional from typing import Optional, Dict, List
import SCons.Warnings import SCons.Warnings
from ansi.color import fg from ansi.color import fg
@ -400,22 +400,26 @@ def generate_embed_app_metadata_actions(source, target, env, for_signature):
return Action(actions) return Action(actions)
def AddAppLaunchTarget(env, appname, launch_target_name): @dataclass
deploy_sources, flipp_dist_paths, validators = [], [], [] class AppDeploymentComponents:
run_script_extra_ars = "" deploy_sources: Dict[str, object] = field(default_factory=dict)
validators: List[object] = field(default_factory=list)
extra_launch_args: str = ""
def _add_dist_targets(app_artifacts): def add_app(self, app_artifacts):
validators.append(app_artifacts.validator)
for _, ext_path in app_artifacts.dist_entries: for _, ext_path in app_artifacts.dist_entries:
deploy_sources.append(app_artifacts.compact) self.deploy_sources[f"/ext/{ext_path}"] = app_artifacts.compact
flipp_dist_paths.append(f"/ext/{ext_path}") self.validators.append(app_artifacts.validator)
return app_artifacts
def _gather_app_components(env, appname) -> AppDeploymentComponents:
components = AppDeploymentComponents()
def _add_host_app_to_targets(host_app): def _add_host_app_to_targets(host_app):
artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None) artifacts_app_to_run = env["EXT_APPS"].get(host_app.appid, None)
_add_dist_targets(artifacts_app_to_run) components.add_app(artifacts_app_to_run)
for plugin in host_app._plugins: for plugin in host_app._plugins:
_add_dist_targets(env["EXT_APPS"].get(plugin.appid, None)) components.add_app(env["EXT_APPS"].get(plugin.appid, None))
artifacts_app_to_run = env.GetExtAppByIdOrPath(appname) artifacts_app_to_run = env.GetExtAppByIdOrPath(appname)
if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN: if artifacts_app_to_run.app.apptype == FlipperAppType.PLUGIN:
@ -427,25 +431,35 @@ def AddAppLaunchTarget(env, appname, launch_target_name):
FlipperAppType.EXTERNAL, FlipperAppType.EXTERNAL,
FlipperAppType.MENUEXTERNAL, FlipperAppType.MENUEXTERNAL,
]: ]:
_add_host_app_to_targets(host_app) components.add_app(host_app)
else: else:
# host app is a built-in app # host app is a built-in app
run_script_extra_ars = f"-a {host_app.name}" components.add_app(artifacts_app_to_run)
_add_dist_targets(artifacts_app_to_run) components.extra_launch_args = f"-a {host_app.name}"
else: else:
raise UserError("Host app is unknown") raise UserError("Host app is unknown")
else: else:
_add_host_app_to_targets(artifacts_app_to_run.app) _add_host_app_to_targets(artifacts_app_to_run.app)
return components
# print(deploy_sources, flipp_dist_paths)
env.PhonyTarget( def AddAppLaunchTarget(env, appname, launch_target_name):
components = _gather_app_components(env, appname)
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=deploy_sources, source=components.deploy_sources.values(),
FLIPPER_FILE_TARGETS=flipp_dist_paths, FLIPPER_FILE_TARGETS=components.deploy_sources.keys(),
EXTRA_ARGS=run_script_extra_ars, EXTRA_ARGS=components.extra_launch_args,
) )
env.Alias(launch_target_name, validators) env.Alias(launch_target_name, components.validators)
return target
def AddAppBuildTarget(env, appname, build_target_name):
components = _gather_app_components(env, appname)
env.Alias(build_target_name, components.validators)
env.Alias(build_target_name, components.deploy_sources.values())
def generate(env, **kw): def generate(env, **kw):
@ -474,6 +488,7 @@ def generate(env, **kw):
env.AddMethod(BuildAppElf) env.AddMethod(BuildAppElf)
env.AddMethod(GetExtAppByIdOrPath) env.AddMethod(GetExtAppByIdOrPath)
env.AddMethod(AddAppLaunchTarget) env.AddMethod(AddAppLaunchTarget)
env.AddMethod(AddAppBuildTarget)
env.Append( env.Append(
BUILDERS={ BUILDERS={

View File

@ -4,15 +4,16 @@ targets_help = """Configuration variables:
tail_help = """ tail_help = """
TASKS: TASKS:
Building: Firmware & apps:
firmware_all, fw_dist: firmware_all, fw_dist:
Build firmware; create distribution package Build firmware; create distribution package
faps, fap_dist: faps, fap_dist:
Build all FAP apps Build all FAP apps
fap_{APPID}, launch_app APPSRC={APPID}: fap_{APPID}, build APPSRC={APPID}; launch APPSRC={APPID}:
Build FAP app with appid={APPID}; upload & start it over USB Build FAP app with appid={APPID}; upload & start it over USB
fap_deploy: fap_deploy:
Build and upload all FAP apps over USB Build and upload all FAP apps over USB
Flashing & debugging: Flashing & debugging:
flash, flash_blackmagic, jflash: flash, flash_blackmagic, jflash:

View File

@ -336,8 +336,10 @@ def ambiguous_app_call(**kw):
if app_to_launch: if app_to_launch:
appenv.AddAppLaunchTarget(app_to_launch, "launch") appenv.AddAppLaunchTarget(app_to_launch, "launch")
appenv.AddAppBuildTarget(app_to_launch, "build")
else: else:
dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None)) dist_env.PhonyTarget("launch", Action(ambiguous_app_call, None))
dist_env.PhonyTarget("build", Action(ambiguous_app_call, None))
# cli handler # cli handler

View File

@ -114,8 +114,20 @@ extapps.resources_dist = appenv.FapDist(appenv["RESOURCES_ROOT"], [])
if appsrc := appenv.subst("$APPSRC"): if appsrc := appenv.subst("$APPSRC"):
appenv.AddAppLaunchTarget(appsrc, "launch_app") launch_target = appenv.AddAppLaunchTarget(appsrc, "launch")
Alias("launch_app", launch_target)
appenv.PhonyTarget(
"launch_app",
Action(
lambda **kw: warn(
WarningOnByDefault,
"The 'launch_app' target is deprecated. Use 'launch' instead.",
),
None,
),
)
appenv.AddAppBuildTarget(appsrc, "build")
# SDK management # SDK management