Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devtool debug build support and update dependencies #370

Merged
Merged
30 changes: 11 additions & 19 deletions client/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,12 @@
"dependencies": {
"find": "^0.3.0",
"node-pty": "^1.0.0",
"semver": "^7.6.3",
"vscode-languageclient": "^9.0.1"
},
"devDependencies": {
"@types/find": "^0.2.4",
"@types/semver": "^7.5.8",
"@types/vscode": "^1.96.0"
},
"workspaces": [
Expand Down
10 changes: 7 additions & 3 deletions client/src/__tests__/unit-tests/driver/scanner.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,11 @@ import { BitBakeProjectScanner } from '../../../driver/BitBakeProjectScanner'
import { BitbakeDriver } from '../../../driver/BitbakeDriver'
import { BITBAKE_TIMEOUT } from '../../../utils/ProcessUtils'
import { mockVscodeEvents } from '../../utils/vscodeMock'
import { importRecipe, removeRecipe } from '../../utils/bitbake'
import { importRecipe, removeRecipe, integrationBitbakeFolder } from '../../utils/bitbake'
import { logger } from '../../../lib/src/utils/OutputLogger'

let bitBakeProjectScanner: BitBakeProjectScanner

const pathToBitbakeFolder = path.join(__dirname, '../../../../../integration-tests/project-folder/sources/poky/bitbake')
const pathToBuildFolder = path.join(__dirname, '../../../../../integration-tests/project-folder/build')
const pathToEnvScript = path.join(__dirname, '../../../../../integration-tests/project-folder/sources/poky/oe-init-build-env')
const workspaceFolder = path.join(__dirname, '../../../../../integration-tests/project-folder')
Expand All @@ -26,7 +25,7 @@ describe('BitBakeProjectScanner', () => {
const bitbakeDriver: BitbakeDriver = new BitbakeDriver()
bitbakeDriver.loadSettings(
{
pathToBitbakeFolder,
pathToBitbakeFolder: integrationBitbakeFolder,
pathToBuildFolder,
pathToEnvScript,
workingDirectory: workspaceFolder,
Expand Down Expand Up @@ -74,6 +73,11 @@ describe('BitBakeProjectScanner', () => {
jest.clearAllMocks()
}, BITBAKE_TIMEOUT)

it('can get the bitbake version', async () => {
const version = bitBakeProjectScanner.scanResult._bitbakeVersion
expect(version).toMatch(/^[\d.]+$/);
})

it('can get a list of layers', async () => {
const layers = bitBakeProjectScanner.scanResult._layers
// poky provides the "core", "yocto" and "yoctobsp" layers
Expand Down
13 changes: 12 additions & 1 deletion client/src/__tests__/unit-tests/ui/bitbake-commands.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ import type childProcess from 'child_process'
import { BitbakeWorkspace } from '../../../ui/BitbakeWorkspace'
import { BitBakeProjectScanner } from '../../../driver/BitBakeProjectScanner'
import { BitbakeDriver } from '../../../driver/BitbakeDriver'
import { registerDevtoolCommands } from '../../../ui/BitbakeCommands'
import { addDevtoolDebugBuild, registerDevtoolCommands } from '../../../ui/BitbakeCommands'
import { clientNotificationManager } from '../../../ui/ClientNotificationManager'
import * as BitbakeTerminal from '../../../ui/BitbakeTerminal'
import * as ProcessUtils from '../../../utils/ProcessUtils'
import { LanguageClient } from 'vscode-languageclient/node'
import { IPty } from 'node-pty'
import { BitbakeScanResult } from '../../../lib/src/types/BitbakeScanResult'
import { BitbakeSettings } from '../../../lib/src/BitbakeSettings'

jest.mock('vscode')

Expand Down Expand Up @@ -58,6 +60,7 @@ describe('Devtool ide-sdk command', () => {
pathToBitbakeFolder: '',
sdkImage: 'core-image-minimal'
}
jest.spyOn(bitBakeProjectScanner, 'scanResult', 'get').mockReturnValue({'_bitbakeVersion': '1.0.0'} as BitbakeScanResult)
const ideSDKCommand = mockExtensionContext(bitBakeProjectScanner)

jest.spyOn(BitbakeTerminal, 'runBitbakeTerminalCustomCommand').mockReturnValue(undefined as unknown as Promise<IPty>)
Expand All @@ -75,6 +78,7 @@ describe('Devtool ide-sdk command', () => {
sdkImage: 'core-image-minimal',
sshTarget: '[email protected]'
}
jest.spyOn(bitBakeProjectScanner, 'scanResult', 'get').mockReturnValue({'_bitbakeVersion': '3.0.0'} as BitbakeScanResult)
const ideSDKCommand = mockExtensionContext(bitBakeProjectScanner)

const commandSpy = jest.spyOn(BitbakeTerminal, 'runBitbakeTerminalCustomCommand').mockReturnValue(undefined as unknown as Promise<IPty>)
Expand All @@ -84,4 +88,11 @@ describe('Devtool ide-sdk command', () => {
await ideSDKCommand('busybox')
expect(commandSpy).toHaveBeenCalledWith(expect.anything(), 'devtool ide-sdk -i code busybox core-image-minimal -t [email protected]', expect.anything())
})

it('should properly detect devtool modify options', async () => {
// Test addDevtoolDebugBuild
expect(await addDevtoolDebugBuild('', {_bitbakeVersion: '3.0.0'} as BitbakeScanResult, {disableDevtoolDebugBuild: false} as BitbakeSettings, undefined as unknown as BitbakeDriver)).toBe(' --debug-build')
expect(await addDevtoolDebugBuild('', {_bitbakeVersion: '3.0.0'} as BitbakeScanResult, {disableDevtoolDebugBuild: true} as BitbakeSettings, undefined as unknown as BitbakeDriver)).toBe('')
expect(await addDevtoolDebugBuild('', {_bitbakeVersion: '1.0.0'} as BitbakeScanResult, {disableDevtoolDebugBuild: false} as BitbakeSettings, undefined as unknown as BitbakeDriver)).toBe('')
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ describe('BitbakeDriver Recipes View', () => {
_layers: [],
_classes: [],
_confFiles: [],
_overrides: [],
_workspaces: []
}
_overrides: []
} as unknown as BitbakeScanResult

vscode.window.registerTreeDataProvider = jest.fn().mockImplementation(
async (viewId: string, treeDataProvider: vscode.TreeDataProvider<BitbakeRecipeTreeItem>): Promise<void> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,13 @@ describe('Devtool Worskapces View', () => {
name: 'dropbear'
}
}],
_includes: [],
_layers: [],
_classes: [],
_overrides: [],
_confFiles: [],
_workspaces: [
{
name: 'dropbear',
path: '/build/workspace/dropbear'
}
]
}
],
} as BitbakeScanResult

const bitBakeProjectScanner = new BitBakeProjectScanner(new BitbakeDriver())

Expand Down
2 changes: 2 additions & 0 deletions client/src/__tests__/utils/bitbake.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import path from 'path'
import fs from 'fs'

export const integrationBitbakeFolder = path.join(__dirname, '../../../../integration-tests/project-folder/sources/poky/bitbake')

/// Copy a recipe into poky
export async function importRecipe (recipePath: string, pokyPath: string): Promise<void> {
const pokyDestinationPath = path.resolve(pokyPath, 'meta/recipes-core/base-files', path.basename(recipePath))
Expand Down
18 changes: 17 additions & 1 deletion client/src/driver/BitBakeProjectScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class BitBakeProjectScanner {
private readonly _confFileExtension: string = 'conf'
onChange: EventEmitter = new EventEmitter()

private _bitbakeScanResult: BitbakeScanResult = { _classes: [], _includes: [], _layers: [], _overrides: [], _recipes: [], _workspaces: [], _confFiles: [] }
private _bitbakeScanResult: BitbakeScanResult = { _classes: [], _includes: [], _layers: [], _overrides: [], _recipes: [], _workspaces: [], _confFiles: [], _bitbakeVersion: '' }
private readonly _bitbakeDriver: BitbakeDriver
private _languageClient: LanguageClient | undefined

Expand Down Expand Up @@ -100,6 +100,7 @@ export class BitBakeProjectScanner {

try {
if (!bitbakeESDKMode) { // Has been set by sanity checking
this.scanBitbakeVersion()
await this.scanAvailableLayers()
this.scanForClasses()
this.scanForIncludeFiles()
Expand Down Expand Up @@ -198,6 +199,21 @@ export class BitBakeProjectScanner {
this._bitbakeScanResult._confFiles = this.searchFiles(this._confFileExtension)
}

private scanBitbakeVersion(): void {
const bitbakeScriptPath = this.bitbakeDriver.bitbakeSettings.pathToBitbakeFolder + '/bin/bitbake'
const bitbakeScriptContent = fs.readFileSync(bitbakeScriptPath, 'utf8')

const versionRegex = /__version__ = "(\d+\.\d+\.\d+)"/
const match = bitbakeScriptContent.match(versionRegex)
if (match === null) {
logger.error('Failed to find bitbake version')
throw new Error('Failed to find bitbake version in ' + bitbakeScriptPath)
WilsonZiweiWang marked this conversation as resolved.
Show resolved Hide resolved
}
logger.info('Bitbake version: ' + match[1])

this._bitbakeScanResult._bitbakeVersion = match[1]
}

public async scanAvailableLayers (): Promise<void> {
this._bitbakeScanResult._layers = new Array < LayerInfo >()
this.containerMountPoint = undefined
Expand Down
2 changes: 1 addition & 1 deletion client/src/driver/BitbakeDriver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export class BitbakeDriver {
})
}

getBuildConfig (property: keyof BitbakeBuildConfigSettings): string | NodeJS.Dict<string> | undefined {
getBuildConfig (property: keyof BitbakeBuildConfigSettings): string | NodeJS.Dict<string> | boolean | undefined {
return getBuildSetting(this.bitbakeSettings, this.activeBuildConfiguration, property)
}

Expand Down
3 changes: 2 additions & 1 deletion client/src/lib/src/BitbakeSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export interface BitbakeBuildConfigSettings {
sshTarget?: string
sdkImage?: string
name?: string
disableDevtoolDebugBuild?: boolean
}

/// Defines the context of a bitbake workspace with all information to call bitbake
Expand Down Expand Up @@ -103,7 +104,7 @@ function expandBuildConfig (settings: Record<string, unknown>, variables: NodeJS
}
}

export function getBuildSetting (settings: BitbakeSettings, buildConfiguration: string, property: keyof BitbakeBuildConfigSettings): string | NodeJS.Dict<string> | undefined {
export function getBuildSetting (settings: BitbakeSettings, buildConfiguration: string, property: keyof BitbakeBuildConfigSettings): string | NodeJS.Dict<string> | boolean | undefined {
if (settings.buildConfigurations !== undefined) {
const buildConfig = settings.buildConfigurations.find(config => config.name === buildConfiguration)
if (buildConfig !== undefined) {
Expand Down
3 changes: 2 additions & 1 deletion client/src/lib/src/types/BitbakeScanResult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { type ParsedPath } from 'path'

// Make sure to increment this number when the structure of the scan data changes
// This will invalidate previous scan data saved for the workspace
export const SCAN_RESULT_VERSION: number = 2
export const SCAN_RESULT_VERSION: number = 3

export interface LayerInfo {
name: string
Expand Down Expand Up @@ -39,6 +39,7 @@ export interface BitbakeScanResult {
_overrides: string[]
_confFiles: ElementInfo[]
_workspaces: DevtoolWorkspaceInfo[]
_bitbakeVersion: string
}

export function scanContainsData (scanResult: BitbakeScanResult): boolean {
Expand Down
49 changes: 40 additions & 9 deletions client/src/ui/BitbakeCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import * as vscode from 'vscode'
import fs from 'fs'
import semver from 'semver';

import { logger } from '../lib/src/utils/OutputLogger'
import { type BitbakeWorkspace } from './BitbakeWorkspace'
Expand All @@ -16,9 +17,9 @@ import { type BitBakeProjectScanner } from '../driver/BitBakeProjectScanner'
import { extractRecipeName } from '../lib/src/utils/files'
import { runBitbakeTerminal, runBitbakeTerminalCustomCommand } from './BitbakeTerminal'
import { type BitbakeDriver } from '../driver/BitbakeDriver'
import { sanitizeForShell } from '../lib/src/BitbakeSettings'
import { BitbakeSettings, sanitizeForShell } from '../lib/src/BitbakeSettings'
import { type BitbakeTaskDefinition, type BitbakeTaskProvider } from './BitbakeTaskProvider'
import { type DevtoolWorkspaceInfo, type LayerInfo } from '../lib/src/types/BitbakeScanResult'
import { BitbakeScanResult, type DevtoolWorkspaceInfo, type LayerInfo } from '../lib/src/types/BitbakeScanResult'
import { DevtoolWorkspaceTreeItem } from './DevtoolWorkspacesView'
import * as child_process from 'child_process'
import { clientNotificationManager } from './ClientNotificationManager'
Expand Down Expand Up @@ -378,11 +379,20 @@ async function rescanProject (bitBakeProjectScanner: BitBakeProjectScanner): Pro
await bitBakeProjectScanner.rescanProject()
}

// Exported for testing
export async function addDevtoolDebugBuild(command: string, scanResult: BitbakeScanResult, settings: BitbakeSettings, bitbakeDriver: BitbakeDriver): Promise<string> {
if (await checkDevtoolDebugBuildAvailable(scanResult, bitbakeDriver) && !settings.disableDevtoolDebugBuild) {
command += ' --debug-build'
}
return command
}

async function devtoolModifyCommand (bitbakeWorkspace: BitbakeWorkspace, bitBakeProjectScanner: BitBakeProjectScanner, uri?: unknown): Promise<void> {
const chosenRecipe = await selectRecipe(bitbakeWorkspace, bitBakeProjectScanner, uri)
if (chosenRecipe !== undefined) {
logger.debug(`Command: devtool-modify: ${chosenRecipe}`)
const command = `devtool modify ${chosenRecipe}`
let command = `devtool modify ${chosenRecipe}`
command = await addDevtoolDebugBuild(command, bitBakeProjectScanner.scanResult, bitBakeProjectScanner.bitbakeDriver.bitbakeSettings, bitBakeProjectScanner.bitbakeDriver)
const process = await runBitbakeTerminalCustomCommand(bitBakeProjectScanner.bitbakeDriver, command, `Bitbake: Devtool Modify: ${chosenRecipe}`)
process.onExit((event) => {
if (event.exitCode === 0) {
Expand Down Expand Up @@ -432,7 +442,7 @@ async function devtoolIdeSDKCommand (bitbakeWorkspace: BitbakeWorkspace, bitBake
clientNotificationManager.showSDKConfigurationError()
return
}
if (!await checkIdeSdkAvailable(bitbakeDriver)) {
if (!await checkIdeSdkAvailable(bitBakeProjectScanner.scanResult, bitBakeProjectScanner.bitbakeDriver)) {
clientNotificationManager.showSDKUnavailableError(chosenRecipe)
return
}
Expand All @@ -443,11 +453,28 @@ async function devtoolIdeSDKCommand (bitbakeWorkspace: BitbakeWorkspace, bitBake
}
}

async function checkIdeSdkAvailable (bitbakeDriver: BitbakeDriver): Promise<boolean> {
const command = "devtool --help | grep 'ide-sdk'"
const process = runBitbakeTerminalCustomCommand(bitbakeDriver, command, 'Bitbake: Devtool ide-sdk: check')
const res = await finishProcessExecution(process)
return res.status === 0
async function checkIdeSdkAvailable (scanResult: BitbakeScanResult, bitbakeDriver: BitbakeDriver): Promise<boolean> {
if(!bitbakeESDKMode) {
// devtool ide-sdk appeared in Yocto version Scarthgap
return bitbakeVersionAbove(scanResult, '2.8.0')
} else {
const command = "devtool --help | grep 'ide-sdk'"
const process = runBitbakeTerminalCustomCommand(bitbakeDriver, command, 'Bitbake: Devtool ide-sdk: check')
const res = await finishProcessExecution(process)
return res.status === 0
}
}

async function checkDevtoolDebugBuildAvailable (scanResult: BitbakeScanResult, bitbakeDriver: BitbakeDriver): Promise<boolean> {
if(!bitbakeESDKMode) {
// devtool debug-build appeared in Yocto version Walnascard
return bitbakeVersionAbove(scanResult, '2.12.0')
} else {
const command = "devtool modify --help | grep '\\-\\-debug-build'"
const process = runBitbakeTerminalCustomCommand(bitbakeDriver, command, 'Bitbake: Devtool debug-build: check')
const res = await finishProcessExecution(process)
return res.status === 0
}
}

function checkIdeSdkConfiguration (bitbakeDriver: BitbakeDriver): boolean {
Expand Down Expand Up @@ -651,3 +678,7 @@ async function devtoolCleanCommand (bitbakeWorkspace: BitbakeWorkspace, bitBakeP
async function collapseActiveList (): Promise<void> {
await vscode.commands.executeCommand('list.collapseAll')
}

function bitbakeVersionAbove (scanResult: BitbakeScanResult, version: string): boolean {
return semver.gt(scanResult._bitbakeVersion, version);
}
2 changes: 1 addition & 1 deletion client/src/ui/BitbakeStatusBar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { BitBakeProjectScanner } from '../driver/BitBakeProjectScanner'
import { BitbakeEnvScanner } from '../driver/BitbakeEnvScanner'

export class BitbakeStatusBar {
private bitbakeScanResults: BitbakeScanResult = { _layers: [], _classes: [], _includes: [], _recipes: [], _overrides: [], _workspaces: [], _confFiles: [] }
private bitbakeScanResults: BitbakeScanResult = { _layers: [], _classes: [], _includes: [], _recipes: [], _overrides: [], _workspaces: [], _confFiles: [], _bitbakeVersion: '' }
private readonly bitbakeProjectScanner: BitBakeProjectScanner
readonly statusBarItem: vscode.StatusBarItem
private scanInProgress = false
Expand Down
Loading
Loading