[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:
parent
9bb04832a8
commit
309f65e401
20
.vscode/example/tasks.json
vendored
20
.vscode/example/tasks.json
vendored
@ -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",
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@ -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={
|
||||||
|
|||||||
@ -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:
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user