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

Chore: Change the settings so the project scanner may work on different setups #13

Merged
merged 2 commits into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions client/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
# BitBake recipe language support in Visual Studio Code

## Set BitBake's path
Some features require to know where your BitBake's folder is located. The extension will by default assume it is located at the root of the project in a folder named `bitbake`. If your BitBake folder is located somewhere else, set its path in the settings in order to have full features.
## Setup the extension
In order to work properly, the extension needs to know your Bitbake's location and build folder. It will make the following assumptions:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can be more specific than "work properly". The extension highlighting works without for instance. Maybe just "For all the features to be enabled,"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also rephrase "it will make the following assumptions" -> "It will look for it at these default locations"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets remove it it in PR #16

- Bitbake's folder is located in `sources/poky/bitbake`, relative to the root of the project.
- Your build folder is located at the root of the project in a folder named `build`

To access BitBake's settings: Files -> Preferences -> Settings [Ctrl+,]. The BitBake's settings are under Extensions.
Ideally, the path to an environment script to configure the BitBake project should also be specified. If it is not specified, the extension will try to configure the environment variables by itself.

These can be configured into the VS Code's settings. More options are available.

To access the settings, you can navigate to **Files -> Preferences -> Settings** (or use the shortcut [**Ctrl+,**]). BitBake's settings are under **Extensions**

## Features

Expand Down
34 changes: 12 additions & 22 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,45 +62,35 @@
"debug"
],
"default": "error",
"description": "Adjust the logging level. error: only errors; info: only information that is useful for the user; debug: the same like info, but with additional debug informations"
"description": "Adjust the logging level: 'error' for reporting only errors, 'info' for displaying information useful to the user, and 'debug' for the same information as 'info,' but with additional debugging details."
},
"bitbake.deepExamine": {
"bitbake.shouldDeepExamine": {
"type": "boolean",
"default": false,
"description": "Activates an deeply examine. If a recipe export an extra package that have not the same name like the recipe file the normal scan will not find this packages. If you like to find the packages you have to activate this option."
"description": "Activate deep examination. If a recipe exports an additional package with a different name than the recipe file, the normal scan will not detect these packages. To find these packages, you need to activate this option."
},
"bitbake.workingFolder": {
"bitbake.pathToEnvScript": {
"type": "string",
"default": "vscode-bitbake-build",
"description": "Use this setting to specify the build folder. Use other folder than for your regular 'build' to avoid collisions."
"default": "oe-init-build-env",
"description": "Set the path to the environment script to configure the BitBake project. If the file does not exist, the extension will attempt to configure the environment variables by itself."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should attempt to configure the variables ourselves. Let's always ask for an env script as is the recommended Yocto workflow.

},
"bitbake.generateWorkingFolder": {
"type": "boolean",
"default": true,
"description": "Use this setting to specify whether or not to generate a build folder. Can help prevent git repo headaches."
},
"bitbake.pathToBashScriptInterpreter": {
"type": "string",
"default": "/bin/bash",
"description": "This interpreter is used to run bash scripts"
},
"bitbake.machine": {
"bitbake.pathToBuildFolder": {
"type": "string",
"default": "",
"description": "This setting is used to forward the machine name to bitbake."
"default": "build",
"description": "Set the build folder for the BitBake project."
},
"bitbake.pathToBitbakeFolder": {
"type": "string",
"default": "./bitbake",
"description": "This setting is used to specify the path to the bitbake folder."
"default": "sources/poky/bitbake",
"description": "Set the path to the BitBake folder."
}
}
},
"commands": [
{
"command": "bitbake.rescan-project",
"title": "BitBake: Rescan Project",
"description": "This command rescans the bitbake project."
"description": "This command rescans the BitBake project."
}
]
},
Expand Down
135 changes: 54 additions & 81 deletions server/src/BitBakeProjectScanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,11 @@ export class BitBakeProjectScanner {
private _classes: ElementInfo[] = new Array < ElementInfo >()
private _includes: ElementInfo[] = new Array < ElementInfo >()
private _recipes: ElementInfo[] = new Array < ElementInfo >()
private _deepExamine: boolean = false
private _settingsScriptInterpreter: string = '/bin/bash'
private _settingsWorkingFolder: string = 'vscode-bitbake-build'
private _settingsGenerateWorkingFolder: boolean = true
private readonly _settingsBitbakeSourceCmd: string = '.'
private _settingsMachine: string | undefined = undefined
private readonly _outputParser: OutputParser
private readonly _oeEnvScript: string = 'oe-init-build-env'
private _shouldDeepExamine: boolean = false
private _pathToBuildFolder: string = 'build'
private _pathToEnvScript: string = 'oe-init-build-env'
private _pathToBitbakeFolder: string = 'bitbake'

constructor (connection: Connection) {
this._outputParser = new OutputParser(connection)
Expand Down Expand Up @@ -80,48 +77,36 @@ export class BitBakeProjectScanner {
return this._recipes
}

get deepExamine (): boolean {
return this._deepExamine
get shouldDeepExamine (): boolean {
return this._shouldDeepExamine
}

set deepExamine (deepExamine: boolean) {
this._deepExamine = deepExamine
set shouldDeepExamine (shouldDeepExamine: boolean) {
this._shouldDeepExamine = shouldDeepExamine
}

get scriptInterpreter (): string {
return this._settingsScriptInterpreter
get pathToBuildFolder (): string {
return this._pathToBuildFolder
}

set scriptInterpreter (scriptInterpreter: string) {
this._settingsScriptInterpreter = scriptInterpreter
set pathToBuildFolder (pathToBuildFolder: string) {
this._pathToBuildFolder = pathToBuildFolder
}

get workingPath (): string {
return this._settingsWorkingFolder
get pathToEnvScript (): string {
return this._pathToEnvScript
}

set workingPath (workingPath: string) {
this._settingsWorkingFolder = workingPath
set pathToEnvScript (pathToEnvScript: string) {
this._pathToEnvScript = pathToEnvScript
}

get generateWorkingPath (): boolean {
return this._settingsGenerateWorkingFolder
get pathToBitbakeFolder (): string {
return this._pathToBitbakeFolder
}

set generateWorkingPath (generateWorkingPath: boolean) {
this._settingsGenerateWorkingFolder = generateWorkingPath
}

get machineName (): string | undefined {
return this._settingsMachine
}

set machineName (machine: string) {
if (machine === '') {
this._settingsMachine = undefined
} else {
this._settingsMachine = machine
}
set pathToBitbakeFolder (pathToBitbakeFolder: string) {
this._pathToBitbakeFolder = pathToBitbakeFolder
}

setProjectPath (projectPath: string): void {
Expand Down Expand Up @@ -299,7 +284,7 @@ export class BitBakeProjectScanner {
let parsingSuccess: boolean = true

try {
parsingOutput = this.executeCommandInBitBakeEnvironment('bitbake -p', this._settingsMachine)
parsingOutput = this.executeCommandInBitBakeEnvironment('bitbake -p')
idillon-sfl marked this conversation as resolved.
Show resolved Hide resolved
} catch (error) {
if (typeof error !== 'string') {
throw error
Expand Down Expand Up @@ -333,7 +318,7 @@ export class BitBakeProjectScanner {
}
}

if (this._deepExamine) {
if (this._shouldDeepExamine) {
const recipesWithOutPath: ElementInfo[] = this._recipes.filter((obj: ElementInfo): boolean => {
return obj.path === undefined
})
Expand Down Expand Up @@ -400,68 +385,56 @@ export class BitBakeProjectScanner {
}
}

private executeCommandInBitBakeEnvironment (command: string, machine: string | undefined = undefined): string {
let returnValue: string = ''

if (this.isBitbakeAvailable()) {
const scriptContent: string = this.generateBitBakeCommandScriptFileContent(command, machine)
const pathToScriptFile: string = this._projectPath + '/' + this._settingsWorkingFolder
const scriptFileName: string = pathToScriptFile + '/executeBitBakeCmd.sh'
private executeCommandInBitBakeEnvironment (command: string): string {
const scriptContent: string = this.generateBitBakeCommandScriptFileContent(command)
const pathToScriptFile: string = this._projectPath + '/' + this._pathToBuildFolder
const scriptFileName: string = pathToScriptFile + '/executeBitBakeCmd.sh'

if (!fs.existsSync(pathToScriptFile)) {
fs.mkdirSync(pathToScriptFile)
}
fs.writeFileSync(scriptFileName, scriptContent)
fs.chmodSync(scriptFileName, '0755')

returnValue = this.executeCommand(scriptFileName)
if (!fs.existsSync(pathToScriptFile)) {
fs.mkdirSync(pathToScriptFile)
}
fs.writeFileSync(scriptFileName, scriptContent)
fs.chmodSync(scriptFileName, '0755')

return returnValue
return this.executeCommand(scriptFileName)
}

private executeCommand (command: string): string {
let stdOutput: string = ''

if (this._projectPath !== null) {
const returnObject = execa.shellSync(command)

if (returnObject.status === 0) {
stdOutput = returnObject.stdout
} else {
const data: Buffer = fs.readFileSync(command)
logger.error('error on executing command: ' + data.toString())
try {
if (this._projectPath !== null) {
const returnObject = execa.shellSync(command)
if (returnObject.status === 0) {
stdOutput = returnObject.stdout
} else {
const data: Buffer = fs.readFileSync(command)
logger.error('error on executing command: ' + data.toString())
}
}
} catch (error: any) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure we should catch the error here because we don't know how to handle it. All callers will also have to check for errors. Error handling should be done at the calling level that can recover, or abort and display an error message.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is outdated, it does not exist anymore

logger.error(error)
}

return stdOutput
}

private generateBitBakeCommandScriptFileContent (bitbakeCommand: string, machine: string | undefined = undefined): string {
private generateBitBakeCommandScriptFileContent (bitbakeCommand: string): string {
idillon-sfl marked this conversation as resolved.
Show resolved Hide resolved
const scriptFileBuffer: string[] = []
let scriptBitbakeCommand: string = bitbakeCommand

scriptFileBuffer.push('#!' + this._settingsScriptInterpreter)
scriptFileBuffer.push(this._settingsBitbakeSourceCmd + ' ./' + this._oeEnvScript + ' ' + this._settingsWorkingFolder + ' > /dev/null')

if (machine !== undefined) {
scriptBitbakeCommand = `MACHINE=${machine} ` + scriptBitbakeCommand
if (fs.existsSync(this._pathToEnvScript)) {
logger.info('using env script')
scriptFileBuffer.push('source ./' + this._pathToEnvScript + ' ' + this._pathToBuildFolder + ' > /dev/null')
} else {
logger.info('not using env script')
scriptFileBuffer.push(
`export PYTHONPATH=${this._pathToBitbakeFolder}/lib:$PYTHONPATH`,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this required? I have not yet encountered cases were I needed to tweak the PATH to run bitbake. This is usually done by oe_init_build_env.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a fallback in case there is no environment script, so the extension still can attempt to work. Maybe it should just fail?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes there will always be an environment file for calling bitbake. It is the recommended workflow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood. I'll make this work into this PR: #16

`export PATH=${this._pathToBitbakeFolder}/bin:$PATH`,
`cd ${this.pathToBuildFolder}`
)
}

scriptFileBuffer.push(scriptBitbakeCommand)
scriptFileBuffer.push(bitbakeCommand)

return scriptFileBuffer.join('\n')
}

private isBitbakeAvailable (): boolean {
const settingActive: boolean = this._settingsGenerateWorkingFolder
const oeEnvScriptExists: boolean = fs.existsSync(this._oeEnvScript)
let bitbakeAvailable: boolean = false

if (settingActive && oeEnvScriptExists) {
bitbakeAvailable = true
}

return bitbakeAvailable
}
}
19 changes: 7 additions & 12 deletions server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,9 @@ interface Settings {

interface BitbakeSettings {
loggingLevel: string
deepExamine: boolean
workingFolder: string
pathToBashScriptInterpreter: string
machine: string
generateWorkingFolder: boolean
shouldDeepExamine: boolean
pathToEnvScript: string
pathToBuildFolder: string
pathToBitbakeFolder: string
}

Expand All @@ -77,14 +75,11 @@ function setSymbolScanner (newSymbolScanner: SymbolScanner | null): void {

connection.onDidChangeConfiguration((change) => {
const settings = change.settings as Settings
bitBakeProjectScanner.deepExamine = settings.bitbake.deepExamine
bitBakeProjectScanner.shouldDeepExamine = settings.bitbake.shouldDeepExamine
logger.level = settings.bitbake.loggingLevel
bitBakeProjectScanner.workingPath = settings.bitbake.workingFolder
bitBakeProjectScanner.generateWorkingPath = settings.bitbake.generateWorkingFolder
bitBakeProjectScanner.scriptInterpreter = settings.bitbake.pathToBashScriptInterpreter
bitBakeProjectScanner.machineName = settings.bitbake.machine
const bitBakeFolder = settings.bitbake.pathToBitbakeFolder
bitBakeDocScanner.parse(bitBakeFolder)
bitBakeProjectScanner.pathToBuildFolder = settings.bitbake.pathToBuildFolder
bitBakeProjectScanner.pathToBitbakeFolder = settings.bitbake.pathToBitbakeFolder
bitBakeDocScanner.parse(settings.bitbake.pathToBitbakeFolder)
})

connection.onDidChangeWatchedFiles((change) => {
Expand Down