Skip to content

Commit

Permalink
Add build use case (fix issue #14)
Browse files Browse the repository at this point in the history
  • Loading branch information
cedelavergne-ledger committed May 15, 2024
1 parent c54554f commit fd9b666
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 29 deletions.
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
"when": "view == mainView && viewItem == functionalTests && ledgerDevTools.showSelectTestUseCase",
"group": "inline"
},
{
"command": "buildUseCase",
"when": "view == mainView && viewItem == buildUseCase",
"group": "inline"
},
{
"command": "rebuildTestUseCaseDeps",
"when": "view == mainView && viewItem == functionalTests && ledgerDevTools.showRebuildTestUseCaseDeps",
Expand Down Expand Up @@ -93,6 +98,13 @@
"category": "Ledger",
"tooltip": "Select the device you want to build your app for."
},
{
"command": "buildUseCase",
"title": "Select build use case",
"category": "Ledger",
"tooltip": "Select the use case you want to build with.",
"icon": "$(tools)"
},
{
"command": "toggleAllTargets",
"title": "Toggle selection of all targets",
Expand Down
77 changes: 74 additions & 3 deletions src/appSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,53 @@ let appList: App[] = [];
let selectedApp: App | undefined;

let appSelectedEmitter: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();

export const onAppSelectedEvent: vscode.Event<void> = appSelectedEmitter.event;

let testUseCaseSelected: vscode.EventEmitter<void> = new vscode.EventEmitter<void>();

export const onTestUseCaseSelected: vscode.Event<void> = testUseCaseSelected.event;

let useCaseSelectedEmitter: vscode.EventEmitter<string> = new vscode.EventEmitter<string>();
export const onUseCaseSelectedEvent: vscode.Event<string> = useCaseSelectedEmitter.event;

export function getSelectedBuidUseCase(): string {
if (selectedApp && selectedApp.selectedBuildUseCase) {
console.log("LEDGER: getSelectedBuidUseCase: " + selectedApp.selectedBuildUseCase.name);
return selectedApp.selectedBuildUseCase.name;
}
// No use case defined in manifest, no selection
return "";
}

export function setBuildUseCase(name: string) {
if (selectedApp && selectedApp?.buildUseCases) {
for (let useCase of selectedApp?.buildUseCases) {
if (useCase.name === name) {
selectedApp.selectedBuildUseCase = useCase;
}
}
}
}

export function showBuildUseCase() {
if (selectedApp) {
if (selectedApp.buildUseCases) {
const items: string[] = [];
for (let useCase of selectedApp.buildUseCases) {
items.push(useCase.name);
}
const result = vscode.window.showQuickPick(items, {
placeHolder: "Please select a use case",
onDidSelectItem: (item) => {
setBuildUseCase(item.toString());
useCaseSelectedEmitter.fire(item.toString());
},
});
return result;
}
return "";
}
}

function detectAppType(appFolder: vscode.Uri): [AppType?, string?] {
const searchPatterns = APP_DETECTION_FILES.map((file) => path.join(appFolder.fsPath, `**/${file}`).replace(/\\/g, "/"));
const makefileOrToml = fg.sync(searchPatterns, { onlyFiles: true, deep: 2 });
Expand Down Expand Up @@ -435,19 +475,50 @@ function parseTestsUsesCasesFromManifest(tomlContent: any): TestUseCase[] | unde
function parseBuildUseCasesFromManifest(tomlContent: any): BuildUseCase[] | undefined {
let useCasesSection = getProperty(tomlContent, "use_cases");
let buildUseCases: BuildUseCase[] | undefined = undefined;
let debugFlagFound: Boolean = false;
let debugNameFound: Boolean = false;

buildUseCases = [];
// Add a default 'release' use case, to build in release mode, without any flag
let buildUseCase: BuildUseCase = {
name: "release",
options: "",
};
buildUseCases.push(buildUseCase);

// Parse 'use_cases' section from manifest to retrieve the configuration
if (useCasesSection) {
console.log(`Found use_cases section in manifest`);
buildUseCases = [];
const useCases = Object.keys(useCasesSection);
for (let useCase of useCases) {
let buildUseCase: BuildUseCase = {
name: useCase,
options: getPropertyOrThrow(useCasesSection, useCase),
};
if (buildUseCase.options === "DEBUG=1") {
// A debug use case already exists
debugFlagFound = true;
}
if (buildUseCase.name === "debug") {
// A use case with name 'debug' already exists
debugNameFound = true;
}
buildUseCases.push(buildUseCase);
console.log(`Found build use case ${useCase} with options ${JSON.stringify(buildUseCase.options)}`);
}
}

// Add a default 'debug' use case if not found in the manifest
if (debugFlagFound === false) {
let buildUseCase: BuildUseCase = {
name: "debug",
options: "DEBUG=1",
};
if (debugNameFound === true) {
buildUseCase.name = "debug_default";
}
buildUseCases.push(buildUseCase);
}
return buildUseCases;
}

Expand Down
21 changes: 20 additions & 1 deletion src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { TargetSelector } from "./targetSelector";
import { StatusBarManager } from "./statusBar";
import { ContainerManager, DevImageStatus } from "./containerManager";
import {
showBuildUseCase,
findAppsInWorkspace,
getSelectedApp,
setSelectedApp,
Expand All @@ -15,7 +16,9 @@ import {
onAppSelectedEvent,
showTestUseCaseSelectorMenu,
onTestUseCaseSelected,
onUseCaseSelectedEvent,
getAndBuildAppTestsDependencies,
getSelectedBuidUseCase,
} from "./appSelector";

let outputChannel: vscode.OutputChannel;
Expand All @@ -41,7 +44,7 @@ export function activate(context: vscode.ExtensionContext) {
let taskProvider = new TaskProvider(treeProvider, targetSelector);
context.subscriptions.push(vscode.tasks.registerTaskProvider(taskType, taskProvider));

let statusBarManager = new StatusBarManager(targetSelector.getSelectedTarget());
let statusBarManager = new StatusBarManager(targetSelector.getSelectedTarget(), getSelectedBuidUseCase());

let containerManager = new ContainerManager(taskProvider);

Expand All @@ -68,6 +71,16 @@ export function activate(context: vscode.ExtensionContext) {
})
);

// Event listener for useCase selection.
// This event is fired when the user selects a build useCase
context.subscriptions.push(
onUseCaseSelectedEvent((data) => {
taskProvider.generateTasks();
statusBarManager.updateBuildUseCaseItem(data);
treeProvider.updateDynamicLabels();
})
);

// Event listener for app selection.
// This event is fired when the user selects an app in the appSelector menu
context.subscriptions.push(
Expand All @@ -93,6 +106,12 @@ export function activate(context: vscode.ExtensionContext) {
})
);

context.subscriptions.push(
vscode.commands.registerCommand("buildUseCase", () => {
showBuildUseCase();
})
);

context.subscriptions.push(
vscode.commands.registerCommand("addTestsPrerequisites", () => {
setAppTestsPrerequisites(taskProvider);
Expand Down
16 changes: 15 additions & 1 deletion src/statusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,25 @@ import { ContainerManager, DevImageStatus } from "./containerManager";
const imageToolTip = "Click to update image and respawn container.";

export class StatusBarManager {
private buildUseCaseItem: vscode.StatusBarItem;
private targetItem: vscode.StatusBarItem;
private devImageItem: vscode.StatusBarItem;

constructor(target: string) {
constructor(target: string, useCase: string) {
this.targetItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
this.targetItem.tooltip = "Click to select another device.";
this.targetItem.command = "selectTarget";
this.targetItem.backgroundColor = new vscode.ThemeColor("statusBarItem.prominentBackground");
this.updateTargetItem(target);

this.buildUseCaseItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
if (useCase !== "") {
this.buildUseCaseItem.tooltip = "Click to select a build use case.";
this.buildUseCaseItem.command = "buildUseCase";
this.buildUseCaseItem.backgroundColor = new vscode.ThemeColor("statusBarItem.prominentBackground");
this.updateBuildUseCaseItem(useCase);
}

this.devImageItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
// Create a Command object with command and arguments
const runDevImageCommand: vscode.Command = {
Expand All @@ -35,6 +44,11 @@ export class StatusBarManager {
this.targetItem.show();
}

public updateBuildUseCaseItem(useCase: string) {
this.buildUseCaseItem.text = `$(tools) L : ${useCase}`;
this.buildUseCaseItem.show();
}

public updateDevImageItem(status: DevImageStatus): void {
const currentApp = getSelectedApp();
if (currentApp) {
Expand Down
2 changes: 1 addition & 1 deletion src/targetSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from "vscode";
import { StatusBarManager } from "./statusBar";
import { TaskProvider } from "./taskProvider";
import { TreeDataProvider } from "./treeView";
import { getSelectedApp } from "./appSelector";
import { getSelectedApp, setBuildUseCase } from "./appSelector";

// Define valid devices
const devices = ["Nano S", "Nano S Plus", "Nano X", "Stax", "Flex"] as const;
Expand Down
27 changes: 8 additions & 19 deletions src/taskProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,6 @@ export class TaskProvider implements vscode.TaskProvider {
state: "enabled",
allSelectedBehavior: "executeForEveryTarget",
},
{
group: "Build",
name: "Build with debug mode",
builders: { ["C"]: this.buildDebugExec },
toolTip: "Build app in debug mode",
dependsOn: this.appSubmodulesInitExec,
state: "enabled",
allSelectedBehavior: "executeForEveryTarget",
},
{
group: "Build",
name: "Clean the build files",
Expand Down Expand Up @@ -294,19 +285,17 @@ export class TaskProvider implements vscode.TaskProvider {
return exec;
}

private buildDebugExec(): string {
// Builds the app with debug mode enabled using the make command, inside the docker container.
const exec = `docker exec -it ${
this.containerName
} bash -c 'export BOLOS_SDK=$(echo ${this.tgtSelector.getSelectedSDK()}) && make -C ${this.buildDir} -j DEBUG=1'`;
return exec;
}

private cBuildExec(): string {

let buildOpt: string = "";
if (this.currentApp && this.currentApp.selectedBuildUseCase?.options) {
buildOpt = this.currentApp.selectedBuildUseCase?.options;
}

const exec = `docker exec -it ${
this.containerName
} bash -c 'export BOLOS_SDK=$(echo ${this.tgtSelector.getSelectedSDK()}) && make -C ${this.buildDir} -j'`;
// Builds the app in release mode using the make command, inside the docker container.
} bash -c 'export BOLOS_SDK=$(echo ${this.tgtSelector.getSelectedSDK()}) && make -C ${this.buildDir} -j ${buildOpt}'`;
// Builds the app using the make command, inside the docker container.
return exec;
}

Expand Down
20 changes: 16 additions & 4 deletions src/treeView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export class TreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
rootItem.iconPath = new vscode.ThemeIcon("vm");
}
if (rootItem.label?.toString().startsWith("Build")) {
rootItem.contextValue = "buildUseCase";
rootItem.iconPath = new vscode.ThemeIcon("tools");
}
if (rootItem.label?.toString().startsWith("Functional")) {
Expand Down Expand Up @@ -181,16 +182,27 @@ export class TreeDataProvider implements vscode.TreeDataProvider<TreeItem> {
let selectTargetItem = this.data.find((item) => item.label && item.label.toString().startsWith("Select target"));
let selectAppItem = this.data.find((item) => item.label && item.label.toString().startsWith("Select app"));
let functionalTestsItem = this.data.find((item) => item.label && item.label.toString().startsWith("Functional"));
let buidUseCaseItem = this.data.find((item) => item.label && item.label.toString().startsWith("Build"));

if (selectAppItem) {
selectAppItem.label = `Select app [${currentApp.folderName}]`;
}
if (selectTargetItem) {
selectTargetItem.label = `Select target [${this.targetSelector.getSelectedTarget()}]`;
}
if (functionalTestsItem && currentApp.selectedTestUseCase) {
functionalTestsItem.label = `Functional Tests [${currentApp.selectedTestUseCase.name}]`;
} else if (functionalTestsItem) {
functionalTestsItem.label = `Functional Tests`;
if (functionalTestsItem) {
if (currentApp.selectedTestUseCase) {
functionalTestsItem.label = `Functional Tests [${currentApp.selectedTestUseCase.name}]`;
} else {
functionalTestsItem.label = `Functional Tests`;
}
}
if (buidUseCaseItem) {
if (currentApp.selectedBuildUseCase) {
buidUseCaseItem.label = `Build [${currentApp.selectedBuildUseCase.name}]`;
} else {
buidUseCaseItem.label = `Build`;
}
}
} else {
// Remove all tree items. The welcome view will be displayed instead.
Expand Down

0 comments on commit fd9b666

Please sign in to comment.