From 1ff4c98f0ed9ecfeba429916db4c566340e49aad Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Fri, 26 Jun 2026 22:11:46 +0900 Subject: [PATCH 01/33] Refactor board commands. --- cli/src/commands/board/flash-runtime.ts | 15 +- cli/src/commands/board/full-clean.ts | 8 +- cli/src/commands/board/remove.ts | 70 +--- cli/src/commands/board/setup.ts | 342 ------------------- cli/src/commands/board/setup/base.ts | 58 ++++ cli/src/commands/board/setup/esp32-darwin.ts | 90 +++++ cli/src/commands/board/setup/host-darwin.ts | 51 +++ cli/src/commands/board/setup/index.ts | 80 +++++ cli/src/commands/board/update.ts | 87 +++-- cli/src/config/constants.ts | 28 -- cli/src/platforms/board-env/base-env.ts | 45 +++ cli/src/platforms/board-env/esp32-env.ts | 109 ++++++ cli/src/platforms/board-env/host-env.ts | 51 +++ cli/src/platforms/board-env/index.ts | 28 ++ 14 files changed, 582 insertions(+), 480 deletions(-) delete mode 100644 cli/src/commands/board/setup.ts create mode 100644 cli/src/commands/board/setup/base.ts create mode 100644 cli/src/commands/board/setup/esp32-darwin.ts create mode 100644 cli/src/commands/board/setup/host-darwin.ts create mode 100644 cli/src/commands/board/setup/index.ts create mode 100644 cli/src/platforms/board-env/base-env.ts create mode 100644 cli/src/platforms/board-env/esp32-env.ts create mode 100644 cli/src/platforms/board-env/host-env.ts create mode 100644 cli/src/platforms/board-env/index.ts diff --git a/cli/src/commands/board/flash-runtime.ts b/cli/src/commands/board/flash-runtime.ts index 1b04281f..5c05213b 100644 --- a/cli/src/commands/board/flash-runtime.ts +++ b/cli/src/commands/board/flash-runtime.ts @@ -1,6 +1,7 @@ import { Command } from "commander"; import inquirer from 'inquirer'; import * as path from 'path'; +import * as os from 'os'; import { SerialPort } from 'serialport' import { BoardName } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; @@ -41,11 +42,19 @@ class ESP32FlashRuntimeHandler extends FlashRuntimeHandler { deviceName = deviceName ?? DEFAULT_DEVICE_NAME; - await exec( - `source ${boardConfig.exportFile} && idf.py -D DEVICE_NAME=${deviceName} build flash -p ${port}`, - { cwd: RUNTIME_ESP_PORT_DIR(runtimeDir) } + await this.runIdfPy( + boardConfig.exportFile, + ['-D', `DEVICE_NAME=${deviceName}`, 'build', 'flash', '-p', port], + RUNTIME_ESP_PORT_DIR(runtimeDir) ) } + + private async runIdfPy(exportFile: string, args: string[], cwd: string) { + const osType = os.platform(); + const preCommand = osType !== 'win32' ? exportFile : `source ${exportFile}`; + + await exec(`${preCommand} && idf.py ${args.join(' ')}`,{ cwd }); + } } function getFlashRuntimeHandler(board: string) { diff --git a/cli/src/commands/board/full-clean.ts b/cli/src/commands/board/full-clean.ts index 83660fa4..b1cec2d3 100644 --- a/cli/src/commands/board/full-clean.ts +++ b/cli/src/commands/board/full-clean.ts @@ -1,9 +1,8 @@ import { Command } from "commander"; import inquirer from 'inquirer'; import { logger } from "../../core/logger"; -import * as fs from '../../core/fs'; import { CommandHandler } from "../command"; -import { GLOBAL_SETTINGS } from "../../config/constants"; +import { BaseBoardEnv } from "../../platforms/board-env"; class FullcleanHandler extends CommandHandler { @@ -12,9 +11,8 @@ class FullcleanHandler extends CommandHandler { } fullclean() { - if (fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_DIR)) { - fs.removeDir(GLOBAL_SETTINGS.BLUESCRIPT_DIR); - } + const env = new BaseBoardEnv(); + env.removeBlueScriptDir(); } } diff --git a/cli/src/commands/board/remove.ts b/cli/src/commands/board/remove.ts index e9aafb75..dac77bb6 100644 --- a/cli/src/commands/board/remove.ts +++ b/cli/src/commands/board/remove.ts @@ -1,73 +1,37 @@ import { Command } from "commander"; import inquirer from 'inquirer'; -import { BoardName } from "../../config/board-utils"; +import { BoardName, isValidBoard } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; -import * as fs from '../../core/fs'; import { CommandHandler } from "../command"; +import { BaseBoardEnv, createBoardEnv } from "../../platforms/board-env"; -abstract class RemoveHandler extends CommandHandler { - async remove() { - await runStep('Removing...', () => this.removeBoard()); - this.globalConfigHandler.save(); - } - abstract isSetup(): boolean; - abstract removeBoard(): Promise; -} +class RemoveHandler extends CommandHandler { + boardName: BoardName; + boardEnv: BaseBoardEnv; -class HostRemoveHandler extends RemoveHandler { - readonly boardName: BoardName = 'host'; - - isSetup(): boolean { - return this.globalConfigHandler.isBoardSetup(this.boardName); + constructor(boardName: BoardName) { + super(); + this.boardName = boardName; + this.boardEnv = createBoardEnv(boardName); } - async removeBoard() { - const boardConfig = this.globalConfigHandler.getBoardConfig('host'); - if (boardConfig === undefined) { - throw new Error(`Cannot find config for ${this.boardName}.`); - } - if (fs.exists(boardConfig.buildDir)) { - fs.removeDir(boardConfig.buildDir); - } - - this.globalConfigHandler.removeBoardConfig(this.boardName); + async remove() { + await runStep('Removing...', async () => this.boardEnv.removeBoardRoot()); + this.globalConfigHandler.save(); } -} - -class ESP32RemoveHandler extends RemoveHandler { - readonly boardName: BoardName = 'esp32'; - + isSetup(): boolean { return this.globalConfigHandler.isBoardSetup(this.boardName); } - - async removeBoard() { - const boardConfig = this.globalConfigHandler.getBoardConfig('esp32'); - if (boardConfig === undefined) { - throw new Error(`Cannot find config for ${this.boardName}.`); - } - if (fs.exists(boardConfig.rootDir)) { - fs.removeDir(boardConfig.rootDir); - } - - this.globalConfigHandler.removeBoardConfig(this.boardName); - } -} - -function getRemoveHandler(board: string) { - if (board === 'esp32') { - return new ESP32RemoveHandler(); - } - if (board === 'host') { - return new HostRemoveHandler(); - } - throw new Error(`Unsupported board name: ${board}`); } export async function handleRemoveCommand(board: string, options: { force?: boolean }) { try { - const removeHandler = getRemoveHandler(board); + if (!isValidBoard(board)) { + throw new Error(`Unsupported board name: ${board}`); + } + const removeHandler = new RemoveHandler(board); // Check if setup has already been completed. if (!removeHandler.isSetup()) { diff --git a/cli/src/commands/board/setup.ts b/cli/src/commands/board/setup.ts deleted file mode 100644 index 6b3ff2ef..00000000 --- a/cli/src/commands/board/setup.ts +++ /dev/null @@ -1,342 +0,0 @@ -import { Command } from "commander"; -import * as path from 'path'; -import * as os from 'os'; -import inquirer from 'inquirer'; -import { logger, runStep, skip } from "../../core/logger"; -import { BoardName } from "../../config/board-utils"; -import { exec } from '../../core/shell'; -import * as fs from '../../core/fs'; -import chalk from "chalk"; -import { CommandHandler } from "../command"; -import { GLOBAL_SETTINGS } from "../../config/constants"; -import { buildHostRuntime } from "../../platforms/runtime/host-board-runtime"; - - -abstract class SetupHandler extends CommandHandler { - - getSetupPlan(): string[] { - const plan: string[] = []; - plan.push(`Download BlueScript runtime from ${GLOBAL_SETTINGS.RUNTIME_ZIP_URL}`); - plan.push(...this.getBoardSetupPlan()); - return plan; - } - - async setup(): Promise { - this.ensureBlueScriptDir(); - await this.downloadBlueScriptRuntimeStep(); - await this.setupBoard(); - this.globalConfigHandler.save(); - } - - private ensureBlueScriptDir() { - if (!fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_DIR)) { - fs.makeDir(GLOBAL_SETTINGS.BLUESCRIPT_DIR); - } - } - - private async downloadBlueScriptRuntimeStep() { - return runStep('Downloading BlueScript runtime...', async () => { - if (this.globalConfigHandler.isRuntimeSetup()) { - return skip('already downloaded.'); - } - await this.downloadBlueScriptRuntime(); - }); - } - - private async downloadBlueScriptRuntime() { - if (fs.exists(GLOBAL_SETTINGS.RUNTIME_DIR)) { - fs.removeDir(GLOBAL_SETTINGS.RUNTIME_DIR); - } - await fs.downloadAndUnzip(GLOBAL_SETTINGS.RUNTIME_ZIP_URL, GLOBAL_SETTINGS.BLUESCRIPT_DIR); - this.globalConfigHandler.setRuntimeDir(GLOBAL_SETTINGS.RUNTIME_DIR); - } - - abstract needSetup(): boolean; - abstract getBoardSetupPlan(): string[]; - abstract setupBoard(): Promise; -} - - -type ESP32SupportedOS = 'macos'; - -export class ESP32SetupHandler extends SetupHandler { - readonly boardName: BoardName = 'esp32'; - private os: ESP32SupportedOS; - - constructor() { - super(); - this.os = this.checkAndGetOS(); - } - - private checkAndGetOS(): ESP32SupportedOS { - if (os.platform() === 'darwin') { - return 'macos'; - } else { - throw new Error('Unsupported OS.'); - } - } - - needSetup(): boolean { - return !this.globalConfigHandler.isBoardSetup(this.boardName); - } - - getBoardSetupPlan(): string[] { - let plan: string[] = []; - if (this.os === 'macos') { - plan.push('Install required packages via Homebrew or MacPorts if they are not installed (cmake, ninja, dfu-util, and ccache).'); - plan.push('Install Python3 via Homebrew or MacPorts if python version is not greater than 3 or python3 is not installed.'); - } else { - throw new Error('Unknown OS.'); - } - plan.push(`Clone ESP-IDF ${GLOBAL_SETTINGS.ESP_IDF_VERSION} from ${GLOBAL_SETTINGS.ESP_IDF_GIT_REPO}.`); - plan.push('Run ESP-IDF install script.'); - return plan; - } - - async setupBoard(): Promise { - await this.installRequiredPackagesStep(); - await this.installPython3Step(); - await this.cloneEspIdfStep(); - await this.runEspIdfInstallScriptStep(); - - this.globalConfigHandler.updateBoardConfig(this.boardName, { - idfVersion: GLOBAL_SETTINGS.ESP_IDF_VERSION, - rootDir: GLOBAL_SETTINGS.ESP_ROOT_DIR, - exportFile: GLOBAL_SETTINGS.ESP_IDF_EXPORT_FILE, - xtensaGccDir: await this.getXtensaGccDir(), - }); - } - - private async installRequiredPackagesStep() { - return runStep('Installing required packages...', async () => { - let packages: string[] = []; - if (!(await this.isPackageInstalled('cmake'))) { packages.push('cmake'); } - if (!(await this.isPackageInstalled('ninja'))) { packages.push('ninja'); } - if (!(await this.isPackageInstalled('dfu-util'))) { packages.push('dfu-util'); } - if (!(await this.isPackageInstalled('ccache'))) { packages.push('ccache'); } - if (packages.length === 0) { - return skip('already installed.'); - } - await this.installEspidfRequiredPackages(packages); - }); - } - - private async installPython3Step() { - return runStep('Installing Python3...', async () => { - if ((await this.isPythonVersionGreaterThan3()) || (await this.isPackageInstalled('python3'))) { - return skip('already installed.'); - } - await this.installPython3(); - }); - } - - private cloneEspIdfStep() { - return runStep( - `Cloning ESP-IDF ${GLOBAL_SETTINGS.ESP_IDF_VERSION} from ${GLOBAL_SETTINGS.ESP_IDF_GIT_REPO}... It may take a while.`, - () => this.cloneEspIdf(), - ); - } - - private runEspIdfInstallScriptStep() { - return runStep( - 'Running ESP-IDF install script...', - () => this.runEspIdfInstallScript() - ); - } - - private async installEspidfRequiredPackages(packages: string[]) { - let installer: string; - if (await this.isPackageInstalled('brew')) { - installer = 'brew'; - } else if (await this.isPackageInstalled('port')) { - installer = 'port'; - } else { - throw new Error('Cannot find package installer. Please install Homebrew or MacPorts and try again.'); - } - - await exec(`${installer} install ${packages.join(' ')}`); - } - - private async installPython3() { - if (await this.isPackageInstalled('brew')) { - await exec('brew install python3'); - } else if (await this.isPackageInstalled('port')) { - await exec('sudo port install python38'); - } else { - throw new Error('Cannot find package installer. Please install Homebrew or MacPorts and try again.'); - } - } - - private async isPackageInstalled(name: string) { - try { - await exec(`which ${name}`, { silent: true }); - return true; - } catch (error) { - return false; - } - } - - private async isPythonVersionGreaterThan3() { - try { - const result = await exec(`python --version`, { silent: true }); - return result.startsWith('Python 3.'); - } catch (error) { - return false; - } - } - - private async cloneEspIdf() { - if (fs.exists(GLOBAL_SETTINGS.ESP_ROOT_DIR)) { - fs.removeDir(GLOBAL_SETTINGS.ESP_ROOT_DIR); - } - if (!(await this.isPackageInstalled('git'))) { - throw new Error('Cannot find git command. Please install git and try again.'); - } - - fs.makeDir(GLOBAL_SETTINGS.ESP_ROOT_DIR); - await exec(`git clone --depth 1 -b ${GLOBAL_SETTINGS.ESP_IDF_VERSION} --recursive ${GLOBAL_SETTINGS.ESP_IDF_GIT_REPO}`, - { cwd: GLOBAL_SETTINGS.ESP_ROOT_DIR }); - } - - private async runEspIdfInstallScript() { - await exec(GLOBAL_SETTINGS.ESP_IDF_INSTALL_FILE); - } - - private async getXtensaGccDir() { - try { - const gccPath = await exec(`source ${GLOBAL_SETTINGS.ESP_IDF_EXPORT_FILE} > /dev/null 2>&1 && which xtensa-esp32-elf-gcc`, { silent:true }); - return path.dirname(gccPath); - } catch (error) { - throw new Error('Failed to get xtensa gcc path.', {cause: error}); - } - - } -} - -export class HostSetupHandler extends SetupHandler { - readonly boardName: BoardName = 'host'; - - constructor() { - super(); - if (os.platform() !== 'darwin') { - throw new Error('Unsupported OS.'); - } - } - - needSetup(): boolean { - return !this.globalConfigHandler.isBoardSetup(this.boardName); - } - - getBoardSetupPlan(): string[] { - return [ - 'Verify that cc and make are installed (Xcode Command Line Tools).', - 'Build host runtime process.', - ]; - } - - async setupBoard(): Promise { - await this.verifyBuildToolsStep(); - const buildDir = await this.buildHostRuntimeStep(); - this.globalConfigHandler.updateBoardConfig(this.boardName, { buildDir: buildDir! }); - } - - private async verifyBuildToolsStep() { - return runStep('Verifying that cc and make are installed...', async () => { - const missing: string[] = []; - if (!(await this.isCommandInstalled('cc'))) { missing.push('cc'); } - if (!(await this.isCommandInstalled('make'))) { missing.push('make'); } - if (missing.length === 0) { - return; - } - throw new Error( - `Missing required tools: ${missing.join(', ')}. Install Xcode Command Line Tools and try again.`, - ); - }); - } - - private buildHostRuntimeStep() { - return runStep('Building host runtime...', async () => { - const runtimeDir = this.globalConfigHandler.getConfig().runtimeDir; - if (!runtimeDir) { - throw new Error('An unexpected error occurred: cannot find runtime directory path.'); - } - return await buildHostRuntime(runtimeDir); - }); - } - - private async isCommandInstalled(name: string) { - try { - await exec(`which ${name}`, { silent: true }); - return true; - } catch { - return false; - } - } -} - - -function getSetupHandler(board: string): SetupHandler { - if (board === 'esp32') { - return new ESP32SetupHandler(); - } - if (board === 'host') { - return new HostSetupHandler(); - } - throw new Error(`Unsupported board name: ${board}`); -} - -export async function handleSetupCommand(board: string) { - try { - const setupHandler = getSetupHandler(board); - - // Check if setup has already been completed. - if (!setupHandler.needSetup()) { - logger.warn(`The setup for ${board} has already been completed.`); - return; - } - - // Ask user if it's ok to proceed with setup. - const setupPlan = setupHandler.getSetupPlan(); - logger.log('The following setup process will be executed:'); - setupPlan.forEach(step => logger.log(` - ${step}`)); - const { proceed } = await inquirer.prompt([ - { - type: 'confirm', - name: 'proceed', - message: 'Do you want to continue?', - default: true, - }, - ]); - if (!proceed) { - logger.warn('Setup cancelled by user.'); - return; - } - - // Setup - await setupHandler.setup(); - - logger.br(); - logger.success(`Success to set up ${board}`); - if (board === 'host') { - logger.info(`Next step: run ${chalk.yellow('bscript project create -b host')}`); - } else { - logger.info(`Next step: run ${chalk.yellow(`bscript board flash-runtime ${board}`)}`); - } - - } catch (error) { - logger.error(`Failed to set up ${board}`); - logger.showError(error); - process.exit(1); - } -} - - -export function registerSetupCommand(program: Command) { - program - .command('setup') - .description('set up the environment for the specified board') - .argument('', 'name of the board to setup (e.g., esp32)') - .action(handleSetupCommand); -} - - diff --git a/cli/src/commands/board/setup/base.ts b/cli/src/commands/board/setup/base.ts new file mode 100644 index 00000000..2959c5cb --- /dev/null +++ b/cli/src/commands/board/setup/base.ts @@ -0,0 +1,58 @@ +import { runStep, skip } from "../../../core/logger"; +import { StepSkip } from "../../../core/logger/step-runner"; +import { CommandHandler } from "../../command"; +import { BoardName } from "../../../config/board-utils"; +import { BaseBoardEnv } from "../../../platforms/board-env/base-env"; + + +export interface Step { + description: string; + actionMessage: string; + action: () => Promise; +} + + +export abstract class SetupHandler extends CommandHandler { + abstract boardName: BoardName; + abstract boardEnv: BaseBoardEnv; + protected setupSteps: Step[] = []; + + constructor() { + super(); + this.loadSetupSteps(); + } + + protected loadSetupSteps() { + this.setupSteps.push({ + description: `Download BlueScript runtime from ${this.boardEnv.runtimeZipUrl}.`, + actionMessage: `Downloading BlueScript runtime from ${this.boardEnv.runtimeZipUrl}...`, + action: this.downloadBlueScriptRuntimeStep.bind(this) + }); + } + + needSetup() { + return !this.globalConfigHandler.isBoardSetup(this.boardName); + } + + async setup() { + this.boardEnv.ensureBlueScriptDir(); + this.boardEnv.refreshBoardRoot(); + for (const step of this.setupSteps) { + runStep(step.actionMessage, step.action); + } + this.globalConfigHandler.save(); + }; + + getSetupPlan(): string[] { + return this.setupSteps.map(step => step.description); + }; + + protected async downloadBlueScriptRuntimeStep() { + if (this.globalConfigHandler.isRuntimeSetup()) { + return skip('already downloaded.'); + } + + this.boardEnv.downloadBlueScriptRuntime(); + this.globalConfigHandler.setRuntimeDir(this.boardEnv.runtimeDir); + } +} diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts new file mode 100644 index 00000000..f27ae851 --- /dev/null +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -0,0 +1,90 @@ +import { SetupHandler } from "./base"; +import { exec } from '../../../core/shell'; +import { skip } from "../../../core/logger"; +import { BoardName } from "../../../config/board-utils"; +import { Esp32DarwinEnv } from "../../../platforms/board-env/esp32-env"; + + +export class Esp32DarwinSetupHandler extends SetupHandler { + boardName: BoardName = "esp32"; + boardEnv: Esp32DarwinEnv; + + constructor() { + super(); + this.boardEnv = new Esp32DarwinEnv(); + } + + protected loadSetupSteps(): void { + super.loadSetupSteps(); + this.setupSteps.push({ + description: "Verify that git, python3 and brew are installed.", + actionMessage: "Verifying that git, python3 and brew are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: "Install required packages via brew if they are not installed (cmake, ninja, dfu-util, and ccache).", + actionMessage: "Installing required packages...", + action: this.installRequiredPackagesStep.bind(this), + }); + this.setupSteps.push({ + description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}... It may take a while.`, + action: this.cloneEspIdfStep.bind(this), + }); + this.setupSteps.push({ + description: "Run ESP-IDF install script.", + actionMessage: "Running ESP-IDF install script...", + action: this.runEspIdfInstallScriptStep.bind(this), + }); + } + + private async verifyPrerequisitsInstalledStep() { + if (!await this.isPackageInstalled("git")) { + throw new Error("Cannot find git command. Please install git and try again."); + } + if (!await this.isPackageInstalled("brew")) { + throw new Error("Cannot find brew command. Please install Homebrew and try again."); + } + if (!(await this.isPythonVersionGreaterThan3()) && !(await this.isPackageInstalled('python3'))) { + throw new Error("Cannot find python3. Please install Python3 and try again."); + } + } + + private async installRequiredPackagesStep() { + let packages: string[] = []; + if (!(await this.isPackageInstalled('cmake'))) { packages.push('cmake'); } + if (!(await this.isPackageInstalled('ninja'))) { packages.push('ninja'); } + if (!(await this.isPackageInstalled('dfu-util'))) { packages.push('dfu-util'); } + if (!(await this.isPackageInstalled('ccache'))) { packages.push('ccache'); } + if (packages.length === 0) { + return skip('already installed.'); + } + await exec(`brew install ${packages.join(' ')}`); + } + + private async cloneEspIdfStep() { + await this.boardEnv.cloneEspIdf(); + } + + private async runEspIdfInstallScriptStep() { + await this.boardEnv.runEspIdfInstallScript(); + } + + private async isPackageInstalled(name: string) { + try { + await exec(`which ${name}`, { silent: true }); + return true; + } catch (error) { + return false; + } + } + + private async isPythonVersionGreaterThan3() { + try { + const result = await exec(`python --version`, { silent: true }); + return result.startsWith('Python 3.'); + } catch (error) { + return false; + } + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-darwin.ts b/cli/src/commands/board/setup/host-darwin.ts new file mode 100644 index 00000000..98e02618 --- /dev/null +++ b/cli/src/commands/board/setup/host-darwin.ts @@ -0,0 +1,51 @@ +import { SetupHandler } from "./base"; +import { exec } from '../../../core/shell'; +import { BoardName } from "../../../config/board-utils"; +import { HostDarwinEnv } from "../../../platforms/board-env/host-env"; + + +export class HostDarwinSetupHandler extends SetupHandler { + boardName: BoardName = "esp32"; + boardEnv: HostDarwinEnv; + + constructor() { + super(); + this.boardEnv = new HostDarwinEnv(); + } + + protected loadSetupSteps(): void { + super.loadSetupSteps(); + this.setupSteps.push({ + description: "Verify that cc and make are installed.", + actionMessage: "Verifying that cc and make are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: "Build host runtime.", + actionMessage: "Building host runtime...", + action: this.buildHostRuntimeStep.bind(this), + }); + } + + private async verifyPrerequisitsInstalledStep() { + if (!await this.isPackageInstalled("cc")) { + throw new Error("Cannot find cc command. Please install cc and try again."); + } + if (!await this.isPackageInstalled("make")) { + throw new Error("Cannot find make command. Please install make and try again."); + } + } + + private async buildHostRuntimeStep() { + await this.boardEnv.buildHostRuntime(); + } + + private async isPackageInstalled(name: string) { + try { + await exec(`which ${name}`, { silent: true }); + return true; + } catch (error) { + return false; + } + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/index.ts b/cli/src/commands/board/setup/index.ts new file mode 100644 index 00000000..bd885915 --- /dev/null +++ b/cli/src/commands/board/setup/index.ts @@ -0,0 +1,80 @@ +import { Command } from "commander"; +import * as os from 'os'; +import inquirer from 'inquirer'; +import { logger } from "../../../core/logger"; +import chalk from "chalk"; +import { SetupHandler } from "./base"; +import { Esp32DarwinSetupHandler } from "./esp32-darwin"; +import { HostDarwinSetupHandler } from "./host-darwin"; + + +function getSetupHandler(board: string): SetupHandler { + const osType = os.platform(); + if (board === 'esp32') { + if (osType === 'darwin') + return new Esp32DarwinSetupHandler(); + throw new Error(`Unsupported OS type: ${osType}.`); + } + if (board === 'host') { + if (osType === 'darwin') + return new HostDarwinSetupHandler(); + throw new Error(`Unsupported OS type: ${osType}.`); + } + throw new Error(`Unsupported board name: ${board}`); +} + +export async function handleSetupCommand(board: string) { + try { + const setupHandler = getSetupHandler(board); + + // Check if setup has already been completed. + if (!setupHandler.needSetup()) { + logger.warn(`The setup for ${board} has already been completed.`); + return; + } + + // Ask user if it's ok to proceed with setup. + const setupPlan = setupHandler.getSetupPlan(); + logger.log('The following setup process will be executed:'); + setupPlan.forEach(step => logger.log(` - ${step}`)); + const { proceed } = await inquirer.prompt([ + { + type: 'confirm', + name: 'proceed', + message: 'Do you want to continue?', + default: true, + }, + ]); + if (!proceed) { + logger.warn('Setup cancelled by user.'); + return; + } + + // Setup + await setupHandler.setup(); + + logger.br(); + logger.success(`Success to set up ${board}`); + if (board === 'host') { + logger.info(`Next step: run ${chalk.yellow('bscript project create -b host')}`); + } else { + logger.info(`Next step: run ${chalk.yellow(`bscript board flash-runtime ${board}`)}`); + } + + } catch (error) { + logger.error(`Failed to set up ${board}`); + logger.showError(error); + process.exit(1); + } +} + + +export function registerSetupCommand(program: Command) { + program + .command('setup') + .description('set up the environment for the specified board') + .argument('', 'name of the board to setup (e.g., esp32)') + .action(handleSetupCommand); +} + + diff --git a/cli/src/commands/board/update.ts b/cli/src/commands/board/update.ts index a3d3d52b..cf521c84 100644 --- a/cli/src/commands/board/update.ts +++ b/cli/src/commands/board/update.ts @@ -3,16 +3,18 @@ import { logger, runStep, skip } from "../../core/logger"; import { CommandHandler } from "../command"; import { GLOBAL_SETTINGS } from "../../config/constants"; import * as fs from '../../core/fs'; -import { exec } from "../../core/shell"; import * as path from 'path'; import { buildHostRuntime } from "../../platforms/runtime/host-board-runtime"; +import { BaseBoardEnv, createBoardEnv, Esp32Env } from "../../platforms/board-env"; class UpdateHandler extends CommandHandler { private existingRuntimeDir: string | undefined; private existingEspDir: string | undefined; + private existingHostDir: string | undefined; private tmpRuntimeDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-runtime'); private tmpEspDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-esp'); + private tmpHostDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-host'); constructor() { super(false); @@ -21,12 +23,8 @@ class UpdateHandler extends CommandHandler { async update() { try { await this.updateRuntimeStep(); - if (this.globalConfigHandler.isBoardSetup('esp32')) { - await this.updateEsp32Step(); - } - if (this.globalConfigHandler.isBoardSetup('host')) { - await this.updateHostStep(); - } + await this.updateEsp32Step(); + await this.updateHostStep(); this.globalConfigHandler.setVersion(GLOBAL_SETTINGS.VM_VERSION); } catch (error) { // Restore @@ -36,6 +34,9 @@ class UpdateHandler extends CommandHandler { if (this.existingEspDir) { fs.moveDir(this.tmpEspDir, this.existingEspDir); } + if (this.existingHostDir) { + fs.moveDir(this.tmpHostDir, this.existingHostDir); + } throw error; } finally { if (fs.exists(this.tmpRuntimeDir)) { @@ -44,8 +45,8 @@ class UpdateHandler extends CommandHandler { if (fs.exists(this.tmpEspDir)) { fs.removeDir(this.tmpEspDir); } + this.globalConfigHandler.save(); } - this.globalConfigHandler.save(); } private updateRuntimeStep() { @@ -54,19 +55,21 @@ class UpdateHandler extends CommandHandler { if (globalConfig.runtimeDir === undefined || globalConfig.version === GLOBAL_SETTINGS.VM_VERSION) { return skip('not needed'); } - this.existingRuntimeDir = globalConfig.runtimeDir; - await this.updateRuntime(this.existingRuntimeDir); + await this.updateRuntime(); }); } private updateEsp32Step() { return runStep('Updating the environment for esp32...', async () => { + if (this.globalConfigHandler.isBoardSetup('esp32')) { + return skip('not setup'); + } const esp32Config = this.globalConfigHandler.getBoardConfig('esp32')!; - if (esp32Config.idfVersion === GLOBAL_SETTINGS.ESP_IDF_VERSION) { + const esp32Env = createBoardEnv('esp32'); + if (esp32Config.idfVersion === esp32Env.idfVersion) { return skip('not needed'); } - this.existingEspDir = esp32Config.rootDir; - await this.updateEsp32(this.existingEspDir); + await this.updateEsp32(esp32Env); }); } @@ -76,51 +79,37 @@ class UpdateHandler extends CommandHandler { if (globalConfig.runtimeDir === undefined || globalConfig.version === GLOBAL_SETTINGS.VM_VERSION) { return skip('not needed'); } - await this.updateHost(globalConfig.runtimeDir); - }); + await this.updateHost(); + }); } - private async updateRuntime(existingRuntimeDir: string) { - fs.moveDir(existingRuntimeDir, this.tmpRuntimeDir); - await fs.downloadAndUnzip(GLOBAL_SETTINGS.RUNTIME_ZIP_URL, GLOBAL_SETTINGS.BLUESCRIPT_DIR); - this.globalConfigHandler.setRuntimeDir(GLOBAL_SETTINGS.RUNTIME_DIR); + private async updateRuntime() { + const env = new BaseBoardEnv(); + this.existingRuntimeDir = env.runtimeDir; + fs.moveDir(env.runtimeDir, this.tmpRuntimeDir); + + env.downloadBlueScriptRuntime(); + this.globalConfigHandler.setRuntimeDir(env.runtimeDir); } - private async updateHost(runtimeDir: string) { - const hostConfig = this.globalConfigHandler.getBoardConfig('host')!; - await buildHostRuntime(runtimeDir, hostConfig.buildDir); + private async updateHost() { + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); } - private async updateEsp32(existingEspDir: string) { - fs.moveDir(existingEspDir, this.tmpEspDir); - fs.makeDir(GLOBAL_SETTINGS.ESP_ROOT_DIR); - await this.cloneEspIdf(); - await this.runEspIdfInstallScript(); + private async updateEsp32(esp32Env: Esp32Env) { + this.existingEspDir = esp32Env.espRootDir; + fs.moveDir(esp32Env.espRootDir, this.tmpEspDir); + esp32Env.refreshBoardRoot(); + + await esp32Env.cloneEspIdf(); + await esp32Env.runEspIdfInstallScript(); this.globalConfigHandler.updateBoardConfig('esp32', { - idfVersion: GLOBAL_SETTINGS.ESP_IDF_VERSION, - rootDir: GLOBAL_SETTINGS.ESP_ROOT_DIR, - exportFile: GLOBAL_SETTINGS.ESP_IDF_EXPORT_FILE, - xtensaGccDir: await this.getXtensaGccDir(), + idfVersion: esp32Env.idfVersion, + rootDir: esp32Env.espRootDir, + xtensaGccDir: await esp32Env.getXtensaGccDir(), }); } - - private async cloneEspIdf() { - await exec(`git clone --depth 1 -b ${GLOBAL_SETTINGS.ESP_IDF_VERSION} --recursive ${GLOBAL_SETTINGS.ESP_IDF_GIT_REPO}`, - { cwd: GLOBAL_SETTINGS.ESP_ROOT_DIR }); - } - - private async runEspIdfInstallScript() { - await exec(GLOBAL_SETTINGS.ESP_IDF_INSTALL_FILE); - } - - private async getXtensaGccDir() { - try { - const gccPath = await exec(`source ${GLOBAL_SETTINGS.ESP_IDF_EXPORT_FILE} > /dev/null 2>&1 && which xtensa-esp32-elf-gcc`, { silent:true }); - return path.dirname(gccPath); - } catch (error) { - throw new Error('Failed to get xtensa gcc path.', {cause: error}); - } - } } export async function handleUpdateCommand() { diff --git a/cli/src/config/constants.ts b/cli/src/config/constants.ts index a1b36e7a..1b170049 100644 --- a/cli/src/config/constants.ts +++ b/cli/src/config/constants.ts @@ -15,32 +15,4 @@ export const GLOBAL_SETTINGS = { get BLUESCRIPT_CONFIG_FILE() { return path.join(this.BLUESCRIPT_DIR, 'config.json'); }, - - get RUNTIME_ZIP_URL() { - return `https://github.com/csg-tokyo/bluescript/releases/download/v${this.VM_VERSION}/release-microcontroller-v${this.VM_VERSION}.zip`; - }, - - get RUNTIME_DIR() { - return path.join(this.BLUESCRIPT_DIR, 'microcontroller'); - }, - - get ESP_ROOT_DIR() { - return path.join(this.BLUESCRIPT_DIR, 'esp'); - }, - - get ESP_IDF_VERSION() { - return 'v5.4'; - }, - - get ESP_IDF_GIT_REPO() { - return 'https://github.com/espressif/esp-idf.git'; - }, - - get ESP_IDF_EXPORT_FILE() { - return path.join(this.ESP_ROOT_DIR, 'esp-idf/export.sh'); - }, - - get ESP_IDF_INSTALL_FILE() { - return path.join(this.ESP_ROOT_DIR, 'esp-idf/install.sh'); - } } diff --git a/cli/src/platforms/board-env/base-env.ts b/cli/src/platforms/board-env/base-env.ts new file mode 100644 index 00000000..91890587 --- /dev/null +++ b/cli/src/platforms/board-env/base-env.ts @@ -0,0 +1,45 @@ +import * as path from 'path'; +import * as fs from '../../core/fs'; +import { GLOBAL_SETTINGS } from "../../config/constants"; + + +const RUNTIME_ZIP_URL = `https://github.com/csg-tokyo/bluescript/releases/download/v${GLOBAL_SETTINGS.VM_VERSION}/release-microcontroller-v${GLOBAL_SETTINGS.VM_VERSION}.zip`; +const RUNTIME_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'microcontroller'); + +export class BaseBoardEnv { + get runtimeZipUrl() { return RUNTIME_ZIP_URL; } + get runtimeDir() { return RUNTIME_DIR; } + + ensureBlueScriptDir() { + if (!fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_DIR)) { + fs.makeDir(GLOBAL_SETTINGS.BLUESCRIPT_DIR); + } + } + + removeBlueScriptDir() { + if (fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_DIR)) { + fs.removeDir(GLOBAL_SETTINGS.BLUESCRIPT_DIR); + } + } + + removeBoardRoot() {} + + refreshBoardRoot() {} + + async downloadBlueScriptRuntime() { + if (fs.exists(RUNTIME_DIR)) { + fs.removeDir(RUNTIME_DIR); + } + await fs.downloadAndUnzip(RUNTIME_ZIP_URL, GLOBAL_SETTINGS.BLUESCRIPT_DIR); + } + + needUpdate(): boolean { + if (!fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE)) { + return false; + } + const currentVersion = GLOBAL_SETTINGS.VM_VERSION; + const configFile = JSON.parse(fs.readFile(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE)); + const existingVersion = configFile.version; + return currentVersion !== existingVersion; + } +} \ No newline at end of file diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts new file mode 100644 index 00000000..4706fdd3 --- /dev/null +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -0,0 +1,109 @@ +import * as path from 'path'; +import * as fs from '../../core/fs'; +import { GLOBAL_SETTINGS } from "../../config/constants"; +import { exec } from '../../core/shell'; +import { BaseBoardEnv } from "./base-env"; + + +const ESP_ROOT_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); +const IDF_GIT_REPO = 'https://github.com/espressif/esp-idf.git'; +const IDF_VERSION = 'v5.4'; +const IDF_DIR = path.join(ESP_ROOT_DIR, 'esp-idf'); +const IDF_EXPORT_SH_FILE = path.join(IDF_DIR, 'export.sh'); +const IDF_INSTALL_SH_FILE = path.join(IDF_DIR, 'install.sh'); +const IDF_TOOLS_PY_FILE = path.join(IDF_DIR, 'tools/idf_tools.py'); +const XTENSA_DIR_NAME = 'xtensa-esp-elf/'; +const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; + + +export abstract class Esp32Env extends BaseBoardEnv { + get espRootDir() { return ESP_ROOT_DIR; } + get idfVersion() { return IDF_VERSION; } + get idfGitRepo() { return IDF_GIT_REPO; } + abstract get idfExportFile(): string; + + async cloneEspIdf() { + await exec( + `git clone --depth 1 -b ${IDF_VERSION} --recursive ${IDF_GIT_REPO}`, + { cwd: ESP_ROOT_DIR } + ); + } + + removeBoardRoot() { + if (fs.exists(ESP_ROOT_DIR)) { + fs.removeDir(ESP_ROOT_DIR); + } + } + + refreshBoardRoot() { + this.removeBoardRoot(); + fs.makeDir(ESP_ROOT_DIR); + } + + abstract runEspIdfInstallScript(): Promise; + abstract getXtensaGccDir(): Promise; + + protected parseKeyValueExport(stdout: string): Map { + const env = new Map(); + + for (const line of stdout.trim().split('\n')) { + if (!line || line.startsWith('ERROR:') || line.startsWith('WARNING:')) { + continue; + } + const eq = line.indexOf('='); + if (eq === -1) continue; + + const key = line.slice(0, eq); + const value = line.slice(eq + 1); + env.set(key, value); + } + + return env; + } + + protected splitPathValue(pathValue: string, separator: string): string[] { + return pathValue + .split(separator) + .map((p) => p.trim()) + .filter((p) => p.length > 0); + } + + protected resolveXtensaGccDirFromExport(stdout: string, pathLabel: string, pathSeparator: string): string { + const env = this.parseKeyValueExport(stdout); + + const pathValue = env.get(pathLabel); + if (!pathValue) { + throw new Error('PATH not found in idf_tools.py export output'); + } + + return this.findXtensaGccDirFromPathEntries(this.splitPathValue(pathValue, pathSeparator)); + } + + protected findXtensaGccDirFromPathEntries(entries: string[]): string { + const xtensaDirPattern = new RegExp(XTENSA_DIR_NAME); + for (const entry of entries) { + if (xtensaDirPattern.test(entry) && fs.exists(path.join(entry, XTENSA_GCC_NAME))) { + return entry; + } + } + + throw new Error(`${XTENSA_DIR_NAME} not found in exported PATH`); + } +} + +export class Esp32DarwinEnv extends Esp32Env { + get idfExportFile() { return IDF_EXPORT_SH_FILE; } + + async runEspIdfInstallScript() { + await exec(IDF_INSTALL_SH_FILE); + } + + async getXtensaGccDir() { + try { + const stdout = await exec(`${IDF_TOOLS_PY_FILE} export --format key-value`); + return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ':'); + } catch (error) { + throw new Error(`Failed to find ${XTENSA_DIR_NAME}.`, { cause: error }); + } + } +} \ No newline at end of file diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts new file mode 100644 index 00000000..28b89c07 --- /dev/null +++ b/cli/src/platforms/board-env/host-env.ts @@ -0,0 +1,51 @@ +import * as path from 'path'; +import * as fs from '../../core/fs'; +import { GLOBAL_SETTINGS } from "../../config/constants"; +import { exec } from '../../core/shell'; +import { BaseBoardEnv } from "./base-env"; + + +const HOST_ROOT_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); + +export abstract class HostEnv extends BaseBoardEnv { + get hostRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); } + get buildDir() { return path.join(this.runtimeDir, 'ports/host/build'); } + get builtinModuleCFile() { return path.join(this.runtimeDir, 'ports/host/std-module.c'); } + get shellCFile() { return path.join(this.runtimeDir, 'ports/host/shell.c'); } + get runtimeCFile() { return path.join(this.runtimeDir, 'core/src/c-runtime.c'); } + get commCFile() { return path.join(this.runtimeDir, 'ports/host/comm.c'); } + + abstract buildHostRuntime(): Promise; + + removeBoardRoot() { + if (fs.exists(HOST_ROOT_DIR)) { + fs.removeDir(HOST_ROOT_DIR); + } + } + + refreshBoardRoot() { + this.removeBoardRoot(); + fs.makeDir(HOST_ROOT_DIR); + } +} + +export class HostDarwinEnv extends HostEnv { + get runtimeSoFile() { return path.join(this.buildDir, 'c-runtime.so'); } + get shellFile() { return path.join(this.buildDir, 'shell'); } + + async buildHostRuntime() { + try { + await exec( + `cc -DLINUX64 -O2 -shared -fPIC -o "${this.runtimeSoFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, + { silent: true }, + ); + await exec( + `cc -DLINUX64 -O2 -o "${this.shellFile}" "${this.shellCFile}" "${this.runtimeSoFile}" -lm -ldl`, + { silent: true }, + ); + } catch(error) { + throw new Error('Failed to compile host runtime.', { cause: error }); + } + + } +} \ No newline at end of file diff --git a/cli/src/platforms/board-env/index.ts b/cli/src/platforms/board-env/index.ts new file mode 100644 index 00000000..0fa6c2c6 --- /dev/null +++ b/cli/src/platforms/board-env/index.ts @@ -0,0 +1,28 @@ +import * as os from 'os'; +import { Esp32Env, Esp32DarwinEnv } from './esp32-env'; +import { BaseBoardEnv } from './base-env'; +import { BoardName } from '../../config/board-utils'; +import { HostEnv, HostDarwinEnv } from './host-env'; + +type BoardEnvMap = { + esp32: Esp32Env; + host: HostEnv; +}; + +export function createBoardEnv(board: B): BoardEnvMap[B]; +export function createBoardEnv(board: BoardName): BoardEnvMap[BoardName] { + const osType = os.platform(); + if (board === 'esp32') { + if (osType === 'darwin') + return new Esp32DarwinEnv(); + throw new Error(`Unsupported OS type: ${osType}.`); + } + if (board === 'host') { + if (osType === 'darwin') + return new HostDarwinEnv(); + throw new Error(`Unsupported OS type: ${osType}.`); + } + throw new Error(`Unsupported board name: ${board}`); +} + +export { BaseBoardEnv, Esp32Env, Esp32DarwinEnv, HostEnv, HostDarwinEnv }; From 1edb4c2751b0bcd0dc8f23745215b1af70a97bf9 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 27 Jun 2026 15:27:13 +0900 Subject: [PATCH 02/33] Update tests. --- cli/src/commands/board/full-clean.ts | 4 +- cli/src/commands/board/remove.ts | 5 +- cli/src/commands/board/setup/base.ts | 16 ++-- cli/src/commands/board/setup/esp32-darwin.ts | 12 ++- cli/src/commands/board/setup/host-darwin.ts | 11 ++- cli/src/commands/board/setup/index.ts | 1 + cli/src/commands/board/update.ts | 13 ++-- cli/src/core/fs.ts | 2 +- .../board-env/{base-env.ts => common-env.ts} | 25 +++--- cli/src/platforms/board-env/esp32-env.ts | 77 ++++++++++++------- cli/src/platforms/board-env/host-env.ts | 22 +++--- cli/src/platforms/board-env/index.ts | 16 +++- cli/src/services/process.ts | 43 +++++++---- cli/tests/commands/board/setup.test.ts | 71 +++++++++++------ cli/tests/commands/board/update.test.ts | 17 ++-- cli/tests/commands/global-env-helper.ts | 43 +++++++---- cli/tests/global-mocks.ts | 3 +- .../integration/project/run.host.test.ts | 8 +- 18 files changed, 249 insertions(+), 140 deletions(-) rename cli/src/platforms/board-env/{base-env.ts => common-env.ts} (59%) diff --git a/cli/src/commands/board/full-clean.ts b/cli/src/commands/board/full-clean.ts index b1cec2d3..13981cc5 100644 --- a/cli/src/commands/board/full-clean.ts +++ b/cli/src/commands/board/full-clean.ts @@ -2,7 +2,7 @@ import { Command } from "commander"; import inquirer from 'inquirer'; import { logger } from "../../core/logger"; import { CommandHandler } from "../command"; -import { BaseBoardEnv } from "../../platforms/board-env"; +import { CommonBoardEnv } from "../../platforms/board-env"; class FullcleanHandler extends CommandHandler { @@ -11,7 +11,7 @@ class FullcleanHandler extends CommandHandler { } fullclean() { - const env = new BaseBoardEnv(); + const env = new CommonBoardEnv(); env.removeBlueScriptDir(); } } diff --git a/cli/src/commands/board/remove.ts b/cli/src/commands/board/remove.ts index dac77bb6..2159d256 100644 --- a/cli/src/commands/board/remove.ts +++ b/cli/src/commands/board/remove.ts @@ -3,12 +3,12 @@ import inquirer from 'inquirer'; import { BoardName, isValidBoard } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; import { CommandHandler } from "../command"; -import { BaseBoardEnv, createBoardEnv } from "../../platforms/board-env"; +import { CommonBoardEnv, createBoardEnv } from "../../platforms/board-env"; class RemoveHandler extends CommandHandler { boardName: BoardName; - boardEnv: BaseBoardEnv; + boardEnv: CommonBoardEnv; constructor(boardName: BoardName) { super(); @@ -18,6 +18,7 @@ class RemoveHandler extends CommandHandler { async remove() { await runStep('Removing...', async () => this.boardEnv.removeBoardRoot()); + this.globalConfigHandler.removeBoardConfig(this.boardName); this.globalConfigHandler.save(); } diff --git a/cli/src/commands/board/setup/base.ts b/cli/src/commands/board/setup/base.ts index 2959c5cb..4f39dcc2 100644 --- a/cli/src/commands/board/setup/base.ts +++ b/cli/src/commands/board/setup/base.ts @@ -2,7 +2,7 @@ import { runStep, skip } from "../../../core/logger"; import { StepSkip } from "../../../core/logger/step-runner"; import { CommandHandler } from "../../command"; import { BoardName } from "../../../config/board-utils"; -import { BaseBoardEnv } from "../../../platforms/board-env/base-env"; +import { CommonBoardEnv } from "../../../platforms/board-env/common-env"; export interface Step { @@ -14,20 +14,20 @@ export interface Step { export abstract class SetupHandler extends CommandHandler { abstract boardName: BoardName; - abstract boardEnv: BaseBoardEnv; + abstract boardEnv: CommonBoardEnv; protected setupSteps: Step[] = []; constructor() { super(); - this.loadSetupSteps(); } - protected loadSetupSteps() { + loadSetupSteps() { this.setupSteps.push({ description: `Download BlueScript runtime from ${this.boardEnv.runtimeZipUrl}.`, actionMessage: `Downloading BlueScript runtime from ${this.boardEnv.runtimeZipUrl}...`, action: this.downloadBlueScriptRuntimeStep.bind(this) }); + this.loadBoardSetupSteps(); } needSetup() { @@ -38,8 +38,9 @@ export abstract class SetupHandler extends CommandHandler { this.boardEnv.ensureBlueScriptDir(); this.boardEnv.refreshBoardRoot(); for (const step of this.setupSteps) { - runStep(step.actionMessage, step.action); + await runStep(step.actionMessage, step.action); } + await this.setBoardConfig(); this.globalConfigHandler.save(); }; @@ -47,12 +48,15 @@ export abstract class SetupHandler extends CommandHandler { return this.setupSteps.map(step => step.description); }; + abstract loadBoardSetupSteps(): void; + abstract setBoardConfig(): Promise; + protected async downloadBlueScriptRuntimeStep() { if (this.globalConfigHandler.isRuntimeSetup()) { return skip('already downloaded.'); } - this.boardEnv.downloadBlueScriptRuntime(); + await this.boardEnv.downloadBlueScriptRuntime(); this.globalConfigHandler.setRuntimeDir(this.boardEnv.runtimeDir); } } diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts index f27ae851..cad97030 100644 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -14,8 +14,7 @@ export class Esp32DarwinSetupHandler extends SetupHandler { this.boardEnv = new Esp32DarwinEnv(); } - protected loadSetupSteps(): void { - super.loadSetupSteps(); + loadBoardSetupSteps(): void { this.setupSteps.push({ description: "Verify that git, python3 and brew are installed.", actionMessage: "Verifying that git, python3 and brew are installed...", @@ -38,6 +37,15 @@ export class Esp32DarwinSetupHandler extends SetupHandler { }); } + async setBoardConfig() { + this.globalConfigHandler.updateBoardConfig(this.boardName, { + idfVersion: this.boardEnv.idfVersion, + rootDir: this.boardEnv.espRootDir, + exportFile: this.boardEnv.idfExportFile, + xtensaGccDir: await this.boardEnv.getXtensaGccDir(), + }); + } + private async verifyPrerequisitsInstalledStep() { if (!await this.isPackageInstalled("git")) { throw new Error("Cannot find git command. Please install git and try again."); diff --git a/cli/src/commands/board/setup/host-darwin.ts b/cli/src/commands/board/setup/host-darwin.ts index 98e02618..1a7e6deb 100644 --- a/cli/src/commands/board/setup/host-darwin.ts +++ b/cli/src/commands/board/setup/host-darwin.ts @@ -5,7 +5,7 @@ import { HostDarwinEnv } from "../../../platforms/board-env/host-env"; export class HostDarwinSetupHandler extends SetupHandler { - boardName: BoardName = "esp32"; + boardName: BoardName = 'host'; boardEnv: HostDarwinEnv; constructor() { @@ -13,8 +13,7 @@ export class HostDarwinSetupHandler extends SetupHandler { this.boardEnv = new HostDarwinEnv(); } - protected loadSetupSteps(): void { - super.loadSetupSteps(); + loadBoardSetupSteps(): void { this.setupSteps.push({ description: "Verify that cc and make are installed.", actionMessage: "Verifying that cc and make are installed...", @@ -27,6 +26,12 @@ export class HostDarwinSetupHandler extends SetupHandler { }); } + async setBoardConfig() { + this.globalConfigHandler.updateBoardConfig('host', { + buildDir: this.boardEnv.buildDir + }) + } + private async verifyPrerequisitsInstalledStep() { if (!await this.isPackageInstalled("cc")) { throw new Error("Cannot find cc command. Please install cc and try again."); diff --git a/cli/src/commands/board/setup/index.ts b/cli/src/commands/board/setup/index.ts index bd885915..cd2fc08d 100644 --- a/cli/src/commands/board/setup/index.ts +++ b/cli/src/commands/board/setup/index.ts @@ -32,6 +32,7 @@ export async function handleSetupCommand(board: string) { logger.warn(`The setup for ${board} has already been completed.`); return; } + setupHandler.loadSetupSteps(); // Ask user if it's ok to proceed with setup. const setupPlan = setupHandler.getSetupPlan(); diff --git a/cli/src/commands/board/update.ts b/cli/src/commands/board/update.ts index cf521c84..8b5777ff 100644 --- a/cli/src/commands/board/update.ts +++ b/cli/src/commands/board/update.ts @@ -4,8 +4,7 @@ import { CommandHandler } from "../command"; import { GLOBAL_SETTINGS } from "../../config/constants"; import * as fs from '../../core/fs'; import * as path from 'path'; -import { buildHostRuntime } from "../../platforms/runtime/host-board-runtime"; -import { BaseBoardEnv, createBoardEnv, Esp32Env } from "../../platforms/board-env"; +import { CommonBoardEnv, createBoardEnv, Esp32Env } from "../../platforms/board-env"; class UpdateHandler extends CommandHandler { @@ -61,7 +60,7 @@ class UpdateHandler extends CommandHandler { private updateEsp32Step() { return runStep('Updating the environment for esp32...', async () => { - if (this.globalConfigHandler.isBoardSetup('esp32')) { + if (!this.globalConfigHandler.isBoardSetup('esp32')) { return skip('not setup'); } const esp32Config = this.globalConfigHandler.getBoardConfig('esp32')!; @@ -75,6 +74,9 @@ class UpdateHandler extends CommandHandler { private updateHostStep() { return runStep('Updating the environment for host...', async () => { + if (!this.globalConfigHandler.isBoardSetup('host')) { + return skip('not setup'); + } const globalConfig = this.globalConfigHandler.getConfig(); if (globalConfig.runtimeDir === undefined || globalConfig.version === GLOBAL_SETTINGS.VM_VERSION) { return skip('not needed'); @@ -84,11 +86,11 @@ class UpdateHandler extends CommandHandler { } private async updateRuntime() { - const env = new BaseBoardEnv(); + const env = new CommonBoardEnv(); this.existingRuntimeDir = env.runtimeDir; fs.moveDir(env.runtimeDir, this.tmpRuntimeDir); - env.downloadBlueScriptRuntime(); + await env.downloadBlueScriptRuntime(); this.globalConfigHandler.setRuntimeDir(env.runtimeDir); } @@ -107,6 +109,7 @@ class UpdateHandler extends CommandHandler { this.globalConfigHandler.updateBoardConfig('esp32', { idfVersion: esp32Env.idfVersion, rootDir: esp32Env.espRootDir, + exportFile: esp32Env.idfExportFile, xtensaGccDir: await esp32Env.getXtensaGccDir(), }); } diff --git a/cli/src/core/fs.ts b/cli/src/core/fs.ts index d79c2a1b..49b9a9c7 100644 --- a/cli/src/core/fs.ts +++ b/cli/src/core/fs.ts @@ -8,7 +8,7 @@ export function makeDir(path: string, recursive: boolean = true) { } export function removeDir(path: string) { - fs.rmSync(path, { recursive: true }); + fs.rmSync(path, { recursive: true, force: true }); } export function moveDir(from: string, to: string) { diff --git a/cli/src/platforms/board-env/base-env.ts b/cli/src/platforms/board-env/common-env.ts similarity index 59% rename from cli/src/platforms/board-env/base-env.ts rename to cli/src/platforms/board-env/common-env.ts index 91890587..7432b5c4 100644 --- a/cli/src/platforms/board-env/base-env.ts +++ b/cli/src/platforms/board-env/common-env.ts @@ -1,14 +1,17 @@ import * as path from 'path'; import * as fs from '../../core/fs'; -import { GLOBAL_SETTINGS } from "../../config/constants"; +import { GLOBAL_SETTINGS } from '../../config/constants'; -const RUNTIME_ZIP_URL = `https://github.com/csg-tokyo/bluescript/releases/download/v${GLOBAL_SETTINGS.VM_VERSION}/release-microcontroller-v${GLOBAL_SETTINGS.VM_VERSION}.zip`; -const RUNTIME_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'microcontroller'); - -export class BaseBoardEnv { - get runtimeZipUrl() { return RUNTIME_ZIP_URL; } - get runtimeDir() { return RUNTIME_DIR; } +export class CommonBoardEnv { + get runtimeDir() { + return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'microcontroller'); + } + + get runtimeZipUrl() { + const v = GLOBAL_SETTINGS.VM_VERSION; + return `https://github.com/csg-tokyo/bluescript/releases/download/v${v}/release-microcontroller-v${v}.zip`; + } ensureBlueScriptDir() { if (!fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_DIR)) { @@ -27,10 +30,10 @@ export class BaseBoardEnv { refreshBoardRoot() {} async downloadBlueScriptRuntime() { - if (fs.exists(RUNTIME_DIR)) { - fs.removeDir(RUNTIME_DIR); + if (fs.exists(this.runtimeDir)) { + fs.removeDir(this.runtimeDir); } - await fs.downloadAndUnzip(RUNTIME_ZIP_URL, GLOBAL_SETTINGS.BLUESCRIPT_DIR); + await fs.downloadAndUnzip(this.runtimeZipUrl, GLOBAL_SETTINGS.BLUESCRIPT_DIR); } needUpdate(): boolean { @@ -42,4 +45,4 @@ export class BaseBoardEnv { const existingVersion = configFile.version; return currentVersion !== existingVersion; } -} \ No newline at end of file +} diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 4706fdd3..243064dc 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -2,47 +2,46 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from "../../config/constants"; import { exec } from '../../core/shell'; -import { BaseBoardEnv } from "./base-env"; +import { CommonBoardEnv } from './common-env'; - -const ESP_ROOT_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); -const IDF_GIT_REPO = 'https://github.com/espressif/esp-idf.git'; -const IDF_VERSION = 'v5.4'; -const IDF_DIR = path.join(ESP_ROOT_DIR, 'esp-idf'); -const IDF_EXPORT_SH_FILE = path.join(IDF_DIR, 'export.sh'); -const IDF_INSTALL_SH_FILE = path.join(IDF_DIR, 'install.sh'); -const IDF_TOOLS_PY_FILE = path.join(IDF_DIR, 'tools/idf_tools.py'); -const XTENSA_DIR_NAME = 'xtensa-esp-elf/'; +const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; - -export abstract class Esp32Env extends BaseBoardEnv { - get espRootDir() { return ESP_ROOT_DIR; } - get idfVersion() { return IDF_VERSION; } - get idfGitRepo() { return IDF_GIT_REPO; } +export abstract class Esp32Env extends CommonBoardEnv { + get espRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); } + get idfDir() { return path.join(this.espRootDir, 'esp-idf'); } + get idfExportShFile() { return path.join(this.idfDir, 'export.sh'); } + get idfInstallShFile() { return path.join(this.idfDir, 'install.sh'); } + get idfExportBatFile() { return path.join(this.idfDir, 'export.bat'); } + get idfInstallBatFile() { return path.join(this.idfDir, 'install.bat'); } + get idfToolsPyFile() { return path.join(this.idfDir, 'tools/idf_tools.py'); } + get idfVersion() { return 'v5.4'; } + get idfGitRepo() { return 'https://github.com/espressif/esp-idf.git'; } abstract get idfExportFile(): string; async cloneEspIdf() { await exec( - `git clone --depth 1 -b ${IDF_VERSION} --recursive ${IDF_GIT_REPO}`, - { cwd: ESP_ROOT_DIR } + `git clone --depth 1 -b ${this.idfVersion} --recursive ${this.idfGitRepo}`, + { cwd: this.espRootDir } ); } removeBoardRoot() { - if (fs.exists(ESP_ROOT_DIR)) { - fs.removeDir(ESP_ROOT_DIR); - } + fs.removeDir(this.espRootDir); } refreshBoardRoot() { this.removeBoardRoot(); - fs.makeDir(ESP_ROOT_DIR); + fs.makeDir(this.espRootDir); } abstract runEspIdfInstallScript(): Promise; abstract getXtensaGccDir(): Promise; + protected get xtensaGccFileName(): string { + return XTENSA_GCC_NAME; + } + protected parseKeyValueExport(stdout: string): Map { const env = new Map(); @@ -80,30 +79,50 @@ export abstract class Esp32Env extends BaseBoardEnv { } protected findXtensaGccDirFromPathEntries(entries: string[]): string { - const xtensaDirPattern = new RegExp(XTENSA_DIR_NAME); for (const entry of entries) { - if (xtensaDirPattern.test(entry) && fs.exists(path.join(entry, XTENSA_GCC_NAME))) { + if (entry.includes(XTENSA_TOOLCHAIN_DIR) && fs.exists(path.join(entry, this.xtensaGccFileName))) { return entry; } } - throw new Error(`${XTENSA_DIR_NAME} not found in exported PATH`); + throw new Error(`${XTENSA_TOOLCHAIN_DIR} not found in exported PATH`); } } export class Esp32DarwinEnv extends Esp32Env { - get idfExportFile() { return IDF_EXPORT_SH_FILE; } + get idfExportFile() { return this.idfExportShFile; } async runEspIdfInstallScript() { - await exec(IDF_INSTALL_SH_FILE); + await exec(this.idfInstallShFile); } async getXtensaGccDir() { try { - const stdout = await exec(`${IDF_TOOLS_PY_FILE} export --format key-value`); + const stdout = await exec(`${this.idfToolsPyFile} export --format key-value`); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ':'); } catch (error) { - throw new Error(`Failed to find ${XTENSA_DIR_NAME}.`, { cause: error }); + throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); } } -} \ No newline at end of file +} + +export class Esp32WindowsEnv extends Esp32Env { + get idfExportFile() { return this.idfExportBatFile; } + + protected get xtensaGccFileName(): string { + return `${XTENSA_GCC_NAME}.exe`; + } + + async runEspIdfInstallScript() { + await exec(this.idfInstallBatFile); + } + + async getXtensaGccDir() { + try { + const stdout = await exec(`${this.idfToolsPyFile} export --format key-value`); + return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ';'); + } catch (error) { + throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); + } + } +} diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 28b89c07..29f69c8b 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -1,13 +1,10 @@ import * as path from 'path'; import * as fs from '../../core/fs'; -import { GLOBAL_SETTINGS } from "../../config/constants"; +import { GLOBAL_SETTINGS } from '../../config/constants'; import { exec } from '../../core/shell'; -import { BaseBoardEnv } from "./base-env"; +import { CommonBoardEnv } from './common-env'; - -const HOST_ROOT_DIR = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); - -export abstract class HostEnv extends BaseBoardEnv { +export abstract class HostEnv extends CommonBoardEnv { get hostRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); } get buildDir() { return path.join(this.runtimeDir, 'ports/host/build'); } get builtinModuleCFile() { return path.join(this.runtimeDir, 'ports/host/std-module.c'); } @@ -18,14 +15,16 @@ export abstract class HostEnv extends BaseBoardEnv { abstract buildHostRuntime(): Promise; removeBoardRoot() { - if (fs.exists(HOST_ROOT_DIR)) { - fs.removeDir(HOST_ROOT_DIR); - } + fs.removeDir(this.hostRootDir); } refreshBoardRoot() { this.removeBoardRoot(); - fs.makeDir(HOST_ROOT_DIR); + fs.makeDir(this.hostRootDir); + } + + removeBuildDir() { + fs.removeDir(this.buildDir); } } @@ -34,6 +33,7 @@ export class HostDarwinEnv extends HostEnv { get shellFile() { return path.join(this.buildDir, 'shell'); } async buildHostRuntime() { + console.log(this.runtimeDir); try { await exec( `cc -DLINUX64 -O2 -shared -fPIC -o "${this.runtimeSoFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, @@ -48,4 +48,4 @@ export class HostDarwinEnv extends HostEnv { } } -} \ No newline at end of file +} diff --git a/cli/src/platforms/board-env/index.ts b/cli/src/platforms/board-env/index.ts index 0fa6c2c6..685350a5 100644 --- a/cli/src/platforms/board-env/index.ts +++ b/cli/src/platforms/board-env/index.ts @@ -1,9 +1,10 @@ import * as os from 'os'; -import { Esp32Env, Esp32DarwinEnv } from './esp32-env'; -import { BaseBoardEnv } from './base-env'; +import { Esp32Env, Esp32DarwinEnv, Esp32WindowsEnv } from './esp32-env'; +import { CommonBoardEnv } from './common-env'; import { BoardName } from '../../config/board-utils'; import { HostEnv, HostDarwinEnv } from './host-env'; + type BoardEnvMap = { esp32: Esp32Env; host: HostEnv; @@ -15,6 +16,8 @@ export function createBoardEnv(board: BoardName): BoardEnvMap[BoardName] { if (board === 'esp32') { if (osType === 'darwin') return new Esp32DarwinEnv(); + if (osType === 'win32') + return new Esp32WindowsEnv(); throw new Error(`Unsupported OS type: ${osType}.`); } if (board === 'host') { @@ -25,4 +28,11 @@ export function createBoardEnv(board: BoardName): BoardEnvMap[BoardName] { throw new Error(`Unsupported board name: ${board}`); } -export { BaseBoardEnv, Esp32Env, Esp32DarwinEnv, HostEnv, HostDarwinEnv }; +export { + CommonBoardEnv, + Esp32Env, + Esp32DarwinEnv, + Esp32WindowsEnv, + HostEnv, + HostDarwinEnv, +}; diff --git a/cli/src/services/process.ts b/cli/src/services/process.ts index c6de8458..083fc544 100644 --- a/cli/src/services/process.ts +++ b/cli/src/services/process.ts @@ -138,7 +138,7 @@ export class ProcessConnection extends Connection { } public async disconnect(): Promise { - if (!this.checkProcessRunning(this.shellProcess)) { + if (!this.shellProcess) { return; } @@ -147,27 +147,44 @@ export class ProcessConnection extends Connection { this.disconnecting = true; await new Promise((resolve) => { - const timeout = setTimeout(() => { - proc.kill('SIGKILL'); + let settled = false; + let timeout: NodeJS.Timeout; + const cleanup = () => { + if (settled) { + return; + } + settled = true; + clearTimeout(timeout); + proc.stdout.removeAllListeners(); + proc.stderr.removeAllListeners(); + proc.stdin.removeAllListeners(); proc.stdout.destroy(); proc.stderr.destroy(); proc.stdin.destroy(); + proc.removeAllListeners(); resolve(); + }; + + if (proc.exitCode !== null || proc.signalCode !== null) { + cleanup(); + return; + } + + timeout = setTimeout(() => { + if (proc.exitCode === null && proc.signalCode === null) { + proc.kill('SIGKILL'); + } + cleanup(); }, 3_000); - timeout.unref(); - proc.once('exit', () => { - clearTimeout(timeout); - proc.stdout.destroy(); - proc.stderr.destroy(); - proc.stdin.destroy(); - resolve(); - }); + proc.once('close', cleanup); proc.stdout.removeAllListeners('data'); proc.stderr.removeAllListeners('data'); - proc.stdin.end(); - proc.kill(); + if (proc.stdin.writable) { + proc.stdin.end(); + } + proc.kill('SIGTERM'); }); this.emit('disconnected', 0); diff --git a/cli/tests/commands/board/setup.test.ts b/cli/tests/commands/board/setup.test.ts index a0f02a61..d74dc622 100644 --- a/cli/tests/commands/board/setup.test.ts +++ b/cli/tests/commands/board/setup.test.ts @@ -7,15 +7,14 @@ import { mockedLogger, mockProcessExit, } from '../mock-helpers'; -import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings } from '../global-env-helper'; +import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings, getTestRuntimeDir, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { HostDarwinEnv } from '../../../src/platforms/board-env/host-env'; +import * as path from 'path'; -jest.mock('../../../src/platforms/runtime/host-board-runtime', () => ({ - buildHostRuntime: jest.fn().mockResolvedValue('/mock/host/build'), - getHostBuildDir: jest.fn(), -})); -import { buildHostRuntime } from '../../../src/platforms/runtime/host-board-runtime'; -const mockedBuildHostRuntime = buildHostRuntime as jest.Mock; +const mockedBuildHostRuntime = jest + .spyOn(HostDarwinEnv.prototype, 'buildHostRuntime') + .mockResolvedValue(); jest.mock('os', () => ({ ...jest.requireActual('os'), @@ -29,6 +28,7 @@ mockedOs.platform.mockReturnValue('darwin'); describe('board setup command', () => { beforeAll(() => { spyGlobalSettings('setup'); + jest.spyOn(HostDarwinEnv.prototype, 'buildHostRuntime').mockResolvedValue(); }) afterEach(() => { @@ -109,16 +109,17 @@ describe('board setup command', () => { if (command.includes('brew') || command.includes('git')) { return ''; } - if (command.includes('xtensa-esp32-elf-gcc')) { - return '/xtensa-esp-elf/bin/xtensa-esp32-elf-gcc'; - } throw new Error('not found'); } + if (command.includes('idf_tools.py export --format key-value')) { + return mockXtensaGccFromIdfToolsExport(); + } if (command.includes('python --version')) { - return 'Python 2.7.18'; + return 'Python 3.7.18'; } return ''; }); + setupEmpyGlobalEnv(); // --- Act --- await handleSetupCommand('esp32'); @@ -133,23 +134,36 @@ describe('board setup command', () => { // 3. Install required packages via Homebrew expect(mockedExec).toHaveBeenCalledWith('brew install cmake ninja dfu-util ccache'); - // 4. Instaall Python 3 if not present - expect(mockedExec).toHaveBeenCalledWith('brew install python3'); - - // 5. Clone ESP-IDF and run install script + // 4. Clone ESP-IDF and run install script expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('git clone'), expect.any(Object)); expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('install.sh')); - // 6. Update and save config + // 5. Update and save config expect(Object.keys(getGlobalConfig().boards)).toContain('esp32'); - // 7. No errors logged + // 6. No errors logged expect(mockedLogger.error).not.toHaveBeenCalled(); }); it('should skip downloading runtime if it exist', async () => { // --- Arrange --- + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); setupDefaultGlobalEnv(); + mockedExec.mockImplementation(async (command: string) => { + if (command.startsWith('which')) { + if (command.includes('brew') || command.includes('git')) { + return ''; + } + throw new Error('not found'); + } + if (command.includes('idf_tools.py export --format key-value')) { + return mockXtensaGccFromIdfToolsExport(); + } + if (command.includes('python --version')) { + return 'Python 3.7.18'; + } + return ''; + }); // --- Act --- await handleSetupCommand('esp32'); @@ -164,6 +178,7 @@ describe('board setup command', () => { it('shold skip install required packages if all packages are installed', async () => { // --- Arrange --- setupEmpyGlobalEnv(); + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); mockedExec.mockImplementation(async (command: string) => { if (command.startsWith('which')) { if (command.includes('brew') || command.includes('git')) { @@ -174,8 +189,11 @@ describe('board setup command', () => { } throw new Error('not found'); } + if (command.includes('idf_tools.py export --format key-value')) { + return mockXtensaGccFromIdfToolsExport(); + } if (command.includes('python --version')) { - return 'Python 2.7.18'; + return 'Python 3.7.18'; } return ''; }); @@ -187,9 +205,11 @@ describe('board setup command', () => { expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('brew install cmake')); }); - it('shold skip install python3 if python3 is already installed', async () => { + it('shold stop if python3 is not installed', async () => { // --- Arrange --- setupEmpyGlobalEnv(); + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); + const exitSpy = mockProcessExit(); mockedExec.mockImplementation(async (command: string) => { if (command.startsWith('which')) { if (command.includes('brew') || command.includes('git')) { @@ -198,7 +218,7 @@ describe('board setup command', () => { throw new Error('not found'); } if (command.includes('python --version')) { - return 'Python 3.7.18'; + return 'Python 2.7.18'; } return ''; }); @@ -207,12 +227,15 @@ describe('board setup command', () => { await handleSetupCommand('esp32'); // --- Assert --- - expect(mockedExec).not.toHaveBeenCalledWith('brew install python3'); + expect(mockedLogger.showError).toHaveBeenCalledWith(new Error('Cannot find python3. Please install Python3 and try again.')); + expect(process.exit).toHaveBeenCalledWith(1); + exitSpy.mockRestore(); }) it('should warn and exit if setup is already completed', async () => { // --- Arrange --- setupGlobalEnvWithEsp32(); + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); // --- Act --- await handleSetupCommand('esp32'); @@ -227,6 +250,7 @@ describe('board setup command', () => { it('should exit with an error for an unsupported OS', async () => { // --- Arrange --- const exitSpy = mockProcessExit(); + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); mockedOs.platform.mockReturnValue('linux'); setupGlobalEnvWithEsp32() @@ -235,7 +259,7 @@ describe('board setup command', () => { // --- Assert --- expect(mockedLogger.error).toHaveBeenCalledWith('Failed to set up esp32'); - expect(mockedLogger.showError).toHaveBeenCalledWith(new Error('Unsupported OS.')); + expect(mockedLogger.showError).toHaveBeenCalledWith(new Error('Unsupported OS type: linux.')); expect(process.exit).toHaveBeenCalledWith(1); exitSpy.mockRestore(); }); @@ -261,7 +285,7 @@ describe('board setup command', () => { expect(mockedInquirer.prompt).toHaveBeenCalledTimes(1); expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); expect(mockedBuildHostRuntime).toHaveBeenCalledTimes(1); - expect(getGlobalConfig().boards.host).toEqual({ buildDir: '/mock/host/build' }); + expect(getGlobalConfig().boards.host).toEqual({ buildDir: path.join(getTestRuntimeDir(), 'ports/host/build') }); expect(mockedLogger.info).toHaveBeenCalledWith(expect.stringContaining('bscript project create')); expect(mockedLogger.info).not.toHaveBeenCalledWith(expect.stringContaining('flash-runtime')); expect(mockedLogger.error).not.toHaveBeenCalled(); @@ -290,6 +314,7 @@ describe('board setup command', () => { it('should warn and exit if setup is already completed', async () => { setupGlobalEnvWithHost(); + mockedInquirer.prompt.mockResolvedValue({ proceed: true }); await handleSetupCommand('host'); diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index 62850978..884a3450 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,8 +1,7 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; -import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION } from '../global-env-helper'; +import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { mockedDownloadAndUnzip, mockedExec, mockProcessExit } from '../mock-helpers'; import * as fs from '../../../src/core/fs'; -import { GLOBAL_SETTINGS } from '../../../src/config/constants'; describe('board update command', () => { @@ -19,8 +18,8 @@ describe('board update command', () => { // --- Arrange --- setupGlobalEnvWithEsp32(true, true); mockedExec.mockImplementation((command: string) => { - if (command.endsWith('which xtensa-esp32-elf-gcc')) { - return 'xtensa-esp-elf/bin'; + if (command.includes('idf_tools.py export --format key-value')) { + return mockXtensaGccFromIdfToolsExport(); } return ''; }); @@ -65,8 +64,8 @@ describe('board update command', () => { const exitSpy = mockProcessExit(); setupGlobalEnvWithEsp32(true, true); mockedExec.mockImplementation((command: string) => { - if (command.endsWith('which xtensa-esp32-elf-gcc')) { - return 'xtensa-esp-elf/bin'; + if (command.includes('idf_tools.py export --format key-value')) { + return mockXtensaGccFromIdfToolsExport(); } return ''; }); @@ -81,7 +80,7 @@ describe('board update command', () => { expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('install')); - expect(fs.exists(GLOBAL_SETTINGS.RUNTIME_DIR)).toBe(true); + expect(fs.exists(getTestRuntimeDir())).toBe(true); expect(getGlobalConfig().version).toMatch(DUMMY_OLD_VM_VERSION); // --- Clean up --- @@ -106,8 +105,8 @@ describe('board update command', () => { expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('install')); - expect(fs.exists(GLOBAL_SETTINGS.RUNTIME_DIR)).toBe(true); - expect(fs.exists(GLOBAL_SETTINGS.ESP_ROOT_DIR)).toBe(true); + expect(fs.exists(getTestRuntimeDir())).toBe(true); + expect(fs.exists(getTestEspRootDir())).toBe(true); expect(getGlobalConfig().version).toMatch(DUMMY_OLD_VM_VERSION); expect(getGlobalConfig().boards.esp32.idfVersion).toMatch(DUMMY_OLD_ESP_IDF_VERSION); diff --git a/cli/tests/commands/global-env-helper.ts b/cli/tests/commands/global-env-helper.ts index 4e4ef05c..0a5388db 100644 --- a/cli/tests/commands/global-env-helper.ts +++ b/cli/tests/commands/global-env-helper.ts @@ -1,11 +1,7 @@ import * as path from "path"; import * as fs from '../../src/core/fs'; import { GLOBAL_SETTINGS } from "../../src/config/constants"; - - -// export const DUMMY_BLUESCRIPT_DIR = path.join(TEMP_DIR, '.bluescript'); -// export const DUMMY_BLUESCRIPT_CONFIG_FILE = path.join(DUMMY_BLUESCRIPT_DIR, 'config.json'); -// const DUMMY_RUNTIME_DIR = path.join(DUMMY_BLUESCRIPT_DIR, 'microcontroller'); +import { CommonBoardEnv, Esp32DarwinEnv } from "../../src/platforms/board-env"; const TEMP_DIR = path.join(__dirname, '../../temp-files'); const DUMMY_BLUESCRIPT_DIR = (suffix: string) => path.join(TEMP_DIR, `.bluescript-${suffix}`); @@ -15,11 +11,15 @@ export const DUMMY_OLD_VM_VERSION = '0.0.0'; export const DUMMY_ESP_IDF_VERSION = 'v5.4'; export const DUMMY_OLD_ESP_IDF_VERSION = 'v5.3'; +function commonBoardEnv() { return new CommonBoardEnv(); } +function esp32BoardEnv() { return new Esp32DarwinEnv(); } +export function getTestRuntimeDir() { return commonBoardEnv().runtimeDir; } +export function getTestEspRootDir() { return esp32BoardEnv().espRootDir; } +export function getTestEspIdfExportFile() { return esp32BoardEnv().idfExportFile; } export function spyGlobalSettings(globalDirSuffix: string) { jest.spyOn(GLOBAL_SETTINGS, 'BLUESCRIPT_DIR', 'get').mockReturnValue(DUMMY_BLUESCRIPT_DIR(globalDirSuffix)); jest.spyOn(GLOBAL_SETTINGS, 'VM_VERSION', 'get').mockReturnValue(DUMMY_VM_VERSION); - jest.spyOn(GLOBAL_SETTINGS, 'ESP_IDF_VERSION', 'get').mockReturnValue(DUMMY_ESP_IDF_VERSION); } export function setupEmpyGlobalEnv() { @@ -47,17 +47,17 @@ export function deleteGlobalEnv() { export function setupDefaultGlobalEnv(isOldVersion = false) { setupGlobalEnv({ version: isOldVersion ? DUMMY_OLD_VM_VERSION : DUMMY_VM_VERSION, - runtimeDir: GLOBAL_SETTINGS.RUNTIME_DIR, + runtimeDir: getTestRuntimeDir(), boards: {} }); - fs.makeDir(GLOBAL_SETTINGS.RUNTIME_DIR); + fs.makeDir(getTestRuntimeDir()); } export function setupGlobalEnvWithHost(isOldVersion = false, buildDir?: string) { - const resolvedBuildDir = buildDir ?? path.join(GLOBAL_SETTINGS.RUNTIME_DIR, 'ports/host/build'); + const resolvedBuildDir = buildDir ?? path.join(getTestRuntimeDir(), 'ports/host/build'); setupGlobalEnv({ version: isOldVersion ? DUMMY_OLD_VM_VERSION : DUMMY_VM_VERSION, - runtimeDir: GLOBAL_SETTINGS.RUNTIME_DIR, + runtimeDir: getTestRuntimeDir(), boards: { host: { buildDir: resolvedBuildDir, @@ -65,7 +65,7 @@ export function setupGlobalEnvWithHost(isOldVersion = false, buildDir?: string) }, }); fs.makeDir(resolvedBuildDir); - fs.makeDir(GLOBAL_SETTINGS.RUNTIME_DIR); + fs.makeDir(getTestRuntimeDir()); } export function setupGlobalEnvWithHostIntegration(runtimeDir: string, buildDir: string) { @@ -83,18 +83,28 @@ export function setupGlobalEnvWithHostIntegration(runtimeDir: string, buildDir: export function setupGlobalEnvWithEsp32(isOldVersion = false, isEspIdfOldVersion = false) { setupGlobalEnv({ version: isOldVersion ? DUMMY_OLD_VM_VERSION : DUMMY_VM_VERSION, - runtimeDir: GLOBAL_SETTINGS.RUNTIME_DIR, + runtimeDir: getTestRuntimeDir(), boards: { esp32: { idfVersion: isEspIdfOldVersion ? DUMMY_OLD_ESP_IDF_VERSION : DUMMY_ESP_IDF_VERSION, - rootDir: GLOBAL_SETTINGS.ESP_ROOT_DIR, - exportFile: GLOBAL_SETTINGS.ESP_IDF_EXPORT_FILE, + rootDir: getTestEspRootDir(), + exportFile: getTestEspIdfExportFile(), xtensaGccDir: "/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin" } } }); - fs.makeDir(GLOBAL_SETTINGS.ESP_ROOT_DIR); - fs.makeDir(GLOBAL_SETTINGS.RUNTIME_DIR); + fs.makeDir(getTestEspRootDir()); + fs.makeDir(getTestRuntimeDir()); +} + +export function mockXtensaGccFromIdfToolsExport(): string { + const gccDir = path.join( + GLOBAL_SETTINGS.BLUESCRIPT_DIR, + '.espressif/tools/xtensa-esp-elf/bin', + ); + fs.makeDir(gccDir); + fs.writeFile(path.join(gccDir, 'xtensa-esp32-elf-gcc'), ''); + return `PATH=${gccDir}:/xtensa-esp-elf-gdb/bin`; } export function getGlobalConfig(): any { @@ -103,4 +113,3 @@ export function getGlobalConfig(): any { } return JSON.parse(fs.readFile(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE)); } - diff --git a/cli/tests/global-mocks.ts b/cli/tests/global-mocks.ts index 7cb1a027..b8b33786 100644 --- a/cli/tests/global-mocks.ts +++ b/cli/tests/global-mocks.ts @@ -23,7 +23,8 @@ jest.mock('../src/core/logger', () => { success: jest.fn(), log: jest.fn(), br: jest.fn(), - showError: jest.fn(), + // showError: jest.fn() + showError: (message: string) => console.log(message), }, } }); diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index 43267d19..c77ccbe1 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { cwd } from '../../../src/core/shell'; import * as fs from '../../../src/core/fs'; import { handleRunCommand } from '../../../src/commands/project/run'; -import { buildHostRuntime } from '../../../src/platforms/runtime/host-board-runtime'; +import { CommonBoardEnv } from '../../../src/platforms/board-env/common-env'; import { deleteGlobalEnv, setupGlobalEnvWithHostIntegration, @@ -19,6 +19,7 @@ import { mockProcessExit, removeDirIfExists, } from '../host-run-helper'; +import { createBoardEnv } from '../../../src/platforms/board-env'; const mockedCwd = cwd as jest.Mock; @@ -35,9 +36,12 @@ describeHost('project run command (host integration)', () => { beforeAll(async () => { spyGlobalSettings('run-integration'); fs.makeDir(TEMP_DIR); + jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(RUNTIME_DIR); if (!fs.exists(SHELL_PATH) || !fs.exists(RUNTIME_SO_PATH)) { - await buildHostRuntime(RUNTIME_DIR, BUILD_DIR); + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); } }); From 29683e5cb3cb14a7012c6318d596dc2da9eb23c7 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 27 Jun 2026 16:15:17 +0900 Subject: [PATCH 03/33] Fix bugs. --- cli/src/commands/board/flash-runtime.ts | 2 +- cli/src/index.ts | 2 +- cli/src/platforms/board-env/host-env.ts | 2 +- .../platforms/runtime/host-board-runtime.ts | 25 ------------------- cli/tests/global-mocks.ts | 3 +-- .../integration/project/repl.host.test.ts | 7 ++++-- .../integration/project/run.host.test.ts | 4 +-- microcontroller/ports/host/comm.c | 12 ++++----- 8 files changed, 17 insertions(+), 40 deletions(-) diff --git a/cli/src/commands/board/flash-runtime.ts b/cli/src/commands/board/flash-runtime.ts index 5c05213b..f1260528 100644 --- a/cli/src/commands/board/flash-runtime.ts +++ b/cli/src/commands/board/flash-runtime.ts @@ -51,7 +51,7 @@ class ESP32FlashRuntimeHandler extends FlashRuntimeHandler { private async runIdfPy(exportFile: string, args: string[], cwd: string) { const osType = os.platform(); - const preCommand = osType !== 'win32' ? exportFile : `source ${exportFile}`; + const preCommand = osType === 'win32' ? exportFile : `source ${exportFile}`; await exec(`${preCommand} && idf.py ${args.join(' ')}`,{ cwd }); } diff --git a/cli/src/index.ts b/cli/src/index.ts index cfde62d8..de0ca217 100644 --- a/cli/src/index.ts +++ b/cli/src/index.ts @@ -4,7 +4,7 @@ import { Command } from 'commander'; import { logger } from './core/logger'; import packageJson from '../package.json'; -import { registerSetupCommand } from './commands/board/setup'; +import { registerSetupCommand } from './commands/board/setup/index'; import { registerRemoveCommand } from './commands/board/remove'; import { registerFlashRuntimeCommand } from './commands/board/flash-runtime'; import { registerListCommand } from './commands/board/list'; diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 29f69c8b..4e1b419b 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -33,7 +33,7 @@ export class HostDarwinEnv extends HostEnv { get shellFile() { return path.join(this.buildDir, 'shell'); } async buildHostRuntime() { - console.log(this.runtimeDir); + fs.makeDir(this.buildDir); try { await exec( `cc -DLINUX64 -O2 -shared -fPIC -o "${this.runtimeSoFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, diff --git a/cli/src/platforms/runtime/host-board-runtime.ts b/cli/src/platforms/runtime/host-board-runtime.ts index 5382b7ba..83c2000c 100644 --- a/cli/src/platforms/runtime/host-board-runtime.ts +++ b/cli/src/platforms/runtime/host-board-runtime.ts @@ -5,34 +5,9 @@ import { ProgramOutput } from "../../core/logger/program-output"; import { BoardRuntime } from "./board-runtime"; import { CompileContext } from "../compiler/compiler-adapter"; import { HostBoardConfig } from "../../config/global-config"; -import * as fs from '../../core/fs'; import { HostService, ProcessConnection } from '../../services/process'; -export async function buildHostRuntime(runtimeDir: string, buildDir?: string): Promise { - const resolvedBuildDir = buildDir ?? path.join(runtimeDir, 'ports/host/build'); - const builtinModuleC = path.join(runtimeDir, 'ports/host/std-module.c'); - const shellC = path.join(runtimeDir, 'ports/host/shell.c'); - const runtimeC = path.join(runtimeDir, 'core/src/c-runtime.c'); - const commC = path.join(runtimeDir, 'ports/host/comm.c'); - const runtimeSo = path.join(resolvedBuildDir, 'c-runtime.so'); - const shell = path.join(resolvedBuildDir, 'shell'); - - fs.makeDir(resolvedBuildDir); - - await exec( - `cc -DLINUX64 -O2 -shared -fPIC -o "${runtimeSo}" "${runtimeC}" "${builtinModuleC}" "${commC}"`, - { silent: true }, - ); - await exec( - `cc -DLINUX64 -O2 -o "${shell}" "${shellC}" "${runtimeSo}" -lm -ldl`, - { silent: true }, - ); - - return resolvedBuildDir; -} - - export class HostBoardRuntime implements BoardRuntime { private programOutput: ProgramOutput; private shellProcess: ProcessConnection; diff --git a/cli/tests/global-mocks.ts b/cli/tests/global-mocks.ts index b8b33786..d2a15341 100644 --- a/cli/tests/global-mocks.ts +++ b/cli/tests/global-mocks.ts @@ -23,8 +23,7 @@ jest.mock('../src/core/logger', () => { success: jest.fn(), log: jest.fn(), br: jest.fn(), - // showError: jest.fn() - showError: (message: string) => console.log(message), + showError: jest.fn() }, } }); diff --git a/cli/tests/integration/project/repl.host.test.ts b/cli/tests/integration/project/repl.host.test.ts index 03f8403f..6a3f75f5 100644 --- a/cli/tests/integration/project/repl.host.test.ts +++ b/cli/tests/integration/project/repl.host.test.ts @@ -8,7 +8,6 @@ import * as path from 'path'; import * as fs from '../../../src/core/fs'; import { handleReplCommand } from '../../../src/commands/repl'; import { logger } from '../../../src/core/logger'; -import { buildHostRuntime } from '../../../src/platforms/runtime/host-board-runtime'; import { deleteGlobalEnv, setupGlobalEnvWithHostIntegration, @@ -23,6 +22,7 @@ import { waitFor, waitForStdoutContains, } from '../host-run-helper'; +import { CommonBoardEnv, createBoardEnv } from '../../../src/platforms/board-env'; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration-repl'); const SHELL_PATH = path.join(HOST_INTEGRATION_BUILD_DIR, 'shell'); @@ -60,7 +60,10 @@ describeHost('repl command (host integration)', () => { fs.makeDir(TEMP_DIR); if (!fs.exists(SHELL_PATH) || !fs.exists(RUNTIME_SO_PATH)) { - await buildHostRuntime(HOST_INTEGRATION_RUNTIME_DIR, HOST_INTEGRATION_BUILD_DIR); + jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(HOST_INTEGRATION_RUNTIME_DIR); + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); } }); diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index c77ccbe1..adc8bf59 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -36,10 +36,10 @@ describeHost('project run command (host integration)', () => { beforeAll(async () => { spyGlobalSettings('run-integration'); fs.makeDir(TEMP_DIR); - jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') - .mockReturnValue(RUNTIME_DIR); if (!fs.exists(SHELL_PATH) || !fs.exists(RUNTIME_SO_PATH)) { + jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(RUNTIME_DIR); const hostEnv = createBoardEnv('host'); await hostEnv.buildHostRuntime(); } diff --git a/microcontroller/ports/host/comm.c b/microcontroller/ports/host/comm.c index 184bfc73..0f7916c9 100644 --- a/microcontroller/ports/host/comm.c +++ b/microcontroller/ports/host/comm.c @@ -12,7 +12,7 @@ static void comm_send(host_protocol_t protocol, char* payload) { snprintf((char*)(line + PROTO_SIZE), PAYLOAD_LEN_SIZE, "%04d", (int)strlen(payload)); line[HEADER_SIZE - 1] = ' '; strcpy((char*)(line + HEADER_SIZE), payload); - fprintf(stdout, line); + fprintf(stdout, "%s", line); fflush(stdout); } @@ -25,13 +25,13 @@ void bs_comm_send_error(char* message) { } void bs_comm_send_exectime(float time) { - char* timestr[16]; + char timestr[16]; snprintf(timestr, sizeof(timestr), "%.4f", time); comm_send(H_PROTOCOL_EXECTIME, timestr); } void bs_comm_send_loadtime(float time) { - char* timestr[16]; + char timestr[16]; snprintf(timestr, sizeof(timestr), "%.2f", time); comm_send(H_PROTOCOL_LOADTIME, timestr); } @@ -40,13 +40,13 @@ static void parse_line(char* line, host_protocol_t* protocol, char* payload) { char protocol_char[PROTO_SIZE]; protocol_char[0] = line[0]; protocol_char[1] = line[1]; - protocol_char[2] = NULL; + protocol_char[2] = '\0'; char payload_len_char[PAYLOAD_LEN_SIZE]; payload_len_char[0] = line[PROTO_SIZE + 0]; payload_len_char[1] = line[PROTO_SIZE + 1]; payload_len_char[2] = line[PROTO_SIZE + 2]; payload_len_char[3] = line[PROTO_SIZE + 3]; - payload_len_char[4] = NULL; + payload_len_char[4] = '\0'; *protocol = atoi(protocol_char); int payload_len = atoi(payload_len_char); for (int i = 0; i < payload_len; i++) { @@ -77,7 +77,7 @@ char* bs_comm_wait_receive(void (*on_load)(char* filename), void (*on_call)(char if (res == NULL) return NULL; - int protocol; + host_protocol_t protocol; char payload[MAX_PAYLOAD_SIZE] = {0}; parse_line(line, &protocol, payload); From b59ebadffc09fead87514f3d53c48c119721de53 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Tue, 30 Jun 2026 21:17:50 +0900 Subject: [PATCH 04/33] Refactor lang. --- cli/src/commands/board/remove.ts | 4 +- cli/src/platforms/board-env/common-env.ts | 11 +- cli/src/platforms/board-env/esp32-env.ts | 4 +- cli/src/platforms/board-env/host-env.ts | 4 +- cli/src/platforms/board-env/index.ts | 3 +- .../compiler/esp32-compiler-adapter.ts | 6 +- .../compiler/host-compiler-adapter.ts | 20 +- .../platforms/runtime/host-board-runtime.ts | 11 +- .../board-toolchain/board-toolchain.ts | 13 +- .../board-toolchain/esp32-toolchain.ts | 43 ++-- .../board-toolchain/host-toolchain.ts | 69 +++--- .../board-toolchain/tools/makefile.ts | 2 +- .../board-toolchain/tools/makefile2.ts | 97 +++++++++ lang/src/compiler/compiler-session.ts | 7 +- lang/src/compiler/package.ts | 199 ++++++++++++++++++ lang/src/compiler/project.ts | 175 +-------------- lang/src/compiler/transpiler-session.ts | 21 +- lang/src/index.ts | 7 +- .../__snapshots__/makefile.test.ts.snap | 177 ---------------- lang/tests/compiler/compiler-esp32.test.ts | 7 +- lang/tests/compiler/compiler-host.test.ts | 95 +++++---- lang/tests/compiler/makefile.test.ts | 43 ---- lang/tests/compiler/test-utils.ts | 19 +- microcontroller/ports/host/shell.c | 4 + 24 files changed, 497 insertions(+), 544 deletions(-) create mode 100644 lang/src/compiler/board-toolchain/tools/makefile2.ts create mode 100644 lang/src/compiler/package.ts delete mode 100644 lang/tests/compiler/__snapshots__/makefile.test.ts.snap delete mode 100644 lang/tests/compiler/makefile.test.ts diff --git a/cli/src/commands/board/remove.ts b/cli/src/commands/board/remove.ts index 2159d256..574b76a4 100644 --- a/cli/src/commands/board/remove.ts +++ b/cli/src/commands/board/remove.ts @@ -3,12 +3,12 @@ import inquirer from 'inquirer'; import { BoardName, isValidBoard } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; import { CommandHandler } from "../command"; -import { CommonBoardEnv, createBoardEnv } from "../../platforms/board-env"; +import { BoardEnv, createBoardEnv } from "../../platforms/board-env"; class RemoveHandler extends CommandHandler { boardName: BoardName; - boardEnv: CommonBoardEnv; + boardEnv: BoardEnv; constructor(boardName: BoardName) { super(); diff --git a/cli/src/platforms/board-env/common-env.ts b/cli/src/platforms/board-env/common-env.ts index 7432b5c4..cea7865e 100644 --- a/cli/src/platforms/board-env/common-env.ts +++ b/cli/src/platforms/board-env/common-env.ts @@ -3,7 +3,7 @@ import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from '../../config/constants'; -export class CommonBoardEnv { +export abstract class BoardEnv { get runtimeDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'microcontroller'); } @@ -25,9 +25,9 @@ export class CommonBoardEnv { } } - removeBoardRoot() {} + abstract removeBoardRoot(): void; - refreshBoardRoot() {} + abstract refreshBoardRoot(): void; async downloadBlueScriptRuntime() { if (fs.exists(this.runtimeDir)) { @@ -46,3 +46,8 @@ export class CommonBoardEnv { return currentVersion !== existingVersion; } } + +export class CommonBoardEnv extends BoardEnv { + removeBoardRoot(): void {} + refreshBoardRoot(): void {} +} diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 243064dc..6eaf8289 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -2,12 +2,12 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from "../../config/constants"; import { exec } from '../../core/shell'; -import { CommonBoardEnv } from './common-env'; +import { BoardEnv } from './common-env'; const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; -export abstract class Esp32Env extends CommonBoardEnv { +export abstract class Esp32Env extends BoardEnv { get espRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); } get idfDir() { return path.join(this.espRootDir, 'esp-idf'); } get idfExportShFile() { return path.join(this.idfDir, 'export.sh'); } diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 4e1b419b..ad9d2a3c 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -2,9 +2,9 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from '../../config/constants'; import { exec } from '../../core/shell'; -import { CommonBoardEnv } from './common-env'; +import { BoardEnv } from './common-env'; -export abstract class HostEnv extends CommonBoardEnv { +export abstract class HostEnv extends BoardEnv { get hostRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); } get buildDir() { return path.join(this.runtimeDir, 'ports/host/build'); } get builtinModuleCFile() { return path.join(this.runtimeDir, 'ports/host/std-module.c'); } diff --git a/cli/src/platforms/board-env/index.ts b/cli/src/platforms/board-env/index.ts index 685350a5..b9e3ac1b 100644 --- a/cli/src/platforms/board-env/index.ts +++ b/cli/src/platforms/board-env/index.ts @@ -1,6 +1,6 @@ import * as os from 'os'; import { Esp32Env, Esp32DarwinEnv, Esp32WindowsEnv } from './esp32-env'; -import { CommonBoardEnv } from './common-env'; +import { CommonBoardEnv, BoardEnv } from './common-env'; import { BoardName } from '../../config/board-utils'; import { HostEnv, HostDarwinEnv } from './host-env'; @@ -30,6 +30,7 @@ export function createBoardEnv(board: BoardName): BoardEnvMap[BoardName] { export { CommonBoardEnv, + BoardEnv, Esp32Env, Esp32DarwinEnv, Esp32WindowsEnv, diff --git a/cli/src/platforms/compiler/esp32-compiler-adapter.ts b/cli/src/platforms/compiler/esp32-compiler-adapter.ts index 3d4d3613..3470183d 100644 --- a/cli/src/platforms/compiler/esp32-compiler-adapter.ts +++ b/cli/src/platforms/compiler/esp32-compiler-adapter.ts @@ -3,7 +3,7 @@ import { ProjectConfigHandler, PROJECT_DEFAULT_PATHS } from "../../config/projec import { BoardName } from "../../config/board-utils"; import { CompilerSession, MemoryImage, MemoryLayout, - Esp32Toolchain, Esp32ToolchainConfig, ProjectForEsp32, PackageForEsp32 + Esp32Toolchain, Esp32ToolchainConfig, Project, PackageForEsp32 } from "@bscript/lang"; import { CompilerAdapter, CompileContext } from "./compiler-adapter"; import * as path from 'path'; @@ -19,7 +19,7 @@ const DUMMY_MEMORY_LAYOUT: MemoryLayout = { export class Esp32CompilerAdapter implements CompilerAdapter { readonly boardName: BoardName = 'esp32'; private boardConfig: Esp32BoardConfig; - private compiler?: CompilerSession; + private compiler?: CompilerSession; constructor( private globalConfigHandler: GlobalConfigHandler, @@ -41,7 +41,7 @@ export class Esp32CompilerAdapter implements CompilerAdapter { if (!memoryLayout) { throw new Error('Memory layout is required to build an ESP32 project.'); } - const project = ProjectForEsp32.load( + const project = Project.load( this.projectConfigHandler.getConfig().projectName, createEsp32PackageReader(this.boardName, this.projectConfigHandler), ); diff --git a/cli/src/platforms/compiler/host-compiler-adapter.ts b/cli/src/platforms/compiler/host-compiler-adapter.ts index 75a886b4..6dc20c9f 100644 --- a/cli/src/platforms/compiler/host-compiler-adapter.ts +++ b/cli/src/platforms/compiler/host-compiler-adapter.ts @@ -2,8 +2,8 @@ import { GlobalConfigHandler } from "../../config/global-config"; import { ProjectConfigHandler, PROJECT_DEFAULT_PATHS } from "../../config/project-config"; import { BoardName } from "../../config/board-utils"; import { - CompilerSession, SharedObject, - HostToolchain, ProjectForHost, Package + CompilerSession, SharedLibrary, + HostUnixToolchain, Project, PackageForHostUnix } from "@bscript/lang"; import { CompilerAdapter, CompileContext } from "./compiler-adapter"; import * as path from 'path'; @@ -11,7 +11,7 @@ import * as path from 'path'; export class HostCompilerAdapter implements CompilerAdapter { readonly boardName: BoardName = 'host'; - private compiler?: CompilerSession; + private compiler?: CompilerSession; constructor( private globalConfigHandler: GlobalConfigHandler, @@ -22,21 +22,21 @@ export class HostCompilerAdapter implements CompilerAdapter { } } - async buildForCheck(): Promise { + async buildForCheck(): Promise { return this.buildProject(); } - async buildProject(_context?: CompileContext): Promise { - const project = ProjectForHost.load( + async buildProject(_context?: CompileContext): Promise { + const project = Project.load( this.projectConfigHandler.getConfig().projectName, createHostPackageReader(this.boardName, this.projectConfigHandler), ); - const toolchain = new HostToolchain(this.getRuntimeDir()); + const toolchain = new HostUnixToolchain(this.getRuntimeDir()); this.compiler = new CompilerSession(toolchain); return this.compiler.buildProject(project); } - async compileFragment(src: string): Promise { + async compileFragment(src: string): Promise { if (!this.compiler) { throw new Error("Cannot compile fragment before building the project."); } @@ -56,7 +56,7 @@ export class HostCompilerAdapter implements CompilerAdapter { export function createHostPackageReader( _boardName: BoardName, projectConfigHandler: ProjectConfigHandler, -): (name: string) => Package { +): (name: string) => PackageForHostUnix { return (name: string) => { const mainRoot = projectConfigHandler.root; const subPackageRoot = path.join(mainRoot, PROJECT_DEFAULT_PATHS.PACKAGES_DIR, name); @@ -66,7 +66,7 @@ export function createHostPackageReader( const configHandler = isMain ? projectConfigHandler.asBoard('host') : ProjectConfigHandler.load(root).asBoard('host'); - return new Package( + return new PackageForHostUnix( name, { rootDir: root, diff --git a/cli/src/platforms/runtime/host-board-runtime.ts b/cli/src/platforms/runtime/host-board-runtime.ts index 83c2000c..a4e66461 100644 --- a/cli/src/platforms/runtime/host-board-runtime.ts +++ b/cli/src/platforms/runtime/host-board-runtime.ts @@ -1,6 +1,5 @@ import * as path from 'path'; -import { exec } from '../../core/shell'; -import { SharedObject } from "@bscript/lang"; +import { SharedLibrary } from "@bscript/lang"; import { ProgramOutput } from "../../core/logger/program-output"; import { BoardRuntime } from "./board-runtime"; import { CompileContext } from "../compiler/compiler-adapter"; @@ -8,7 +7,7 @@ import { HostBoardConfig } from "../../config/global-config"; import { HostService, ProcessConnection } from '../../services/process'; -export class HostBoardRuntime implements BoardRuntime { +export class HostBoardRuntime implements BoardRuntime { private programOutput: ProgramOutput; private shellProcess: ProcessConnection; private hostService: HostService; @@ -46,11 +45,11 @@ export class HostBoardRuntime implements BoardRuntime { return {}; } - async load(output: SharedObject): Promise { - return this.hostService.load(output.soFile); + async load(output: SharedLibrary): Promise { + return this.hostService.load(output.filePath); } - async execute(output: SharedObject): Promise { + async execute(output: SharedLibrary): Promise { let exectime = 0; for (const entry of output.entryNames) { exectime += await this.hostService.execute(entry.name); diff --git a/lang/src/compiler/board-toolchain/board-toolchain.ts b/lang/src/compiler/board-toolchain/board-toolchain.ts index de564456..8ed4ba5b 100644 --- a/lang/src/compiler/board-toolchain/board-toolchain.ts +++ b/lang/src/compiler/board-toolchain/board-toolchain.ts @@ -1,4 +1,5 @@ import { Project } from '../project'; +import { Package } from '../package'; export type MemoryLayout = { iram:{address:number, size:number}, @@ -38,16 +39,16 @@ export type MemoryImage = { entryPoints: {isMain: boolean, address: number}[] } -export type SharedObject = { - soFile: string, +export type SharedLibrary = { + filePath: string, entryNames: { isMain: boolean, name: string}[], }; -export type CompileOutput = MemoryImage | SharedObject; +export type CompileOutput = MemoryImage | SharedLibrary; -export interface BoardToolchain

{ +export interface BoardToolchain

{ get cProlog(): string; get builtinModulePath(): string; - compileAndLink(project: P, entryPoints: string[]): Promise; - additionalCompileAndLink(project: P, entryPoints: string[]): Promise; + compileAndLink(project: Project

, entryPoints: string[]): Promise; + additionalCompileAndLink(project: Project, entryPoints: string[]): Promise; } \ No newline at end of file diff --git a/lang/src/compiler/board-toolchain/esp32-toolchain.ts b/lang/src/compiler/board-toolchain/esp32-toolchain.ts index 40d3789a..07f55afd 100644 --- a/lang/src/compiler/board-toolchain/esp32-toolchain.ts +++ b/lang/src/compiler/board-toolchain/esp32-toolchain.ts @@ -1,9 +1,10 @@ import * as path from "path"; import * as fs from "fs"; -import { PackageForEsp32, ProjectForEsp32 } from "../project"; +import { PackageForEsp32 } from "../package"; +import { Project } from "../project"; import { BoardToolchain, MemoryImage, MemoryLayout, ShadowMemory } from "./board-toolchain"; import { executeCommand, getErrorMessage } from "../utils"; -import { generateMakefile, esp32MakefilePreset } from "./tools/makefile"; +import { generateMakefile, esp32MakefilePreset } from "./tools/makefile2"; import { ElfReader } from "./tools/elf-reader"; import generateLinkerScript from "./tools/linker-script"; @@ -14,7 +15,7 @@ export type Esp32ToolchainConfig = { espDir: string } -export class Esp32Toolchain implements BoardToolchain { +export class Esp32Toolchain implements BoardToolchain { public memory: ShadowMemory; private config: Esp32ToolchainConfig; @@ -42,31 +43,31 @@ export class Esp32Toolchain implements BoardToolchain [s.name, s])); } - async compileAndLink(project: ProjectForEsp32, entryPoints: string[]): Promise { + async compileAndLink(project: Project, entryPoints: string[]): Promise { for (const pkg of project.usedDependencies) { - await this.compileC(project, pkg); + await this.compilePackage(pkg); this.compiledPackages.add(pkg.name); } - await this.compileC(project, project.mainPackage); + await this.compilePackage(project.mainPackage); const elfPath = await this.link(project, entryPoints); return this.extractBinary(elfPath, entryPoints); } - async additionalCompileAndLink(project: ProjectForEsp32, entryPoints: string[]): Promise { + async additionalCompileAndLink(project: Project, entryPoints: string[]): Promise { for (const pkg of project.usedDependencies) { if (!this.compiledPackages.has(pkg.name)) { - await this.compileC(project, pkg); + await this.compilePackage(pkg); this.compiledPackages.add(pkg.name); } } - await this.compileC(project, project.mainPackage); + await this.compilePackage(project.mainPackage); const elfPath = await this.link(project, entryPoints); return this.extractBinary(elfPath, entryPoints); } - private async compileC(project: ProjectForEsp32, pkg: PackageForEsp32): Promise { + private async compilePackage(pkg: PackageForEsp32): Promise { try { - const archivePath = project.archiveFile(pkg); + const archivePath = pkg.archiveFile; const includeDirs = [ ...this.espIdfComponents.getIncludeDirs(pkg.espIdfComponents), ...this.espIdfComponents.commonIncludeDirs @@ -77,21 +78,21 @@ export class Esp32Toolchain implements BoardToolchain { + private async link(project: Project, entryPoints: string[]): Promise { try { const cwd = process.cwd(); - const elfPath = project.elfFile(); + const elfPath = project.mainPackage.elfFile; const archives = this.getArchivesWithEspComponents(project); const linkerscript = generateLinkerScript( @@ -102,7 +103,7 @@ export class Esp32Toolchain implements BoardToolchain): string[] { const espArchivesFromMain = this.espIdfComponents.getArchiveFilePaths(project.mainPackage.espIdfComponents); - const resultArchives = [project.archiveFile(project.mainPackage), ...espArchivesFromMain]; + const resultArchives = [project.mainPackage.archiveFile, ...espArchivesFromMain]; const visitedEspArchives = new Set(espArchivesFromMain); @@ -157,7 +158,7 @@ export class Esp32Toolchain implements BoardToolchain addEspArchive(ar)); } diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 7f7cd957..5d3e0759 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -1,16 +1,17 @@ import * as path from "path"; import * as fs from "fs"; -import { BoardToolchain, SharedObject } from "./board-toolchain"; -import { Package, ProjectForHost } from "../project"; -import { generateMakefile, hostMakefilePreset } from "./tools/makefile"; +import { BoardToolchain, SharedLibrary } from "./board-toolchain"; +import { Project } from "../project"; +import { Package, PackageForHostUnix } from "../package"; +import { generateMakefile, hostUnixMakefilePrest } from "./tools/makefile2"; import { executeCommand, getErrorMessage } from "../utils"; -export class HostToolchain implements BoardToolchain { - private runtimeDir: string; - private compileId: number = 0; - private compiledPackages = new Set(); - private generatedSoFiles: string[] = []; +export abstract class HostToolchain

implements BoardToolchain { + protected runtimeDir: string; + protected compileId: number = 0; + protected compiledPackages = new Set(); + protected generatedSharedLibs: string[] = []; constructor(runtimeDir: string) { this.runtimeDir = runtimeDir; @@ -28,51 +29,55 @@ export class HostToolchain implements BoardToolchain { + async compileAndLink(project: Project

, entryPoints: string[]): Promise { const archiveFiles: string[] = []; for (const pkg of project.usedDependencies) { - archiveFiles.push(await this.compilePackage(project, pkg)); + archiveFiles.push(await this.compilePackage(pkg)); this.compiledPackages.add(pkg.name); } - archiveFiles.push(await this.compilePackage(project, project.mainPackage)); - const soFile = project.soFile(); - await this.link(archiveFiles, entryPoints, soFile); - this.generatedSoFiles.push(soFile); + archiveFiles.push(await this.compilePackage(project.mainPackage)); + const sharedLib = await this.link(project, archiveFiles, entryPoints); + this.generatedSharedLibs.push(sharedLib); return { - soFile, + filePath: sharedLib, entryNames: entryPoints.map(name => ({isMain: name === project.mainPackage.name, name})), } } - async additionalCompileAndLink(project: ProjectForHost, entryPoints: string[]): Promise { + async additionalCompileAndLink(project: Project

, entryPoints: string[]): Promise { const archiveFiles: string[] = []; for (const pkg of project.usedDependencies) { if (!this.compiledPackages.has(pkg.name)) { - archiveFiles.push(await this.compilePackage(project, pkg)); + archiveFiles.push(await this.compilePackage(pkg)); this.compiledPackages.add(pkg.name); } } - archiveFiles.push(await this.compilePackage(project, project.mainPackage)); - const soFile = project.soFile(this.compileId++); - await this.link(archiveFiles, entryPoints, soFile); - this.generatedSoFiles.push(soFile); + archiveFiles.push(await this.compilePackage(project.mainPackage)); + const sharedLib = await this.link(project, archiveFiles, entryPoints); + this.generatedSharedLibs.push(sharedLib); return { - soFile, + filePath: sharedLib, entryNames: entryPoints.map(name => ({isMain: name === project.mainPackage.name, name})), } } - private async compilePackage(project: ProjectForHost, pkg: Package): Promise { + abstract compilePackage(pkg: P): Promise; + abstract link(project: Project

, archiveFiles: string[], entryPoints: string[]): Promise; +} + +export class HostUnixToolchain extends HostToolchain { + async compilePackage(pkg: PackageForHostUnix): Promise { try { - const archiveFile = project.archiveFile(pkg); + const archiveFile = pkg.archiveFile; // Remove old archive file. if (fs.existsSync(archiveFile)) { fs.rmSync(archiveFile, { force: true }); } - const makefile = generateMakefile(hostMakefilePreset(pkg, archiveFile)); - project.writeMakefile(pkg, makefile); + pkg.copyNativeFilesToDist(); + const makefile = generateMakefile(hostUnixMakefilePrest(pkg)); + pkg.writeMakefile(makefile); await executeCommand('make', [], pkg.resolvedDistDir); return archiveFile; } catch (error) { @@ -80,25 +85,23 @@ export class HostToolchain implements BoardToolchain { + async link(project: Project, archiveFiles: string[], entryPoints: string[]): Promise { try { const keepEntrySymbols = entryPoints.map( - (sym) => `-Wl,-u,${this.linkerSymbolName(sym)}`, + (sym) => `-Wl,-u,_${sym}`, ); + const outputFile = project.mainPackage.soFile(this.compileId++); const args = [ '-shared', '-fPIC', '-o', outputFile, ...archiveFiles, - ...this.generatedSoFiles, + ...this.generatedSharedLibs, this.runtimeSo, '-lm', '-ldl', ...keepEntrySymbols, ]; await executeCommand('cc', args); + return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, {cause: error}); } diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index 6f6b504a..2e0a7554 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -1,4 +1,4 @@ -import { Package } from "../../project"; +import { Package } from "../../package"; type MakefileConfig = { diff --git a/lang/src/compiler/board-toolchain/tools/makefile2.ts b/lang/src/compiler/board-toolchain/tools/makefile2.ts new file mode 100644 index 00000000..cb7c5275 --- /dev/null +++ b/lang/src/compiler/board-toolchain/tools/makefile2.ts @@ -0,0 +1,97 @@ +import { PackageForEsp32, PackageForHostUnix } from "../../package" + +type MakefileConfig = { + outputFile: string, + objectFiles: string[], + headerFilesInDist: string[], + includeDirs: string[], + compileFlags: string[], + distDir: string, + buildDir: string, + toolchain: { + cc: string, + ar: string + } +} + +export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], toolchainDir: string): MakefileConfig { + return { + outputFile: pkg.archiveFile, + objectFiles: pkg.objectFiles, + headerFilesInDist: pkg.headerFilesInDist, + includeDirs: [pkg.distDir, ...includeDirs], + compileFlags: [ + '-O2', '-w', '-fno-common', + '-ffunction-sections', '-fdata-sections', + '-mtext-section-literals', '-mlongcalls', + '-fno-zero-initialized-in-bss', + ], + distDir: pkg.resolvedDistDir, + buildDir: pkg.resolvedBuildDir, + toolchain: { + cc: `${toolchainDir}/xtensa-esp32-elf-gcc`, + ar: `${toolchainDir}/xtensa-esp32-elf-ar` + } + } +} + +export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { + return { + outputFile: pkg.archiveFile, + objectFiles: pkg.objectFiles, + headerFilesInDist: pkg.headerFilesInDist, + includeDirs: [pkg.resolvedDistDir], + compileFlags: ['-O2', '-w', '-fPIC', '-DLINUX64'], + distDir: pkg.resolvedDistDir, + buildDir: pkg.resolvedBuildDir, + toolchain: { + cc: `cc`, + ar: `ar` + } + } +} + +export function generateMakefile(config: MakefileConfig) { + return ` + +# === Variable settings === +CC := ${config.toolchain.cc} +AR := ${config.toolchain.ar} +DIST_DIR := ${config.distDir} +BUILD_DIR := ${config.buildDir} +TARGET := ${config.outputFile} +OBJECTS := ${config.objectFiles.join(' ')} +DIST_HEADERS := ${config.headerFilesInDist} +INCLUDES := ${config.includeDirs.map(path => `-I ${path}`).join(' ')} +CFLAGS := $(INCLUDES) ${config.compileFlags.join(' ')} + + +.PHONY: all +all: $(TARGET) + +# Build rules +# -------------------------------------------------------- + +$(TARGET): $(OBJECTS) | $(DIST_HEADERS) +\t@echo "Archiving library: $@" +\t@mkdir -p $(@D) +\t$(AR) rcs $@ $^ + +vpath %.c $(DIST_DIR) + +$(BUILD_DIR)/%.o: $(DIST_DIR)/%.c +\t@echo "Compiling: $< -> $@" +\t@mkdir -p $(@D) +\t$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ + +-include $(wildcard $(BUILD_DIR)/*.d); + +# -------------------------------------------------------- + +.PHONY: clean +clean: +\t@echo "Cleaning dist directory..." +\t@rm -rf $(DIST_DIR) + + ` +} \ No newline at end of file diff --git a/lang/src/compiler/compiler-session.ts b/lang/src/compiler/compiler-session.ts index 532edd91..ea0d9d8b 100644 --- a/lang/src/compiler/compiler-session.ts +++ b/lang/src/compiler/compiler-session.ts @@ -1,18 +1,19 @@ import { BoardToolchain, CompileOutput } from "./board-toolchain/board-toolchain"; +import { Package } from "./package"; import { Project } from "./project"; import { TranspilerSession } from "./transpiler-session"; -export class CompilerSession

{ +export class CompilerSession

{ private transpiler: TranspilerSession; private toolchain: BoardToolchain; - private project: P | null = null; + private project: Project

| null = null; constructor(toolchain: BoardToolchain) { this.transpiler = new TranspilerSession(toolchain.builtinModulePath, toolchain.cProlog); this.toolchain = toolchain; } - public async buildProject(project: P): Promise { + public async buildProject(project: Project

): Promise { this.project = project; project.check(); diff --git a/lang/src/compiler/package.ts b/lang/src/compiler/package.ts new file mode 100644 index 00000000..e8b26231 --- /dev/null +++ b/lang/src/compiler/package.ts @@ -0,0 +1,199 @@ +import * as fs from "fs"; +import * as path from "path"; + + +type RelativePath = string; +type AbsolutePath = string; + +export class Package { + readonly name: string; + readonly rootDir: AbsolutePath; + readonly entry: RelativePath; + readonly sourceDir: RelativePath; + readonly distDir: RelativePath; + readonly buildDir: RelativePath; + readonly packageDir: RelativePath; + readonly dependencies: string[]; + + get resolvedEntry(): AbsolutePath { return path.join(this.rootDir, this.entry); } + get resolvedSourceDir(): AbsolutePath { return path.join(this.rootDir, this.sourceDir); } + get resolvedDistDir(): AbsolutePath { return path.join(this.rootDir, this.distDir); } + get resolvedBuildDir(): AbsolutePath { return path.join(this.rootDir, this.buildDir); } + get resolvedPackageDir(): AbsolutePath { return path.join(this.rootDir, this.packageDir); } + get archiveFile(): AbsolutePath { return path.join(this.resolvedBuildDir, `lib${this.name}.a`); } + get objectFiles(): AbsolutePath[] { + const objects: AbsolutePath[] = []; + this.walkFiles(this.resolvedDistDir, (name, fullPath) => { + if (fullPath.endsWith('.c')) { + objects.push(this.toObjectFile(fullPath)); + } + }, [this.resolvedBuildDir]); + return objects; + } + get headerFilesInDist(): AbsolutePath[] { + const headers: AbsolutePath[] = []; + this.walkFiles(this.resolvedDistDir, (name, fullPath) => { + if (fullPath.endsWith('.h')) { + headers.push(fullPath); + } + }, [this.resolvedBuildDir]); + return headers; + } + + constructor( + name: string, + path: { + rootDir: AbsolutePath, + entry: RelativePath, + sourceDir: RelativePath, + distDir: RelativePath, + buildDir: RelativePath, + packageDir: RelativePath, + }, + dependencies: string[], + ) { + this.name = name; + this.dependencies = dependencies; + this.rootDir = path.rootDir; + this.sourceDir = path.sourceDir; + this.entry = path.entry; + this.distDir = path.distDir; + this.buildDir = path.buildDir; + this.packageDir = path.packageDir; + } + + check() { + const invalidBsFilePattern = /^\d+\.bs$/; + const invalidCFilePattern = /^bs_.*\.c$/; + if (!fs.existsSync(this.sourceDir)) { + return; + } + this.walkFiles(this.resolvedSourceDir, (name, fullPath) => { + if (invalidBsFilePattern.test(name)) { + throw new Error( + `Invalid file name: ${fullPath}\n` + + `BlueScript source file names cannot consist solely of digits.` + ); + } + if (invalidCFilePattern.test(name)) { + throw new Error( + `Invalid file name: ${fullPath}\n` + + `You cannot use 'bs_' prefix for C source file names.` + ); + } + }, [this.resolvedDistDir, this.packageDir]); + } + + copyNativeFilesToDist() { + this.walkFiles(this.resolvedSourceDir, (name, fullPath) => { + if (name.endsWith('.c') || name.endsWith('.h')) { + const dest = this.replacePrefix(this.resolvedSourceDir, this.resolvedDistDir, fullPath); + fs.cpSync(fullPath, dest); + } + }, [this.resolvedDistDir, this.packageDir]); + } + + clean(): void { + fs.rmSync(this.resolvedDistDir, { recursive: true, force: true }); + } + + readSourceFile(p: RelativePath): string { + const filePath = path.join(this.rootDir, p); + try { + return fs.readFileSync(filePath).toString('utf-8'); + } + catch (e) { + throw new Error(`Cannot find a module ${filePath} in ${this.name}`); + } + } + + writeCFile(srcPath: RelativePath, data: string) { + const parsed = path.parse(srcPath); + const cRelativePath = path.join(parsed.dir, `bs_${parsed.name}.c`); + const filePath = path.join(this.resolvedDistDir, cRelativePath); + const cDir = path.dirname(filePath); + fs.mkdirSync(cDir, { recursive: true }); + fs.writeFileSync(filePath, data); + } + + writeMakefile(data: string) { + const filePath = path.join(this.resolvedDistDir, 'Makefile'); + fs.writeFileSync(filePath, data); + return filePath; + } + + protected walkFiles(dir: string, handler: (name: string, fullPath: string) => void, ignorDirs?: string[]) { + for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { + const fullPath = path.join(dir, entry.name); + if (entry.isDirectory()) { + if (ignorDirs?.includes(fullPath)) { + continue; + } + this.walkFiles(fullPath, handler, ignorDirs); + } else if (entry.isFile()) { + handler(entry.name, fullPath); + } + } + } + + private toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { + const source = cFileInDist; + const dist = this.resolvedDistDir; + const prefix = dist.endsWith("/") ? dist : dist + "/"; + if (!source.startsWith(prefix) || !source.endsWith(".c")) { + throw new Error(`Invalid dist source: ${source}`); + } + const relative = source.slice(prefix.length, -2); // remove ".c" + return path.join(this.resolvedBuildDir, `${relative}.o`); + } + + protected replacePrefix(fromDir: AbsolutePath, toDir: AbsolutePath, filePath: AbsolutePath): string { + if (filePath === fromDir) return toDir; + const prefix = filePath.endsWith("/") ? fromDir : fromDir + "/"; + if (!filePath.startsWith(prefix)) { + throw new Error(`Path ${filePath} is not under ${fromDir}`); + } + return toDir + "/" + filePath.slice(prefix.length); + } +} + +export class PackageForEsp32 extends Package { + public readonly espIdfComponents: string[]; + + constructor( + name: string, + path: { + rootDir: AbsolutePath, + entry: RelativePath, + sourceDir: RelativePath, + distDir: RelativePath, + buildDir: RelativePath, + packageDir: RelativePath, + }, + dependencies: string[], + espIdfComponents: string[], + ) { + super(name, path, dependencies); + this.espIdfComponents = espIdfComponents; + } + + get elfFile(): AbsolutePath { + return path.join(this.resolvedBuildDir, `${this.name}.elf`); + } + + writeLinkerScript(data: string) { + const filePath = path.join(this.resolvedBuildDir, "linkerscript.ld"); + fs.writeFileSync(filePath, data); + return filePath; + } +} + +export class PackageForHostUnix extends Package { + soFile(id?: number): AbsolutePath { + return path.join( + this.resolvedBuildDir, + `${this.name}${id ?? ''}.so` + ); + } +} + diff --git a/lang/src/compiler/project.ts b/lang/src/compiler/project.ts index 78224c56..3dd63447 100644 --- a/lang/src/compiler/project.ts +++ b/lang/src/compiler/project.ts @@ -1,70 +1,6 @@ -import * as fs from "fs"; -import * as path from "path"; +import { Package } from "./package"; -export type RelativePath = string; -export type AbsolutePath = string; - -export class Package { - public readonly name: string; - public readonly rootDir: AbsolutePath; - public readonly entry: RelativePath; - public readonly sourceDir: RelativePath; - public readonly distDir: RelativePath; - public readonly buildDir: RelativePath; - public readonly packageDir: RelativePath; - public readonly dependencies: string[]; - - public get resolvedEntry(): AbsolutePath { return path.join(this.rootDir, this.entry); } - public get resolvedSourceDir(): AbsolutePath { return path.join(this.rootDir, this.sourceDir); } - public get resolvedDistDir(): AbsolutePath { return path.join(this.rootDir, this.distDir); } - public get resolvedBuildDir(): AbsolutePath { return path.join(this.rootDir, this.buildDir); } - public get resolvedPackageDir(): AbsolutePath { return path.join(this.rootDir, this.packageDir); } - - constructor( - name: string, - path: { - rootDir: AbsolutePath, - entry: RelativePath, - sourceDir: RelativePath, - distDir: RelativePath, - buildDir: RelativePath, - packageDir: RelativePath, - }, - dependencies: string[], - ) { - this.name = name; - this.dependencies = dependencies; - this.rootDir = path.rootDir; - this.sourceDir = path.sourceDir; - this.entry = path.entry; - this.distDir = path.distDir; - this.buildDir = path.buildDir; - this.packageDir = path.packageDir; - } -} - -export class PackageForEsp32 extends Package { - public readonly espIdfComponents: string[]; - - constructor( - name: string, - path: { - rootDir: AbsolutePath, - entry: RelativePath, - sourceDir: RelativePath, - distDir: RelativePath, - buildDir: RelativePath, - packageDir: RelativePath, - }, - dependencies: string[], - espIdfComponents: string[], - ) { - super(name, path, dependencies); - this.espIdfComponents = espIdfComponents; - } -} - export class Project

{ public readonly mainPackage: P; public readonly dependencies: Map; @@ -79,7 +15,7 @@ export class Project

{ return [...this.usedDependenciesMap.values()]; } - protected static loadHelper

( + static load

( mainPackageName: string, packageReader: (name: string) => P ) { @@ -104,58 +40,15 @@ export class Project

{ return new Project

(mainPackage, dependencies); } - check() { - const invalidFilePattern = /^\d+\.bs$/; - if (!fs.existsSync(this.mainPackage.sourceDir)) { - return; - } - const files = fs.readdirSync(this.mainPackage.resolvedSourceDir); - - for (const file of files) { - if (invalidFilePattern.test(file)) { - const fullPath = path.join(this.mainPackage.resolvedSourceDir, file); - throw new Error( - `Invalid file name: ${fullPath}\n` + - `BlueScript source file names cannot consist solely of digits.` - ); - } - } - } - - clean() { - this.cleanDistDir(this.mainPackage); + clean() { + this.mainPackage.clean(); for (const dep of this.dependencies.values()) { - this.cleanDistDir(dep); - } - } - - private cleanDistDir(pkg: P): void { - fs.rmSync(pkg.resolvedDistDir, { recursive: true, force: true }); - } - - readSourceFile(pkg: P, relativePath: RelativePath): string { - const filePath = path.join(pkg.rootDir, relativePath); - try { - return fs.readFileSync(filePath).toString('utf-8'); + dep.clean(); } - catch (e) { - throw new Error(`Cannot find a module ${filePath} in ${pkg.name}`); - } - } - - writeCFile(pkg: P, relativeSourceFilePath: RelativePath, data: string) { - const parsed = path.parse(relativeSourceFilePath); - const cRelativePath = path.join(parsed.dir, `bs_${parsed.name}.c`); - const filePath = path.join(pkg.resolvedDistDir, cRelativePath); - const cDir = path.dirname(filePath); - fs.mkdirSync(cDir, { recursive: true }); - fs.writeFileSync(filePath, data); } - writeMakefile(pkg: P, data: string) { - const filePath = path.join(pkg.resolvedDistDir, 'Makefile'); - fs.writeFileSync(filePath, data); - return filePath; + check() { + this.mainPackage.check(); } addUsedDependency(pkg: P) { @@ -163,58 +56,4 @@ export class Project

{ this.usedDependenciesMap.set(pkg.name, pkg); } } - - archiveFile(pkg: Package): AbsolutePath { - return path.join(pkg.resolvedBuildDir, `lib${pkg.name}.a`); - } -} - - -export class ProjectForEsp32 extends Project { - private constructor(mainPackage: PackageForEsp32, dependencies: Map) { - super(mainPackage, dependencies); - } - - public static load( - mainPackageName: string, - packageReader: (name: string) => PackageForEsp32, - ): ProjectForEsp32 { - const project = Project.loadHelper(mainPackageName, packageReader); - return new ProjectForEsp32(project.mainPackage, project.dependencies); - } - - writeLinkerScript(data: string) { - const filePath = path.join(this.mainPackage.resolvedBuildDir, "linkerscript.ld"); - fs.writeFileSync(filePath, data); - return filePath; - } - - elfFile(): AbsolutePath { - return path.join( - this.mainPackage.resolvedBuildDir, - `${this.mainPackage.name}.elf` - ); - } } - - -export class ProjectForHost extends Project { - private constructor(mainPackage: Package, dependencies: Map) { - super(mainPackage, dependencies); - } - - public static load( - mainPackageName: string, - packageReader: (name: string) => Package, - ): ProjectForHost { - const project = Project.loadHelper(mainPackageName, packageReader); - return new ProjectForHost(project.mainPackage, project.dependencies); - } - - soFile(id?: number): AbsolutePath { - return path.join( - this.mainPackage.resolvedBuildDir, - `${this.mainPackage.name}${id ?? ''}.so` - ); - } -} \ No newline at end of file diff --git a/lang/src/compiler/transpiler-session.ts b/lang/src/compiler/transpiler-session.ts index 02eb1bfa..502a3bac 100644 --- a/lang/src/compiler/transpiler-session.ts +++ b/lang/src/compiler/transpiler-session.ts @@ -2,28 +2,29 @@ import { GlobalVariableNameTable } from "../transpiler/code-generator/variables" import { transpile } from "../transpiler/code-generator/code-generator"; import * as fs from "fs"; import * as path from "path"; -import { AbsolutePath, RelativePath, Package, Project } from "./project"; +import { Package } from "./package"; +import { Project } from "./project"; class PathInPkg { public pkg: Package; - public relativePath: RelativePath; - public absolutePath: AbsolutePath; + public relativePath: string; + public absolutePath: string; - constructor(pkg: Package, relativePath: RelativePath) { + constructor(pkg: Package, relativePath: string) { this.pkg = pkg; this.checkRelativePath(relativePath); this.relativePath = relativePath; this.absolutePath = path.join(pkg.rootDir, this.relativePath); } - public resolve(targetRelativePath: RelativePath): PathInPkg { + public resolve(targetRelativePath: string): PathInPkg { const currentDir = path.dirname(this.relativePath); const resolvedRelativePath = path.join(currentDir, targetRelativePath); return new PathInPkg(this.pkg, resolvedRelativePath); } - private checkRelativePath(relativePath: RelativePath) { + private checkRelativePath(relativePath: string) { // check if the relative path is under the source dir const absolutePath = path.join(this.pkg.rootDir, relativePath); if (!absolutePath.startsWith(this.pkg.resolvedSourceDir)) { @@ -49,7 +50,7 @@ export class TranspilerSession { public transpile(project: Project): string[] { let entryPath: PathInPkg = new PathInPkg(project.mainPackage, project.mainPackage.entry); - const src = project.readSourceFile(entryPath.pkg, entryPath.relativePath); + const src = entryPath.pkg.readSourceFile(entryPath.relativePath); return this.transpileHelper(project, entryPath, src); } @@ -67,7 +68,7 @@ export class TranspilerSession { this.globalNames, this.makeImporter(entryPath, entryPoints, project) ); - project.writeCFile(entryPath.pkg, entryPath.relativePath, this.cProlog + result.code); + entryPath.pkg.writeCFile(entryPath.relativePath, this.cProlog + result.code); this.globalNames = result.names; entryPoints.push(result.main); return entryPoints; @@ -81,7 +82,7 @@ export class TranspilerSession { if (mod) return mod; else { - const src = project.readSourceFile(newPath.pkg, newPath.relativePath); + const src = newPath.pkg.readSourceFile(newPath.relativePath); const result = transpile( this.sessionId++, src, @@ -91,7 +92,7 @@ export class TranspilerSession { ); this.modules.set(newPath.absolutePath, result.names); entryPoints.push(result.main); - project.writeCFile(newPath.pkg, newPath.relativePath, this.cProlog + result.code); + newPath.pkg.writeCFile(newPath.relativePath, this.cProlog + result.code); return result.names; } } diff --git a/lang/src/index.ts b/lang/src/index.ts index c4e5ad9f..0eac844e 100644 --- a/lang/src/index.ts +++ b/lang/src/index.ts @@ -1,6 +1,7 @@ export { ErrorLog as CompileError } from './transpiler/utils'; export { CompilerSession } from './compiler/compiler-session'; -export { Package, PackageForEsp32, Project, ProjectForEsp32, ProjectForHost } from './compiler/project'; +export { Project } from './compiler/project'; +export { Package, PackageForEsp32, PackageForHostUnix } from './compiler/package'; export { Esp32Toolchain, Esp32ToolchainConfig } from './compiler/board-toolchain/esp32-toolchain'; -export { HostToolchain } from './compiler/board-toolchain/host-toolchain'; -export { MemoryLayout, MemoryImage, CompileOutput, SharedObject } from './compiler/board-toolchain/board-toolchain'; \ No newline at end of file +export { HostToolchain, HostUnixToolchain } from './compiler/board-toolchain/host-toolchain'; +export { MemoryLayout, MemoryImage, CompileOutput, SharedLibrary } from './compiler/board-toolchain/board-toolchain'; \ No newline at end of file diff --git a/lang/tests/compiler/__snapshots__/makefile.test.ts.snap b/lang/tests/compiler/__snapshots__/makefile.test.ts.snap deleted file mode 100644 index 31635675..00000000 --- a/lang/tests/compiler/__snapshots__/makefile.test.ts.snap +++ /dev/null @@ -1,177 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`generateMakefile generates makefile for esp32 archive file. 1`] = ` -"# === Basic settings === -CC := /opt/esp-toolchain/xtensa-esp32-elf-gcc -AR := /opt/esp-toolchain/xtensa-esp32-elf-ar - -# === Directory settings === -SRC_DIR := /project/myapp/src -DIST_DIR := /project/myapp/dist -BUILD_DIR := /project/myapp/dist/build -PACKAGES_DIR := /project/myapp/packages - -TARGET := /project/myapp/dist/build/libmyapp.a - -# === Check for illegal file name prefixes === -ILLEGAL_PREFIX_FILES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "bs_*.c" -print) -ifneq ($(ILLEGAL_PREFIX_FILES),) - $(error ERROR: You cannot use 'bs_' prefix for C source file names. Please remove or rename the following files: \\ - $(ILLEGAL_PREFIX_FILES)) -endif - -# === Source and object file settings === -ORIG_SOURCES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.c" -print) -ORIG_HEADERS := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.h" -print) -DIST_SOURCES := $(foreach src,$(ORIG_SOURCES), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)) \\ -) -DIST_HEADERS := $(foreach hdr,$(ORIG_HEADERS), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)) \\ -) -DIST_SOURCES += $(shell find $(DIST_DIR) -path $(BUILD_DIR) -prune -o -type f -name "bs_*.c" -print) -OBJECTS := $(patsubst $(DIST_DIR)/%.c, $(BUILD_DIR)/%.o, $(DIST_SOURCES)) - -# === Compilation settings === -INCLUDES := -I $(DIST_DIR) -I $(SRC_DIR) -I /opt/esp-idf/components/freertos/include -I /opt/esp-idf/components/esp_common/include -CFLAGS := $(INCLUDES) -O2 -w -fno-common -ffunction-sections -fdata-sections -mtext-section-literals -mlongcalls -fno-zero-initialized-in-bss - -# ==================================================================== -.PHONY: all - -all: $(TARGET) - -# Copy rules -# -------------------------------------------------------- - -define COPY_RULE_TEMPLATE -$(1): $(2) - @echo "Copying $$< to $$@" - @mkdir -p $$(dir $$@) - @cp $$< $$@ -endef - -$(foreach src,$(ORIG_SOURCES), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)), \\ - $(src) \\ - )) \\ -) - -$(foreach hdr,$(ORIG_HEADERS), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)), \\ - $(hdr) \\ - )) \\ -) - -# Build rules -# -------------------------------------------------------- - -$(TARGET): $(OBJECTS) | $(DIST_HEADERS) - @echo "Archiving library: $@" - @mkdir -p $(@D) - $(AR) rcs $@ $^ - -vpath %.c $(DIST_DIR) - -$(BUILD_DIR)/%.o: $(DIST_DIR)/%.c - @echo "Compiling: $< -> $@" - @mkdir -p $(@D) - $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ - --include $(wildcard $(BUILD_DIR)/*.d) - -.PHONY: clean -clean: - @echo "Cleaning dist directory..." - @rm -rf $(DIST_DIR)" -`; - -exports[`generateMakefile generates makefile for host shared library. 1`] = ` -"# === Basic settings === -CC := cc -AR := ar - -# === Directory settings === -SRC_DIR := /project/myapp/src -DIST_DIR := /project/myapp/dist -BUILD_DIR := /project/myapp/dist/build -PACKAGES_DIR := /project/myapp/packages - -TARGET := /project/myapp/dist/build/libmyapp.a - -# === Check for illegal file name prefixes === -ILLEGAL_PREFIX_FILES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "bs_*.c" -print) -ifneq ($(ILLEGAL_PREFIX_FILES),) - $(error ERROR: You cannot use 'bs_' prefix for C source file names. Please remove or rename the following files: \\ - $(ILLEGAL_PREFIX_FILES)) -endif - -# === Source and object file settings === -ORIG_SOURCES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.c" -print) -ORIG_HEADERS := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.h" -print) -DIST_SOURCES := $(foreach src,$(ORIG_SOURCES), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)) \\ -) -DIST_HEADERS := $(foreach hdr,$(ORIG_HEADERS), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)) \\ -) -DIST_SOURCES += $(shell find $(DIST_DIR) -path $(BUILD_DIR) -prune -o -type f -name "bs_*.c" -print) -OBJECTS := $(patsubst $(DIST_DIR)/%.c, $(BUILD_DIR)/%.o, $(DIST_SOURCES)) - -# === Compilation settings === -INCLUDES := -I $(DIST_DIR) -I $(SRC_DIR) -CFLAGS := $(INCLUDES) -O2 -w -fPIC -DLINUX64 - -# ==================================================================== -.PHONY: all - -all: $(TARGET) - -# Copy rules -# -------------------------------------------------------- - -define COPY_RULE_TEMPLATE -$(1): $(2) - @echo "Copying $$< to $$@" - @mkdir -p $$(dir $$@) - @cp $$< $$@ -endef - -$(foreach src,$(ORIG_SOURCES), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)), \\ - $(src) \\ - )) \\ -) - -$(foreach hdr,$(ORIG_HEADERS), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)), \\ - $(hdr) \\ - )) \\ -) - -# Build rules -# -------------------------------------------------------- - -$(TARGET): $(OBJECTS) | $(DIST_HEADERS) - @echo "Archiving library: $@" - @mkdir -p $(@D) - $(AR) rcs $@ $^ - -vpath %.c $(DIST_DIR) - -$(BUILD_DIR)/%.o: $(DIST_DIR)/%.c - @echo "Compiling: $< -> $@" - @mkdir -p $(@D) - $(CC) $(CFLAGS) -MMD -MP -c $< -o $@ - --include $(wildcard $(BUILD_DIR)/*.d) - -.PHONY: clean -clean: - @echo "Cleaning dist directory..." - @rm -rf $(DIST_DIR)" -`; diff --git a/lang/tests/compiler/compiler-esp32.test.ts b/lang/tests/compiler/compiler-esp32.test.ts index c7dd6929..a68666bc 100644 --- a/lang/tests/compiler/compiler-esp32.test.ts +++ b/lang/tests/compiler/compiler-esp32.test.ts @@ -2,7 +2,8 @@ import * as fs from 'fs'; import * as path from 'path'; import { getEsp32CompilerConfig, Esp32CompilerTestEnv } from './test-utils'; import { CompilerSession } from '../../src/compiler/compiler-session'; -import { ProjectForEsp32 } from '../../src/compiler/project'; +import { Project } from '../../src/compiler/project'; +import { PackageForEsp32 } from '../../src/compiler/package'; import { Esp32Toolchain } from '../../src/compiler/board-toolchain/esp32-toolchain'; import { MemoryImage } from '../../src/compiler/board-toolchain/board-toolchain'; @@ -15,12 +16,12 @@ const memoryLayout = { const compilerConfig = getEsp32CompilerConfig(); const compile = async (testEnv: Esp32CompilerTestEnv) => { - const project = ProjectForEsp32.load( + const project = Project.load( testEnv.mainPackageName, testEnv.getPackageReader() ); const toolchain = new Esp32Toolchain(compilerConfig, memoryLayout); - const session = new CompilerSession(toolchain); + const session = new CompilerSession(toolchain); await session.buildProject(project); return session; } diff --git a/lang/tests/compiler/compiler-host.test.ts b/lang/tests/compiler/compiler-host.test.ts index 980afa91..6903b1b4 100644 --- a/lang/tests/compiler/compiler-host.test.ts +++ b/lang/tests/compiler/compiler-host.test.ts @@ -1,9 +1,11 @@ import * as path from "path"; import * as fs from "fs"; -import { ProjectForHost } from "../../src/compiler/project"; -import { HostToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; -import { HostCompilerTestEnv, runtimeDir } from "./test-utils"; -import { SharedObject } from "../../src/compiler/board-toolchain/board-toolchain"; +import * as os from 'os'; +import { Project } from "../../src/compiler/project"; +import { PackageForHostUnix } from "../../src/compiler/package"; +import { HostUnixToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; +import { HostUnixCompilerTestEnv, runtimeDir } from "./test-utils"; +import { SharedLibrary } from "../../src/compiler/board-toolchain/board-toolchain"; import { CompilerSession } from "../../src/compiler/compiler-session"; import { executeCommand } from "../../src/compiler/utils"; @@ -13,27 +15,40 @@ const shellC = path.join(runtimeDir, 'ports/host/shell.c'); const executableShell = path.join(runtimeBuildDir, 'shell'); const runtimeSo = path.join(runtimeBuildDir, 'c-runtime.so'); const runtimeC = path.join(runtimeDir, 'core/src/c-runtime.c'); +const commC = path.join(runtimeDir, 'ports/host/comm.c'); const buildRuntime = async () => { fs.mkdirSync(runtimeBuildDir, { recursive: true }); - await executeCommand('cc', ["-DLINUX64", "-O2", "-shared", "-fPIC", "-o", runtimeSo, runtimeC, builtinModuleC]); + await executeCommand('cc', ["-DLINUX64", "-O2", "-shared", "-fPIC", "-o", runtimeSo, runtimeC, builtinModuleC, commC]); await executeCommand('cc', ["-DLINUX64", "-O2", "-o", executableShell, shellC, runtimeSo, "-lm", "-ldl"]); } -const compile = async (testEnv: HostCompilerTestEnv) => { - const project = ProjectForHost.load( - testEnv.mainPackageName, - testEnv.getPackageReader() - ); - const toolchain = new HostToolchain(runtimeDir); - const session = new CompilerSession(toolchain); - await session.buildProject(project); - return session; +const createTestEnv = () => { + if (os.platform() === 'darwin') { + return new HostUnixCompilerTestEnv('compiler-test-host') + } else { + throw new Error('Unsupported OS.'); + } +} + +const compile = async (testEnv: HostUnixCompilerTestEnv) => { + if (os.platform() === 'darwin') { + let toolchain = new HostUnixToolchain(runtimeDir); + const project = Project.load( + testEnv.mainPackageName, + testEnv.getPackageReader() as (name: string) => PackageForHostUnix + ); + const session = new CompilerSession(toolchain); + await session.buildProject(project); + return session; + } else { + throw new Error('Unsupported OS.'); + } } describe('Test single compile: Compiler for Host', () => { - const testEnv = new HostCompilerTestEnv('compiler-test-host'); + const testEnv = createTestEnv(); beforeAll(async () => { await buildRuntime(); @@ -53,7 +68,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', '1 + 1'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should throw error if index.bs does not exist.', async () => { @@ -67,7 +82,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', 'print("hello world")'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with std object.', async () => { @@ -75,7 +90,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', 'console.log("hello world")'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('can change source directory.', async () => { @@ -83,7 +98,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './src/index.bs', 'print("hello world")'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('can change entry file.', async () => { @@ -91,7 +106,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './src/main.bs', 'print("hello world")'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a module import.', async () => { @@ -102,7 +117,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from './module1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should throw error if an imported module does not exist.', async () => { @@ -143,7 +158,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {addMul} from './module1';\naddMul(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with module imports from dir.', async () => { @@ -161,7 +176,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {addMul} from './dir/module1';\naddMul(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a package import.', async () => { @@ -173,7 +188,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from 'package1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a package import 2.', async () => { @@ -185,7 +200,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from 'package1/module1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a package import from different source directory.', async () => { @@ -195,7 +210,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from 'package1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a package import from different source directory and different entry file.', async () => { @@ -205,7 +220,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from 'package1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with an unused package.', async () => { @@ -215,7 +230,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `1 + 1;`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with a package import 2.', async () => { @@ -227,7 +242,7 @@ describe('Test single compile: Compiler for Host', () => { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {add} from 'package1/module1';\nadd(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs with some package imports.', async () => { @@ -248,7 +263,7 @@ mul(1, 2);` ); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should throw error if an imported package does not exist.', async () => { @@ -275,7 +290,7 @@ mul(1, 2);` testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {addMul} from 'package1';\naddMul(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs which imports a package with a module import.', async () => { @@ -291,7 +306,7 @@ mul(1, 2);` testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', `import {addMul} from 'package1';\naddMul(1, 2);`); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs which imports a package and a module.', async () => { @@ -313,7 +328,7 @@ add(1, 2); // mul(1,2); `); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should treat a class imported via different routes as the same class.', async () => { @@ -340,7 +355,7 @@ getShapeArea(shape); ` ); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs which includes c file.', async () => { @@ -353,7 +368,7 @@ function foo() { `); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs which includes custom c file.', async () => { @@ -367,7 +382,7 @@ function foo() { `); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); it('should compile index.bs which includes custom header file.', async () => { @@ -382,7 +397,7 @@ function foo() { `); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); expect(fs.existsSync(path.join(testEnv.root, 'dist/add.h'))).toBe(true); }); @@ -402,19 +417,19 @@ function foo() { testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', '1 + 1'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); testEnv.addSourceFile(testEnv.mainPackageName, './index.bs', '1 + 3'); await compile(testEnv); - expect(testEnv.resultSharedObjectExists()).toBe(true); + expect(testEnv.resultSharedLibraryExists()).toBe(true); }); }); describe('Test additional compile: Compiler for ESP32', () => { - const testEnv = new HostCompilerTestEnv('compiler-test-host'); + const testEnv = createTestEnv(); beforeEach(() => { testEnv.init(); diff --git a/lang/tests/compiler/makefile.test.ts b/lang/tests/compiler/makefile.test.ts deleted file mode 100644 index beac149c..00000000 --- a/lang/tests/compiler/makefile.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { describe, expect, test } from '@jest/globals'; -import { generateMakefile, esp32MakefilePreset, hostMakefilePreset } from '../../src/compiler/board-toolchain/tools/makefile'; -import { Package } from '../../src/compiler/project'; - -function createTestPackage(name = 'myapp', rootDir = '/project/myapp'): Package { - return new Package( - name, - { - rootDir, - entry: './src/index.bs', - sourceDir: './src', - distDir: './dist', - buildDir: './dist/build', - packageDir: './packages', - }, - [], - ); -} - -describe('generateMakefile', () => { - test('generates makefile for esp32 archive file.', () => { - const pkg = createTestPackage(); - const makefile = generateMakefile(esp32MakefilePreset( - '/opt/esp-toolchain', - pkg, - [ - '/opt/esp-idf/components/freertos/include', - '/opt/esp-idf/components/esp_common/include', - ], - '/project/myapp/dist/build/libmyapp.a', - )); - expect(makefile).toMatchSnapshot(); - }); - - test('generates makefile for host shared library.', () => { - const pkg = createTestPackage(); - const makefile = generateMakefile(hostMakefilePreset( - pkg, - '/project/myapp/dist/build/libmyapp.a', - )); - expect(makefile).toMatchSnapshot(); - }); -}); diff --git a/lang/tests/compiler/test-utils.ts b/lang/tests/compiler/test-utils.ts index b71470f9..4c001725 100644 --- a/lang/tests/compiler/test-utils.ts +++ b/lang/tests/compiler/test-utils.ts @@ -1,6 +1,6 @@ import { execSync } from "child_process"; import { Esp32ToolchainConfig } from "../../src/compiler/board-toolchain/esp32-toolchain"; -import { Package, PackageForEsp32 } from "../../src/compiler/project"; +import { Package, PackageForEsp32, PackageForHostUnix } from "../../src/compiler/package"; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; @@ -110,9 +110,10 @@ export class Esp32CompilerTestEnv extends CompilerTestEnv { } } -export class HostCompilerTestEnv extends CompilerTestEnv { + +export class HostUnixCompilerTestEnv extends CompilerTestEnv { public createMainPackage(dependencies: string[] = [], srcDir: string = ".", entryFile?: string): void { - const pkg = new Package( + const pkg = new PackageForHostUnix( this.mainPackageName, { rootDir: this.root, @@ -130,7 +131,7 @@ export class HostCompilerTestEnv extends CompilerTestEnv { public createSubPackage(name: string, dependencies: string[] = [], srcDir: string = ".", entryFile?: string): void { const root = path.join(this.root, 'packages', name); fs.mkdirSync(root, {recursive: true}); - const pkg = new Package( + const pkg = new PackageForHostUnix( name, { rootDir: root, @@ -145,8 +146,12 @@ export class HostCompilerTestEnv extends CompilerTestEnv { this.addPackage(pkg); } - public resultSharedObjectExists() { - const soPath = path.join(this.root, `dist/build/${this.mainPackageName}.so`); - return fs.existsSync(soPath); + public resultSharedLibraryExists() { + const buildDir = path.join(this.root, 'dist/build/'); + const pattern = new RegExp(`^${this.mainPackageName}\\d+\\.so$`); + for (const name of fs.readdirSync(buildDir)) { + if(pattern.test(name) ) { return true; } + } + return false; } } \ No newline at end of file diff --git a/microcontroller/ports/host/shell.c b/microcontroller/ports/host/shell.c index 3d7114d2..852f8a0b 100644 --- a/microcontroller/ports/host/shell.c +++ b/microcontroller/ports/host/shell.c @@ -25,7 +25,11 @@ static float get_time_ms() { static void load(char* filename) { float start_time = get_time_ms(); +#ifndef WIN_MINGW file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); +#else + file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); +#endif bs_comm_send_loadtime(get_time_ms() - start_time); } From 13421fca73cf9eef7cfa1f9db2ff2103aa787453 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Tue, 30 Jun 2026 21:20:08 +0900 Subject: [PATCH 05/33] Refactor lang. --- .../board-toolchain/esp32-toolchain.ts | 2 +- .../board-toolchain/host-toolchain.ts | 2 +- .../board-toolchain/tools/makefile.ts | 155 +++++------------- .../board-toolchain/tools/makefile2.ts | 97 ----------- 4 files changed, 46 insertions(+), 210 deletions(-) delete mode 100644 lang/src/compiler/board-toolchain/tools/makefile2.ts diff --git a/lang/src/compiler/board-toolchain/esp32-toolchain.ts b/lang/src/compiler/board-toolchain/esp32-toolchain.ts index 07f55afd..97f51535 100644 --- a/lang/src/compiler/board-toolchain/esp32-toolchain.ts +++ b/lang/src/compiler/board-toolchain/esp32-toolchain.ts @@ -4,7 +4,7 @@ import { PackageForEsp32 } from "../package"; import { Project } from "../project"; import { BoardToolchain, MemoryImage, MemoryLayout, ShadowMemory } from "./board-toolchain"; import { executeCommand, getErrorMessage } from "../utils"; -import { generateMakefile, esp32MakefilePreset } from "./tools/makefile2"; +import { generateMakefile, esp32MakefilePreset } from "./tools/makefile"; import { ElfReader } from "./tools/elf-reader"; import generateLinkerScript from "./tools/linker-script"; diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 5d3e0759..69273f62 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import { BoardToolchain, SharedLibrary } from "./board-toolchain"; import { Project } from "../project"; import { Package, PackageForHostUnix } from "../package"; -import { generateMakefile, hostUnixMakefilePrest } from "./tools/makefile2"; +import { generateMakefile, hostUnixMakefilePrest } from "./tools/makefile"; import { executeCommand, getErrorMessage } from "../utils"; diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index 2e0a7554..cb7c5275 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -1,25 +1,33 @@ -import { Package } from "../../package"; - +import { PackageForEsp32, PackageForHostUnix } from "../../package" type MakefileConfig = { - pkg: Package, + outputFile: string, + objectFiles: string[], + headerFilesInDist: string[], includeDirs: string[], compileFlags: string[], - outputFile: string, - toolchain: { cc: string; ar: string } + distDir: string, + buildDir: string, + toolchain: { + cc: string, + ar: string + } } - -export function esp32MakefilePreset(toolchainDir: string, pkg: Package, includeDirs: string[], outputFile: string): MakefileConfig { +export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], toolchainDir: string): MakefileConfig { return { - pkg, includeDirs, + outputFile: pkg.archiveFile, + objectFiles: pkg.objectFiles, + headerFilesInDist: pkg.headerFilesInDist, + includeDirs: [pkg.distDir, ...includeDirs], compileFlags: [ '-O2', '-w', '-fno-common', '-ffunction-sections', '-fdata-sections', '-mtext-section-literals', '-mlongcalls', '-fno-zero-initialized-in-bss', ], - outputFile, + distDir: pkg.resolvedDistDir, + buildDir: pkg.resolvedBuildDir, toolchain: { cc: `${toolchainDir}/xtensa-esp32-elf-gcc`, ar: `${toolchainDir}/xtensa-esp32-elf-ar` @@ -27,12 +35,15 @@ export function esp32MakefilePreset(toolchainDir: string, pkg: Package, includeD } } -export function hostMakefilePreset(pkg: Package, outputFile: string): MakefileConfig { +export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { return { - pkg, - includeDirs: [], + outputFile: pkg.archiveFile, + objectFiles: pkg.objectFiles, + headerFilesInDist: pkg.headerFilesInDist, + includeDirs: [pkg.resolvedDistDir], compileFlags: ['-O2', '-w', '-fPIC', '-DLINUX64'], - outputFile, + distDir: pkg.resolvedDistDir, + buildDir: pkg.resolvedBuildDir, toolchain: { cc: `cc`, ar: `ar` @@ -40,105 +51,25 @@ export function hostMakefilePreset(pkg: Package, outputFile: string): MakefileCo } } -export function generateMakefile(config: MakefileConfig): string { - return [ - // preamble - renderHeader(config), - renderValidation(config), - renderSourceVars(config), - renderCompileFlags(config), - - // body - renderPhonyAll(config), - renderCopyRules(config), - renderBuildRules(config), - renderClean(config) - ].join('\n\n'); -} +export function generateMakefile(config: MakefileConfig) { + return ` -function renderHeader(config: MakefileConfig): string { - const { pkg } = config; - return `# === Basic settings === +# === Variable settings === CC := ${config.toolchain.cc} AR := ${config.toolchain.ar} +DIST_DIR := ${config.distDir} +BUILD_DIR := ${config.buildDir} +TARGET := ${config.outputFile} +OBJECTS := ${config.objectFiles.join(' ')} +DIST_HEADERS := ${config.headerFilesInDist} +INCLUDES := ${config.includeDirs.map(path => `-I ${path}`).join(' ')} +CFLAGS := $(INCLUDES) ${config.compileFlags.join(' ')} -# === Directory settings === -SRC_DIR := ${pkg.resolvedSourceDir} -DIST_DIR := ${pkg.resolvedDistDir} -BUILD_DIR := ${pkg.resolvedBuildDir} -PACKAGES_DIR := ${pkg.resolvedPackageDir} - -TARGET := ${config.outputFile}`; -} - -function renderValidation(_config: MakefileConfig): string { - return `# === Check for illegal file name prefixes === -ILLEGAL_PREFIX_FILES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "bs_*.c" -print) -ifneq ($(ILLEGAL_PREFIX_FILES),) - $(error ERROR: You cannot use 'bs_' prefix for C source file names. Please remove or rename the following files: \\ - $(ILLEGAL_PREFIX_FILES)) -endif`; -} - -function renderSourceVars(_config: MakefileConfig): string { - return `# === Source and object file settings === -ORIG_SOURCES := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.c" -print) -ORIG_HEADERS := $(shell find $(SRC_DIR) -path $(DIST_DIR) -prune -o -path $(PACKAGES_DIR) -prune -o -type f -name "*.h" -print) -DIST_SOURCES := $(foreach src,$(ORIG_SOURCES), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)) \\ -) -DIST_HEADERS := $(foreach hdr,$(ORIG_HEADERS), \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)) \\ -) -DIST_SOURCES += $(shell find $(DIST_DIR) -path $(BUILD_DIR) -prune -o -type f -name "bs_*.c" -print) -OBJECTS := $(patsubst $(DIST_DIR)/%.c, $(BUILD_DIR)/%.o, $(DIST_SOURCES))`; -} - -function renderCompileFlags(config: MakefileConfig): string { - const extraIncludes = config.includeDirs.map(path => `-I ${path}`).join(' '); - const includes = extraIncludes - ? `-I $(DIST_DIR) -I $(SRC_DIR) ${extraIncludes}` - : `-I $(DIST_DIR) -I $(SRC_DIR)`; - return `# === Compilation settings === -INCLUDES := ${includes} -CFLAGS := $(INCLUDES) ${config.compileFlags.join(' ')}`; -} -function renderPhonyAll(_config: MakefileConfig): string { - return `# ==================================================================== .PHONY: all +all: $(TARGET) -all: $(TARGET)`; -} - -function renderCopyRules(_config: MakefileConfig): string { - return `# Copy rules -# -------------------------------------------------------- - -define COPY_RULE_TEMPLATE -$(1): $(2) -\t@echo "Copying $$< to $$@" -\t@mkdir -p $$(dir $$@) -\t@cp $$< $$@ -endef - -$(foreach src,$(ORIG_SOURCES), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(src)), \\ - $(src) \\ - )) \\ -) - -$(foreach hdr,$(ORIG_HEADERS), \\ - $(eval $(call COPY_RULE_TEMPLATE, \\ - $(subst $(SRC_DIR),$(DIST_DIR), $(hdr)), \\ - $(hdr) \\ - )) \\ -)`; -} - -function renderBuildRules(_config: MakefileConfig): string { - return `# Build rules +# Build rules # -------------------------------------------------------- $(TARGET): $(OBJECTS) | $(DIST_HEADERS) @@ -153,12 +84,14 @@ $(BUILD_DIR)/%.o: $(DIST_DIR)/%.c \t@mkdir -p $(@D) \t$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ --include $(wildcard $(BUILD_DIR)/*.d)`; -} +-include $(wildcard $(BUILD_DIR)/*.d); -function renderClean(_config: MakefileConfig): string { - return `.PHONY: clean +# -------------------------------------------------------- + +.PHONY: clean clean: \t@echo "Cleaning dist directory..." -\t@rm -rf $(DIST_DIR)`; -} +\t@rm -rf $(DIST_DIR) + + ` +} \ No newline at end of file diff --git a/lang/src/compiler/board-toolchain/tools/makefile2.ts b/lang/src/compiler/board-toolchain/tools/makefile2.ts deleted file mode 100644 index cb7c5275..00000000 --- a/lang/src/compiler/board-toolchain/tools/makefile2.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { PackageForEsp32, PackageForHostUnix } from "../../package" - -type MakefileConfig = { - outputFile: string, - objectFiles: string[], - headerFilesInDist: string[], - includeDirs: string[], - compileFlags: string[], - distDir: string, - buildDir: string, - toolchain: { - cc: string, - ar: string - } -} - -export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], toolchainDir: string): MakefileConfig { - return { - outputFile: pkg.archiveFile, - objectFiles: pkg.objectFiles, - headerFilesInDist: pkg.headerFilesInDist, - includeDirs: [pkg.distDir, ...includeDirs], - compileFlags: [ - '-O2', '-w', '-fno-common', - '-ffunction-sections', '-fdata-sections', - '-mtext-section-literals', '-mlongcalls', - '-fno-zero-initialized-in-bss', - ], - distDir: pkg.resolvedDistDir, - buildDir: pkg.resolvedBuildDir, - toolchain: { - cc: `${toolchainDir}/xtensa-esp32-elf-gcc`, - ar: `${toolchainDir}/xtensa-esp32-elf-ar` - } - } -} - -export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { - return { - outputFile: pkg.archiveFile, - objectFiles: pkg.objectFiles, - headerFilesInDist: pkg.headerFilesInDist, - includeDirs: [pkg.resolvedDistDir], - compileFlags: ['-O2', '-w', '-fPIC', '-DLINUX64'], - distDir: pkg.resolvedDistDir, - buildDir: pkg.resolvedBuildDir, - toolchain: { - cc: `cc`, - ar: `ar` - } - } -} - -export function generateMakefile(config: MakefileConfig) { - return ` - -# === Variable settings === -CC := ${config.toolchain.cc} -AR := ${config.toolchain.ar} -DIST_DIR := ${config.distDir} -BUILD_DIR := ${config.buildDir} -TARGET := ${config.outputFile} -OBJECTS := ${config.objectFiles.join(' ')} -DIST_HEADERS := ${config.headerFilesInDist} -INCLUDES := ${config.includeDirs.map(path => `-I ${path}`).join(' ')} -CFLAGS := $(INCLUDES) ${config.compileFlags.join(' ')} - - -.PHONY: all -all: $(TARGET) - -# Build rules -# -------------------------------------------------------- - -$(TARGET): $(OBJECTS) | $(DIST_HEADERS) -\t@echo "Archiving library: $@" -\t@mkdir -p $(@D) -\t$(AR) rcs $@ $^ - -vpath %.c $(DIST_DIR) - -$(BUILD_DIR)/%.o: $(DIST_DIR)/%.c -\t@echo "Compiling: $< -> $@" -\t@mkdir -p $(@D) -\t$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ - --include $(wildcard $(BUILD_DIR)/*.d); - -# -------------------------------------------------------- - -.PHONY: clean -clean: -\t@echo "Cleaning dist directory..." -\t@rm -rf $(DIST_DIR) - - ` -} \ No newline at end of file From cd10de655e911f92542f42b61fa5dc785da29bc6 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Tue, 30 Jun 2026 22:19:03 +0900 Subject: [PATCH 06/33] Add windows to lang. --- .../board-toolchain/host-toolchain.ts | 71 ++++++++++++- .../board-toolchain/tools/makefile.ts | 19 +++- lang/src/compiler/package.ts | 9 ++ lang/tests/compiler/compiler-host.test.ts | 46 +-------- .../compiler/{test-utils.ts => test-env.ts} | 47 ++++++++- lang/tests/compiler/test-utils-host.ts | 99 +++++++++++++++++++ microcontroller/ports/host/comm.c | 1 - microcontroller/ports/host/shell.c | 40 +++++++- microcontroller/ports/host/std-module.bs | 32 ++++-- microcontroller/ports/host/std-module.c | 32 ++++-- 10 files changed, 322 insertions(+), 74 deletions(-) rename lang/tests/compiler/{test-utils.ts => test-env.ts} (76%) create mode 100644 lang/tests/compiler/test-utils-host.ts diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 69273f62..4fc8f4ff 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -2,8 +2,8 @@ import * as path from "path"; import * as fs from "fs"; import { BoardToolchain, SharedLibrary } from "./board-toolchain"; import { Project } from "../project"; -import { Package, PackageForHostUnix } from "../package"; -import { generateMakefile, hostUnixMakefilePrest } from "./tools/makefile"; +import { Package, PackageForHostUnix, PackageForHostWindows } from "../package"; +import { generateMakefile, hostUnixMakefilePrest, hostWindowsMakefilePreset } from "./tools/makefile"; import { executeCommand, getErrorMessage } from "../utils"; @@ -26,8 +26,6 @@ export abstract class HostToolchain

implements BoardToolchain get cRuntimeH() { return path.join(this.runtimeDir, 'core/include/c-runtime.h'); } get builtinModulePath() { return path.join(this.runtimeDir, 'ports/host/std-module.bs'); } get runtimeBuildDir() { return path.join(this.runtimeDir, 'ports/host/build'); } - get executableShell() { return path.join(this.runtimeBuildDir, 'shell'); } - get runtimeSo() { return path.join(this.runtimeBuildDir, 'c-runtime.so'); } async compileAndLink(project: Project

, entryPoints: string[]): Promise { const archiveFiles: string[] = []; @@ -66,6 +64,8 @@ export abstract class HostToolchain

implements BoardToolchain } export class HostUnixToolchain extends HostToolchain { + get runtimeSo() { return path.join(this.runtimeBuildDir, 'c-runtime.so'); } + async compilePackage(pkg: PackageForHostUnix): Promise { try { const archiveFile = pkg.archiveFile; @@ -106,4 +106,67 @@ export class HostUnixToolchain extends HostToolchain { throw new Error(`Failed to link: ${getErrorMessage(error)}`, {cause: error}); } } +} + +export class HostWindowsToolchain extends HostToolchain { + private readonly toolchainPrefix?: string; + + constructor(runtimeDir: string, toolchainPrefix?: string) { + super(runtimeDir); + this.toolchainPrefix = toolchainPrefix; + } + + get runtimeDll(): string { + return path.join(this.runtimeBuildDir, 'c-runtime.dll'); + } + + async compilePackage(pkg: PackageForHostWindows): Promise { + try { + const archiveFile = pkg.archiveFile; + if (fs.existsSync(archiveFile)) { + fs.rmSync(archiveFile, { force: true }); + } + pkg.copyNativeFilesToDist(); + const makefile = generateMakefile( + hostWindowsMakefilePreset(pkg, this.toolchainPrefix), + ); + pkg.writeMakefile(makefile); + await executeCommand('mingw32-make', [], pkg.resolvedDistDir); + return archiveFile; + } catch (error) { + throw new Error( + `Failed to compile package ${pkg.name}: ${getErrorMessage(error)}`, + { cause: error }, + ); + } + } + + async link( + project: Project, + archiveFiles: string[], + entryPoints: string[], + ): Promise { + try { + const keepEntrySymbols = entryPoints.map( + (sym) => `-Wl,-u,${sym}`, + ); + const outputFile = project.mainPackage.dllFile(this.compileId++); + const args = [ + '-shared', + '-o', outputFile, + ...archiveFiles, + ...this.generatedSharedLibs, + this.runtimeDll, + '-lm', + ...keepEntrySymbols, + ]; + const linker = this.toolchainPrefix + ? path.join(this.toolchainPrefix, 'gcc') + : 'gcc'; + await executeCommand(linker, args); + return outputFile; + } catch (error) { + throw new Error(`Failed to link: ${getErrorMessage(error)}`, { cause: error }); + } + } } \ No newline at end of file diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index cb7c5275..fe0ff49e 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -1,4 +1,4 @@ -import { PackageForEsp32, PackageForHostUnix } from "../../package" +import { PackageForEsp32, PackageForHostUnix, PackageForHostWindows } from "../../package" type MakefileConfig = { outputFile: string, @@ -51,6 +51,23 @@ export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { } } +export function hostWindowsMakefilePreset(pkg: PackageForHostWindows, toolchainPrefix?: string): MakefileConfig { + const toMakePath = (p: string) => p.replace(/\\/g, '/'); + return { + outputFile: toMakePath(pkg.archiveFile), + objectFiles: pkg.objectFiles.map(toMakePath), + headerFilesInDist: pkg.headerFilesInDist.map(toMakePath), + includeDirs: [toMakePath(pkg.resolvedDistDir)], + compileFlags: ['-O2', '-w', '-DLINUX64', '-DWIN64'], + distDir: toMakePath(pkg.resolvedDistDir), + buildDir: toMakePath(pkg.resolvedBuildDir), + toolchain: { + cc: toolchainPrefix ? `${toMakePath(toolchainPrefix)}/gcc` : 'gcc', + ar: toolchainPrefix ? `${toMakePath(toolchainPrefix)}/ar` : 'ar', + }, + }; +} + export function generateMakefile(config: MakefileConfig) { return ` diff --git a/lang/src/compiler/package.ts b/lang/src/compiler/package.ts index e8b26231..fdd0924b 100644 --- a/lang/src/compiler/package.ts +++ b/lang/src/compiler/package.ts @@ -197,3 +197,12 @@ export class PackageForHostUnix extends Package { } } +export class PackageForHostWindows extends Package { + dllFile(id?: number): AbsolutePath { + return path.join( + this.resolvedBuildDir, + `${this.name}${id ?? ''}.dll` + ); + } +} + diff --git a/lang/tests/compiler/compiler-host.test.ts b/lang/tests/compiler/compiler-host.test.ts index 6903b1b4..cc0b975c 100644 --- a/lang/tests/compiler/compiler-host.test.ts +++ b/lang/tests/compiler/compiler-host.test.ts @@ -1,50 +1,6 @@ import * as path from "path"; import * as fs from "fs"; -import * as os from 'os'; -import { Project } from "../../src/compiler/project"; -import { PackageForHostUnix } from "../../src/compiler/package"; -import { HostUnixToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; -import { HostUnixCompilerTestEnv, runtimeDir } from "./test-utils"; -import { SharedLibrary } from "../../src/compiler/board-toolchain/board-toolchain"; -import { CompilerSession } from "../../src/compiler/compiler-session"; -import { executeCommand } from "../../src/compiler/utils"; - -const runtimeBuildDir = path.join(runtimeDir, 'ports/host/build'); -const builtinModuleC = path.join(runtimeDir, 'ports/host/std-module.c'); -const shellC = path.join(runtimeDir, 'ports/host/shell.c'); -const executableShell = path.join(runtimeBuildDir, 'shell'); -const runtimeSo = path.join(runtimeBuildDir, 'c-runtime.so'); -const runtimeC = path.join(runtimeDir, 'core/src/c-runtime.c'); -const commC = path.join(runtimeDir, 'ports/host/comm.c'); - -const buildRuntime = async () => { - fs.mkdirSync(runtimeBuildDir, { recursive: true }); - await executeCommand('cc', ["-DLINUX64", "-O2", "-shared", "-fPIC", "-o", runtimeSo, runtimeC, builtinModuleC, commC]); - await executeCommand('cc', ["-DLINUX64", "-O2", "-o", executableShell, shellC, runtimeSo, "-lm", "-ldl"]); -} - -const createTestEnv = () => { - if (os.platform() === 'darwin') { - return new HostUnixCompilerTestEnv('compiler-test-host') - } else { - throw new Error('Unsupported OS.'); - } -} - -const compile = async (testEnv: HostUnixCompilerTestEnv) => { - if (os.platform() === 'darwin') { - let toolchain = new HostUnixToolchain(runtimeDir); - const project = Project.load( - testEnv.mainPackageName, - testEnv.getPackageReader() as (name: string) => PackageForHostUnix - ); - const session = new CompilerSession(toolchain); - await session.buildProject(project); - return session; - } else { - throw new Error('Unsupported OS.'); - } -} +import { buildRuntime, createTestEnv, compile } from "./test-utils-host"; describe('Test single compile: Compiler for Host', () => { diff --git a/lang/tests/compiler/test-utils.ts b/lang/tests/compiler/test-env.ts similarity index 76% rename from lang/tests/compiler/test-utils.ts rename to lang/tests/compiler/test-env.ts index 4c001725..dd58b958 100644 --- a/lang/tests/compiler/test-utils.ts +++ b/lang/tests/compiler/test-env.ts @@ -1,6 +1,6 @@ import { execSync } from "child_process"; import { Esp32ToolchainConfig } from "../../src/compiler/board-toolchain/esp32-toolchain"; -import { Package, PackageForEsp32, PackageForHostUnix } from "../../src/compiler/package"; +import { Package, PackageForEsp32, PackageForHostUnix, PackageForHostWindows } from "../../src/compiler/package"; import * as fs from 'fs'; import * as path from 'path'; import * as os from 'os'; @@ -146,6 +146,51 @@ export class HostUnixCompilerTestEnv extends CompilerTestEnv this.addPackage(pkg); } + public resultSharedLibraryExists() { + const buildDir = path.join(this.root, 'dist/build/'); + const pattern = new RegExp(`^${this.mainPackageName}\\d+\\.so$`); + for (const name of fs.readdirSync(buildDir)) { + if(pattern.test(name) ) { return true; } + } + return false; + } +} + +export class HostWindowsCompilerTestEnv extends CompilerTestEnv { + public createMainPackage(dependencies: string[] = [], srcDir: string = ".", entryFile?: string): void { + const pkg = new PackageForHostWindows( + this.mainPackageName, + { + rootDir: this.root, + entry: entryFile ?? path.join(srcDir, 'index.bs'), + sourceDir: srcDir, + distDir: "./dist", + buildDir: "./dist/build", + packageDir: "./packages", + }, + dependencies, + ); + this.addPackage(pkg); + } + + public createSubPackage(name: string, dependencies: string[] = [], srcDir: string = ".", entryFile?: string): void { + const root = path.join(this.root, 'packages', name); + fs.mkdirSync(root, {recursive: true}); + const pkg = new PackageForHostWindows( + name, + { + rootDir: root, + entry: entryFile ?? path.join(srcDir, 'index.bs'), + sourceDir: srcDir, + distDir: "./dist", + buildDir: "./dist/build", + packageDir: "./packages", + }, + dependencies, + ) + this.addPackage(pkg); + } + public resultSharedLibraryExists() { const buildDir = path.join(this.root, 'dist/build/'); const pattern = new RegExp(`^${this.mainPackageName}\\d+\\.so$`); diff --git a/lang/tests/compiler/test-utils-host.ts b/lang/tests/compiler/test-utils-host.ts new file mode 100644 index 00000000..78691f78 --- /dev/null +++ b/lang/tests/compiler/test-utils-host.ts @@ -0,0 +1,99 @@ +import * as path from "path"; +import * as fs from "fs"; +import * as os from 'os'; +import { Project } from "../../src/compiler/project"; +import { PackageForHostUnix, PackageForHostWindows } from "../../src/compiler/package"; +import { HostUnixToolchain, HostWindowsToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; +import { HostUnixCompilerTestEnv, HostWindowsCompilerTestEnv, runtimeDir } from "./test-env"; +import { SharedLibrary } from "../../src/compiler/board-toolchain/board-toolchain"; +import { CompilerSession } from "../../src/compiler/compiler-session"; +import { executeCommand } from "../../src/compiler/utils"; + + +const runtimeBuildDir = path.join(runtimeDir, 'ports/host/build'); +const builtinModuleC = path.join(runtimeDir, 'ports/host/std-module.c'); +const shellC = path.join(runtimeDir, 'ports/host/shell.c'); +const runtimeC = path.join(runtimeDir, 'core/src/c-runtime.c'); +const commC = path.join(runtimeDir, 'ports/host/comm.c'); + +// Unix (darwin) +const runtimeSo = path.join(runtimeBuildDir, 'c-runtime.so'); +const executableShell = path.join(runtimeBuildDir, 'shell'); + +// Windows +const runtimeDll = path.join(runtimeBuildDir, 'c-runtime.dll'); +const executableShellWin = path.join(runtimeBuildDir, 'shell.exe'); + +const buildRuntimeUnix = async () => { + fs.mkdirSync(runtimeBuildDir, { recursive: true }); + await executeCommand('cc', [ + '-DLINUX64', '-O2', '-shared', '-fPIC', + '-o', runtimeSo, + runtimeC, builtinModuleC, commC, + ]); + await executeCommand('cc', [ + '-DLINUX64', '-O2', + '-o', executableShell, + shellC, runtimeSo, '-lm', '-ldl', + ]); +}; + +const buildRuntimeWindows = async () => { + fs.mkdirSync(runtimeBuildDir, { recursive: true }); + await executeCommand('gcc', [ + '-DLINUX64', '-DWIN64', '-O2', '-shared', + '-o', runtimeDll, + runtimeC, builtinModuleC, commC, + ]); + await executeCommand('gcc', [ + '-DLINUX64', '-DWIN64', '-O2', + '-o', executableShellWin, + shellC, runtimeDll, '-lm', + ]); +}; + +export const buildRuntime = async () => { + if (os.platform() === 'darwin') { + await buildRuntimeUnix(); + } else if (os.platform() === 'win32') { + await buildRuntimeWindows(); + } else { + throw new Error('Unsupported OS.'); + } +}; + +export const createTestEnv = () => { + if (os.platform() === 'darwin') { + return new HostUnixCompilerTestEnv('compiler-test-host') + } else if (os.platform() === 'win32') { + return new HostWindowsCompilerTestEnv('compiler-test-host') + } else { + throw new Error('Unsupported OS.'); + } +} + +export const compile = async (testEnv: HostUnixCompilerTestEnv | HostWindowsCompilerTestEnv) => { + if (os.platform() === 'darwin') { + let toolchain = new HostUnixToolchain(runtimeDir); + const project = Project.load( + testEnv.mainPackageName, + testEnv.getPackageReader() as (name: string) => PackageForHostUnix + ); + const session = new CompilerSession(toolchain); + await session.buildProject(project); + return session; + } else if (os.platform() === 'win32') { + let toolchain = new HostWindowsToolchain(runtimeDir); + const project = Project.load( + testEnv.mainPackageName, + testEnv.getPackageReader() as (name: string) => PackageForHostWindows + ); + const session = new CompilerSession(toolchain); + await session.buildProject(project); + return session; + } else { + throw new Error('Unsupported OS.'); + } +} + + diff --git a/microcontroller/ports/host/comm.c b/microcontroller/ports/host/comm.c index 0f7916c9..4e31b8df 100644 --- a/microcontroller/ports/host/comm.c +++ b/microcontroller/ports/host/comm.c @@ -1,7 +1,6 @@ #include #include #include -#include #include "./comm.h" diff --git a/microcontroller/ports/host/shell.c b/microcontroller/ports/host/shell.c index 852f8a0b..52c9311e 100644 --- a/microcontroller/ports/host/shell.c +++ b/microcontroller/ports/host/shell.c @@ -3,17 +3,23 @@ #include #include #include -#include -#include #include "../../core/include/c-runtime.h" #include "./comm.h" +#ifndef _WIN32 +#include +#include +#else +#include +#endif + extern void bluescript_main0_(); void* file_handle; static float get_time_ms() { +#ifndef _WIN32 static struct timespec ts0 = { 0, -1 }; struct timespec ts; if (ts0.tv_nsec < 0) @@ -21,14 +27,34 @@ static float get_time_ms() { clock_gettime(CLOCK_REALTIME, &ts); return (float)(ts.tv_sec - ts0.tv_sec) * 1000.0 + (float)(ts.tv_nsec - ts0.tv_nsec) / 1000000.0; +#else + static LARGE_INTEGER freq = { 0 }; + static LARGE_INTEGER start = { 0 }; + LARGE_INTEGER now; + if (freq.QuadPart == 0) { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + } + QueryPerformanceCounter(&now); + return (float)(now.QuadPart - start.QuadPart) * 1000.0f / (float)freq.QuadPart; +#endif } static void load(char* filename) { float start_time = get_time_ms(); -#ifndef WIN_MINGW +#ifndef _WIN32 + if (file_handle != NULL) { + dlclose(file_handle); + } file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); #else - file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (file_handle != NULL) { + FreeLibrary((HMODULE)file_handle); + } + file_handle = (void*)LoadLibraryA(filename); + if (file_handle == NULL) { + fprintf(stderr, "Error: failed to load %s (error %lu)\n", filename, GetLastError()); + } #endif bs_comm_send_loadtime(get_time_ms() - start_time); } @@ -38,7 +64,11 @@ static int call(char* funcname) { fprintf(stderr, "Error: module is not loaded\n"); return 1; } - void (*fptr)() = dlsym(file_handle, funcname); +#ifndef _WIN32 + void (*fptr)(void) = (void (*)(void))dlsym(file_handle, funcname); +#else + void (*fptr)(void) = (void (*)(void))GetProcAddress((HMODULE)file_handle, funcname); +#endif if (fptr == NULL) { fprintf(stderr, "Error: %s() is not found\n", funcname); return 1; diff --git a/microcontroller/ports/host/std-module.bs b/microcontroller/ports/host/std-module.bs index 6a0c504f..fe94a93c 100644 --- a/microcontroller/ports/host/std-module.bs +++ b/microcontroller/ports/host/std-module.bs @@ -41,6 +41,28 @@ void print_message(value_t m) { send_message("\n", cls->name); } } + +static float get_time_ms() { +#ifndef _WIN32 + static struct timespec ts0 = { 0, -1 }; + struct timespec ts; + if (ts0.tv_nsec < 0) + clock_gettime(CLOCK_REALTIME, &ts0); + + clock_gettime(CLOCK_REALTIME, &ts); + return (float)(ts.tv_sec - ts0.tv_sec) * 1000.0 + (float)(ts.tv_nsec - ts0.tv_nsec) / 1000000.0; +#else + static LARGE_INTEGER freq = { 0 }; + static LARGE_INTEGER start = { 0 }; + LARGE_INTEGER now; + if (freq.QuadPart == 0) { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + } + QueryPerformanceCounter(&now); + return (float)(now.QuadPart - start.QuadPart) * 1000.0f / (float)freq.QuadPart; +#endif +} ` function print(message: any) { @@ -61,15 +83,7 @@ class Console { class Time { now(): float { let t: integer = 0 - code` - static struct timespec ts0 = { 0, -1 }; - struct timespec ts; - if (ts0.tv_nsec < 0) - clock_gettime(CLOCK_REALTIME, &ts0); - - clock_gettime(CLOCK_REALTIME, &ts); - ${t} = (int32_t)((ts.tv_sec - ts0.tv_sec) * 1000 + (ts.tv_nsec - ts0.tv_nsec) / 1000000); - ` + code`${t} = get_time_ms();` return t } } diff --git a/microcontroller/ports/host/std-module.c b/microcontroller/ports/host/std-module.c index 3dbdbf4e..5e81d072 100644 --- a/microcontroller/ports/host/std-module.c +++ b/microcontroller/ports/host/std-module.c @@ -38,6 +38,29 @@ void print_message(value_t m) { } +static float get_time_ms() { +#ifndef _WIN32 + static struct timespec ts0 = { 0, -1 }; + struct timespec ts; + if (ts0.tv_nsec < 0) + clock_gettime(CLOCK_REALTIME, &ts0); + + clock_gettime(CLOCK_REALTIME, &ts); + return (float)(ts.tv_sec - ts0.tv_sec) * 1000.0 + (float)(ts.tv_nsec - ts0.tv_nsec) / 1000000.0; +#else + static LARGE_INTEGER freq = { 0 }; + static LARGE_INTEGER start = { 0 }; + LARGE_INTEGER now; + if (freq.QuadPart == 0) { + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); + } + QueryPerformanceCounter(&now); + return (float)(now.QuadPart - start.QuadPart) * 1000.0f / (float)freq.QuadPart; +#endif +} + + extern struct func_body _print; void mth_0_Console(value_t self, value_t _message); void mth_1_Console(value_t self, value_t _message); @@ -97,14 +120,7 @@ float mth_0_Time(value_t self) { func_rootset.values[0] = self; { int32_t _t = 0; - - static struct timespec ts0 = { 0, -1 }; - struct timespec ts; - if (ts0.tv_nsec < 0) - clock_gettime(CLOCK_REALTIME, &ts0); - - clock_gettime(CLOCK_REALTIME, &ts); - _t = (int32_t)((ts.tv_sec - ts0.tv_sec) * 1000 + (ts.tv_nsec - ts0.tv_nsec) / 1000000); + _t = get_time_ms(); ; { float ret_value_ = (_t); DELETE_ROOT_SET(func_rootset); return ret_value_; } } From 1616c1ce78882c83fc0504e90da8545cd560cb29 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Thu, 2 Jul 2026 20:14:59 +0900 Subject: [PATCH 07/33] fix on windows. --- .../board-toolchain/host-toolchain.ts | 2 ++ .../board-toolchain/tools/makefile.ts | 4 +-- lang/src/compiler/package.ts | 26 ++++++++++++++++++- lang/src/compiler/utils.ts | 2 +- lang/tests/compiler/compiler-host.test.ts | 5 ++-- lang/tests/compiler/test-env.ts | 2 +- microcontroller/core/src/c-runtime.c | 10 +++++++ microcontroller/ports/host/shell.c | 8 +++--- microcontroller/ports/host/std-module.bs | 7 ++++- microcontroller/ports/host/std-module.c | 7 ++++- package-lock.json | 17 ------------ 11 files changed, 60 insertions(+), 30 deletions(-) diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 4fc8f4ff..b06c4ba6 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -127,10 +127,12 @@ export class HostWindowsToolchain extends HostToolchain { fs.rmSync(archiveFile, { force: true }); } pkg.copyNativeFilesToDist(); + pkg.createBuildDir(); const makefile = generateMakefile( hostWindowsMakefilePreset(pkg, this.toolchainPrefix), ); pkg.writeMakefile(makefile); + await executeCommand('mingw32-make', [], pkg.resolvedDistDir); return archiveFile; } catch (error) { diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index fe0ff49e..70eb5104 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -91,14 +91,14 @@ all: $(TARGET) $(TARGET): $(OBJECTS) | $(DIST_HEADERS) \t@echo "Archiving library: $@" -\t@mkdir -p $(@D) +\t@mkdir -p "$(@D)" \t$(AR) rcs $@ $^ vpath %.c $(DIST_DIR) $(BUILD_DIR)/%.o: $(DIST_DIR)/%.c \t@echo "Compiling: $< -> $@" -\t@mkdir -p $(@D) +\t@mkdir -p "$(@D)" \t$(CC) $(CFLAGS) -MMD -MP -c $< -o $@ -include $(wildcard $(BUILD_DIR)/*.d); diff --git a/lang/src/compiler/package.ts b/lang/src/compiler/package.ts index fdd0924b..2c88cf27 100644 --- a/lang/src/compiler/package.ts +++ b/lang/src/compiler/package.ts @@ -121,6 +121,10 @@ export class Package { fs.writeFileSync(filePath, data); return filePath; } + + createBuildDir() { + fs.mkdirSync(this.resolvedBuildDir, { recursive: true }); + } protected walkFiles(dir: string, handler: (name: string, fullPath: string) => void, ignorDirs?: string[]) { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { @@ -136,7 +140,7 @@ export class Package { } } - private toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { + protected toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { const source = cFileInDist; const dist = this.resolvedDistDir; const prefix = dist.endsWith("/") ? dist : dist + "/"; @@ -198,6 +202,26 @@ export class PackageForHostUnix extends Package { } export class PackageForHostWindows extends Package { + protected replacePrefix(fromDir: AbsolutePath, toDir: AbsolutePath, filePath: AbsolutePath): string { + if (filePath === fromDir) return toDir; + const prefix = filePath.endsWith("\\") ? fromDir : fromDir + "\\"; + if (!filePath.startsWith(prefix)) { + throw new Error(`Path ${filePath} is not under ${fromDir}`); + } + return toDir + "/" + filePath.slice(prefix.length); + } + + protected toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { + const source = cFileInDist; + const dist = this.resolvedDistDir; + const prefix = dist.endsWith("\\") ? dist : dist + "\\"; + if (!source.startsWith(prefix) || !source.endsWith(".c")) { + throw new Error(`Invalid dist source: ${source}`); + } + const relative = source.slice(prefix.length, -2); // remove ".c" + return path.join(this.resolvedBuildDir, `${relative}.o`); + } + dllFile(id?: number): AbsolutePath { return path.join( this.resolvedBuildDir, diff --git a/lang/src/compiler/utils.ts b/lang/src/compiler/utils.ts index 14bbda44..04530b09 100644 --- a/lang/src/compiler/utils.ts +++ b/lang/src/compiler/utils.ts @@ -2,7 +2,7 @@ import { spawn } from "child_process"; export function executeCommand(command: string, args: string[], cwd?: string, showStdout = false, showStderr = false): Promise { return new Promise((resolve, reject) => { - const executeProcess = spawn(command, args, { shell: false, cwd }); + const executeProcess = spawn(command, args, { shell: true, cwd }); let stdout = ''; let stderr = ''; diff --git a/lang/tests/compiler/compiler-host.test.ts b/lang/tests/compiler/compiler-host.test.ts index cc0b975c..d178c55c 100644 --- a/lang/tests/compiler/compiler-host.test.ts +++ b/lang/tests/compiler/compiler-host.test.ts @@ -86,7 +86,8 @@ describe('Test single compile: Compiler for Host', () => { it('should throw error if an imported module is imported with absolute path.', async () => { testEnv.createMainPackage(); testEnv.addSourceFile(testEnv.mainPackageName, './module1.bs', `export function add(a: integer, b:integer) {return a + b}`); - testEnv.addSourceFile(testEnv.mainPackageName, '/index.bs', `import {add} from '${testEnv.getSourceFilePath(testEnv.mainPackageName, './module1.bs')}';\nadd(1, 2);`); + const absPath = testEnv.getSourceFilePath(testEnv.mainPackageName, './module1.bs').replace(/\\/g, '/'); + testEnv.addSourceFile(testEnv.mainPackageName, '/index.bs', `import {add} from '${absPath}';\nadd(1, 2);`); await expect(compile(testEnv)).rejects.toThrow(`This module system does not support importing from absolute paths.`); }); @@ -365,7 +366,7 @@ function foo() { } `); - await expect(compile(testEnv)).rejects.toThrow(`do not support implicit function declarations`); + await expect(compile(testEnv)).rejects.toThrow(/implicit/i); }); it('should compile index.bs again after editing file.', async () => { diff --git a/lang/tests/compiler/test-env.ts b/lang/tests/compiler/test-env.ts index dd58b958..4dd47197 100644 --- a/lang/tests/compiler/test-env.ts +++ b/lang/tests/compiler/test-env.ts @@ -193,7 +193,7 @@ export class HostWindowsCompilerTestEnv extends CompilerTestEnv #include -#include #include #include "../../core/include/c-runtime.h" #include "./comm.h" +#ifndef _WIN32 +#include +#include +#else +#include +#endif void send_message(const char* format, ...) { diff --git a/microcontroller/ports/host/std-module.c b/microcontroller/ports/host/std-module.c index 5e81d072..3e458e7f 100644 --- a/microcontroller/ports/host/std-module.c +++ b/microcontroller/ports/host/std-module.c @@ -1,10 +1,15 @@ #include #include -#include #include #include "../../core/include/c-runtime.h" #include "./comm.h" +#ifndef _WIN32 +#include +#include +#else +#include +#endif void send_message(const char* format, ...) { static char message[MAX_LINE_SIZE]; diff --git a/package-lock.json b/package-lock.json index 7ef8ed20..9e51884e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19511,23 +19511,6 @@ } } }, - "node_modules/tailwindcss/node_modules/yaml": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", - "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" - } - }, "node_modules/tapable": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", From 06dacb88d7a524944a069ea360264b9ea4da222c Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Thu, 2 Jul 2026 20:19:22 +0900 Subject: [PATCH 08/33] Adding windows to cli. --- cli/src/commands/board/setup/esp32-windows.ts | 82 +++++++++++++++++++ cli/src/commands/board/setup/host-darwin.ts | 6 +- cli/src/commands/board/setup/host-windows.ts | 49 +++++++++++ cli/src/commands/board/setup/index.ts | 6 ++ cli/src/config/global-config.ts | 6 +- cli/src/platforms/board-env/esp32-env.ts | 9 +- cli/src/platforms/board-env/host-env.ts | 21 +++++ cli/src/platforms/board-env/index.ts | 5 +- .../platforms/runtime/host-board-runtime.ts | 2 +- 9 files changed, 178 insertions(+), 8 deletions(-) create mode 100644 cli/src/commands/board/setup/esp32-windows.ts create mode 100644 cli/src/commands/board/setup/host-windows.ts diff --git a/cli/src/commands/board/setup/esp32-windows.ts b/cli/src/commands/board/setup/esp32-windows.ts new file mode 100644 index 00000000..1e20330f --- /dev/null +++ b/cli/src/commands/board/setup/esp32-windows.ts @@ -0,0 +1,82 @@ +import { SetupHandler } from "./base"; +import { exec } from '../../../core/shell'; +import { skip } from "../../../core/logger"; +import { BoardName } from "../../../config/board-utils"; +import { Esp32DarwinEnv, Esp32WindowsEnv } from "../../../platforms/board-env/esp32-env"; + + +export class Esp32WindowsSetupHandler extends SetupHandler { + boardName: BoardName = "host"; + boardEnv: Esp32WindowsEnv; + + constructor() { + super(); + this.boardEnv = new Esp32WindowsEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that git and python3 are installed.", + actionMessage: "Verifying that git and python3 are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}... It may take a while.`, + action: this.cloneEspIdfStep.bind(this), + }); + this.setupSteps.push({ + description: "Run ESP-IDF install script.", + actionMessage: "Running ESP-IDF install script...", + action: this.runEspIdfInstallScriptStep.bind(this), + }); + } + + async setBoardConfig() { + this.globalConfigHandler.updateBoardConfig(this.boardName, { + idfVersion: this.boardEnv.idfVersion, + rootDir: this.boardEnv.espRootDir, + exportFile: this.boardEnv.idfExportFile, + xtensaGccDir: await this.boardEnv.getXtensaGccDir(), + }); + } + + private async verifyPrerequisitsInstalledStep() { + if (!await this.isPackageInstalled("git")) { + throw new Error("Cannot find git command. Please install git and try again."); + } + if (!(await this.isPythonVersionGreaterThan3()) && !(await this.isPackageInstalled('python3'))) { + throw new Error("Cannot find python3. Please install Python3 and try again."); + } + } + + private async cloneEspIdfStep() { + await this.boardEnv.cloneEspIdf(); + } + + private async runEspIdfInstallScriptStep() { + await this.boardEnv.runEspIdfInstallScript(); + } + + private async isPackageInstalled(name: string) { + // try { + // await exec(`which ${name}`, { silent: true }); + // return true; + // } catch (error) { + // return false; + // } + // TODO + return true; + } + + private async isPythonVersionGreaterThan3() { + // try { + // const result = await exec(`python --version`, { silent: true }); + // return result.startsWith('Python 3.'); + // } catch (error) { + // return false; + // } + // TODO + return false; + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-darwin.ts b/cli/src/commands/board/setup/host-darwin.ts index 1a7e6deb..dfc72590 100644 --- a/cli/src/commands/board/setup/host-darwin.ts +++ b/cli/src/commands/board/setup/host-darwin.ts @@ -28,7 +28,11 @@ export class HostDarwinSetupHandler extends SetupHandler { async setBoardConfig() { this.globalConfigHandler.updateBoardConfig('host', { - buildDir: this.boardEnv.buildDir + rootDir: this.boardEnv.hostRootDir, + shellFile: this.boardEnv.shellFile, + gccCommand: 'cc', + makeCommand: 'make', + arCommand: 'ar' }) } diff --git a/cli/src/commands/board/setup/host-windows.ts b/cli/src/commands/board/setup/host-windows.ts new file mode 100644 index 00000000..1aae21e9 --- /dev/null +++ b/cli/src/commands/board/setup/host-windows.ts @@ -0,0 +1,49 @@ +import { SetupHandler } from "./base"; +import { exec } from '../../../core/shell'; +import { BoardName } from "../../../config/board-utils"; +import { HostWindowsEnv } from "../../../platforms/board-env/host-env"; + + +export class HostWindowsSetupHandler extends SetupHandler { + boardName: BoardName = 'host'; + boardEnv: HostWindowsEnv; + + constructor() { + super(); + this.boardEnv = new HostWindowsEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that MinGW is installed.", // write version + actionMessage: "Verifying that MinGW is installed...", + action: this.installMinGWStep.bind(this), + }); + this.setupSteps.push({ + description: "Build host runtime.", + actionMessage: "Building host runtime...", + action: this.buildHostRuntimeStep.bind(this), + }); + } + + async setBoardConfig() { + this.globalConfigHandler.updateBoardConfig('host', { + rootDir: this.boardEnv.hostRootDir, + shellFile: this.boardEnv.shellFile, + gccCommand: 'gcc', + makeCommand: 'mingw32-make', + arCommand: 'ar' + }) + } + private async installMinGWStep() { + // TODO + } + + private async buildHostRuntimeStep() { + await this.boardEnv.buildHostRuntime(); + } + + private async isPackageInstalled(name: string) { + // TODO + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/index.ts b/cli/src/commands/board/setup/index.ts index cd2fc08d..e209be40 100644 --- a/cli/src/commands/board/setup/index.ts +++ b/cli/src/commands/board/setup/index.ts @@ -6,6 +6,8 @@ import chalk from "chalk"; import { SetupHandler } from "./base"; import { Esp32DarwinSetupHandler } from "./esp32-darwin"; import { HostDarwinSetupHandler } from "./host-darwin"; +import { Esp32WindowsSetupHandler } from "./esp32-windows"; +import { HostWindowsSetupHandler } from "./host-windows"; function getSetupHandler(board: string): SetupHandler { @@ -13,11 +15,15 @@ function getSetupHandler(board: string): SetupHandler { if (board === 'esp32') { if (osType === 'darwin') return new Esp32DarwinSetupHandler(); + if (osType === 'win32') + return new Esp32WindowsSetupHandler(); throw new Error(`Unsupported OS type: ${osType}.`); } if (board === 'host') { if (osType === 'darwin') return new HostDarwinSetupHandler(); + if (osType === 'win32') + return new HostWindowsSetupHandler(); throw new Error(`Unsupported OS type: ${osType}.`); } throw new Error(`Unsupported board name: ${board}`); diff --git a/cli/src/config/global-config.ts b/cli/src/config/global-config.ts index 223ee6e3..d35bf2f0 100644 --- a/cli/src/config/global-config.ts +++ b/cli/src/config/global-config.ts @@ -12,7 +12,11 @@ const esp32BoardSchema = z.object({ }); const hostBoardSchema = z.object({ - buildDir: z.string(), + rootDir: z.string(), + shellFile: z.string(), + gccCommand: z.string(), + makeCommand: z.string(), + arCommand: z.string() }); const boardConfigSchema = z.object({ diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 6eaf8289..5d77b46b 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -10,10 +10,6 @@ const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; export abstract class Esp32Env extends BoardEnv { get espRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); } get idfDir() { return path.join(this.espRootDir, 'esp-idf'); } - get idfExportShFile() { return path.join(this.idfDir, 'export.sh'); } - get idfInstallShFile() { return path.join(this.idfDir, 'install.sh'); } - get idfExportBatFile() { return path.join(this.idfDir, 'export.bat'); } - get idfInstallBatFile() { return path.join(this.idfDir, 'install.bat'); } get idfToolsPyFile() { return path.join(this.idfDir, 'tools/idf_tools.py'); } get idfVersion() { return 'v5.4'; } get idfGitRepo() { return 'https://github.com/espressif/esp-idf.git'; } @@ -90,6 +86,9 @@ export abstract class Esp32Env extends BoardEnv { } export class Esp32DarwinEnv extends Esp32Env { + get idfExportShFile() { return path.join(this.idfDir, 'export.sh'); } + get idfInstallShFile() { return path.join(this.idfDir, 'install.sh'); } + get idfExportFile() { return this.idfExportShFile; } async runEspIdfInstallScript() { @@ -107,6 +106,8 @@ export class Esp32DarwinEnv extends Esp32Env { } export class Esp32WindowsEnv extends Esp32Env { + get idfExportBatFile() { return path.join(this.idfDir, 'export.bat'); } + get idfInstallBatFile() { return path.join(this.idfDir, 'install.bat'); } get idfExportFile() { return this.idfExportBatFile; } protected get xtensaGccFileName(): string { diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index ad9d2a3c..7667136c 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -49,3 +49,24 @@ export class HostDarwinEnv extends HostEnv { } } + +export class HostWindowsEnv extends HostEnv { + get runtimeDllFile() { return path.join(this.buildDir, 'c-runtime.dll'); } + get shellFile() { return path.join(this.buildDir, 'shell.exe'); } + + async buildHostRuntime() { + fs.makeDir(this.buildDir); + try { + await exec( + `gcc -DLINUX64 -O2 -shared -o "${this.runtimeDllFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, + { silent: true }, + ); + await exec( + `gcc -DLINUX64 -O2 -o "${this.shellFile}" "${this.shellCFile}" "${this.runtimeDllFile}" -lm`, + { silent: true }, + ); + } catch (error) { + throw new Error('Failed to compile host runtime.', { cause: error }); + } + } +} diff --git a/cli/src/platforms/board-env/index.ts b/cli/src/platforms/board-env/index.ts index b9e3ac1b..c0fad756 100644 --- a/cli/src/platforms/board-env/index.ts +++ b/cli/src/platforms/board-env/index.ts @@ -2,7 +2,7 @@ import * as os from 'os'; import { Esp32Env, Esp32DarwinEnv, Esp32WindowsEnv } from './esp32-env'; import { CommonBoardEnv, BoardEnv } from './common-env'; import { BoardName } from '../../config/board-utils'; -import { HostEnv, HostDarwinEnv } from './host-env'; +import { HostEnv, HostDarwinEnv, HostWindowsEnv } from './host-env'; type BoardEnvMap = { @@ -23,6 +23,8 @@ export function createBoardEnv(board: BoardName): BoardEnvMap[BoardName] { if (board === 'host') { if (osType === 'darwin') return new HostDarwinEnv(); + if (osType === 'win32') + return new HostWindowsEnv(); throw new Error(`Unsupported OS type: ${osType}.`); } throw new Error(`Unsupported board name: ${board}`); @@ -36,4 +38,5 @@ export { Esp32WindowsEnv, HostEnv, HostDarwinEnv, + HostWindowsEnv, }; diff --git a/cli/src/platforms/runtime/host-board-runtime.ts b/cli/src/platforms/runtime/host-board-runtime.ts index a4e66461..683b4009 100644 --- a/cli/src/platforms/runtime/host-board-runtime.ts +++ b/cli/src/platforms/runtime/host-board-runtime.ts @@ -62,6 +62,6 @@ export class HostBoardRuntime implements BoardRuntime { } private getShellPath(): string { - return path.join(this.boardConfig.buildDir, 'shell'); + return path.join(this.boardConfig.shellFile); } } From 9b302a065b15f4f8d01d7b08db4d7ae51ed3077a Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Thu, 2 Jul 2026 21:30:40 +0900 Subject: [PATCH 09/33] Add windows to lang test. --- lang/tests/compiler/compiler-esp32.test.ts | 7 ++- lang/tests/compiler/test-env.ts | 12 ---- lang/tests/compiler/test-utils-esp32.ts | 69 ++++++++++++++++++++++ 3 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 lang/tests/compiler/test-utils-esp32.ts diff --git a/lang/tests/compiler/compiler-esp32.test.ts b/lang/tests/compiler/compiler-esp32.test.ts index a68666bc..d351fa4b 100644 --- a/lang/tests/compiler/compiler-esp32.test.ts +++ b/lang/tests/compiler/compiler-esp32.test.ts @@ -1,6 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; -import { getEsp32CompilerConfig, Esp32CompilerTestEnv } from './test-utils'; +import { Esp32CompilerTestEnv } from './test-env'; +import { getEsp32ToolchainConfig } from './test-utils-esp32'; import { CompilerSession } from '../../src/compiler/compiler-session'; import { Project } from '../../src/compiler/project'; import { PackageForEsp32 } from '../../src/compiler/package'; @@ -13,14 +14,14 @@ const memoryLayout = { iflash: { address: 0x40150000, size: 10000 }, dflash: { address: 0x3f43d000, size: 10000 }, } -const compilerConfig = getEsp32CompilerConfig(); +const toolchainConfig = getEsp32ToolchainConfig(); const compile = async (testEnv: Esp32CompilerTestEnv) => { const project = Project.load( testEnv.mainPackageName, testEnv.getPackageReader() ); - const toolchain = new Esp32Toolchain(compilerConfig, memoryLayout); + const toolchain = new Esp32Toolchain(toolchainConfig, memoryLayout); const session = new CompilerSession(toolchain); await session.buildProject(project); return session; diff --git a/lang/tests/compiler/test-env.ts b/lang/tests/compiler/test-env.ts index 4dd47197..46f4236b 100644 --- a/lang/tests/compiler/test-env.ts +++ b/lang/tests/compiler/test-env.ts @@ -1,21 +1,9 @@ -import { execSync } from "child_process"; -import { Esp32ToolchainConfig } from "../../src/compiler/board-toolchain/esp32-toolchain"; import { Package, PackageForEsp32, PackageForHostUnix, PackageForHostWindows } from "../../src/compiler/package"; import * as fs from 'fs'; import * as path from 'path'; -import * as os from 'os'; export const runtimeDir = path.resolve(__dirname, '../../../microcontroller'); -export function getEsp32CompilerConfig(): Esp32ToolchainConfig { - const gccPath = execSync('source ~/esp/esp-idf/export.sh &> /dev/null && which xtensa-esp32-elf-gcc').toString(); - const espDir = path.join(os.homedir(), 'esp'); - return { - runtimeDir: runtimeDir, - compilerToolchainDir: path.resolve(gccPath, '../'), - espDir - } -} class CompilerTestEnv

{ readonly root: string; diff --git a/lang/tests/compiler/test-utils-esp32.ts b/lang/tests/compiler/test-utils-esp32.ts new file mode 100644 index 00000000..12cd49e5 --- /dev/null +++ b/lang/tests/compiler/test-utils-esp32.ts @@ -0,0 +1,69 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import * as os from 'os'; +import { execFileSync } from "child_process"; +import { Esp32ToolchainConfig } from "../../src/compiler/board-toolchain/esp32-toolchain"; + + +const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; +const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; + +export const runtimeDir = path.resolve(__dirname, '../../../microcontroller'); + +export function getEsp32ToolchainConfig(): Esp32ToolchainConfig { + const osType = os.platform(); + if (osType === 'darwin') { + const espDir = path.join(os.homedir(), 'esp'); + const idfToolsPy = path.join(espDir, 'esp-idf', 'tools', 'idf_tools.py'); + const stdout = runIdfToolsExport(idfToolsPy); + const compilerToolchainDir = findXtensaGccDirFromIdfExport(stdout, ':', XTENSA_GCC_NAME); + return { runtimeDir, compilerToolchainDir, espDir }; + } else if (osType === 'win32') { + const espDir = path.join(os.homedir(), 'esp'); + const idfToolsPy = path.join(espDir, 'esp-idf', 'tools', 'idf_tools.py'); + const stdout = runIdfToolsExport(idfToolsPy); + const compilerToolchainDir = findXtensaGccDirFromIdfExport( + stdout, + ';', + `${XTENSA_GCC_NAME}.exe`, + ); + return { + runtimeDir, + compilerToolchainDir, + espDir, + }; + } else { + throw new Error('Unsupported OS.'); + } + +} + + +function findXtensaGccDirFromIdfExport( + stdout: string, + pathSeparator: string, + gccFileName: string, +): string { + for (const line of stdout.trim().split('\n')) { + if (!line || line.startsWith('ERROR:') || line.startsWith('WARNING:')) continue; + const eq = line.indexOf('='); + if (eq === -1) continue; + + const key = line.slice(0, eq); + const value = line.slice(eq + 1); + if (key !== 'PATH') continue; + + for (const entry of value.split(pathSeparator).map((p) => p.trim()).filter(Boolean)) { + if (entry.includes(XTENSA_TOOLCHAIN_DIR) && fs.existsSync(path.join(entry, gccFileName))) { + return entry; + } + } + } + throw new Error(`${XTENSA_TOOLCHAIN_DIR} not found in idf_tools.py export output`); +} + +function runIdfToolsExport(idfToolsPy: string): string { + return execFileSync('python', [idfToolsPy, 'export', '--format', 'key-value'], { + encoding: 'utf8', + }); +} \ No newline at end of file From 7f31b7b247531920a7dde1005a60a5a240707e34 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Fri, 3 Jul 2026 18:26:15 +0900 Subject: [PATCH 10/33] Add changes to run lang esp32 tests on windows. --- .../board-toolchain/esp32-toolchain.ts | 14 +- .../board-toolchain/host-toolchain.ts | 1 - .../board-toolchain/tools/makefile.ts | 23 +- lang/src/compiler/package.ts | 29 +- lang/tests/compiler/compiler-esp32.test.ts | 5 +- lang/tests/compiler/test-utils-esp32.ts | 24 +- microcontroller/ports/esp32/sdkconfig | 194 +++- microcontroller/ports/esp32/sdkconfig.old | 1034 +++++++++-------- 8 files changed, 761 insertions(+), 563 deletions(-) diff --git a/lang/src/compiler/board-toolchain/esp32-toolchain.ts b/lang/src/compiler/board-toolchain/esp32-toolchain.ts index 97f51535..6064c7c3 100644 --- a/lang/src/compiler/board-toolchain/esp32-toolchain.ts +++ b/lang/src/compiler/board-toolchain/esp32-toolchain.ts @@ -11,7 +11,12 @@ import generateLinkerScript from "./tools/linker-script"; export type Esp32ToolchainConfig = { runtimeDir: string, - compilerToolchainDir: string, + compilerToolchain: { + gcc: string, + ar: string, + ld: string, + make: string + }, espDir: string } @@ -32,7 +37,8 @@ export class Esp32Toolchain implements BoardToolchain { fs.rmSync(archiveFile, { force: true }); } pkg.copyNativeFilesToDist(); - pkg.createBuildDir(); const makefile = generateMakefile( hostWindowsMakefilePreset(pkg, this.toolchainPrefix), ); diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index 70eb5104..06486ff9 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -14,23 +14,27 @@ type MakefileConfig = { } } -export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], toolchainDir: string): MakefileConfig { +function toMakePath(p: string) { + return p.replace(/\\/g, '/'); +}; + +export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], toolchain: {gcc: string, ar: string}): MakefileConfig { return { - outputFile: pkg.archiveFile, - objectFiles: pkg.objectFiles, - headerFilesInDist: pkg.headerFilesInDist, - includeDirs: [pkg.distDir, ...includeDirs], + outputFile: toMakePath(pkg.archiveFile), + objectFiles: pkg.objectFiles.map(toMakePath), + headerFilesInDist: pkg.headerFilesInDist.map(toMakePath), + includeDirs: [pkg.resolvedBuildDir, ...includeDirs].map(toMakePath), compileFlags: [ '-O2', '-w', '-fno-common', '-ffunction-sections', '-fdata-sections', '-mtext-section-literals', '-mlongcalls', '-fno-zero-initialized-in-bss', ], - distDir: pkg.resolvedDistDir, - buildDir: pkg.resolvedBuildDir, + distDir: toMakePath(pkg.resolvedDistDir), + buildDir: toMakePath(pkg.resolvedBuildDir), toolchain: { - cc: `${toolchainDir}/xtensa-esp32-elf-gcc`, - ar: `${toolchainDir}/xtensa-esp32-elf-ar` + cc: toMakePath(toolchain.gcc), + ar: toMakePath(toolchain.ar) } } } @@ -52,7 +56,6 @@ export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { } export function hostWindowsMakefilePreset(pkg: PackageForHostWindows, toolchainPrefix?: string): MakefileConfig { - const toMakePath = (p: string) => p.replace(/\\/g, '/'); return { outputFile: toMakePath(pkg.archiveFile), objectFiles: pkg.objectFiles.map(toMakePath), diff --git a/lang/src/compiler/package.ts b/lang/src/compiler/package.ts index 2c88cf27..527e0e8f 100644 --- a/lang/src/compiler/package.ts +++ b/lang/src/compiler/package.ts @@ -5,6 +5,7 @@ import * as path from "path"; type RelativePath = string; type AbsolutePath = string; + export class Package { readonly name: string; readonly rootDir: AbsolutePath; @@ -122,10 +123,6 @@ export class Package { return filePath; } - createBuildDir() { - fs.mkdirSync(this.resolvedBuildDir, { recursive: true }); - } - protected walkFiles(dir: string, handler: (name: string, fullPath: string) => void, ignorDirs?: string[]) { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const fullPath = path.join(dir, entry.name); @@ -143,7 +140,7 @@ export class Package { protected toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { const source = cFileInDist; const dist = this.resolvedDistDir; - const prefix = dist.endsWith("/") ? dist : dist + "/"; + const prefix = dist.endsWith(path.sep) ? dist : dist + path.sep; if (!source.startsWith(prefix) || !source.endsWith(".c")) { throw new Error(`Invalid dist source: ${source}`); } @@ -153,7 +150,7 @@ export class Package { protected replacePrefix(fromDir: AbsolutePath, toDir: AbsolutePath, filePath: AbsolutePath): string { if (filePath === fromDir) return toDir; - const prefix = filePath.endsWith("/") ? fromDir : fromDir + "/"; + const prefix = filePath.endsWith(path.sep) ? fromDir : fromDir + path.sep; if (!filePath.startsWith(prefix)) { throw new Error(`Path ${filePath} is not under ${fromDir}`); } @@ -202,26 +199,6 @@ export class PackageForHostUnix extends Package { } export class PackageForHostWindows extends Package { - protected replacePrefix(fromDir: AbsolutePath, toDir: AbsolutePath, filePath: AbsolutePath): string { - if (filePath === fromDir) return toDir; - const prefix = filePath.endsWith("\\") ? fromDir : fromDir + "\\"; - if (!filePath.startsWith(prefix)) { - throw new Error(`Path ${filePath} is not under ${fromDir}`); - } - return toDir + "/" + filePath.slice(prefix.length); - } - - protected toObjectFile(cFileInDist: AbsolutePath): AbsolutePath { - const source = cFileInDist; - const dist = this.resolvedDistDir; - const prefix = dist.endsWith("\\") ? dist : dist + "\\"; - if (!source.startsWith(prefix) || !source.endsWith(".c")) { - throw new Error(`Invalid dist source: ${source}`); - } - const relative = source.slice(prefix.length, -2); // remove ".c" - return path.join(this.resolvedBuildDir, `${relative}.o`); - } - dllFile(id?: number): AbsolutePath { return path.join( this.resolvedBuildDir, diff --git a/lang/tests/compiler/compiler-esp32.test.ts b/lang/tests/compiler/compiler-esp32.test.ts index d351fa4b..1782cf9e 100644 --- a/lang/tests/compiler/compiler-esp32.test.ts +++ b/lang/tests/compiler/compiler-esp32.test.ts @@ -36,7 +36,7 @@ describe('Test single compile: Compiler for ESP32', () => { }); afterAll(() => { - testEnv.delete(); + // testEnv.delete(); }); @@ -99,7 +99,8 @@ describe('Test single compile: Compiler for ESP32', () => { it('should throw error if an imported module is imported with absolute path.', async () => { testEnv.createMainPackage(); testEnv.addSourceFile(testEnv.mainPackageName, './module1.bs', `export function add(a: integer, b:integer) {return a + b}`); - testEnv.addSourceFile(testEnv.mainPackageName, '/index.bs', `import {add} from '${testEnv.getSourceFilePath(testEnv.mainPackageName, './module1.bs')}';\nadd(1, 2);`); + const absPath = testEnv.getSourceFilePath(testEnv.mainPackageName, './module1.bs').replace(/\\/g, '/'); + testEnv.addSourceFile(testEnv.mainPackageName, '/index.bs', `import {add} from '${absPath}';\nadd(1, 2);`); await expect(compile(testEnv)).rejects.toThrow(`This module system does not support importing from absolute paths.`); }); diff --git a/lang/tests/compiler/test-utils-esp32.ts b/lang/tests/compiler/test-utils-esp32.ts index 12cd49e5..f5a1577c 100644 --- a/lang/tests/compiler/test-utils-esp32.ts +++ b/lang/tests/compiler/test-utils-esp32.ts @@ -17,7 +17,16 @@ export function getEsp32ToolchainConfig(): Esp32ToolchainConfig { const idfToolsPy = path.join(espDir, 'esp-idf', 'tools', 'idf_tools.py'); const stdout = runIdfToolsExport(idfToolsPy); const compilerToolchainDir = findXtensaGccDirFromIdfExport(stdout, ':', XTENSA_GCC_NAME); - return { runtimeDir, compilerToolchainDir, espDir }; + return { + runtimeDir, + compilerToolchain: { + gcc: path.join(compilerToolchainDir, 'xtensa-esp32-elf-gcc'), + ar: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ar'), + ld: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ld'), + make: 'make' + }, + espDir + }; } else if (osType === 'win32') { const espDir = path.join(os.homedir(), 'esp'); const idfToolsPy = path.join(espDir, 'esp-idf', 'tools', 'idf_tools.py'); @@ -27,10 +36,15 @@ export function getEsp32ToolchainConfig(): Esp32ToolchainConfig { ';', `${XTENSA_GCC_NAME}.exe`, ); - return { - runtimeDir, - compilerToolchainDir, - espDir, + return { + runtimeDir, + compilerToolchain: { + gcc: path.join(compilerToolchainDir, 'xtensa-esp32-elf-gcc.exe'), + ar: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ar.exe'), + ld: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ld.exe'), + make: 'mingw32-make' + }, + espDir }; } else { throw new Error('Unsupported OS.'); diff --git a/microcontroller/ports/esp32/sdkconfig b/microcontroller/ports/esp32/sdkconfig index 098056d1..2183722b 100644 --- a/microcontroller/ports/esp32/sdkconfig +++ b/microcontroller/ports/esp32/sdkconfig @@ -1,10 +1,7 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration # -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" -CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" -CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y @@ -71,6 +68,7 @@ CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y CONFIG_SOC_CPU_CORES_NUM=2 @@ -79,7 +77,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y @@ -91,13 +89,13 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 -CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y CONFIG_SOC_I2C_NUM=2 CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y @@ -155,6 +153,7 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y @@ -175,6 +174,8 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 @@ -197,13 +198,13 @@ CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 -CONFIG_SOC_MPI_OPERATIONS_NUM=y +CONFIG_SOC_MPI_OPERATIONS_NUM=1 CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y @@ -235,6 +236,7 @@ CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y +CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y @@ -244,7 +246,7 @@ CONFIG_IDF_TOOLCHAIN_GCC=y CONFIG_IDF_TARGET_ARCH_XTENSA=y CONFIG_IDF_TARGET_ARCH="xtensa" CONFIG_IDF_TARGET="esp32" -CONFIG_IDF_INIT_VERSION="5.4.1" +CONFIG_IDF_INIT_VERSION="5.4.4" CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 @@ -337,7 +339,7 @@ CONFIG_APP_COMPILE_TIME_DATE=y # CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set # CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set # CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set -CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 # end of Application manager CONFIG_ESP_ROM_HAS_CRC_LE=y @@ -371,14 +373,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set CONFIG_ESPTOOLPY_FLASHFREQ="40m" # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" # CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set @@ -392,13 +394,13 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 # # Partition Table # -# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +CONFIG_PARTITION_TABLE_SINGLE_APP=y # CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set # CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set -CONFIG_PARTITION_TABLE_CUSTOM=y +# CONFIG_PARTITION_TABLE_CUSTOM is not set CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # end of Partition Table @@ -406,9 +408,9 @@ CONFIG_PARTITION_TABLE_MD5=y # # Compiler options # -# CONFIG_COMPILER_OPTIMIZATION_DEBUG is not set +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y # CONFIG_COMPILER_OPTIMIZATION_SIZE is not set -CONFIG_COMPILER_OPTIMIZATION_PERF=y +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_COMPILER_OPTIMIZATION_NONE is not set CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set @@ -471,8 +473,7 @@ CONFIG_BT_BTC_TASK_STACK_SIZE=3072 CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BT_BTU_TASK_STACK_SIZE=4096 -# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +CONFIG_BT_BTU_TASK_STACK_SIZE=4352 CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y # CONFIG_BT_CLASSIC_ENABLED is not set CONFIG_BT_BLE_ENABLED=y @@ -487,14 +488,28 @@ CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 # CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set # CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set # CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set +# CONFIG_BT_GATTS_SECURITY_LEVELS_CHAR is not set +# CONFIG_BT_GATTS_KEY_MATERIAL_CHAR is not set CONFIG_BT_GATTC_ENABLE=y CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 CONFIG_BT_GATTC_NOTIF_REG_MAX=5 # CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_SMP_ENABLE=y # CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set # CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set +CONFIG_BT_BLE_SMP_BOND_NVS_FLASH=y +# CONFIG_BT_BLE_RPA_SUPPORTED is not set + +# +# Bluedroid debug option +# +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +# CONFIG_BT_BLUEDROID_MEM_STATS is not set +# CONFIG_BT_BLUEDROID_THREAD_DEBUG is not set +# end of Bluedroid debug option + # CONFIG_BT_STACK_NO_LOG is not set # @@ -674,15 +689,16 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_MULTI_CONNECTION_ENBALE=y # CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set # CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set -# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set CONFIG_BT_SMP_ENABLE=y CONFIG_BT_SMP_MAX_BONDS=15 # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set -CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_MAX_DEVICE_NAME_LEN=32 -# CONFIG_BT_BLE_RPA_SUPPORTED is not set CONFIG_BT_BLE_RPA_TIMEOUT=900 -# CONFIG_BT_BLE_42_FEATURES_SUPPORTED is not set +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +CONFIG_BT_BLE_42_DTM_TEST_EN=y +CONFIG_BT_BLE_42_ADV_EN=y +CONFIG_BT_BLE_42_SCAN_EN=y +CONFIG_BT_BLE_VENDOR_HCI_EN=y # CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set # CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set # end of Bluedroid Options @@ -699,8 +715,8 @@ CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF=0 CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT_EFF=0 CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 -CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y # CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 @@ -734,12 +750,15 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# BLE disconnect when instant passed +# BLE disconnects when Instant Passed (0x28) occurs # # CONFIG_BTDM_BLE_LLCP_CONN_UPDATE is not set # CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE is not set -# end of BLE disconnect when instant passed +# end of BLE disconnects when Instant Passed (0x28) occurs +CONFIG_BTDM_BLE_CHAN_ASS_EN=y +CONFIG_BTDM_BLE_PING_EN=y +# CONFIG_BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 is not set CONFIG_BTDM_RESERVE_DRAM=0xdb5c CONFIG_BTDM_CTRL_HLI=y # end of Controller Options @@ -748,6 +767,19 @@ CONFIG_BTDM_CTRL_HLI=y # Common Options # CONFIG_BT_ALARM_MAX_NUM=50 +CONFIG_BT_SMP_CRYPTO_STACK_NATIVE=y +# CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT is not set +# CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS is not set + +# +# BLE Log +# +# CONFIG_BLE_LOG_ENABLED is not set +# end of BLE Log + +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set +# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set # end of Common Options # CONFIG_BT_HCI_LOG_DEBUG_EN is not set @@ -781,6 +813,7 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # CONFIG_ADC_DISABLE_DAC=y # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # # Legacy ADC Calibration Configuration @@ -796,42 +829,55 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # Legacy DAC Driver Configurations # # CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy DAC Driver Configurations # # Legacy MCPWM Driver Configurations # # CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy MCPWM Driver Configurations # # Legacy Timer Group Driver Configurations # # CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy Timer Group Driver Configurations # # Legacy RMT Driver Configurations # # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy RMT Driver Configurations # # Legacy I2S Driver Configurations # # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy I2S Driver Configurations +# +# Legacy I2C Driver Configurations +# +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + # # Legacy PCNT Driver Configurations # # CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy PCNT Driver Configurations # # Legacy SDM Driver Configurations # # CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy SDM Driver Configurations # end of Driver Configurations @@ -857,6 +903,7 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -914,6 +961,7 @@ CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y # CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set # end of ESP-Driver:GPTimer Configurations @@ -992,6 +1040,14 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # CONFIG_UART_ISR_IN_IRAM is not set # end of ESP-Driver:UART Configurations +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + # # Ethernet # @@ -1030,6 +1086,13 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + # # ESP HTTP client # @@ -1141,7 +1204,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # # Peripheral Control # -CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y +# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set # end of Peripheral Control # @@ -1202,8 +1265,11 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -1283,8 +1349,15 @@ CONFIG_ESP_CONSOLE_UART=y CONFIG_ESP_CONSOLE_UART_NUM=0 CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 -# CONFIG_ESP_INT_WDT is not set -# CONFIG_ESP_TASK_WDT_EN is not set +CONFIG_ESP_INT_WDT=y +CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 +CONFIG_ESP_INT_WDT_CHECK_CPU1=y +CONFIG_ESP_TASK_WDT_EN=y +CONFIG_ESP_TASK_WDT_INIT=y +# CONFIG_ESP_TASK_WDT_PANIC is not set +CONFIG_ESP_TASK_WDT_TIMEOUT_S=5 +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP_PANIC_HANDLER_IRAM is not set # CONFIG_ESP_DEBUG_STUBS_ENABLE is not set CONFIG_ESP_DEBUG_OCDAWARE=y @@ -1369,7 +1442,7 @@ CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y -# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y # CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 @@ -1388,10 +1461,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # # CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set # end of WPS Configuration Options # CONFIG_ESP_WIFI_DEBUG_PRINT is not set -# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1447,6 +1520,14 @@ CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set # CONFIG_FATFS_USE_LABEL is not set CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1488,6 +1569,7 @@ CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 # # Port # +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y # CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set @@ -1528,7 +1610,6 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y -# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1582,7 +1663,7 @@ CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 # # Format # -CONFIG_LOG_COLORS=y +# CONFIG_LOG_COLORS is not set CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set # end of Format @@ -1630,7 +1711,7 @@ CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y # CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y # CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set -CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 @@ -1705,6 +1786,7 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set # CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set @@ -1764,8 +1846,8 @@ CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y # CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y # CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set -CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y -# CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y # CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set # end of Hooks @@ -1792,6 +1874,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1810,7 +1893,7 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 # CONFIG_MBEDTLS_ECP_RESTARTABLE is not set CONFIG_MBEDTLS_CMAC_C=y CONFIG_MBEDTLS_HARDWARE_AES=y -# CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER is not set +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y CONFIG_MBEDTLS_HARDWARE_MPI=y # CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set CONFIG_MBEDTLS_HARDWARE_SHA=y @@ -1821,6 +1904,7 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y # CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y @@ -1895,13 +1979,14 @@ CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y CONFIG_MBEDTLS_ECP_NIST_OPTIM=y -CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set # CONFIG_MBEDTLS_POLY1305_C is not set # CONFIG_MBEDTLS_CHACHA20_C is not set # CONFIG_MBEDTLS_HKDF_C is not set # CONFIG_MBEDTLS_THREADING_C is not set CONFIG_MBEDTLS_ERROR_STRINGS=y CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -1953,6 +2038,8 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # # CONFIG_OPENTHREAD_SPINEL_ONLY is not set # end of OpenThread Spinel + +# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -1961,6 +2048,7 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -2004,6 +2092,7 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -2181,9 +2270,9 @@ CONFIG_LOG_BOOTLOADER_LEVEL=3 CONFIG_FLASHMODE_DIO=y # CONFIG_FLASHMODE_DOUT is not set CONFIG_MONITOR_BAUD=115200 -# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set -# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set -# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y # CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set # CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y @@ -2205,8 +2294,7 @@ CONFIG_BTC_TASK_STACK_SIZE=3072 CONFIG_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BTU_TASK_STACK_SIZE=4096 -# CONFIG_BLUEDROID_MEM_DEBUG is not set +CONFIG_BTU_TASK_STACK_SIZE=4352 # CONFIG_CLASSIC_BT_ENABLED is not set CONFIG_GATTS_ENABLE=y # CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set @@ -2214,8 +2302,10 @@ CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 CONFIG_GATTC_ENABLE=y # CONFIG_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BLE_SMP_ENABLE=y # CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BLUEDROID_MEM_DEBUG is not set # CONFIG_HCI_TRACE_LEVEL_NONE is not set # CONFIG_HCI_TRACE_LEVEL_ERROR is not set CONFIG_HCI_TRACE_LEVEL_WARNING=y @@ -2377,17 +2467,14 @@ CONFIG_BLUFI_TRACE_LEVEL_WARNING=y # CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set # CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 -# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set CONFIG_SMP_ENABLE=y # CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set -CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y # CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY is not set # CONFIG_BTDM_CONTROLLER_MODE_BTDM is not set CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 -CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y # CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4 is not set @@ -2460,7 +2547,15 @@ CONFIG_CONSOLE_UART_DEFAULT=y CONFIG_CONSOLE_UART=y CONFIG_CONSOLE_UART_NUM=0 CONFIG_CONSOLE_UART_BAUDRATE=115200 -# CONFIG_INT_WDT is not set +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_INT_WDT_CHECK_CPU1=y +CONFIG_TASK_WDT=y +CONFIG_ESP_TASK_WDT=y +# CONFIG_TASK_WDT_PANIC is not set +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP32_DEBUG_STUBS_ENABLE is not set CONFIG_ESP32_DEBUG_OCDAWARE=y CONFIG_BROWNOUT_DET=y @@ -2497,8 +2592,6 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y -CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y @@ -2519,7 +2612,6 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y # CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set # CONFIG_WPA_WPS_STRICT is not set # CONFIG_WPA_DEBUG_PRINT is not set -# CONFIG_WPA_TESTING_OPTIONS is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y diff --git a/microcontroller/ports/esp32/sdkconfig.old b/microcontroller/ports/esp32/sdkconfig.old index 93ec205c..9eca7b5e 100644 --- a/microcontroller/ports/esp32/sdkconfig.old +++ b/microcontroller/ports/esp32/sdkconfig.old @@ -1,20 +1,21 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration # -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" -CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" -CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y +CONFIG_SOC_UART_SUPPORTED=y CONFIG_SOC_MCPWM_SUPPORTED=y +CONFIG_SOC_GPTIMER_SUPPORTED=y CONFIG_SOC_SDMMC_HOST_SUPPORTED=y CONFIG_SOC_BT_SUPPORTED=y CONFIG_SOC_PCNT_SUPPORTED=y +CONFIG_SOC_PHY_SUPPORTED=y CONFIG_SOC_WIFI_SUPPORTED=y CONFIG_SOC_SDIO_SLAVE_SUPPORTED=y CONFIG_SOC_TWAI_SUPPORTED=y +CONFIG_SOC_EFUSE_SUPPORTED=y CONFIG_SOC_EMAC_SUPPORTED=y CONFIG_SOC_ULP_SUPPORTED=y CONFIG_SOC_CCOMP_TIMER_SUPPORTED=y @@ -24,6 +25,9 @@ CONFIG_SOC_RTC_MEM_SUPPORTED=y CONFIG_SOC_I2S_SUPPORTED=y CONFIG_SOC_RMT_SUPPORTED=y CONFIG_SOC_SDM_SUPPORTED=y +CONFIG_SOC_GPSPI_SUPPORTED=y +CONFIG_SOC_LEDC_SUPPORTED=y +CONFIG_SOC_I2C_SUPPORTED=y CONFIG_SOC_SUPPORT_COEXISTENCE=y CONFIG_SOC_AES_SUPPORTED=y CONFIG_SOC_MPI_SUPPORTED=y @@ -31,6 +35,17 @@ CONFIG_SOC_SHA_SUPPORTED=y CONFIG_SOC_FLASH_ENC_SUPPORTED=y CONFIG_SOC_SECURE_BOOT_SUPPORTED=y CONFIG_SOC_TOUCH_SENSOR_SUPPORTED=y +CONFIG_SOC_BOD_SUPPORTED=y +CONFIG_SOC_ULP_FSM_SUPPORTED=y +CONFIG_SOC_CLK_TREE_SUPPORTED=y +CONFIG_SOC_MPU_SUPPORTED=y +CONFIG_SOC_WDT_SUPPORTED=y +CONFIG_SOC_SPI_FLASH_SUPPORTED=y +CONFIG_SOC_RNG_SUPPORTED=y +CONFIG_SOC_LIGHT_SLEEP_SUPPORTED=y +CONFIG_SOC_DEEP_SLEEP_SUPPORTED=y +CONFIG_SOC_LP_PERIPH_SHARE_INTERRUPT=y +CONFIG_SOC_PM_SUPPORTED=y CONFIG_SOC_DPORT_WORKAROUND_DIS_INTERRUPT_LVL=5 CONFIG_SOC_XTAL_SUPPORT_26M=y CONFIG_SOC_XTAL_SUPPORT_40M=y @@ -47,45 +62,55 @@ CONFIG_SOC_ADC_DIGI_MIN_BITWIDTH=9 CONFIG_SOC_ADC_DIGI_MAX_BITWIDTH=12 CONFIG_SOC_ADC_DIGI_RESULT_BYTES=2 CONFIG_SOC_ADC_DIGI_DATA_BYTES_PER_CONV=4 +CONFIG_SOC_ADC_DIGI_MONITOR_NUM=0 CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_HIGH=2 CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 -CONFIG_SOC_RTC_SLOW_CLOCK_SUPPORT_8MD256=y +CONFIG_SOC_ADC_SHARED_POWER=y +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y -CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=5 CONFIG_SOC_CPU_CORES_NUM=2 CONFIG_SOC_CPU_INTR_NUM=32 CONFIG_SOC_CPU_HAS_FPU=y +CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 -CONFIG_SOC_DAC_PERIPH_NUM=2 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 +CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y CONFIG_SOC_GPIO_PORT=1 CONFIG_SOC_GPIO_PIN_COUNT=40 CONFIG_SOC_GPIO_VALID_GPIO_MASK=0xFFFFFFFFFF +CONFIG_SOC_GPIO_IN_RANGE_MAX=39 +CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA +CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y +CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 CONFIG_SOC_I2C_NUM=2 +CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 +CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y -CONFIG_SOC_CLK_APLL_SUPPORTED=y -CONFIG_SOC_APLL_MULTIPLIER_OUT_MIN_HZ=350000000 -CONFIG_SOC_APLL_MULTIPLIER_OUT_MAX_HZ=500000000 -CONFIG_SOC_APLL_MIN_HZ=5303031 -CONFIG_SOC_APLL_MAX_HZ=125000000 +CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y +CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y CONFIG_SOC_I2S_SUPPORTS_APLL=y +CONFIG_SOC_I2S_SUPPORTS_PLL_F160M=y CONFIG_SOC_I2S_SUPPORTS_PDM=y CONFIG_SOC_I2S_SUPPORTS_PDM_TX=y +CONFIG_SOC_I2S_PDM_MAX_TX_LINES=1 CONFIG_SOC_I2S_SUPPORTS_PDM_RX=y +CONFIG_SOC_I2S_PDM_MAX_RX_LINES=1 CONFIG_SOC_I2S_SUPPORTS_ADC_DAC=y CONFIG_SOC_I2S_SUPPORTS_ADC=y CONFIG_SOC_I2S_SUPPORTS_DAC=y CONFIG_SOC_I2S_SUPPORTS_LCD_CAMERA=y +CONFIG_SOC_I2S_MAX_DATA_WIDTH=24 CONFIG_SOC_I2S_TRANS_SIZE_ALIGN_WORD=y CONFIG_SOC_I2S_LCD_I80_VARIANT=y CONFIG_SOC_LCD_I80_SUPPORTED=y @@ -95,8 +120,9 @@ CONFIG_SOC_LEDC_HAS_TIMER_SPECIFIC_MUX=y CONFIG_SOC_LEDC_SUPPORT_APB_CLOCK=y CONFIG_SOC_LEDC_SUPPORT_REF_TICK=y CONFIG_SOC_LEDC_SUPPORT_HS_MODE=y +CONFIG_SOC_LEDC_TIMER_NUM=4 CONFIG_SOC_LEDC_CHANNEL_NUM=8 -CONFIG_SOC_LEDC_TIMER_BIT_WIDE_NUM=20 +CONFIG_SOC_LEDC_TIMER_BIT_WIDTH=20 CONFIG_SOC_MCPWM_GROUPS=2 CONFIG_SOC_MCPWM_TIMERS_PER_GROUP=3 CONFIG_SOC_MCPWM_OPERATORS_PER_GROUP=3 @@ -107,6 +133,8 @@ CONFIG_SOC_MCPWM_GPIO_FAULTS_PER_GROUP=3 CONFIG_SOC_MCPWM_CAPTURE_TIMERS_PER_GROUP=y CONFIG_SOC_MCPWM_CAPTURE_CHANNELS_PER_TIMER=3 CONFIG_SOC_MCPWM_GPIO_SYNCHROS_PER_GROUP=3 +CONFIG_SOC_MMU_PERIPH_NUM=2 +CONFIG_SOC_MMU_LINEAR_ADDRESS_REGION_NUM=3 CONFIG_SOC_MPU_MIN_REGION_SIZE=0x20000000 CONFIG_SOC_MPU_REGIONS_MAX_NUM=8 CONFIG_SOC_PCNT_GROUPS=1 @@ -125,13 +153,16 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y +CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 +CONFIG_SOC_SDM_CLK_SUPPORT_APB=y CONFIG_SOC_SPI_HD_BOTH_INOUT_SUPPORTED=y CONFIG_SOC_SPI_AS_CS_SUPPORTED=y CONFIG_SOC_SPI_PERIPH_NUM=3 CONFIG_SOC_SPI_DMA_CHAN_NUM=2 CONFIG_SOC_SPI_MAX_CS_NUM=3 +CONFIG_SOC_SPI_SUPPORT_CLK_APB=y CONFIG_SOC_SPI_MAXIMUM_BUFFER_SIZE=64 CONFIG_SOC_SPI_MAX_PRE_DIVIDER=8192 CONFIG_SOC_MEMSPI_SRC_FREQ_80M_SUPPORTED=y @@ -143,12 +174,17 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y -CONFIG_SOC_TOUCH_VERSION_1=y +CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 +CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 +CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 -CONFIG_SOC_TOUCH_PAD_MEASURE_WAIT_MAX=0xFF +CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 +CONFIG_SOC_TWAI_CONTROLLER_NUM=1 CONFIG_SOC_TWAI_BRP_MIN=2 +CONFIG_SOC_TWAI_CLK_SUPPORT_APB=y CONFIG_SOC_TWAI_SUPPORT_MULTI_ADDRESS_LAYOUT=y CONFIG_SOC_UART_NUM=3 +CONFIG_SOC_UART_HP_NUM=3 CONFIG_SOC_UART_SUPPORT_APB_CLK=y CONFIG_SOC_UART_SUPPORT_REF_TICK=y CONFIG_SOC_UART_FIFO_LEN=128 @@ -156,36 +192,61 @@ CONFIG_SOC_UART_BITRATE_MAX=5000000 CONFIG_SOC_SPIRAM_SUPPORTED=y CONFIG_SOC_SPI_MEM_SUPPORT_CONFIG_GPIO_BY_EFUSE=y CONFIG_SOC_SHA_SUPPORT_PARALLEL_ENG=y +CONFIG_SOC_SHA_ENDIANNESS_BE=y CONFIG_SOC_SHA_SUPPORT_SHA1=y CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y +CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 +CONFIG_SOC_MPI_OPERATIONS_NUM=1 CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 +CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y +CONFIG_SOC_PM_SUPPORT_EXT1_WAKEUP=y CONFIG_SOC_PM_SUPPORT_EXT_WAKEUP=y CONFIG_SOC_PM_SUPPORT_TOUCH_SENSOR_WAKEUP=y CONFIG_SOC_PM_SUPPORT_RTC_PERIPH_PD=y CONFIG_SOC_PM_SUPPORT_RTC_FAST_MEM_PD=y CONFIG_SOC_PM_SUPPORT_RTC_SLOW_MEM_PD=y +CONFIG_SOC_PM_SUPPORT_RC_FAST_PD=y +CONFIG_SOC_PM_SUPPORT_VDDSDIO_PD=y CONFIG_SOC_PM_SUPPORT_MODEM_PD=y +CONFIG_SOC_CONFIGURABLE_VDDSDIO_SUPPORTED=y +CONFIG_SOC_PM_MODEM_PD_BY_SW=y +CONFIG_SOC_CLK_APLL_SUPPORTED=y +CONFIG_SOC_CLK_RC_FAST_D256_SUPPORTED=y +CONFIG_SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256=y +CONFIG_SOC_CLK_RC_FAST_SUPPORT_CALIBRATION=y +CONFIG_SOC_CLK_XTAL32K_SUPPORTED=y CONFIG_SOC_SDMMC_USE_IOMUX=y CONFIG_SOC_SDMMC_NUM_SLOTS=2 CONFIG_SOC_WIFI_WAPI_SUPPORT=y CONFIG_SOC_WIFI_CSI_SUPPORT=y CONFIG_SOC_WIFI_MESH_SUPPORT=y +CONFIG_SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW=y +CONFIG_SOC_WIFI_NAN_SUPPORT=y CONFIG_SOC_BLE_SUPPORTED=y CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y +CONFIG_SOC_BLUFI_SUPPORTED=y +CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y +CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y +CONFIG_SOC_ULP_HAS_ADC=y +CONFIG_SOC_PHY_COMBO_MODULE=y +CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y CONFIG_IDF_CMAKE=y +CONFIG_IDF_TOOLCHAIN="gcc" +CONFIG_IDF_TOOLCHAIN_GCC=y CONFIG_IDF_TARGET_ARCH_XTENSA=y CONFIG_IDF_TARGET_ARCH="xtensa" CONFIG_IDF_TARGET="esp32" +CONFIG_IDF_INIT_VERSION="5.4.4" CONFIG_IDF_TARGET_ESP32=y CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 @@ -193,7 +254,7 @@ CONFIG_IDF_FIRMWARE_CHIP_ID=0x0000 # Build type # CONFIG_APP_BUILD_TYPE_APP_2NDBOOT=y -# CONFIG_APP_BUILD_TYPE_ELF_RAM is not set +# CONFIG_APP_BUILD_TYPE_RAM is not set CONFIG_APP_BUILD_GENERATE_BINARIES=y CONFIG_APP_BUILD_BOOTLOADER=y CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y @@ -206,11 +267,23 @@ CONFIG_APP_BUILD_USE_FLASH_SECTIONS=y # # Bootloader config # + +# +# Bootloader manager +# +CONFIG_BOOTLOADER_COMPILE_TIME_DATE=y +CONFIG_BOOTLOADER_PROJECT_VER=1 +# end of Bootloader manager + CONFIG_BOOTLOADER_OFFSET_IN_FLASH=0x1000 CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE is not set + +# +# Log +# # CONFIG_BOOTLOADER_LOG_LEVEL_NONE is not set # CONFIG_BOOTLOADER_LOG_LEVEL_ERROR is not set # CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set @@ -219,6 +292,14 @@ CONFIG_BOOTLOADER_LOG_LEVEL_INFO=y # CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set CONFIG_BOOTLOADER_LOG_LEVEL=3 +# +# Format +# +# CONFIG_BOOTLOADER_LOG_COLORS is not set +CONFIG_BOOTLOADER_LOG_TIMESTAMP_SOURCE_CPU_TICKS=y +# end of Format +# end of Log + # # Serial Flash Configurations # @@ -258,14 +339,23 @@ CONFIG_APP_COMPILE_TIME_DATE=y # CONFIG_APP_EXCLUDE_PROJECT_VER_VAR is not set # CONFIG_APP_EXCLUDE_PROJECT_NAME_VAR is not set # CONFIG_APP_PROJECT_VER_FROM_CONFIG is not set -CONFIG_APP_RETRIEVE_LEN_ELF_SHA=16 +CONFIG_APP_RETRIEVE_LEN_ELF_SHA=9 # end of Application manager CONFIG_ESP_ROM_HAS_CRC_LE=y CONFIG_ESP_ROM_HAS_CRC_BE=y CONFIG_ESP_ROM_HAS_MZ_CRC32=y CONFIG_ESP_ROM_HAS_JPEG_DECODE=y +CONFIG_ESP_ROM_HAS_UART_BUF_SWITCH=y CONFIG_ESP_ROM_NEEDS_SWSETUP_WORKAROUND=y +CONFIG_ESP_ROM_HAS_NEWLIB=y +CONFIG_ESP_ROM_HAS_NEWLIB_NANO_FORMAT=y +CONFIG_ESP_ROM_HAS_NEWLIB_32BIT_TIME=y +CONFIG_ESP_ROM_HAS_SW_FLOAT=y +CONFIG_ESP_ROM_USB_OTG_NUM=-1 +CONFIG_ESP_ROM_USB_SERIAL_DEVICE_NUM=-1 +CONFIG_ESP_ROM_SUPPORT_DEEP_SLEEP_WAKEUP_STUB=y +CONFIG_ESP_ROM_HAS_OUTPUT_PUTC_FUNC=y # # Serial flasher config @@ -283,14 +373,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set CONFIG_ESPTOOLPY_FLASHFREQ="40m" # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="4MB" +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" # CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set @@ -304,12 +394,13 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 # # Partition Table # -# CONFIG_PARTITION_TABLE_SINGLE_APP is not set +CONFIG_PARTITION_TABLE_SINGLE_APP=y # CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set -CONFIG_PARTITION_TABLE_CUSTOM=y +# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set +# CONFIG_PARTITION_TABLE_CUSTOM is not set CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # end of Partition Table @@ -317,13 +408,14 @@ CONFIG_PARTITION_TABLE_MD5=y # # Compiler options # -# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set +CONFIG_COMPILER_OPTIMIZATION_DEBUG=y # CONFIG_COMPILER_OPTIMIZATION_SIZE is not set -CONFIG_COMPILER_OPTIMIZATION_PERF=y +# CONFIG_COMPILER_OPTIMIZATION_PERF is not set # CONFIG_COMPILER_OPTIMIZATION_NONE is not set CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set +CONFIG_COMPILER_ASSERT_NDEBUG_EVALUATE=y CONFIG_COMPILER_FLOAT_LIB_FROM_GCCLIB=y CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2 # CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT is not set @@ -334,8 +426,18 @@ CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y # CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set # CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set # CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set +# CONFIG_COMPILER_NO_MERGE_CONSTANTS is not set # CONFIG_COMPILER_WARN_WRITE_STRINGS is not set +CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS=y +# CONFIG_COMPILER_DISABLE_GCC12_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC13_WARNINGS is not set +# CONFIG_COMPILER_DISABLE_GCC14_WARNINGS is not set # CONFIG_COMPILER_DUMP_RTL_FILES is not set +CONFIG_COMPILER_RT_LIB_GCCLIB=y +CONFIG_COMPILER_RT_LIB_NAME="gcc" +CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y +# CONFIG_COMPILER_ORPHAN_SECTIONS_PLACE is not set +# CONFIG_COMPILER_STATIC_ANALYZER is not set # end of Compiler options # @@ -357,319 +459,33 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # Bluetooth # -CONFIG_BT_ENABLED=y -CONFIG_BT_BLUEDROID_ENABLED=y -# CONFIG_BT_NIMBLE_ENABLED is not set -# CONFIG_BT_CONTROLLER_ONLY is not set -CONFIG_BT_CONTROLLER_ENABLED=y -# CONFIG_BT_CONTROLLER_DISABLED is not set - -# -# Bluedroid Options -# -CONFIG_BT_BTC_TASK_STACK_SIZE=3072 -CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y -# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set -CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 -CONFIG_BT_BTU_TASK_STACK_SIZE=4096 -# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set -# CONFIG_BT_CLASSIC_ENABLED is not set -CONFIG_BT_BLE_ENABLED=y -CONFIG_BT_GATTS_ENABLE=y -# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set -# CONFIG_BT_BLE_BLUFI_ENABLE is not set -CONFIG_BT_GATT_MAX_SR_PROFILES=8 -CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100 -# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set -CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y -CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 -# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set -# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set -# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set -CONFIG_BT_GATTC_ENABLE=y -CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 -CONFIG_BT_GATTC_NOTIF_REG_MAX=5 -# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set -CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 -CONFIG_BT_BLE_SMP_ENABLE=y -# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set -# CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set -# CONFIG_BT_STACK_NO_LOG is not set - -# -# BT DEBUG LOG LEVEL -# -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 -# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_HID_TRACE_LEVEL=2 -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set -CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set -# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set -CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 -# end of BT DEBUG LOG LEVEL - -CONFIG_BT_ACL_CONNECTIONS=4 -CONFIG_BT_MULTI_CONNECTION_ENBALE=y -# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set -# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set -# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set -CONFIG_BT_SMP_ENABLE=y -CONFIG_BT_SMP_MAX_BONDS=15 -# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set -CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 -CONFIG_BT_MAX_DEVICE_NAME_LEN=32 -# CONFIG_BT_BLE_RPA_SUPPORTED is not set -CONFIG_BT_BLE_RPA_TIMEOUT=900 -# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set -# end of Bluedroid Options - -# -# Controller Options -# -CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y -# CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set -# CONFIG_BTDM_CTRL_MODE_BTDM is not set -CONFIG_BTDM_CTRL_BLE_MAX_CONN=3 -CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 -CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 -CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 -CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 -CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 -CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 -CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y -# CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set -CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 -CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y -# CONFIG_BTDM_CTRL_HCI_MODE_UART_H4 is not set - -# -# MODEM SLEEP Options -# -CONFIG_BTDM_CTRL_MODEM_SLEEP=y -CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG=y -# CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED is not set -CONFIG_BTDM_CTRL_LPCLK_SEL_MAIN_XTAL=y -# end of MODEM SLEEP Options - -CONFIG_BTDM_BLE_DEFAULT_SCA_250PPM=y -CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 -CONFIG_BTDM_BLE_SCAN_DUPL=y -CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE=y -# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA is not set -# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE is not set -CONFIG_BTDM_SCAN_DUPL_TYPE=0 -CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=100 -CONFIG_BTDM_SCAN_DUPL_CACHE_REFRESH_PERIOD=0 -# CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN is not set -CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y -# CONFIG_BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set -CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y -CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 -CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 -CONFIG_BTDM_RESERVE_DRAM=0xdb5c -CONFIG_BTDM_CTRL_HLI=y -# end of Controller Options - -# CONFIG_BT_HCI_LOG_DEBUG_EN is not set +# CONFIG_BT_ENABLED is not set # # Common Options # -CONFIG_BT_ALARM_MAX_NUM=50 -# end of Common Options -# end of Bluetooth - -# CONFIG_BLE_MESH is not set # -# Driver Configurations +# BLE Log # +# CONFIG_BLE_LOG_ENABLED is not set +# end of BLE Log -# -# Legacy ADC Configuration -# -CONFIG_ADC_DISABLE_DAC=y -# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set +# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set +# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +# end of Common Options +# end of Bluetooth # -# Legacy ADC Calibration Configuration +# Console Library # -CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y -CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y -CONFIG_ADC_CAL_LUT_ENABLE=y -# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set -# end of Legacy ADC Calibration Configuration -# end of Legacy ADC Configuration +# CONFIG_CONSOLE_SORTED_HELP is not set +# end of Console Library # -# SPI Configuration +# Driver Configurations # -# CONFIG_SPI_MASTER_IN_IRAM is not set -CONFIG_SPI_MASTER_ISR_IN_IRAM=y -# CONFIG_SPI_SLAVE_IN_IRAM is not set -CONFIG_SPI_SLAVE_ISR_IN_IRAM=y -# end of SPI Configuration # # TWAI Configuration @@ -683,69 +499,76 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # end of TWAI Configuration # -# UART Configuration +# Legacy ADC Driver Configuration # -# CONFIG_UART_ISR_IN_IRAM is not set -# end of UART Configuration +CONFIG_ADC_DISABLE_DAC=y +# CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # -# GPIO Configuration +# Legacy ADC Calibration Configuration # -# CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL is not set -# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set -# end of GPIO Configuration +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y +# CONFIG_ADC_CALI_SUPPRESS_DEPRECATE_WARN is not set +# end of Legacy ADC Calibration Configuration +# end of Legacy ADC Driver Configuration # -# Sigma Delta Modulator Configuration +# Legacy DAC Driver Configurations # -# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set -# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_ENABLE_DEBUG_LOG is not set -# end of Sigma Delta Modulator Configuration +# CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy DAC Driver Configurations # -# GPTimer Configuration +# Legacy MCPWM Driver Configurations # -# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set -# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set -# end of GPTimer Configuration +# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy MCPWM Driver Configurations # -# PCNT Configuration +# Legacy Timer Group Driver Configurations # -# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set -# CONFIG_PCNT_ISR_IRAM_SAFE is not set -# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set -# end of PCNT Configuration +# CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy Timer Group Driver Configurations # -# RMT Configuration +# Legacy RMT Driver Configurations # -# CONFIG_RMT_ISR_IRAM_SAFE is not set -# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_RMT_ENABLE_DEBUG_LOG is not set -# end of RMT Configuration +# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy RMT Driver Configurations # -# MCPWM Configuration +# Legacy I2S Driver Configurations # -# CONFIG_MCPWM_ISR_IRAM_SAFE is not set -# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set -# CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set -# end of MCPWM Configuration +# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2S Driver Configurations # -# I2S Configuration +# Legacy I2C Driver Configurations # -# CONFIG_I2S_ISR_IRAM_SAFE is not set -# CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_I2S_ENABLE_DEBUG_LOG is not set -# end of I2S Configuration +# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy I2C Driver Configurations + +# +# Legacy PCNT Driver Configurations +# +# CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy PCNT Driver Configurations + +# +# Legacy SDM Driver Configurations +# +# CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set +# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set +# end of Legacy SDM Driver Configurations # end of Driver Configurations # @@ -765,9 +588,12 @@ CONFIG_EFUSE_MAX_BLK_LEN=192 CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_USE_SECURE_ELEMENT is not set # CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set -# CONFIG_ESP_TLS_SERVER is not set +# CONFIG_ESP_TLS_SERVER_SESSION_TICKETS is not set +# CONFIG_ESP_TLS_SERVER_CERT_SELECT_HOOK is not set +# CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set +CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -785,14 +611,131 @@ CONFIG_ADC_CALI_LUT_ENABLE=y # end of ADC Calibration Configurations CONFIG_ADC_DISABLE_DAC_OUTPUT=y +# CONFIG_ADC_ENABLE_DEBUG_LOG is not set # end of ADC and ADC Calibration +# +# Wireless Coexistence +# +CONFIG_ESP_COEX_ENABLED=y +# CONFIG_ESP_COEX_GPIO_DEBUG is not set +# end of Wireless Coexistence + # # Common ESP-related # CONFIG_ESP_ERR_TO_NAME_LOOKUP=y # end of Common ESP-related +# +# ESP-Driver:DAC Configurations +# +# CONFIG_DAC_CTRL_FUNC_IN_IRAM is not set +# CONFIG_DAC_ISR_IRAM_SAFE is not set +# CONFIG_DAC_ENABLE_DEBUG_LOG is not set +CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y +# end of ESP-Driver:DAC Configurations + +# +# ESP-Driver:GPIO Configurations +# +# CONFIG_GPIO_ESP32_SUPPORT_SWITCH_SLP_PULL is not set +# CONFIG_GPIO_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:GPIO Configurations + +# +# ESP-Driver:GPTimer Configurations +# +CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y +# CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set +# CONFIG_GPTIMER_ISR_IRAM_SAFE is not set +CONFIG_GPTIMER_OBJ_CACHE_SAFE=y +# CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:GPTimer Configurations + +# +# ESP-Driver:I2C Configurations +# +# CONFIG_I2C_ISR_IRAM_SAFE is not set +# CONFIG_I2C_ENABLE_DEBUG_LOG is not set +# CONFIG_I2C_ENABLE_SLAVE_DRIVER_VERSION_2 is not set +# end of ESP-Driver:I2C Configurations + +# +# ESP-Driver:I2S Configurations +# +# CONFIG_I2S_ISR_IRAM_SAFE is not set +# CONFIG_I2S_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:I2S Configurations + +# +# ESP-Driver:LEDC Configurations +# +# CONFIG_LEDC_CTRL_FUNC_IN_IRAM is not set +# end of ESP-Driver:LEDC Configurations + +# +# ESP-Driver:MCPWM Configurations +# +# CONFIG_MCPWM_ISR_IRAM_SAFE is not set +# CONFIG_MCPWM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_MCPWM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:MCPWM Configurations + +# +# ESP-Driver:PCNT Configurations +# +# CONFIG_PCNT_CTRL_FUNC_IN_IRAM is not set +# CONFIG_PCNT_ISR_IRAM_SAFE is not set +# CONFIG_PCNT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:PCNT Configurations + +# +# ESP-Driver:RMT Configurations +# +# CONFIG_RMT_ISR_IRAM_SAFE is not set +# CONFIG_RMT_RECV_FUNC_IN_IRAM is not set +# CONFIG_RMT_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:RMT Configurations + +# +# ESP-Driver:Sigma Delta Modulator Configurations +# +# CONFIG_SDM_CTRL_FUNC_IN_IRAM is not set +# CONFIG_SDM_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Sigma Delta Modulator Configurations + +# +# ESP-Driver:SPI Configurations +# +# CONFIG_SPI_MASTER_IN_IRAM is not set +CONFIG_SPI_MASTER_ISR_IN_IRAM=y +# CONFIG_SPI_SLAVE_IN_IRAM is not set +CONFIG_SPI_SLAVE_ISR_IN_IRAM=y +# end of ESP-Driver:SPI Configurations + +# +# ESP-Driver:Touch Sensor Configurations +# +# CONFIG_TOUCH_CTRL_FUNC_IN_IRAM is not set +# CONFIG_TOUCH_ISR_IRAM_SAFE is not set +# CONFIG_TOUCH_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:Touch Sensor Configurations + +# +# ESP-Driver:UART Configurations +# +# CONFIG_UART_ISR_IN_IRAM is not set +# end of ESP-Driver:UART Configurations + +# +# ESP-Driver:UHCI Configurations +# +# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set +# CONFIG_UHCI_ISR_CACHE_SAFE is not set +# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:UHCI Configurations + # # Ethernet # @@ -825,14 +768,27 @@ CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR=y # # GDB Stub # +CONFIG_ESP_GDBSTUB_ENABLED=y +# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y +CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub +# +# ESP HID +# +CONFIG_ESPHID_TASK_SIZE_BT=2048 +CONFIG_ESPHID_TASK_SIZE_BLE=4096 +# end of ESP HID + # # ESP HTTP client # CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS=y # CONFIG_ESP_HTTP_CLIENT_ENABLE_BASIC_AUTH is not set # CONFIG_ESP_HTTP_CLIENT_ENABLE_DIGEST_AUTH is not set +# CONFIG_ESP_HTTP_CLIENT_ENABLE_CUSTOM_TRANSPORT is not set +CONFIG_ESP_HTTP_CLIENT_EVENT_POST_TIMEOUT=2000 # end of ESP HTTP client # @@ -845,6 +801,7 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32 # CONFIG_HTTPD_LOG_PURGE_DATA is not set # CONFIG_HTTPD_WS_SUPPORT is not set # CONFIG_HTTPD_QUEUE_WORK_BLOCKING is not set +CONFIG_HTTPD_SERVER_EVENT_POST_TIMEOUT=2000 # end of HTTP Server # @@ -852,12 +809,14 @@ CONFIG_HTTPD_PURGE_BUF_LEN=32 # # CONFIG_ESP_HTTPS_OTA_DECRYPT_CB is not set # CONFIG_ESP_HTTPS_OTA_ALLOW_HTTP is not set +CONFIG_ESP_HTTPS_OTA_EVENT_POST_TIMEOUT=2000 # end of ESP HTTPS OTA # # ESP HTTPS server # # CONFIG_ESP_HTTPS_SERVER_ENABLE is not set +CONFIG_ESP_HTTPS_SERVER_EVENT_POST_TIMEOUT=2000 # end of ESP HTTPS server # @@ -882,6 +841,12 @@ CONFIG_ESP_REV_MIN_FULL=0 # CONFIG_ESP32_REV_MAX_FULL=399 CONFIG_ESP_REV_MAX_FULL=399 +CONFIG_ESP_EFUSE_BLOCK_REV_MIN_FULL=0 +CONFIG_ESP_EFUSE_BLOCK_REV_MAX_FULL=99 + +# +# Maximum Supported ESP32 eFuse Block Revision (eFuse Block Rev v0.99) +# # end of Chip revision # @@ -891,10 +856,13 @@ CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_STA=y CONFIG_ESP_MAC_ADDR_UNIVERSE_WIFI_AP=y CONFIG_ESP_MAC_ADDR_UNIVERSE_BT=y CONFIG_ESP_MAC_ADDR_UNIVERSE_ETH=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES_FOUR=y +CONFIG_ESP_MAC_UNIVERSAL_MAC_ADDRESSES=4 # CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 # CONFIG_ESP_MAC_IGNORE_MAC_CRC_ERROR is not set +# CONFIG_ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC is not set # end of MAC Config # @@ -905,7 +873,9 @@ CONFIG_ESP_SLEEP_FLASH_LEAKAGE_WORKAROUND=y # CONFIG_ESP_SLEEP_MSPI_NEED_ALL_IO_PU is not set CONFIG_ESP_SLEEP_RTC_BUS_ISO_WORKAROUND=y # CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND is not set -CONFIG_ESP_SLEEP_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP_SLEEP_WAIT_FLASH_READY_EXTRA_DELAY=2000 +# CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION is not set +# CONFIG_ESP_SLEEP_DEBUG is not set CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=y # end of Sleep Config @@ -929,57 +899,72 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # Main XTAL Config # # CONFIG_XTAL_FREQ_26 is not set +# CONFIG_XTAL_FREQ_32 is not set CONFIG_XTAL_FREQ_40=y # CONFIG_XTAL_FREQ_AUTO is not set CONFIG_XTAL_FREQ=40 # end of Main XTAL Config -# end of Hardware Settings -# -# LCD and Touch Panel -# +CONFIG_ESP_SPI_BUS_LOCK_ISR_FUNCS_IN_IRAM=y +# end of Hardware Settings # -# LCD Touch Drivers are maintained in the IDF Component Registry +# ESP-Driver:LCD Controller Configurations # +# CONFIG_LCD_ENABLE_DEBUG_LOG is not set +# end of ESP-Driver:LCD Controller Configurations # -# LCD Peripheral Configuration +# ESP-MM: Memory Management Configurations # -CONFIG_LCD_PANEL_IO_FORMAT_BUF_SIZE=32 -# CONFIG_LCD_ENABLE_DEBUG_LOG is not set -# end of LCD Peripheral Configuration -# end of LCD and Touch Panel +# end of ESP-MM: Memory Management Configurations # # ESP NETIF Adapter # CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL=120 +# CONFIG_ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION is not set CONFIG_ESP_NETIF_TCPIP_LWIP=y # CONFIG_ESP_NETIF_LOOPBACK is not set +CONFIG_ESP_NETIF_USES_TCPIP_WITH_BSD_API=y +CONFIG_ESP_NETIF_REPORT_DATA_TRAFFIC=y # CONFIG_ESP_NETIF_RECEIVE_REPORT_ERRORS is not set # CONFIG_ESP_NETIF_L2_TAP is not set # CONFIG_ESP_NETIF_BRIDGE_EN is not set +# CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF is not set # end of ESP NETIF Adapter +# +# Partition API Configuration +# +# end of Partition API Configuration + # # PHY # +CONFIG_ESP_PHY_ENABLED=y CONFIG_ESP_PHY_CALIBRATION_AND_DATA_STORAGE=y # CONFIG_ESP_PHY_INIT_DATA_IN_PARTITION is not set CONFIG_ESP_PHY_MAX_WIFI_TX_POWER=20 CONFIG_ESP_PHY_MAX_TX_POWER=20 # CONFIG_ESP_PHY_REDUCE_TX_POWER is not set +# CONFIG_ESP_PHY_ENABLE_CERT_TEST is not set CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 +CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 +# CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set +# CONFIG_ESP_PHY_RECORD_USED_TIME is not set +CONFIG_ESP_PHY_IRAM_OPT=y +# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # # Power Management # # CONFIG_PM_ENABLE is not set +# CONFIG_PM_SLP_IRAM_OPT is not set # end of Power Management # @@ -994,6 +979,11 @@ CONFIG_ESP_PHY_CALIBRATION_MODE=0 # CONFIG_RINGBUF_PLACE_FUNCTIONS_INTO_FLASH is not set # end of ESP Ringbuf +# +# ESP Security Specific +# +# end of ESP Security Specific + # # ESP System Settings # @@ -1006,6 +996,12 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=160 # Memory # # CONFIG_ESP32_USE_FIXED_STATIC_RAM_SIZE is not set + +# +# Non-backward compatible options +# +# CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM is not set +# end of Non-backward compatible options # end of Memory # @@ -1019,7 +1015,7 @@ CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0 CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y # CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set # CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set -# CONFIG_ESP_SYSTEM_GDBSTUB_RUNTIME is not set +CONFIG_ESP_SYSTEM_PANIC_REBOOT_DELAY_SECONDS=0 # # Memory protection @@ -1038,8 +1034,8 @@ CONFIG_ESP_CONSOLE_UART_DEFAULT=y # CONFIG_ESP_CONSOLE_UART_CUSTOM is not set # CONFIG_ESP_CONSOLE_NONE is not set CONFIG_ESP_CONSOLE_UART=y -CONFIG_ESP_CONSOLE_MULTIPLE_UART=y CONFIG_ESP_CONSOLE_UART_NUM=0 +CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0 CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200 CONFIG_ESP_INT_WDT=y CONFIG_ESP_INT_WDT_TIMEOUT_MS=300 @@ -1053,7 +1049,8 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP_PANIC_HANDLER_IRAM is not set # CONFIG_ESP_DEBUG_STUBS_ENABLE is not set CONFIG_ESP_DEBUG_OCDAWARE=y -CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5=y +# CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y # # Brownout Detector @@ -1083,54 +1080,80 @@ CONFIG_ESP_IPC_ISR_ENABLE=y # end of IPC (Inter-Processor Call) # -# High resolution timer (esp_timer) +# ESP Timer (High Resolution Timer) # # CONFIG_ESP_TIMER_PROFILING is not set CONFIG_ESP_TIME_FUNCS_USE_RTC_TIMER=y CONFIG_ESP_TIME_FUNCS_USE_ESP_TIMER=y CONFIG_ESP_TIMER_TASK_STACK_SIZE=3584 CONFIG_ESP_TIMER_INTERRUPT_LEVEL=1 +# CONFIG_ESP_TIMER_SHOW_EXPERIMENTAL is not set +CONFIG_ESP_TIMER_TASK_AFFINITY=0x0 +CONFIG_ESP_TIMER_TASK_AFFINITY_CPU0=y +CONFIG_ESP_TIMER_ISR_AFFINITY_CPU0=y # CONFIG_ESP_TIMER_SUPPORTS_ISR_DISPATCH_METHOD is not set CONFIG_ESP_TIMER_IMPL_TG0_LAC=y -# end of High resolution timer (esp_timer) +# end of ESP Timer (High Resolution Timer) # # Wi-Fi # -CONFIG_ESP32_WIFI_ENABLED=y -CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE=y -# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set -CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 -CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 -# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y -CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 -CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP_WIFI_ENABLED=y +CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +# CONFIG_ESP_WIFI_STATIC_TX_BUFFER is not set +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP_WIFI_STATIC_RX_MGMT_BUFFER=y # CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUFFER is not set CONFIG_ESP_WIFI_DYNAMIC_RX_MGMT_BUF=0 CONFIG_ESP_WIFI_RX_MGMT_BUF_NUM_DEF=5 -# CONFIG_ESP32_WIFI_CSI_ENABLED is not set -CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y -CONFIG_ESP32_WIFI_TX_BA_WIN=6 -CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y -CONFIG_ESP32_WIFI_RX_BA_WIN=6 -CONFIG_ESP32_WIFI_NVS_ENABLED=y -CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y -# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set -CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752 -CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32 -CONFIG_ESP32_WIFI_IRAM_OPT=y -CONFIG_ESP32_WIFI_RX_IRAM_OPT=y -CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE=y -CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA=y +# CONFIG_ESP_WIFI_CSI_ENABLED is not set +CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP_WIFI_TX_BA_WIN=6 +CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP_WIFI_RX_BA_WIN=6 +CONFIG_ESP_WIFI_NVS_ENABLED=y +CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y +# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set +CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752 +CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32 +CONFIG_ESP_WIFI_IRAM_OPT=y +# CONFIG_ESP_WIFI_EXTRA_IRAM_OPT is not set +CONFIG_ESP_WIFI_RX_IRAM_OPT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_SAE=y +CONFIG_ESP_WIFI_ENABLE_SAE_PK=y +CONFIG_ESP_WIFI_SOFTAP_SAE_SUPPORT=y +CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA=y # CONFIG_ESP_WIFI_SLP_IRAM_OPT is not set +CONFIG_ESP_WIFI_SLP_DEFAULT_MIN_ACTIVE_TIME=50 +CONFIG_ESP_WIFI_SLP_DEFAULT_MAX_ACTIVE_TIME=10 +CONFIG_ESP_WIFI_SLP_DEFAULT_WAIT_BROADCAST_DATA_TIME=15 CONFIG_ESP_WIFI_STA_DISCONNECTED_PM_ENABLE=y -# CONFIG_ESP_WIFI_GMAC_SUPPORT is not set +CONFIG_ESP_WIFI_GMAC_SUPPORT=y CONFIG_ESP_WIFI_SOFTAP_SUPPORT=y # CONFIG_ESP_WIFI_SLP_BEACON_LOST_OPT is not set CONFIG_ESP_WIFI_ESPNOW_MAX_ENCRYPT_NUM=7 +# CONFIG_ESP_WIFI_NAN_ENABLE is not set +CONFIG_ESP_WIFI_MBEDTLS_CRYPTO=y +CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y +# CONFIG_ESP_WIFI_WAPI_PSK is not set +# CONFIG_ESP_WIFI_11KV_SUPPORT is not set +# CONFIG_ESP_WIFI_MBO_SUPPORT is not set +# CONFIG_ESP_WIFI_DPP_SUPPORT is not set +# CONFIG_ESP_WIFI_11R_SUPPORT is not set +# CONFIG_ESP_WIFI_WPS_SOFTAP_REGISTRAR is not set + +# +# WPS Configuration Options +# +# CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set +# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set +# end of WPS Configuration Options + +# CONFIG_ESP_WIFI_DEBUG_PRINT is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1147,18 +1170,11 @@ CONFIG_ESP_COREDUMP_ENABLE_TO_NONE=y # FAT Filesystem support # CONFIG_FATFS_VOLUME_COUNT=2 +CONFIG_FATFS_LFN_NONE=y +# CONFIG_FATFS_LFN_HEAP is not set +# CONFIG_FATFS_LFN_STACK is not set # CONFIG_FATFS_SECTOR_512 is not set -# CONFIG_FATFS_SECTOR_1024 is not set -# CONFIG_FATFS_SECTOR_2048 is not set CONFIG_FATFS_SECTOR_4096=y -CONFIG_FATFS_SECTORS_PER_CLUSTER_1=y -# CONFIG_FATFS_SECTORS_PER_CLUSTER_2 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_4 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_8 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_16 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_32 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_64 is not set -# CONFIG_FATFS_SECTORS_PER_CLUSTER_128 is not set # CONFIG_FATFS_CODEPAGE_DYNAMIC is not set CONFIG_FATFS_CODEPAGE_437=y # CONFIG_FATFS_CODEPAGE_720 is not set @@ -1181,17 +1197,26 @@ CONFIG_FATFS_CODEPAGE_437=y # CONFIG_FATFS_CODEPAGE_936 is not set # CONFIG_FATFS_CODEPAGE_949 is not set # CONFIG_FATFS_CODEPAGE_950 is not set -CONFIG_FATFS_AUTO_TYPE=y -# CONFIG_FATFS_FAT12 is not set -# CONFIG_FATFS_FAT16 is not set CONFIG_FATFS_CODEPAGE=437 -CONFIG_FATFS_LFN_NONE=y -# CONFIG_FATFS_LFN_HEAP is not set -# CONFIG_FATFS_LFN_STACK is not set CONFIG_FATFS_FS_LOCK=0 CONFIG_FATFS_TIMEOUT_MS=10000 CONFIG_FATFS_PER_FILE_CACHE=y # CONFIG_FATFS_USE_FASTSEEK is not set +CONFIG_FATFS_USE_STRFUNC_NONE=y +# CONFIG_FATFS_USE_STRFUNC_WITHOUT_CRLF_CONV is not set +# CONFIG_FATFS_USE_STRFUNC_WITH_CRLF_CONV is not set +CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 +# CONFIG_FATFS_IMMEDIATE_FSYNC is not set +# CONFIG_FATFS_USE_LABEL is not set +CONFIG_FATFS_LINK_LOCK=y +# CONFIG_FATFS_USE_DYN_BUFFERS is not set + +# +# File system free space calculation behavior +# +CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 +CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 +# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1213,18 +1238,30 @@ CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1536 # CONFIG_FREERTOS_USE_TICK_HOOK is not set CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 # CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY is not set +CONFIG_FREERTOS_USE_TIMERS=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_NAME="Tmr Svc" +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU0 is not set +# CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1 is not set +CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY=y +CONFIG_FREERTOS_TIMER_SERVICE_TASK_CORE_AFFINITY=0x7FFFFFFF CONFIG_FREERTOS_TIMER_TASK_PRIORITY=1 CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=2048 CONFIG_FREERTOS_TIMER_QUEUE_LENGTH=10 CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=1 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set +# CONFIG_FREERTOS_USE_LIST_DATA_INTEGRITY_CHECK_BYTES is not set # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set +# CONFIG_FREERTOS_USE_APPLICATION_TASK_TAG is not set # end of Kernel # # Port # +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y # CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set +CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS=y +# CONFIG_FREERTOS_TASK_PRE_DELETION_HOOK is not set # CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP is not set CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y CONFIG_FREERTOS_ISR_STACKSIZE=1536 @@ -1235,15 +1272,21 @@ CONFIG_FREERTOS_CORETIMER_0=y # CONFIG_FREERTOS_CORETIMER_1 is not set CONFIG_FREERTOS_SYSTICK_USES_CCOUNT=y # CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH is not set -# CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH is not set # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set -CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y -CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y # end of Port +# +# Extra +# +# end of Extra + +CONFIG_FREERTOS_PORT=y CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION=y CONFIG_FREERTOS_DEBUG_OCDAWARE=y +CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT=y +CONFIG_FREERTOS_PLACE_SNAPSHOT_FUNS_INTO_FLASH=y +CONFIG_FREERTOS_NUMBER_OF_CORES=2 # end of FreeRTOS # @@ -1254,6 +1297,8 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y # CONFIG_HAL_ASSERTION_SILENT is not set # CONFIG_HAL_ASSERTION_ENABLE is not set CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 +CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y +CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1265,11 +1310,18 @@ CONFIG_HEAP_POISONING_DISABLED=y CONFIG_HEAP_TRACING_OFF=y # CONFIG_HEAP_TRACING_STANDALONE is not set # CONFIG_HEAP_TRACING_TOHOST is not set +# CONFIG_HEAP_USE_HOOKS is not set +# CONFIG_HEAP_TASK_TRACKING is not set # CONFIG_HEAP_ABORT_WHEN_ALLOCATION_FAILS is not set +# CONFIG_HEAP_PLACE_FUNCTION_INTO_FLASH is not set # end of Heap memory debugging # -# Log output +# Log +# + +# +# Log Level # # CONFIG_LOG_DEFAULT_LEVEL_NONE is not set # CONFIG_LOG_DEFAULT_LEVEL_ERROR is not set @@ -1282,14 +1334,34 @@ CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y # CONFIG_LOG_MAXIMUM_LEVEL_DEBUG is not set # CONFIG_LOG_MAXIMUM_LEVEL_VERBOSE is not set CONFIG_LOG_MAXIMUM_LEVEL=3 -CONFIG_LOG_COLORS=y + +# +# Level Settings +# +# CONFIG_LOG_MASTER_LEVEL is not set +CONFIG_LOG_DYNAMIC_LEVEL_CONTROL=y +# CONFIG_LOG_TAG_LEVEL_IMPL_NONE is not set +# CONFIG_LOG_TAG_LEVEL_IMPL_LINKED_LIST is not set +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_AND_LINKED_LIST=y +# CONFIG_LOG_TAG_LEVEL_CACHE_ARRAY is not set +CONFIG_LOG_TAG_LEVEL_CACHE_BINARY_MIN_HEAP=y +CONFIG_LOG_TAG_LEVEL_IMPL_CACHE_SIZE=31 +# end of Level Settings +# end of Log Level + +# +# Format +# +# CONFIG_LOG_COLORS is not set CONFIG_LOG_TIMESTAMP_SOURCE_RTOS=y # CONFIG_LOG_TIMESTAMP_SOURCE_SYSTEM is not set -# end of Log output +# end of Format +# end of Log # # LWIP # +CONFIG_LWIP_ENABLE=y CONFIG_LWIP_LOCAL_HOSTNAME="espressif" # CONFIG_LWIP_NETIF_API is not set CONFIG_LWIP_TCPIP_TASK_PRIO=18 @@ -1298,7 +1370,10 @@ CONFIG_LWIP_TCPIP_TASK_PRIO=18 CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y # CONFIG_LWIP_L2_TO_L3_COPY is not set # CONFIG_LWIP_IRAM_OPTIMIZATION is not set +# CONFIG_LWIP_EXTRA_IRAM_OPTIMIZATION is not set CONFIG_LWIP_TIMERS_ONDEMAND=y +CONFIG_LWIP_ND6=y +# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set CONFIG_LWIP_MAX_SOCKETS=10 # CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set # CONFIG_LWIP_SO_LINGER is not set @@ -1311,6 +1386,7 @@ CONFIG_LWIP_IP4_FRAG=y CONFIG_LWIP_IP6_FRAG=y # CONFIG_LWIP_IP4_REASSEMBLY is not set # CONFIG_LWIP_IP6_REASSEMBLY is not set +CONFIG_LWIP_IP_REASS_MAX_PBUFS=10 # CONFIG_LWIP_IP_FORWARD is not set # CONFIG_LWIP_STATS is not set CONFIG_LWIP_ESP_GRATUITOUS_ARP=y @@ -1319,10 +1395,12 @@ CONFIG_LWIP_ESP_MLDV6_REPORT=y CONFIG_LWIP_MLDV6_TMR_INTERVAL=40 CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=32 CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y +# CONFIG_LWIP_DHCP_DOES_ACD_CHECK is not set +# CONFIG_LWIP_DHCP_DOES_NOT_CHECK_OFFERED_IP is not set # CONFIG_LWIP_DHCP_DISABLE_CLIENT_ID is not set CONFIG_LWIP_DHCP_DISABLE_VENDOR_CLASS_ID=y # CONFIG_LWIP_DHCP_RESTORE_LAST_IP is not set -CONFIG_LWIP_DHCP_OPTIONS_LEN=68 +CONFIG_LWIP_DHCP_OPTIONS_LEN=69 CONFIG_LWIP_NUM_NETIF_CLIENT_DATA=0 CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 @@ -1332,9 +1410,12 @@ CONFIG_LWIP_DHCP_COARSE_TIMER_SECS=1 CONFIG_LWIP_DHCPS=y CONFIG_LWIP_DHCPS_LEASE_UNIT=60 CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_DHCPS_STATIC_ENTRIES=y +CONFIG_LWIP_DHCPS_ADD_DNS=y # end of DHCP server # CONFIG_LWIP_AUTOIP is not set +CONFIG_LWIP_IPV4=y CONFIG_LWIP_IPV6=y # CONFIG_LWIP_IPV6_AUTOCONFIG is not set CONFIG_LWIP_IPV6_NUM_ADDRESSES=3 @@ -1358,6 +1439,7 @@ CONFIG_LWIP_TCP_FIN_WAIT_TIMEOUT=20000 CONFIG_LWIP_TCP_SND_BUF_DEFAULT=5760 CONFIG_LWIP_TCP_WND_DEFAULT=5760 CONFIG_LWIP_TCP_RECVMBOX_SIZE=6 +CONFIG_LWIP_TCP_ACCEPTMBOX_SIZE=6 CONFIG_LWIP_TCP_QUEUE_OOSEQ=y CONFIG_LWIP_TCP_OOSEQ_TIMEOUT=6 CONFIG_LWIP_TCP_OOSEQ_MAX_PBUFS=4 @@ -1388,11 +1470,13 @@ CONFIG_LWIP_TCPIP_TASK_AFFINITY_NO_AFFINITY=y # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU0 is not set # CONFIG_LWIP_TCPIP_TASK_AFFINITY_CPU1 is not set CONFIG_LWIP_TCPIP_TASK_AFFINITY=0x7FFFFFFF -# CONFIG_LWIP_PPP_SUPPORT is not set CONFIG_LWIP_IPV6_MEMP_NUM_ND6_QUEUE=3 CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 -CONFIG_LWIP_ND6=y -# CONFIG_LWIP_FORCE_ROUTER_FORWARDING is not set +CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 +CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 +CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 +# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set +# CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set # @@ -1415,17 +1499,20 @@ CONFIG_LWIP_MAX_RAW_PCBS=16 CONFIG_LWIP_SNTP_MAX_SERVERS=1 # CONFIG_LWIP_DHCP_GET_NTP_SRV is not set CONFIG_LWIP_SNTP_UPDATE_DELAY=3600000 +CONFIG_LWIP_SNTP_STARTUP_DELAY=y +CONFIG_LWIP_SNTP_MAXIMUM_STARTUP_DELAY=5000 # end of SNTP -CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 - # # DNS # +CONFIG_LWIP_DNS_MAX_HOST_IP=1 CONFIG_LWIP_DNS_MAX_SERVERS=3 # CONFIG_LWIP_FALLBACK_DNS_SERVER_SUPPORT is not set +# CONFIG_LWIP_DNS_SETSERVER_WITH_NETIF is not set # end of DNS +CONFIG_LWIP_BRIDGEIF_MAX_PORTS=7 CONFIG_LWIP_ESP_LWIP_ASSERT=y # @@ -1440,11 +1527,16 @@ CONFIG_LWIP_HOOK_IP6_ROUTE_NONE=y CONFIG_LWIP_HOOK_ND6_GET_GW_NONE=y # CONFIG_LWIP_HOOK_ND6_GET_GW_DEFAULT is not set # CONFIG_LWIP_HOOK_ND6_GET_GW_CUSTOM is not set +CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_NONE=y +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_DEFAULT is not set +# CONFIG_LWIP_HOOK_IP6_SELECT_SRC_ADDR_CUSTOM is not set CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y # CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_DEFAULT is not set # CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_CUSTOM is not set -CONFIG_LWIP_HOOK_IP6_INPUT_NONE=y -# CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT is not set +CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_NONE=y +# CONFIG_LWIP_HOOK_DNS_EXT_RESOLVE_CUSTOM is not set +# CONFIG_LWIP_HOOK_IP6_INPUT_NONE is not set +CONFIG_LWIP_HOOK_IP6_INPUT_DEFAULT=y # CONFIG_LWIP_HOOK_IP6_INPUT_CUSTOM is not set # end of Hooks @@ -1471,6 +1563,7 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y +# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1482,14 +1575,16 @@ CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=y # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_CMN is not set # CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_NONE is not set # CONFIG_MBEDTLS_CUSTOM_CERTIFICATE_BUNDLE is not set +# CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEPRECATED_LIST is not set CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_MAX_CERTS=200 # end of Certificate Bundle # CONFIG_MBEDTLS_ECP_RESTARTABLE is not set CONFIG_MBEDTLS_CMAC_C=y CONFIG_MBEDTLS_HARDWARE_AES=y -# CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER is not set +CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER=y CONFIG_MBEDTLS_HARDWARE_MPI=y +# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set CONFIG_MBEDTLS_HARDWARE_SHA=y CONFIG_MBEDTLS_ROM_MD5=y # CONFIG_MBEDTLS_ATCA_HW_ECDSA_SIGN is not set @@ -1498,7 +1593,9 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y +CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y +# CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y # CONFIG_MBEDTLS_TLS_SERVER_ONLY is not set # CONFIG_MBEDTLS_TLS_CLIENT_ONLY is not set @@ -1552,6 +1649,8 @@ CONFIG_MBEDTLS_X509_CSR_PARSE_C=y # end of Certificates CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y +CONFIG_MBEDTLS_PK_PARSE_EC_COMPRESSED=y # CONFIG_MBEDTLS_DHM_C is not set CONFIG_MBEDTLS_ECDH_C=y CONFIG_MBEDTLS_ECDSA_C=y @@ -1569,12 +1668,14 @@ CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y CONFIG_MBEDTLS_ECP_NIST_OPTIM=y -CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM=y +# CONFIG_MBEDTLS_ECP_FIXED_POINT_OPTIM is not set # CONFIG_MBEDTLS_POLY1305_C is not set # CONFIG_MBEDTLS_CHACHA20_C is not set # CONFIG_MBEDTLS_HKDF_C is not set # CONFIG_MBEDTLS_THREADING_C is not set -# CONFIG_MBEDTLS_LARGE_KEY_SOFTWARE_MPI is not set +CONFIG_MBEDTLS_ERROR_STRINGS=y +CONFIG_MBEDTLS_FS_IO=y +# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -1613,12 +1714,21 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # NVS # # CONFIG_NVS_ASSERT_ERROR_CHECK is not set +# CONFIG_NVS_LEGACY_DUP_KEYS_COMPATIBILITY is not set # end of NVS # # OpenThread # # CONFIG_OPENTHREAD_ENABLED is not set + +# +# OpenThread Spinel +# +# CONFIG_OPENTHREAD_SPINEL_ONLY is not set +# end of OpenThread Spinel + +# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -1627,6 +1737,7 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y +CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -1668,6 +1779,9 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # # Features here require specific hardware (READ DOCS FIRST!) # +CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 +# CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set +# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -1693,6 +1807,11 @@ CONFIG_SPI_FLASH_WRITE_CHUNK_SIZE=8192 # # Auto-detect flash chips # +CONFIG_SPI_FLASH_VENDOR_XMC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_GD_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_ISSI_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_MXIC_SUPPORTED=y +CONFIG_SPI_FLASH_VENDOR_WINBOND_SUPPORTED=y CONFIG_SPI_FLASH_SUPPORT_ISSI_CHIP=y CONFIG_SPI_FLASH_SUPPORT_MXIC_CHIP=y CONFIG_SPI_FLASH_SUPPORT_GD_CHIP=y @@ -1757,6 +1876,11 @@ CONFIG_WS_BUFFER_SIZE=1024 # Ultra Low Power (ULP) Co-processor # # CONFIG_ULP_COPROC_ENABLED is not set + +# +# ULP Debugging Options +# +# end of ULP Debugging Options # end of Ultra Low Power (ULP) Co-processor # @@ -1771,11 +1895,6 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y # CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL is not set # end of Unity unit testing library -# -# Root Hub configuration -# -# end of Root Hub configuration - # # Virtual file system # @@ -1783,13 +1902,17 @@ CONFIG_VFS_SUPPORT_IO=y CONFIG_VFS_SUPPORT_DIR=y CONFIG_VFS_SUPPORT_SELECT=y CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SELECT_IN_RAM is not set CONFIG_VFS_SUPPORT_TERMIOS=y +CONFIG_VFS_MAX_COUNT=8 # # Host File System I/O (Semihosting) # CONFIG_VFS_SEMIHOSTFS_MAX_MOUNT_POINTS=1 # end of Host File System I/O (Semihosting) + +CONFIG_VFS_INITIALIZE_DEV_NULL=y # end of Virtual file system # @@ -1805,26 +1928,9 @@ CONFIG_WL_SECTOR_SIZE=4096 # CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 -# CONFIG_WIFI_PROV_BLE_BONDING is not set -# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set -# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set # end of Wi-Fi Provisioning Manager - -# -# Supplicant -# -CONFIG_WPA_MBEDTLS_CRYPTO=y -CONFIG_WPA_MBEDTLS_TLS_CLIENT=y -# CONFIG_WPA_WAPI_PSK is not set -# CONFIG_WPA_DEBUG_PRINT is not set -# CONFIG_WPA_TESTING_OPTIONS is not set -# CONFIG_WPA_WPS_STRICT is not set -# CONFIG_WPA_11KV_SUPPORT is not set -# CONFIG_WPA_MBO_SUPPORT is not set -# CONFIG_WPA_DPP_SUPPORT is not set -# CONFIG_WPA_11R_SUPPORT is not set -# CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set -# end of Supplicant # end of Component config + +# CONFIG_IDF_EXPERIMENTAL_FEATURES is not set From 8e4e165450ad22cfd8bbbacc6794ae38cf22b3b5 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 4 Jul 2026 11:03:56 +0900 Subject: [PATCH 11/33] Add windows to cli --- cli/src/commands/board/flash-runtime.ts | 2 +- cli/src/commands/board/setup/esp32-darwin.ts | 42 +++++--------- cli/src/commands/board/setup/esp32-windows.ts | 55 ++++++++---------- cli/src/commands/board/setup/host-darwin.ts | 23 +++----- cli/src/commands/board/setup/host-windows.ts | 39 +++++++++---- cli/src/commands/board/setup/utils.ts | 32 ++++++++++ cli/src/commands/board/update.ts | 23 +++++++- cli/src/config/global-config.ts | 15 +++-- cli/src/platforms/board-env/esp32-env.ts | 29 +++++----- cli/src/platforms/board-env/host-env.ts | 2 + .../compiler/esp32-compiler-adapter.ts | 5 +- .../compiler/host-compiler-adapter.ts | 58 ++++++++++++++----- cli/tests/commands/board/setup.test.ts | 6 +- cli/tests/commands/global-env-helper.ts | 25 ++++++-- cli/tests/config/global-config.test.ts | 7 ++- .../integration/project/repl.host.test.ts | 12 ++-- .../integration/project/run.host.test.ts | 14 ++--- .../board-toolchain/host-toolchain.ts | 42 +++++++------- .../board-toolchain/tools/makefile.ts | 14 ++--- lang/src/index.ts | 4 +- lang/tests/compiler/compiler-esp32.test.ts | 2 +- lang/tests/compiler/compiler-host.test.ts | 2 +- lang/tests/compiler/test-utils-esp32.ts | 14 +++-- lang/tests/compiler/test-utils-host.ts | 26 +++++++-- microcontroller/ports/host/shell.c | 6 -- 25 files changed, 302 insertions(+), 197 deletions(-) create mode 100644 cli/src/commands/board/setup/utils.ts diff --git a/cli/src/commands/board/flash-runtime.ts b/cli/src/commands/board/flash-runtime.ts index f1260528..ca256108 100644 --- a/cli/src/commands/board/flash-runtime.ts +++ b/cli/src/commands/board/flash-runtime.ts @@ -51,7 +51,7 @@ class ESP32FlashRuntimeHandler extends FlashRuntimeHandler { private async runIdfPy(exportFile: string, args: string[], cwd: string) { const osType = os.platform(); - const preCommand = osType === 'win32' ? exportFile : `source ${exportFile}`; + const preCommand = osType === 'win32' ? `call ${exportFile}` : `source ${exportFile}`; await exec(`${preCommand} && idf.py ${args.join(' ')}`,{ cwd }); } diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts index cad97030..665f4d7c 100644 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -1,8 +1,10 @@ import { SetupHandler } from "./base"; import { exec } from '../../../core/shell'; import { skip } from "../../../core/logger"; +import * as path from 'path'; import { BoardName } from "../../../config/board-utils"; import { Esp32DarwinEnv } from "../../../platforms/board-env/esp32-env"; +import { isPackageInstalledOnUnix, isPythonVersionGreaterThan3 } from "./utils"; export class Esp32DarwinSetupHandler extends SetupHandler { @@ -38,32 +40,38 @@ export class Esp32DarwinSetupHandler extends SetupHandler { } async setBoardConfig() { + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(); this.globalConfigHandler.updateBoardConfig(this.boardName, { idfVersion: this.boardEnv.idfVersion, rootDir: this.boardEnv.espRootDir, exportFile: this.boardEnv.idfExportFile, - xtensaGccDir: await this.boardEnv.getXtensaGccDir(), + toolchain: { + gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), + ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), + ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), + make: 'make' + }, }); } private async verifyPrerequisitsInstalledStep() { - if (!await this.isPackageInstalled("git")) { + if (!await isPackageInstalledOnUnix("git")) { throw new Error("Cannot find git command. Please install git and try again."); } - if (!await this.isPackageInstalled("brew")) { + if (!await isPackageInstalledOnUnix("brew")) { throw new Error("Cannot find brew command. Please install Homebrew and try again."); } - if (!(await this.isPythonVersionGreaterThan3()) && !(await this.isPackageInstalled('python3'))) { + if (!(await isPythonVersionGreaterThan3()) && !(await isPackageInstalledOnUnix('python3'))) { throw new Error("Cannot find python3. Please install Python3 and try again."); } } private async installRequiredPackagesStep() { let packages: string[] = []; - if (!(await this.isPackageInstalled('cmake'))) { packages.push('cmake'); } - if (!(await this.isPackageInstalled('ninja'))) { packages.push('ninja'); } - if (!(await this.isPackageInstalled('dfu-util'))) { packages.push('dfu-util'); } - if (!(await this.isPackageInstalled('ccache'))) { packages.push('ccache'); } + if (!(await isPackageInstalledOnUnix('cmake'))) { packages.push('cmake'); } + if (!(await isPackageInstalledOnUnix('ninja'))) { packages.push('ninja'); } + if (!(await isPackageInstalledOnUnix('dfu-util'))) { packages.push('dfu-util'); } + if (!(await isPackageInstalledOnUnix('ccache'))) { packages.push('ccache'); } if (packages.length === 0) { return skip('already installed.'); } @@ -77,22 +85,4 @@ export class Esp32DarwinSetupHandler extends SetupHandler { private async runEspIdfInstallScriptStep() { await this.boardEnv.runEspIdfInstallScript(); } - - private async isPackageInstalled(name: string) { - try { - await exec(`which ${name}`, { silent: true }); - return true; - } catch (error) { - return false; - } - } - - private async isPythonVersionGreaterThan3() { - try { - const result = await exec(`python --version`, { silent: true }); - return result.startsWith('Python 3.'); - } catch (error) { - return false; - } - } } \ No newline at end of file diff --git a/cli/src/commands/board/setup/esp32-windows.ts b/cli/src/commands/board/setup/esp32-windows.ts index 1e20330f..15f01d84 100644 --- a/cli/src/commands/board/setup/esp32-windows.ts +++ b/cli/src/commands/board/setup/esp32-windows.ts @@ -1,13 +1,13 @@ import { SetupHandler } from "./base"; -import { exec } from '../../../core/shell'; -import { skip } from "../../../core/logger"; +import * as path from 'path'; import { BoardName } from "../../../config/board-utils"; -import { Esp32DarwinEnv, Esp32WindowsEnv } from "../../../platforms/board-env/esp32-env"; - +import { Esp32WindowsEnv } from "../../../platforms/board-env/esp32-env"; +import { isPackageInstalledOnWindows, isPythonVersionGreaterThan3 } from "./utils"; export class Esp32WindowsSetupHandler extends SetupHandler { - boardName: BoardName = "host"; + boardName: BoardName = "esp32"; boardEnv: Esp32WindowsEnv; + makeCommand?: string; constructor() { super(); @@ -16,7 +16,7 @@ export class Esp32WindowsSetupHandler extends SetupHandler { loadBoardSetupSteps(): void { this.setupSteps.push({ - description: "Verify that git and python3 are installed.", + description: "Verify that git, python3 and make are installed.", actionMessage: "Verifying that git and python3 are installed...", action: this.verifyPrerequisitsInstalledStep.bind(this), }); @@ -33,21 +33,36 @@ export class Esp32WindowsSetupHandler extends SetupHandler { } async setBoardConfig() { + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(); this.globalConfigHandler.updateBoardConfig(this.boardName, { idfVersion: this.boardEnv.idfVersion, rootDir: this.boardEnv.espRootDir, exportFile: this.boardEnv.idfExportFile, - xtensaGccDir: await this.boardEnv.getXtensaGccDir(), + toolchain: { + gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), + ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), + ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), + make: this.makeCommand! + }, }); } private async verifyPrerequisitsInstalledStep() { - if (!await this.isPackageInstalled("git")) { + if (!await isPackageInstalledOnWindows("git")) { throw new Error("Cannot find git command. Please install git and try again."); } - if (!(await this.isPythonVersionGreaterThan3()) && !(await this.isPackageInstalled('python3'))) { + if (!(await isPythonVersionGreaterThan3()) && !(await isPackageInstalledOnWindows('python3'))) { throw new Error("Cannot find python3. Please install Python3 and try again."); } + + // make command + if (await isPackageInstalledOnWindows('make')) { + this.makeCommand = 'make'; + } else if (await isPackageInstalledOnWindows('mingw32-make')) { + this.makeCommand = 'mingw32-make'; + } else { + throw new Error("Cannot find make or mingw32-make command. Please install make or mingw32-make and try again."); + } } private async cloneEspIdfStep() { @@ -57,26 +72,4 @@ export class Esp32WindowsSetupHandler extends SetupHandler { private async runEspIdfInstallScriptStep() { await this.boardEnv.runEspIdfInstallScript(); } - - private async isPackageInstalled(name: string) { - // try { - // await exec(`which ${name}`, { silent: true }); - // return true; - // } catch (error) { - // return false; - // } - // TODO - return true; - } - - private async isPythonVersionGreaterThan3() { - // try { - // const result = await exec(`python --version`, { silent: true }); - // return result.startsWith('Python 3.'); - // } catch (error) { - // return false; - // } - // TODO - return false; - } } \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-darwin.ts b/cli/src/commands/board/setup/host-darwin.ts index dfc72590..6ef2b9c2 100644 --- a/cli/src/commands/board/setup/host-darwin.ts +++ b/cli/src/commands/board/setup/host-darwin.ts @@ -1,7 +1,7 @@ import { SetupHandler } from "./base"; -import { exec } from '../../../core/shell'; import { BoardName } from "../../../config/board-utils"; import { HostDarwinEnv } from "../../../platforms/board-env/host-env"; +import { isPackageInstalledOnUnix } from "./utils"; export class HostDarwinSetupHandler extends SetupHandler { @@ -30,17 +30,19 @@ export class HostDarwinSetupHandler extends SetupHandler { this.globalConfigHandler.updateBoardConfig('host', { rootDir: this.boardEnv.hostRootDir, shellFile: this.boardEnv.shellFile, - gccCommand: 'cc', - makeCommand: 'make', - arCommand: 'ar' + toolchain: { + gcc: 'cc', + ar: 'ar', + make: 'make' + }, }) } private async verifyPrerequisitsInstalledStep() { - if (!await this.isPackageInstalled("cc")) { + if (!await isPackageInstalledOnUnix("cc")) { throw new Error("Cannot find cc command. Please install cc and try again."); } - if (!await this.isPackageInstalled("make")) { + if (!await isPackageInstalledOnUnix("make")) { throw new Error("Cannot find make command. Please install make and try again."); } } @@ -48,13 +50,4 @@ export class HostDarwinSetupHandler extends SetupHandler { private async buildHostRuntimeStep() { await this.boardEnv.buildHostRuntime(); } - - private async isPackageInstalled(name: string) { - try { - await exec(`which ${name}`, { silent: true }); - return true; - } catch (error) { - return false; - } - } } \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-windows.ts b/cli/src/commands/board/setup/host-windows.ts index 1aae21e9..2e0075c2 100644 --- a/cli/src/commands/board/setup/host-windows.ts +++ b/cli/src/commands/board/setup/host-windows.ts @@ -2,6 +2,7 @@ import { SetupHandler } from "./base"; import { exec } from '../../../core/shell'; import { BoardName } from "../../../config/board-utils"; import { HostWindowsEnv } from "../../../platforms/board-env/host-env"; +import { isPackageInstalledOnWindows } from "./utils"; export class HostWindowsSetupHandler extends SetupHandler { @@ -17,7 +18,7 @@ export class HostWindowsSetupHandler extends SetupHandler { this.setupSteps.push({ description: "Verify that MinGW is installed.", // write version actionMessage: "Verifying that MinGW is installed...", - action: this.installMinGWStep.bind(this), + action: this.verifyMingwIsInstalledStep.bind(this), }); this.setupSteps.push({ description: "Build host runtime.", @@ -30,20 +31,38 @@ export class HostWindowsSetupHandler extends SetupHandler { this.globalConfigHandler.updateBoardConfig('host', { rootDir: this.boardEnv.hostRootDir, shellFile: this.boardEnv.shellFile, - gccCommand: 'gcc', - makeCommand: 'mingw32-make', - arCommand: 'ar' + toolchain: { + gcc: 'gcc', + ar: 'ar', + make: 'mingw32-make' + }, }) } - private async installMinGWStep() { - // TODO + + private async verifyMingwIsInstalledStep() { + if (await isPackageInstalledOnWindows('gcc')) { + if (!await this.isMingwGccAvailable()) { + throw new Error("gcc is not a MinGW compiler. Please install MinGW-w64 and add it to PATH."); + } + } else { + throw new Error("Cannot find gcc command. Please install MinGW-w64 and add it to PATH."); + } } - private async buildHostRuntimeStep() { - await this.boardEnv.buildHostRuntime(); + private async isMingwGccAvailable(): Promise { + const machine = await this.getGccTargetMachine(); + return machine?.includes('mingw') ?? false; } - private async isPackageInstalled(name: string) { - // TODO + private async getGccTargetMachine(): Promise { + try { + return (await exec('gcc -dumpmachine', { silent: true })).trim(); + } catch { + return undefined; + } + } + + private async buildHostRuntimeStep() { + await this.boardEnv.buildHostRuntime(); } } \ No newline at end of file diff --git a/cli/src/commands/board/setup/utils.ts b/cli/src/commands/board/setup/utils.ts new file mode 100644 index 00000000..f304e066 --- /dev/null +++ b/cli/src/commands/board/setup/utils.ts @@ -0,0 +1,32 @@ +import { exec } from '../../../core/shell'; + + +export async function isPackageInstalledOnUnix(name: string) { + try { + await exec(`which ${name}`, { silent: true }); + return true; + } catch (error) { + return false; + } +} + +export async function isPackageInstalledOnWindows(name: string) { + try { + await exec(`where ${name}`, { silent: true }); + return true; + } catch (error) { + return false; + } +} + +export async function isPythonVersionGreaterThan3() { + try { + const result = await exec( + `python -c "import sys; print(sys.version_info.major)"`, + { silent: true }, + ); + return result.trim() === '3'; + } catch { + return false; + } +} \ No newline at end of file diff --git a/cli/src/commands/board/update.ts b/cli/src/commands/board/update.ts index 8b5777ff..512a8013 100644 --- a/cli/src/commands/board/update.ts +++ b/cli/src/commands/board/update.ts @@ -5,6 +5,7 @@ import { GLOBAL_SETTINGS } from "../../config/constants"; import * as fs from '../../core/fs'; import * as path from 'path'; import { CommonBoardEnv, createBoardEnv, Esp32Env } from "../../platforms/board-env"; +import { Esp32BoardConfig } from "../../config/global-config"; class UpdateHandler extends CommandHandler { @@ -44,6 +45,9 @@ class UpdateHandler extends CommandHandler { if (fs.exists(this.tmpEspDir)) { fs.removeDir(this.tmpEspDir); } + if (fs.exists(this.tmpHostDir)) { + fs.removeDir(this.tmpHostDir); + } this.globalConfigHandler.save(); } } @@ -68,7 +72,7 @@ class UpdateHandler extends CommandHandler { if (esp32Config.idfVersion === esp32Env.idfVersion) { return skip('not needed'); } - await this.updateEsp32(esp32Env); + await this.updateEsp32(esp32Env, esp32Config); }); } @@ -97,20 +101,31 @@ class UpdateHandler extends CommandHandler { private async updateHost() { const hostEnv = createBoardEnv('host'); await hostEnv.buildHostRuntime(); + const boardConfig = this.globalConfigHandler.getBoardConfig('host')!; + this.globalConfigHandler.updateBoardConfig('host', { + shellFile: hostEnv.shellFile, + toolchain: boardConfig.toolchain, + }); } - private async updateEsp32(esp32Env: Esp32Env) { + private async updateEsp32(esp32Env: Esp32Env, boardConfig: Esp32BoardConfig) { this.existingEspDir = esp32Env.espRootDir; fs.moveDir(esp32Env.espRootDir, this.tmpEspDir); esp32Env.refreshBoardRoot(); await esp32Env.cloneEspIdf(); await esp32Env.runEspIdfInstallScript(); + const xtensaGccDir = await esp32Env.getXtensaGccDir(); this.globalConfigHandler.updateBoardConfig('esp32', { idfVersion: esp32Env.idfVersion, rootDir: esp32Env.espRootDir, exportFile: esp32Env.idfExportFile, - xtensaGccDir: await esp32Env.getXtensaGccDir(), + toolchain: { + gcc: path.join(xtensaGccDir, esp32Env.xtensaGccFileName), + ar: path.join(xtensaGccDir, esp32Env.xtensaArFileName), + ld: path.join(xtensaGccDir, esp32Env.xtensaLdFileName), + make: boardConfig.toolchain.make + }, }); } } @@ -126,6 +141,8 @@ export async function handleUpdateCommand() { } catch (error) { logger.error(`Failed to update board environments.`); logger.showError(error); + + logger.info(`Remove ${GLOBAL_SETTINGS.BLUESCRIPT_DIR} and setup boards one by one.`); process.exit(1); } } diff --git a/cli/src/config/global-config.ts b/cli/src/config/global-config.ts index d35bf2f0..c4931c63 100644 --- a/cli/src/config/global-config.ts +++ b/cli/src/config/global-config.ts @@ -8,15 +8,22 @@ const esp32BoardSchema = z.object({ idfVersion: z.string(), rootDir: z.string(), exportFile: z.string(), - xtensaGccDir: z.string(), + toolchain: z.object({ + gcc: z.string(), + ar: z.string(), + ld: z.string(), + make: z.string(), + }), }); const hostBoardSchema = z.object({ rootDir: z.string(), shellFile: z.string(), - gccCommand: z.string(), - makeCommand: z.string(), - arCommand: z.string() + toolchain: z.object({ + gcc: z.string(), + ar: z.string(), + make: z.string(), + }), }); const boardConfigSchema = z.object({ diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 5d77b46b..27526fce 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -6,6 +6,8 @@ import { BoardEnv } from './common-env'; const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; +const XTENSA_AR_NAME = 'xtensa-esp32-elf-ar'; +const XTENSA_LD_NAME = 'xtensa-esp32-elf-ld'; export abstract class Esp32Env extends BoardEnv { get espRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'esp'); } @@ -14,6 +16,12 @@ export abstract class Esp32Env extends BoardEnv { get idfVersion() { return 'v5.4'; } get idfGitRepo() { return 'https://github.com/espressif/esp-idf.git'; } abstract get idfExportFile(): string; + abstract get xtensaGccFileName(): string; + abstract get xtensaArFileName(): string; + abstract get xtensaLdFileName(): string; + + abstract runEspIdfInstallScript(): Promise; + abstract getXtensaGccDir(): Promise; async cloneEspIdf() { await exec( @@ -31,13 +39,6 @@ export abstract class Esp32Env extends BoardEnv { fs.makeDir(this.espRootDir); } - abstract runEspIdfInstallScript(): Promise; - abstract getXtensaGccDir(): Promise; - - protected get xtensaGccFileName(): string { - return XTENSA_GCC_NAME; - } - protected parseKeyValueExport(stdout: string): Map { const env = new Map(); @@ -86,10 +87,11 @@ export abstract class Esp32Env extends BoardEnv { } export class Esp32DarwinEnv extends Esp32Env { - get idfExportShFile() { return path.join(this.idfDir, 'export.sh'); } get idfInstallShFile() { return path.join(this.idfDir, 'install.sh'); } - - get idfExportFile() { return this.idfExportShFile; } + get idfExportFile() { return path.join(this.idfDir, 'export.sh'); } + get xtensaGccFileName() { return XTENSA_GCC_NAME; } + get xtensaArFileName() { return XTENSA_AR_NAME; } + get xtensaLdFileName() { return XTENSA_LD_NAME; } async runEspIdfInstallScript() { await exec(this.idfInstallShFile); @@ -109,10 +111,9 @@ export class Esp32WindowsEnv extends Esp32Env { get idfExportBatFile() { return path.join(this.idfDir, 'export.bat'); } get idfInstallBatFile() { return path.join(this.idfDir, 'install.bat'); } get idfExportFile() { return this.idfExportBatFile; } - - protected get xtensaGccFileName(): string { - return `${XTENSA_GCC_NAME}.exe`; - } + get xtensaGccFileName(): string { return `${XTENSA_GCC_NAME}.exe`; } + get xtensaArFileName(): string { return `${XTENSA_AR_NAME}.exe`; } + get xtensaLdFileName(): string { return `${XTENSA_LD_NAME}.exe`; } async runEspIdfInstallScript() { await exec(this.idfInstallBatFile); diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 7667136c..39a7ed85 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -12,6 +12,7 @@ export abstract class HostEnv extends BoardEnv { get runtimeCFile() { return path.join(this.runtimeDir, 'core/src/c-runtime.c'); } get commCFile() { return path.join(this.runtimeDir, 'ports/host/comm.c'); } + abstract get shellFile(): string; abstract buildHostRuntime(): Promise; removeBoardRoot() { @@ -58,6 +59,7 @@ export class HostWindowsEnv extends HostEnv { fs.makeDir(this.buildDir); try { await exec( + // `gcc -DLINUX64 -O2 -shared -o "${this.runtimeDllFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, `gcc -DLINUX64 -O2 -shared -o "${this.runtimeDllFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, { silent: true }, ); diff --git a/cli/src/platforms/compiler/esp32-compiler-adapter.ts b/cli/src/platforms/compiler/esp32-compiler-adapter.ts index 3470183d..5dce8205 100644 --- a/cli/src/platforms/compiler/esp32-compiler-adapter.ts +++ b/cli/src/platforms/compiler/esp32-compiler-adapter.ts @@ -65,13 +65,14 @@ export class Esp32CompilerAdapter implements CompilerAdapter { } return { runtimeDir, - compilerToolchainDir: this.boardConfig.xtensaGccDir, + compilerToolchain: this.boardConfig.toolchain, espDir: this.boardConfig.rootDir, }; } } -export function createEsp32PackageReader( + +function createEsp32PackageReader( _boardName: BoardName, projectConfigHandler: ProjectConfigHandler, ): (name: string) => PackageForEsp32 { diff --git a/cli/src/platforms/compiler/host-compiler-adapter.ts b/cli/src/platforms/compiler/host-compiler-adapter.ts index 6dc20c9f..7ebc9361 100644 --- a/cli/src/platforms/compiler/host-compiler-adapter.ts +++ b/cli/src/platforms/compiler/host-compiler-adapter.ts @@ -1,25 +1,31 @@ -import { GlobalConfigHandler } from "../../config/global-config"; +import { GlobalConfigHandler, HostBoardConfig } from "../../config/global-config"; import { ProjectConfigHandler, PROJECT_DEFAULT_PATHS } from "../../config/project-config"; import { BoardName } from "../../config/board-utils"; import { CompilerSession, SharedLibrary, - HostUnixToolchain, Project, PackageForHostUnix + HostUnixToolchain, HostToolchainConfig, HostWindowsToolchain, Project, PackageForHostUnix, PackageForHostWindows } from "@bscript/lang"; import { CompilerAdapter, CompileContext } from "./compiler-adapter"; import * as path from 'path'; +import * as os from 'os'; +type HostPackageClass = typeof PackageForHostUnix | typeof PackageForHostWindows; + export class HostCompilerAdapter implements CompilerAdapter { readonly boardName: BoardName = 'host'; - private compiler?: CompilerSession; + private boardConfig: HostBoardConfig; + private compiler?: CompilerSession; constructor( private globalConfigHandler: GlobalConfigHandler, private projectConfigHandler: ProjectConfigHandler, ) { - if (!this.globalConfigHandler.isBoardSetup(this.boardName)) { + const boardConfig = this.globalConfigHandler.getBoardConfig('host'); + if (boardConfig === undefined) { throw new Error(`The environment for ${this.boardName} is not set up.`); } + this.boardConfig = boardConfig; } async buildForCheck(): Promise { @@ -27,13 +33,33 @@ export class HostCompilerAdapter implements CompilerAdapter { } async buildProject(_context?: CompileContext): Promise { - const project = Project.load( - this.projectConfigHandler.getConfig().projectName, - createHostPackageReader(this.boardName, this.projectConfigHandler), - ); - const toolchain = new HostUnixToolchain(this.getRuntimeDir()); - this.compiler = new CompilerSession(toolchain); - return this.compiler.buildProject(project); + const runtimeDir = this.getRuntimeDir(); + const compilerConfig: HostToolchainConfig = { + runtimeDir, + compilerToolchain: this.boardConfig.toolchain, + }; + + if (os.platform() === 'darwin') { + const project = Project.load( + this.projectConfigHandler.getConfig().projectName, + createHostPackageReader(this.projectConfigHandler, PackageForHostUnix), + ); + const toolchain = new HostUnixToolchain(compilerConfig); + this.compiler = new CompilerSession(toolchain); + return this.compiler.buildProject(project); + } + + if (os.platform() === 'win32') { + const project = Project.load( + this.projectConfigHandler.getConfig().projectName, + createHostPackageReader(this.projectConfigHandler, PackageForHostWindows), + ); + const toolchain = new HostWindowsToolchain(compilerConfig); + this.compiler = new CompilerSession(toolchain); + return this.compiler.buildProject(project); + } + + throw new Error('Unsupported OS.'); } async compileFragment(src: string): Promise { @@ -53,10 +79,10 @@ export class HostCompilerAdapter implements CompilerAdapter { } } -export function createHostPackageReader( - _boardName: BoardName, +function createHostPackageReader( projectConfigHandler: ProjectConfigHandler, -): (name: string) => PackageForHostUnix { + PackageClass: T, +): (name: string) => InstanceType { return (name: string) => { const mainRoot = projectConfigHandler.root; const subPackageRoot = path.join(mainRoot, PROJECT_DEFAULT_PATHS.PACKAGES_DIR, name); @@ -66,7 +92,7 @@ export function createHostPackageReader( const configHandler = isMain ? projectConfigHandler.asBoard('host') : ProjectConfigHandler.load(root).asBoard('host'); - return new PackageForHostUnix( + return new PackageClass( name, { rootDir: root, @@ -77,7 +103,7 @@ export function createHostPackageReader( packageDir: PROJECT_DEFAULT_PATHS.PACKAGES_DIR, }, Object.keys(configHandler.dependencies), - ); + ) as InstanceType; } catch (error) { throw new Error(`Failed to read ${name}.`, { cause: error }); } diff --git a/cli/tests/commands/board/setup.test.ts b/cli/tests/commands/board/setup.test.ts index d74dc622..490ebf53 100644 --- a/cli/tests/commands/board/setup.test.ts +++ b/cli/tests/commands/board/setup.test.ts @@ -114,8 +114,8 @@ describe('board setup command', () => { if (command.includes('idf_tools.py export --format key-value')) { return mockXtensaGccFromIdfToolsExport(); } - if (command.includes('python --version')) { - return 'Python 3.7.18'; + if (command.includes('python -c "import sys; print(sys.version_info.major)')) { + return '3'; } return ''; }); @@ -285,7 +285,7 @@ describe('board setup command', () => { expect(mockedInquirer.prompt).toHaveBeenCalledTimes(1); expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); expect(mockedBuildHostRuntime).toHaveBeenCalledTimes(1); - expect(getGlobalConfig().boards.host).toEqual({ buildDir: path.join(getTestRuntimeDir(), 'ports/host/build') }); + expect(Object.keys(getGlobalConfig().boards)).toContain('host'); expect(mockedLogger.info).toHaveBeenCalledWith(expect.stringContaining('bscript project create')); expect(mockedLogger.info).not.toHaveBeenCalledWith(expect.stringContaining('flash-runtime')); expect(mockedLogger.error).not.toHaveBeenCalled(); diff --git a/cli/tests/commands/global-env-helper.ts b/cli/tests/commands/global-env-helper.ts index 0a5388db..bc268551 100644 --- a/cli/tests/commands/global-env-helper.ts +++ b/cli/tests/commands/global-env-helper.ts @@ -1,7 +1,8 @@ import * as path from "path"; +import * as os from "os"; import * as fs from '../../src/core/fs'; import { GLOBAL_SETTINGS } from "../../src/config/constants"; -import { CommonBoardEnv, Esp32DarwinEnv } from "../../src/platforms/board-env"; +import { CommonBoardEnv, Esp32DarwinEnv, HostDarwinEnv } from "../../src/platforms/board-env"; const TEMP_DIR = path.join(__dirname, '../../temp-files'); const DUMMY_BLUESCRIPT_DIR = (suffix: string) => path.join(TEMP_DIR, `.bluescript-${suffix}`); @@ -60,8 +61,10 @@ export function setupGlobalEnvWithHost(isOldVersion = false, buildDir?: string) runtimeDir: getTestRuntimeDir(), boards: { host: { - buildDir: resolvedBuildDir, - }, + rootDir: path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'), + shellFile: path.join(resolvedBuildDir, 'shell'), + toolchain: { gcc: 'cc', ar: 'ar', make: 'make' }, + } }, }); fs.makeDir(resolvedBuildDir); @@ -69,12 +72,19 @@ export function setupGlobalEnvWithHost(isOldVersion = false, buildDir?: string) } export function setupGlobalEnvWithHostIntegration(runtimeDir: string, buildDir: string) { + const osType = os.platform(); + const shellFileName = osType === 'win32' ? 'shell.exe' : 'shell'; + const toolchain = osType === 'win32' + ? { gcc: 'gcc', ar: 'ar', make: 'mingw32-make' } + : { gcc: 'cc', ar: 'ar', make: 'make' }; setupGlobalEnv({ version: DUMMY_VM_VERSION, runtimeDir, boards: { host: { - buildDir, + rootDir: path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'), + shellFile: path.join(buildDir, shellFileName), + toolchain, }, }, }); @@ -89,7 +99,12 @@ export function setupGlobalEnvWithEsp32(isOldVersion = false, isEspIdfOldVersion idfVersion: isEspIdfOldVersion ? DUMMY_OLD_ESP_IDF_VERSION : DUMMY_ESP_IDF_VERSION, rootDir: getTestEspRootDir(), exportFile: getTestEspIdfExportFile(), - xtensaGccDir: "/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin" + toolchain: { + gcc: '/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-gcc', + ar: '/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-ar', + ld: '/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-ld', + make: 'make', + }, } } }); diff --git a/cli/tests/config/global-config.test.ts b/cli/tests/config/global-config.test.ts index bf00adef..dba84fb7 100644 --- a/cli/tests/config/global-config.test.ts +++ b/cli/tests/config/global-config.test.ts @@ -44,7 +44,12 @@ describe('GlobalConfigHandler', () => { idfVersion: 'v5.4', rootDir: 'root/dir', exportFile: 'export.sh', - xtensaGccDir:'gcc', + toolchain: { + gcc: 'gcc', + ar: 'ar', + ld: 'ld', + make: 'make', + }, } const handler = GlobalConfigHandler.load(); handler.updateBoardConfig('esp32', boardConfig); diff --git a/cli/tests/integration/project/repl.host.test.ts b/cli/tests/integration/project/repl.host.test.ts index 6a3f75f5..5972079d 100644 --- a/cli/tests/integration/project/repl.host.test.ts +++ b/cli/tests/integration/project/repl.host.test.ts @@ -22,7 +22,7 @@ import { waitFor, waitForStdoutContains, } from '../host-run-helper'; -import { CommonBoardEnv, createBoardEnv } from '../../../src/platforms/board-env'; +import { BoardEnv, createBoardEnv } from '../../../src/platforms/board-env'; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration-repl'); const SHELL_PATH = path.join(HOST_INTEGRATION_BUILD_DIR, 'shell'); @@ -59,12 +59,10 @@ describeHost('repl command (host integration)', () => { spyGlobalSettings('repl-integration'); fs.makeDir(TEMP_DIR); - if (!fs.exists(SHELL_PATH) || !fs.exists(RUNTIME_SO_PATH)) { - jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') - .mockReturnValue(HOST_INTEGRATION_RUNTIME_DIR); - const hostEnv = createBoardEnv('host'); - await hostEnv.buildHostRuntime(); - } + jest.spyOn(BoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(HOST_INTEGRATION_RUNTIME_DIR); + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); }); beforeEach(() => { diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index adc8bf59..e78a25bd 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { cwd } from '../../../src/core/shell'; import * as fs from '../../../src/core/fs'; import { handleRunCommand } from '../../../src/commands/project/run'; -import { CommonBoardEnv } from '../../../src/platforms/board-env/common-env'; +import { BoardEnv } from '../../../src/platforms/board-env/common-env'; import { deleteGlobalEnv, setupGlobalEnvWithHostIntegration, @@ -27,8 +27,6 @@ const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration'); const RUNTIME_DIR = path.resolve(__dirname, '../../../../microcontroller'); const BUILD_DIR = path.join(RUNTIME_DIR, 'ports/host/build'); const PROJECT_ROOT = path.join(TEMP_DIR, 'run-project'); -const SHELL_PATH = path.join(BUILD_DIR, 'shell'); -const RUNTIME_SO_PATH = path.join(BUILD_DIR, 'c-runtime.so'); const describeHost = process.platform === 'darwin' ? describe : describe.skip; @@ -37,12 +35,10 @@ describeHost('project run command (host integration)', () => { spyGlobalSettings('run-integration'); fs.makeDir(TEMP_DIR); - if (!fs.exists(SHELL_PATH) || !fs.exists(RUNTIME_SO_PATH)) { - jest.spyOn(CommonBoardEnv.prototype, 'runtimeDir', 'get') - .mockReturnValue(RUNTIME_DIR); - const hostEnv = createBoardEnv('host'); - await hostEnv.buildHostRuntime(); - } + jest.spyOn(BoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(RUNTIME_DIR); + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); }); beforeEach(() => { diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index e33adf5e..6f7a3340 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -6,15 +6,23 @@ import { Package, PackageForHostUnix, PackageForHostWindows } from "../package"; import { generateMakefile, hostUnixMakefilePrest, hostWindowsMakefilePreset } from "./tools/makefile"; import { executeCommand, getErrorMessage } from "../utils"; +export type HostToolchainConfig = { + runtimeDir: string, + compilerToolchain: { + gcc: string, + ar: string, + make: string + }, +} export abstract class HostToolchain

implements BoardToolchain { - protected runtimeDir: string; + protected config: HostToolchainConfig; protected compileId: number = 0; protected compiledPackages = new Set(); protected generatedSharedLibs: string[] = []; - constructor(runtimeDir: string) { - this.runtimeDir = runtimeDir; + constructor(config: HostToolchainConfig) { + this.config = config; } get cProlog() { @@ -23,9 +31,9 @@ export abstract class HostToolchain

implements BoardToolchain #include "${this.cRuntimeH}" `; } - get cRuntimeH() { return path.join(this.runtimeDir, 'core/include/c-runtime.h'); } - get builtinModulePath() { return path.join(this.runtimeDir, 'ports/host/std-module.bs'); } - get runtimeBuildDir() { return path.join(this.runtimeDir, 'ports/host/build'); } + get cRuntimeH() { return path.join(this.config.runtimeDir, 'core/include/c-runtime.h'); } + get builtinModulePath() { return path.join(this.config.runtimeDir, 'ports/host/std-module.bs'); } + get runtimeBuildDir() { return path.join(this.config.runtimeDir, 'ports/host/build'); } async compileAndLink(project: Project

, entryPoints: string[]): Promise { const archiveFiles: string[] = []; @@ -76,9 +84,9 @@ export class HostUnixToolchain extends HostToolchain { } pkg.copyNativeFilesToDist(); - const makefile = generateMakefile(hostUnixMakefilePrest(pkg)); + const makefile = generateMakefile(hostUnixMakefilePrest(pkg, this.config.compilerToolchain)); pkg.writeMakefile(makefile); - await executeCommand('make', [], pkg.resolvedDistDir); + await executeCommand(this.config.compilerToolchain.make, [], pkg.resolvedDistDir); return archiveFile; } catch (error) { throw new Error(`Failed to compile package ${pkg.name}: ${getErrorMessage(error)}`, {cause: error}); @@ -100,7 +108,7 @@ export class HostUnixToolchain extends HostToolchain { '-lm', '-ldl', ...keepEntrySymbols, ]; - await executeCommand('cc', args); + await executeCommand(this.config.compilerToolchain.gcc, args); return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, {cause: error}); @@ -109,13 +117,6 @@ export class HostUnixToolchain extends HostToolchain { } export class HostWindowsToolchain extends HostToolchain { - private readonly toolchainPrefix?: string; - - constructor(runtimeDir: string, toolchainPrefix?: string) { - super(runtimeDir); - this.toolchainPrefix = toolchainPrefix; - } - get runtimeDll(): string { return path.join(this.runtimeBuildDir, 'c-runtime.dll'); } @@ -128,11 +129,11 @@ export class HostWindowsToolchain extends HostToolchain { } pkg.copyNativeFilesToDist(); const makefile = generateMakefile( - hostWindowsMakefilePreset(pkg, this.toolchainPrefix), + hostWindowsMakefilePreset(pkg, this.config.compilerToolchain), ); pkg.writeMakefile(makefile); - await executeCommand('mingw32-make', [], pkg.resolvedDistDir); + await executeCommand(this.config.compilerToolchain.make, [], pkg.resolvedDistDir); return archiveFile; } catch (error) { throw new Error( @@ -161,10 +162,7 @@ export class HostWindowsToolchain extends HostToolchain { '-lm', ...keepEntrySymbols, ]; - const linker = this.toolchainPrefix - ? path.join(this.toolchainPrefix, 'gcc') - : 'gcc'; - await executeCommand(linker, args); + await executeCommand(this.config.compilerToolchain.gcc, args); return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, { cause: error }); diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index 06486ff9..8ffde896 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -39,7 +39,7 @@ export function esp32MakefilePreset(pkg: PackageForEsp32, includeDirs: string[], } } -export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { +export function hostUnixMakefilePrest(pkg: PackageForHostUnix, toolchain: {gcc: string, ar: string}) { return { outputFile: pkg.archiveFile, objectFiles: pkg.objectFiles, @@ -49,24 +49,24 @@ export function hostUnixMakefilePrest(pkg: PackageForHostUnix) { distDir: pkg.resolvedDistDir, buildDir: pkg.resolvedBuildDir, toolchain: { - cc: `cc`, - ar: `ar` + cc: toolchain.gcc, + ar: toolchain.ar } } } -export function hostWindowsMakefilePreset(pkg: PackageForHostWindows, toolchainPrefix?: string): MakefileConfig { +export function hostWindowsMakefilePreset(pkg: PackageForHostWindows, toolchain: {gcc: string, ar: string}): MakefileConfig { return { outputFile: toMakePath(pkg.archiveFile), objectFiles: pkg.objectFiles.map(toMakePath), headerFilesInDist: pkg.headerFilesInDist.map(toMakePath), includeDirs: [toMakePath(pkg.resolvedDistDir)], - compileFlags: ['-O2', '-w', '-DLINUX64', '-DWIN64'], + compileFlags: ['-O2', '-w', '-DLINUX64'], distDir: toMakePath(pkg.resolvedDistDir), buildDir: toMakePath(pkg.resolvedBuildDir), toolchain: { - cc: toolchainPrefix ? `${toMakePath(toolchainPrefix)}/gcc` : 'gcc', - ar: toolchainPrefix ? `${toMakePath(toolchainPrefix)}/ar` : 'ar', + cc: toolchain.gcc, + ar: toolchain.ar }, }; } diff --git a/lang/src/index.ts b/lang/src/index.ts index 0eac844e..89a76b5d 100644 --- a/lang/src/index.ts +++ b/lang/src/index.ts @@ -1,7 +1,7 @@ export { ErrorLog as CompileError } from './transpiler/utils'; export { CompilerSession } from './compiler/compiler-session'; export { Project } from './compiler/project'; -export { Package, PackageForEsp32, PackageForHostUnix } from './compiler/package'; +export { Package, PackageForEsp32, PackageForHostUnix, PackageForHostWindows } from './compiler/package'; export { Esp32Toolchain, Esp32ToolchainConfig } from './compiler/board-toolchain/esp32-toolchain'; -export { HostToolchain, HostUnixToolchain } from './compiler/board-toolchain/host-toolchain'; +export { HostToolchain, HostToolchainConfig, HostUnixToolchain, HostWindowsToolchain } from './compiler/board-toolchain/host-toolchain'; export { MemoryLayout, MemoryImage, CompileOutput, SharedLibrary } from './compiler/board-toolchain/board-toolchain'; \ No newline at end of file diff --git a/lang/tests/compiler/compiler-esp32.test.ts b/lang/tests/compiler/compiler-esp32.test.ts index 1782cf9e..9386b137 100644 --- a/lang/tests/compiler/compiler-esp32.test.ts +++ b/lang/tests/compiler/compiler-esp32.test.ts @@ -36,7 +36,7 @@ describe('Test single compile: Compiler for ESP32', () => { }); afterAll(() => { - // testEnv.delete(); + testEnv.delete(); }); diff --git a/lang/tests/compiler/compiler-host.test.ts b/lang/tests/compiler/compiler-host.test.ts index d178c55c..6daa5b29 100644 --- a/lang/tests/compiler/compiler-host.test.ts +++ b/lang/tests/compiler/compiler-host.test.ts @@ -15,7 +15,7 @@ describe('Test single compile: Compiler for Host', () => { }); afterAll(() => { - // testEnv.delete(); + testEnv.delete(); }); diff --git a/lang/tests/compiler/test-utils-esp32.ts b/lang/tests/compiler/test-utils-esp32.ts index f5a1577c..98978465 100644 --- a/lang/tests/compiler/test-utils-esp32.ts +++ b/lang/tests/compiler/test-utils-esp32.ts @@ -7,6 +7,8 @@ import { Esp32ToolchainConfig } from "../../src/compiler/board-toolchain/esp32-t const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; +const XTENSA_AR_NAME = 'xtensa-esp32-elf-ar'; +const XTENSA_LD_NAME = 'xtensa-esp32-elf-ld'; export const runtimeDir = path.resolve(__dirname, '../../../microcontroller'); @@ -20,9 +22,9 @@ export function getEsp32ToolchainConfig(): Esp32ToolchainConfig { return { runtimeDir, compilerToolchain: { - gcc: path.join(compilerToolchainDir, 'xtensa-esp32-elf-gcc'), - ar: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ar'), - ld: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ld'), + gcc: path.join(compilerToolchainDir, XTENSA_GCC_NAME), + ar: path.join(compilerToolchainDir, XTENSA_AR_NAME), + ld: path.join(compilerToolchainDir, XTENSA_LD_NAME), make: 'make' }, espDir @@ -39,9 +41,9 @@ export function getEsp32ToolchainConfig(): Esp32ToolchainConfig { return { runtimeDir, compilerToolchain: { - gcc: path.join(compilerToolchainDir, 'xtensa-esp32-elf-gcc.exe'), - ar: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ar.exe'), - ld: path.join(compilerToolchainDir, 'xtensa-esp32-elf-ld.exe'), + gcc: path.join(compilerToolchainDir, `${XTENSA_GCC_NAME}.exe`), + ar: path.join(compilerToolchainDir, `${XTENSA_AR_NAME}.exe`), + ld: path.join(compilerToolchainDir, `${XTENSA_LD_NAME}.exe`), make: 'mingw32-make' }, espDir diff --git a/lang/tests/compiler/test-utils-host.ts b/lang/tests/compiler/test-utils-host.ts index 78691f78..b779783f 100644 --- a/lang/tests/compiler/test-utils-host.ts +++ b/lang/tests/compiler/test-utils-host.ts @@ -3,7 +3,7 @@ import * as fs from "fs"; import * as os from 'os'; import { Project } from "../../src/compiler/project"; import { PackageForHostUnix, PackageForHostWindows } from "../../src/compiler/package"; -import { HostUnixToolchain, HostWindowsToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; +import { HostToolchainConfig, HostUnixToolchain, HostWindowsToolchain } from "../../src/compiler/board-toolchain/host-toolchain"; import { HostUnixCompilerTestEnv, HostWindowsCompilerTestEnv, runtimeDir } from "./test-env"; import { SharedLibrary } from "../../src/compiler/board-toolchain/board-toolchain"; import { CompilerSession } from "../../src/compiler/compiler-session"; @@ -41,12 +41,12 @@ const buildRuntimeUnix = async () => { const buildRuntimeWindows = async () => { fs.mkdirSync(runtimeBuildDir, { recursive: true }); await executeCommand('gcc', [ - '-DLINUX64', '-DWIN64', '-O2', '-shared', + '-DLINUX64', '-O2', '-shared', '-o', runtimeDll, runtimeC, builtinModuleC, commC, ]); await executeCommand('gcc', [ - '-DLINUX64', '-DWIN64', '-O2', + '-DLINUX64', '-O2', '-o', executableShellWin, shellC, runtimeDll, '-lm', ]); @@ -74,7 +74,15 @@ export const createTestEnv = () => { export const compile = async (testEnv: HostUnixCompilerTestEnv | HostWindowsCompilerTestEnv) => { if (os.platform() === 'darwin') { - let toolchain = new HostUnixToolchain(runtimeDir); + const compilerConfig: HostToolchainConfig = { + runtimeDir, + compilerToolchain: { + gcc: 'cc', + ar: 'ar', + make: 'make' + } + } + let toolchain = new HostUnixToolchain(compilerConfig); const project = Project.load( testEnv.mainPackageName, testEnv.getPackageReader() as (name: string) => PackageForHostUnix @@ -83,7 +91,15 @@ export const compile = async (testEnv: HostUnixCompilerTestEnv | HostWindowsComp await session.buildProject(project); return session; } else if (os.platform() === 'win32') { - let toolchain = new HostWindowsToolchain(runtimeDir); + const compilerConfig: HostToolchainConfig = { + runtimeDir, + compilerToolchain: { + gcc: 'gcc', + ar: 'ar', + make: 'mingw32-make' + } + } + let toolchain = new HostWindowsToolchain(compilerConfig); const project = Project.load( testEnv.mainPackageName, testEnv.getPackageReader() as (name: string) => PackageForHostWindows diff --git a/microcontroller/ports/host/shell.c b/microcontroller/ports/host/shell.c index abbaa2bd..0d95d09c 100644 --- a/microcontroller/ports/host/shell.c +++ b/microcontroller/ports/host/shell.c @@ -43,14 +43,8 @@ static float get_time_ms() { static void load(char* filename) { float start_time = get_time_ms(); #ifndef _WIN32 - if (file_handle != NULL) { - dlclose(file_handle); - } file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); #else - if (file_handle != NULL) { - FreeLibrary((HMODULE)file_handle); - } file_handle = (void*)LoadLibraryA(filename); if (file_handle == NULL) { fprintf(stderr, "Error: failed to load %s (error %lu)\n", filename, GetLastError()); From eeed07d47cea075b0cf15cb0b9b8db0da95024a5 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 4 Jul 2026 12:45:03 +0900 Subject: [PATCH 12/33] Fix cli integration tests for windows. --- cli/README.md | 8 ++-- cli/docs/manual-test.md | 8 ++-- cli/tests/integration/host-run-helper.ts | 30 ++++++++++++++ .../integration/project/repl.host.test.ts | 15 ++----- .../integration/project/run.host.test.ts | 41 +++++++++---------- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/cli/README.md b/cli/README.md index 191c36ea..996c40d9 100644 --- a/cli/README.md +++ b/cli/README.md @@ -18,7 +18,7 @@ Build and test the CLI package: cd cli npm run build npm test # unit tests only -npm run test:integration # host integration tests (macOS + cc) +npm run test:integration # host integration tests (macOS or Windows) npm run test:all # unit + integration ``` @@ -27,10 +27,10 @@ npm run test:all # unit + integration | Script | Jest project | Location | Notes | | :--- | :--- | :--- | :--- | | `npm test` | `unit` | `tests/**/*.test.ts` (excludes `integration/`) | Mocks fs, shell, logger, devices | -| `npm run test:integration` | `integration` | `tests/integration/**/*.test.ts` | Real host `shell` process; macOS only | +| `npm run test:integration` | `integration` | `tests/integration/**/*.test.ts` | Real host `shell` process; macOS or Windows (MinGW-w64) | | `npm run test:all` | both | — | Run before merging CLI changes | -**Integration test requirements:** macOS, `cc`, and the `microcontroller/` tree at the repository root. On first run, tests build `microcontroller/ports/host/build/shell` and `c-runtime.so` if missing. Tests are skipped automatically on non-macOS platforms. +**Integration test requirements:** macOS (`cc`) or Windows (MinGW-w64: `gcc`, `mingw32-make`), and the `microcontroller/` tree at the repository root. On first run, tests build `microcontroller/ports/host/build/shell` (or `shell.exe`) and `c-runtime.so` (or `c-runtime.dll`) if missing. Tests are skipped automatically on Linux and other unsupported platforms. **Integration coverage (14 tests):** @@ -61,7 +61,7 @@ bscript -v Before merging CLI changes or cutting a release: -1. Run `npm run test:all` (or at least `npm test`; on macOS also `npm run test:integration`). +1. Run `npm run test:all` (or at least `npm test`; on macOS or Windows also `npm run test:integration`). 2. Follow the manual QA checklist: **[docs/manual-test.md](./docs/manual-test.md)** - **Daily PRs:** run automated tests plus **Quick smoke (host)** (~15 minutes). diff --git a/cli/docs/manual-test.md b/cli/docs/manual-test.md index b11ed505..426088f6 100644 --- a/cli/docs/manual-test.md +++ b/cli/docs/manual-test.md @@ -49,8 +49,8 @@ Host integration tests live in `cli/tests/integration/`. They spawn the real hos | Requirement | Detail | | :--- | :--- | -| OS | macOS only (tests are skipped on other platforms) | -| Toolchain | `cc` (builds `microcontroller/ports/host/build/` on first run if missing) | +| OS | macOS or Windows (tests are skipped on Linux and other platforms) | +| Toolchain | macOS: `cc`; Windows: MinGW-w64 (`gcc`, `mingw32-make`). Builds `microcontroller/ports/host/build/` on first run if missing. | | Repo layout | Run from `cli/` with the `microcontroller/` tree at the repository root | ```bash @@ -734,9 +734,9 @@ For failures, include the item ID (e.g. `MT-PROJ-RUN-03`) in Notes or link to an ## Coverage map: automated vs manual -Jest **unit** tests in `cli/tests/` mock filesystem, network, and device I/O. **Integration** tests in `cli/tests/integration/` use real host runtime processes on macOS. Use this table to avoid re-testing automated behavior manually while ensuring gaps are covered. +Jest **unit** tests in `cli/tests/` mock filesystem, network, and device I/O. **Integration** tests in `cli/tests/integration/` use real host runtime processes on macOS or Windows. Use this table to avoid re-testing automated behavior manually while ensuring gaps are covered. -| Area | Unit tests | Integration tests (host, macOS) | Manual testing still needed | +| Area | Unit tests | Integration tests (host, macOS/Windows) | Manual testing still needed | | :--- | :--- | :--- | :--- | | `board setup` | Handler logic, macOS paths, skip-if-done | — | Real download, ESP-IDF install, host runtime build | | `board flash-runtime` | ESP32 handler, host rejection, port prompt mocked, `deviceName` passed to build | — | Actual USB flash on hardware; BLE advertised name after flash | diff --git a/cli/tests/integration/host-run-helper.ts b/cli/tests/integration/host-run-helper.ts index eb205809..1825bd92 100644 --- a/cli/tests/integration/host-run-helper.ts +++ b/cli/tests/integration/host-run-helper.ts @@ -1,7 +1,13 @@ +import * as os from 'os'; import * as path from 'path'; import * as fs from '../../src/core/fs'; import { ProjectConfigHandler } from '../../src/config/project-config'; import { PROJECT_DEFAULT_PATHS } from '../../src/config/project-config'; +import { BoardEnv, createBoardEnv } from '../../src/platforms/board-env'; +import { isPackageInstalledOnWindows } from '../../src/commands/board/setup/utils'; + +const isHostPlatform = os.platform() === 'darwin' || os.platform() === 'win32'; +export const describeHostIntegration = isHostPlatform ? describe : describe.skip; export type HostPackageSpec = { name: string; @@ -129,3 +135,27 @@ export const HOST_INTEGRATION_RUNTIME_DIR = path.resolve(__dirname, '../../../microcontroller'); export const HOST_INTEGRATION_BUILD_DIR = path.join(HOST_INTEGRATION_RUNTIME_DIR, 'ports/host/build'); + +export async function assertHostIntegrationPrerequisites(): Promise { + if (process.platform !== 'win32') { + return; + } + if (!await isPackageInstalledOnWindows('gcc')) { + throw new Error( + 'MinGW-w64 gcc is required for host integration tests on Windows.', + ); + } + if (!await isPackageInstalledOnWindows('mingw32-make')) { + throw new Error( + 'mingw32-make is required for host integration tests on Windows.', + ); + } +} + +export async function ensureHostRuntimeBuilt(): Promise { + await assertHostIntegrationPrerequisites(); + jest.spyOn(BoardEnv.prototype, 'runtimeDir', 'get') + .mockReturnValue(HOST_INTEGRATION_RUNTIME_DIR); + const hostEnv = createBoardEnv('host'); + await hostEnv.buildHostRuntime(); +} diff --git a/cli/tests/integration/project/repl.host.test.ts b/cli/tests/integration/project/repl.host.test.ts index 5972079d..c31f66b7 100644 --- a/cli/tests/integration/project/repl.host.test.ts +++ b/cli/tests/integration/project/repl.host.test.ts @@ -15,6 +15,8 @@ import { } from '../../commands/global-env-helper'; import { captureOutput, + describeHostIntegration, + ensureHostRuntimeBuilt, HOST_INTEGRATION_BUILD_DIR, HOST_INTEGRATION_RUNTIME_DIR, mockProcessExit, @@ -22,13 +24,8 @@ import { waitFor, waitForStdoutContains, } from '../host-run-helper'; -import { BoardEnv, createBoardEnv } from '../../../src/platforms/board-env'; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration-repl'); -const SHELL_PATH = path.join(HOST_INTEGRATION_BUILD_DIR, 'shell'); -const RUNTIME_SO_PATH = path.join(HOST_INTEGRATION_BUILD_DIR, 'c-runtime.so'); - -const describeHost = process.platform === 'darwin' ? describe : describe.skip; let replLineHandler: ((line: string) => void) | undefined; let replCloseHandler: (() => void) | undefined; @@ -52,17 +49,13 @@ function createMockReadline(): readline.Interface { } as unknown as readline.Interface; } -describeHost('repl command (host integration)', () => { +describeHostIntegration('repl command (host integration)', () => { jest.setTimeout(30000); beforeAll(async () => { spyGlobalSettings('repl-integration'); fs.makeDir(TEMP_DIR); - - jest.spyOn(BoardEnv.prototype, 'runtimeDir', 'get') - .mockReturnValue(HOST_INTEGRATION_RUNTIME_DIR); - const hostEnv = createBoardEnv('host'); - await hostEnv.buildHostRuntime(); + await ensureHostRuntimeBuilt(); }); beforeEach(() => { diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index e78a25bd..5a1b52ed 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -7,7 +7,6 @@ import * as path from 'path'; import { cwd } from '../../../src/core/shell'; import * as fs from '../../../src/core/fs'; import { handleRunCommand } from '../../../src/commands/project/run'; -import { BoardEnv } from '../../../src/platforms/board-env/common-env'; import { deleteGlobalEnv, setupGlobalEnvWithHostIntegration, @@ -16,34 +15,32 @@ import { import { captureStdout, createHostProject, + describeHostIntegration, + ensureHostRuntimeBuilt, + HOST_INTEGRATION_BUILD_DIR, + HOST_INTEGRATION_RUNTIME_DIR, mockProcessExit, removeDirIfExists, } from '../host-run-helper'; -import { createBoardEnv } from '../../../src/platforms/board-env'; const mockedCwd = cwd as jest.Mock; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration'); -const RUNTIME_DIR = path.resolve(__dirname, '../../../../microcontroller'); -const BUILD_DIR = path.join(RUNTIME_DIR, 'ports/host/build'); const PROJECT_ROOT = path.join(TEMP_DIR, 'run-project'); -const describeHost = process.platform === 'darwin' ? describe : describe.skip; - -describeHost('project run command (host integration)', () => { +describeHostIntegration('project run command (host integration)', () => { beforeAll(async () => { spyGlobalSettings('run-integration'); fs.makeDir(TEMP_DIR); - - jest.spyOn(BoardEnv.prototype, 'runtimeDir', 'get') - .mockReturnValue(RUNTIME_DIR); - const hostEnv = createBoardEnv('host'); - await hostEnv.buildHostRuntime(); + await ensureHostRuntimeBuilt(); }); beforeEach(() => { deleteGlobalEnv(); - setupGlobalEnvWithHostIntegration(RUNTIME_DIR, BUILD_DIR); + setupGlobalEnvWithHostIntegration( + HOST_INTEGRATION_RUNTIME_DIR, + HOST_INTEGRATION_BUILD_DIR, + ); removeDirIfExists(PROJECT_ROOT); fs.makeDir(PROJECT_ROOT); mockedCwd.mockReturnValue(PROJECT_ROOT); @@ -60,7 +57,7 @@ describeHost('project run command (host integration)', () => { createHostProject(PROJECT_ROOT, { 'src/index.bs': 'console.log("hello from run");', - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -81,7 +78,7 @@ console.log("built-in"); print("via print"); console.log(time.now()); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -105,7 +102,7 @@ function greet(): void { } greet(); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -130,7 +127,7 @@ export function add(a: integer, b: integer): integer { import { add } from "./math-utils"; console.log(add(10, 20)); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -150,7 +147,7 @@ console.log(add(10, 20)); import { mul } from "math-lib"; console.log(mul(3, 4)); `.trim(), - }, RUNTIME_DIR, 'test-run', [{ + }, HOST_INTEGRATION_RUNTIME_DIR, 'test-run', [{ name: 'math-lib', sources: { 'src/index.bs': ` @@ -186,7 +183,7 @@ function pow(x: float, y: float): float { console.log(pow(2.0, 3.0)); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -214,7 +211,7 @@ function main(): void { main(); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -243,7 +240,7 @@ function main(): void { main(); `.trim(), - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); @@ -259,7 +256,7 @@ main(); createHostProject(PROJECT_ROOT, { 'src/index.bs': 'this is not valid bluescript', - }, RUNTIME_DIR); + }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); From b1d6ba499632a29ec0b1bc3318e2c8b56fcd146a Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sat, 4 Jul 2026 16:51:02 +0900 Subject: [PATCH 13/33] Debugging --- cli/src/platforms/board-env/esp32-env.ts | 3 +- cli/src/services/ble-result.txt | 102 +++++++++++++++++++++++ cli/src/services/ble.ts | 19 +++++ package.json | 2 +- 4 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 cli/src/services/ble-result.txt diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 27526fce..bb46b21d 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -65,6 +65,7 @@ export abstract class Esp32Env extends BoardEnv { } protected resolveXtensaGccDirFromExport(stdout: string, pathLabel: string, pathSeparator: string): string { + console.log(stdout) const env = this.parseKeyValueExport(stdout); const pathValue = env.get(pathLabel); @@ -121,7 +122,7 @@ export class Esp32WindowsEnv extends Esp32Env { async getXtensaGccDir() { try { - const stdout = await exec(`${this.idfToolsPyFile} export --format key-value`); + const stdout = await exec(`python ${this.idfToolsPyFile} export --format key-value`); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ';'); } catch (error) { throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); diff --git a/cli/src/services/ble-result.txt b/cli/src/services/ble-result.txt new file mode 100644 index 00000000..14513eb8 --- /dev/null +++ b/cli/src/services/ble-result.txt @@ -0,0 +1,102 @@ +>bscript project run +INFO: Connecting...foo +foo2 +Foo3 +foo4 +foo41 +[ + Service { + _noble: Noble { + initialized: true, + address: 'unknown', + _state: 'poweredOn', + _bindings: [NobleWinrt], + _peripherals: [Object], + _services: [Object], + _characteristics: [Object], + _descriptors: [Object], + _discoveredPeripheralUUids: [Object], + _events: [Object: null prototype], + _eventsCount: 2, + _allowDuplicates: false + }, + _peripheralId: '083af2438a6a', + uuid: '1801', + name: 'Generic Attribute', + type: 'org.bluetooth.service.generic_attribute', + includedServiceUuids: null, + characteristics: null + }, + Service { + _noble: Noble { + initialized: true, + address: 'unknown', + _state: 'poweredOn', + _bindings: [NobleWinrt], + _peripherals: [Object], + _services: [Object], + _characteristics: [Object], + _descriptors: [Object], + _discoveredPeripheralUUids: [Object], + _events: [Object: null prototype], + _eventsCount: 2, + _allowDuplicates: false + }, + _peripheralId: '083af2438a6a', + uuid: '1800', + name: 'Generic Access', + type: 'org.bluetooth.service.generic_access', + includedServiceUuids: null, + characteristics: null + }, + Service { + _noble: Noble { + initialized: true, + address: 'unknown', + _state: 'poweredOn', + _bindings: [NobleWinrt], + _peripherals: [Object], + _services: [Object], + _characteristics: [Object], + _descriptors: [Object], + _discoveredPeripheralUUids: [Object], + _events: [Object: null prototype], + _eventsCount: 2, + _allowDuplicates: false + }, + _peripheralId: '083af2438a6a', + uuid: 'ff', + name: null, + type: null, + includedServiceUuids: null, + characteristics: null + } +] +service Service { + _noble: Noble { + initialized: true, + address: 'unknown', + _state: 'poweredOn', + _bindings: NobleWinrt { _events: [Object: null prototype], _eventsCount: 25 }, + _peripherals: { '083af2438a6a': [Peripheral] }, + _services: { '083af2438a6a': [Object] }, + _characteristics: { '083af2438a6a': [Object] }, + _descriptors: { '083af2438a6a': [Object] }, + _discoveredPeripheralUUids: { '083af2438a6a': true }, + _events: [Object: null prototype] { + warning: [Function (anonymous)], + newListener: [Function (anonymous)] + }, + _eventsCount: 2, + _allowDuplicates: false + }, + _peripheralId: '083af2438a6a', + uuid: 'ff', + name: null, + type: null, + includedServiceUuids: null, + characteristics: null +} +GetGattServicesForUuidAsync: no service with given id +BLEManager::DiscoverCharacteristics::::operator (): GetService error +^C \ No newline at end of file diff --git a/cli/src/services/ble.ts b/cli/src/services/ble.ts index 7bce82cd..454b3948 100644 --- a/cli/src/services/ble.ts +++ b/cli/src/services/ble.ts @@ -180,7 +180,9 @@ export class BleConnection extends Connection { }; noble.on('discover', this.discoverHandler); }); + console.log("foo") await noble.stopScanningAsync(); + console.log("foo2") this.peripheral = peripheral; this.peripheral.on('disconnect', (event) => { this.emit('disconnected', event); @@ -192,22 +194,39 @@ export class BleConnection extends Connection { this.status = 'connected'; this.emit('connected'); }); + console.log("Foo3") await peripheral.connectAsync(); + console.log("foo4") + const result1 = await peripheral.discoverServicesAsync(); + console.log("foo41") + console.log(result1) + const service = result1.find(s => s.uuid === 'ff'); + console.log('service', service) + const ch1 = await service?.discoverCharacteristicsAsync(); + console.log("foo412") + console.log(ch1) + const result = await peripheral.discoverAllServicesAndCharacteristicsAsync(); + console.log("foo42") + console.log(result) const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync( [SERVICE_UUID], [CHARACTERISTIC_UUID] ); + console.log("foo5") if (characteristics.length === 0) { throw new Error('Target characteristic not found.'); } + console.log("foo6") this.characteristic = characteristics[0]; this.characteristic.on('data', (data, isNotification) => { if (isNotification) { this.emit('receiveData', data); } }) + console.log("foo7") await this.characteristic.subscribeAsync(); + console.log("foo8") } private async waitForPoweredOn(): Promise { diff --git a/package.json b/package.json index d5604285..0e0b4fb3 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,6 @@ "typescript": "^5.9.2" }, "scripts": { - "build": "tsc -b && npm run build -w @bscript/notebook" + "build": "tsc -b" } } From 96333446535343da8b0f440f5f0d4bbbbac942be Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 4 Jul 2026 16:52:06 +0900 Subject: [PATCH 14/33] Fix cli integration tests for windows. --- cli/src/commands/repl.ts | 6 +- cli/src/services/ble.ts | 7 + cli/src/services/host-protocol.ts | 8 + cli/tests/integration/host-run-helper.ts | 60 ++- .../integration/project/repl.host.test.ts | 21 +- .../integration/project/run.host.test.ts | 49 +-- microcontroller/ports/esp32/main/ble.c | 1 + microcontroller/ports/esp32/sdkconfig | 132 ++---- microcontroller/ports/esp32/sdkconfig.old | 384 ++++++++++++++---- microcontroller/ports/host/comm.h | 2 +- microcontroller/ports/host/shell.c | 3 + 11 files changed, 457 insertions(+), 216 deletions(-) diff --git a/cli/src/commands/repl.ts b/cli/src/commands/repl.ts index 8dd4d58b..dfec3d4c 100644 --- a/cli/src/commands/repl.ts +++ b/cli/src/commands/repl.ts @@ -25,7 +25,9 @@ function defaultReplReadlineFactory(): readline.Interface { class ReplHandler extends CommandHandler { static readonly TEMP_PROJECT_NAME = 'temp'; - static readonly tempProjectDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, this.TEMP_PROJECT_NAME); + static get tempProjectDir(): string { + return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, ReplHandler.TEMP_PROJECT_NAME); + } private projectConfigHandler: ProjectConfigHandler; private platform: ReturnType; @@ -68,10 +70,10 @@ class ReplHandler extends CommandHandler { this.createTempProject(); await this.runRepl(); - this.deleteTempProject(); this.rl.close(); await runStep('Disconnecting...', () => this.platform.runtime.disconnect()); + this.deleteTempProject(); process.exit(0); } diff --git a/cli/src/services/ble.ts b/cli/src/services/ble.ts index 7bce82cd..bee6ad17 100644 --- a/cli/src/services/ble.ts +++ b/cli/src/services/ble.ts @@ -194,6 +194,13 @@ export class BleConnection extends Connection { }); await peripheral.connectAsync(); + const services = await peripheral.discoverServicesAsync(); + console.log(services) + const serviceff = services.find(s => s.uuid === SERVICE_UUID); + // console.log(serviceff); + const ch = await serviceff?.discoverCharacteristicsAsync(); + console.log(ch); + const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync( [SERVICE_UUID], [CHARACTERISTIC_UUID] diff --git a/cli/src/services/host-protocol.ts b/cli/src/services/host-protocol.ts index d76da443..37553bf3 100644 --- a/cli/src/services/host-protocol.ts +++ b/cli/src/services/host-protocol.ts @@ -10,7 +10,15 @@ export enum HostProtocol { Max } +export const HOST_MAX_PAYLOAD_SIZE = 256; + export function hostProtocolBuilder(protocol: HostProtocol, payload: string) { + if (payload.length > HOST_MAX_PAYLOAD_SIZE) { + throw new Error( + `Host protocol payload exceeds ${HOST_MAX_PAYLOAD_SIZE} bytes ` + + `(got ${payload.length}): ${payload}`, + ); + } const protocolStr = String(protocol).padStart(2, '0'); const payloadLen = String(payload.length).padStart(4, '0'); return `${protocolStr} ${payloadLen} ${payload}\n`; diff --git a/cli/tests/integration/host-run-helper.ts b/cli/tests/integration/host-run-helper.ts index 1825bd92..23e9ba76 100644 --- a/cli/tests/integration/host-run-helper.ts +++ b/cli/tests/integration/host-run-helper.ts @@ -1,3 +1,4 @@ +import * as nodeFs from 'fs'; import * as os from 'os'; import * as path from 'path'; import * as fs from '../../src/core/fs'; @@ -5,6 +6,7 @@ import { ProjectConfigHandler } from '../../src/config/project-config'; import { PROJECT_DEFAULT_PATHS } from '../../src/config/project-config'; import { BoardEnv, createBoardEnv } from '../../src/platforms/board-env'; import { isPackageInstalledOnWindows } from '../../src/commands/board/setup/utils'; +import { logger } from '../../src/core/logger'; const isHostPlatform = os.platform() === 'darwin' || os.platform() === 'win32'; export const describeHostIntegration = isHostPlatform ? describe : describe.skip; @@ -68,9 +70,32 @@ export function createHostProject( handler.save(root); } -export function removeDirIfExists(dir: string) { - if (fs.exists(dir)) { - fs.removeDir(dir); +export async function removeDirIfExists(dir: string, retries = 5): Promise { + if (!fs.exists(dir)) { + return; + } + for (let i = 0; i < retries; i++) { + try { + fs.removeDir(dir); + return; + } catch (error: unknown) { + const code = (error as NodeJS.ErrnoException).code; + if ((code !== 'EPERM' && code !== 'EBUSY') || i === retries - 1) { + throw error; + } + await new Promise((resolve) => setTimeout(resolve, 200 * (i + 1))); + } + } +} + +export async function removeChildDirsWithPrefix(parentDir: string, prefix: string): Promise { + if (!nodeFs.existsSync(parentDir)) { + return; + } + for (const name of nodeFs.readdirSync(parentDir)) { + if (name.startsWith(prefix)) { + await removeDirIfExists(path.join(parentDir, name)); + } } } @@ -159,3 +184,32 @@ export async function ensureHostRuntimeBuilt(): Promise { const hostEnv = createBoardEnv('host'); await hostEnv.buildHostRuntime(); } + +export function dumpRunDiagnostics( + exitSpy: jest.SpyInstance, + stdout?: { text: () => string }, +): void { + const code = exitSpy.mock.calls[0]?.[0]; + const lines = [ + `exit code: ${code}`, + `logger.error: ${JSON.stringify((logger.error as jest.Mock).mock.calls, null, 2)}`, + `logger.showError: ${(logger.showError as jest.Mock).mock.calls + .map(([err]) => (err instanceof Error ? err.message : String(err))) + .join(' | ')}`, + ]; + if (stdout) { + lines.push(`stdout: ${stdout.text()}`); + } + console.error(lines.join('\n')); +} +export function expectExitCode( + exitSpy: jest.SpyInstance, + expected: number, + stdout?: { text: () => string }, +): void { + const actual = exitSpy.mock.calls[0]?.[0]; + if (actual !== expected) { + dumpRunDiagnostics(exitSpy, stdout); + } + expect(exitSpy).toHaveBeenCalledWith(expected); +} diff --git a/cli/tests/integration/project/repl.host.test.ts b/cli/tests/integration/project/repl.host.test.ts index c31f66b7..0dbfe8d1 100644 --- a/cli/tests/integration/project/repl.host.test.ts +++ b/cli/tests/integration/project/repl.host.test.ts @@ -17,18 +17,22 @@ import { captureOutput, describeHostIntegration, ensureHostRuntimeBuilt, + expectExitCode, HOST_INTEGRATION_BUILD_DIR, HOST_INTEGRATION_RUNTIME_DIR, mockProcessExit, removeDirIfExists, + removeChildDirsWithPrefix, waitFor, waitForStdoutContains, } from '../host-run-helper'; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration-repl'); +const GLOBAL_TEMP_DIR = path.join(__dirname, '../../../temp-files'); let replLineHandler: ((line: string) => void) | undefined; let replCloseHandler: (() => void) | undefined; +let replTestCounter = 0; function createMockReadline(): readline.Interface { return { @@ -53,13 +57,13 @@ describeHostIntegration('repl command (host integration)', () => { jest.setTimeout(30000); beforeAll(async () => { - spyGlobalSettings('repl-integration'); fs.makeDir(TEMP_DIR); await ensureHostRuntimeBuilt(); }); beforeEach(() => { jest.clearAllMocks(); + spyGlobalSettings(`repl-integration-${++replTestCounter}`); deleteGlobalEnv(); setupGlobalEnvWithHostIntegration( HOST_INTEGRATION_RUNTIME_DIR, @@ -69,9 +73,10 @@ describeHostIntegration('repl command (host integration)', () => { replCloseHandler = undefined; }); - afterAll(() => { + afterAll(async () => { deleteGlobalEnv(); - removeDirIfExists(TEMP_DIR); + await removeDirIfExists(TEMP_DIR); + await removeChildDirsWithPrefix(GLOBAL_TEMP_DIR, '.bluescript-repl-integration-'); }); async function sendReplLine( @@ -115,7 +120,7 @@ describeHostIntegration('repl command (host integration)', () => { await closeRepl(); await replPromise; - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, output); expect(output.text()).toContain('repl entry'); output.restore(); @@ -130,7 +135,7 @@ describeHostIntegration('repl command (host integration)', () => { await closeRepl(); await replPromise; - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, output); expect(output.text()).toContain('init'); expect(output.text()).toContain('via print'); @@ -146,7 +151,7 @@ describeHostIntegration('repl command (host integration)', () => { await closeRepl(); await replPromise; - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, output); output.restore(); exitSpy.mockRestore(); @@ -164,7 +169,7 @@ describeHostIntegration('repl command (host integration)', () => { await closeRepl(); await replPromise; - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, output); output.restore(); exitSpy.mockRestore(); @@ -184,7 +189,7 @@ describeHostIntegration('repl command (host integration)', () => { await closeRepl(); await replPromise; - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, output); expect(output.text()).toContain('after error'); output.restore(); diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index 5a1b52ed..b23a902e 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -17,6 +17,7 @@ import { createHostProject, describeHostIntegration, ensureHostRuntimeBuilt, + expectExitCode, HOST_INTEGRATION_BUILD_DIR, HOST_INTEGRATION_RUNTIME_DIR, mockProcessExit, @@ -26,7 +27,9 @@ import { const mockedCwd = cwd as jest.Mock; const TEMP_DIR = path.join(__dirname, '../../../temp-files/integration'); -const PROJECT_ROOT = path.join(TEMP_DIR, 'run-project'); + +let currentProjectRoot: string; +let testCounter = 0; describeHostIntegration('project run command (host integration)', () => { beforeAll(async () => { @@ -41,27 +44,27 @@ describeHostIntegration('project run command (host integration)', () => { HOST_INTEGRATION_RUNTIME_DIR, HOST_INTEGRATION_BUILD_DIR, ); - removeDirIfExists(PROJECT_ROOT); - fs.makeDir(PROJECT_ROOT); - mockedCwd.mockReturnValue(PROJECT_ROOT); + currentProjectRoot = path.join(TEMP_DIR, `run-project-${++testCounter}`); + fs.makeDir(currentProjectRoot); + mockedCwd.mockReturnValue(currentProjectRoot); }); - afterAll(() => { + afterAll(async () => { deleteGlobalEnv(); - removeDirIfExists(TEMP_DIR); + await removeDirIfExists(TEMP_DIR); }); it('runs a program and prints output', async () => { const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': 'console.log("hello from run");', }, HOST_INTEGRATION_RUNTIME_DIR); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('hello from run'); stdout.restore(); @@ -72,7 +75,7 @@ describeHostIntegration('project run command (host integration)', () => { const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': ` console.log("built-in"); print("via print"); @@ -82,7 +85,7 @@ console.log(time.now()); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('built-in'); expect(stdout.text()).toContain('via print'); @@ -94,7 +97,7 @@ console.log(time.now()); const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': ` const message = "hello"; function greet(): void { @@ -106,7 +109,7 @@ greet(); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('hello'); stdout.restore(); @@ -117,7 +120,7 @@ greet(); const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/math-utils.bs': ` export function add(a: integer, b: integer): integer { return a + b; @@ -131,7 +134,7 @@ console.log(add(10, 20)); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('30'); stdout.restore(); @@ -142,7 +145,7 @@ console.log(add(10, 20)); const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': ` import { mul } from "math-lib"; console.log(mul(3, 4)); @@ -160,7 +163,7 @@ export function mul(a: integer, b: integer): integer { await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('12'); stdout.restore(); @@ -171,7 +174,7 @@ export function mul(a: integer, b: integer): integer { const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': ` code\`#include \` @@ -187,7 +190,7 @@ console.log(pow(2.0, 3.0)); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toMatch(/8(\.0+)?/); stdout.restore(); @@ -198,7 +201,7 @@ console.log(pow(2.0, 3.0)); const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/add.c': 'int add(int a, int b) { return a + b; }', 'src/index.bs': ` code\`#include "./add.c"\` @@ -215,7 +218,7 @@ main(); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('30'); stdout.restore(); @@ -226,7 +229,7 @@ main(); const exitSpy = mockProcessExit(); const stdout = captureStdout(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/add.h': 'int add(int a, int b);', 'src/add.c': '#include "add.h"\nint add(int a, int b) { return a + b; }', 'src/index.bs': ` @@ -244,7 +247,7 @@ main(); await handleRunCommand({ withRepl: false, withNotebook: false }); - expect(exitSpy).toHaveBeenCalledWith(0); + expectExitCode(exitSpy, 0, stdout); expect(stdout.text()).toContain('11'); stdout.restore(); @@ -254,7 +257,7 @@ main(); it('exits with an error when compilation fails', async () => { const exitSpy = mockProcessExit(); - createHostProject(PROJECT_ROOT, { + createHostProject(currentProjectRoot, { 'src/index.bs': 'this is not valid bluescript', }, HOST_INTEGRATION_RUNTIME_DIR); diff --git a/microcontroller/ports/esp32/main/ble.c b/microcontroller/ports/esp32/main/ble.c index 4ada41a4..3bdb5c01 100644 --- a/microcontroller/ports/esp32/main/ble.c +++ b/microcontroller/ports/esp32/main/ble.c @@ -461,6 +461,7 @@ void bs_ble_init(void) ESP_LOGE(GATTS_TAG, "%s enable bluetooth failed\n", __func__); return; } + puts(DEVICE_NAME); ret = esp_ble_gatts_register_callback(gatts_event_handler); if (ret){ diff --git a/microcontroller/ports/esp32/sdkconfig b/microcontroller/ports/esp32/sdkconfig index 2183722b..add276d4 100644 --- a/microcontroller/ports/esp32/sdkconfig +++ b/microcontroller/ports/esp32/sdkconfig @@ -1,7 +1,10 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Configuration # +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" +CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" +CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y @@ -68,7 +71,6 @@ CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 CONFIG_SOC_ADC_SHARED_POWER=y -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y CONFIG_SOC_CPU_CORES_NUM=2 @@ -77,7 +79,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y @@ -89,13 +91,13 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y CONFIG_SOC_I2C_NUM=2 CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y -CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y @@ -153,7 +155,6 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y -CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y @@ -174,8 +175,6 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y -CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 -CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 @@ -198,13 +197,13 @@ CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 -CONFIG_SOC_MPI_OPERATIONS_NUM=1 +CONFIG_SOC_MPI_OPERATIONS_NUM=y CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y @@ -236,7 +235,6 @@ CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y -CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y @@ -394,13 +392,13 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 # # Partition Table # -CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set # CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set # CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set -# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # end of Partition Table @@ -474,6 +472,7 @@ CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BT_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y # CONFIG_BT_CLASSIC_ENABLED is not set CONFIG_BT_BLE_ENABLED=y @@ -488,28 +487,14 @@ CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 # CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set # CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set # CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set -# CONFIG_BT_GATTS_SECURITY_LEVELS_CHAR is not set -# CONFIG_BT_GATTS_KEY_MATERIAL_CHAR is not set CONFIG_BT_GATTC_ENABLE=y CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 CONFIG_BT_GATTC_NOTIF_REG_MAX=5 # CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 -CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_SMP_ENABLE=y # CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set # CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set -CONFIG_BT_BLE_SMP_BOND_NVS_FLASH=y -# CONFIG_BT_BLE_RPA_SUPPORTED is not set - -# -# Bluedroid debug option -# -# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set -# CONFIG_BT_BLUEDROID_MEM_STATS is not set -# CONFIG_BT_BLUEDROID_THREAD_DEBUG is not set -# end of Bluedroid debug option - # CONFIG_BT_STACK_NO_LOG is not set # @@ -689,16 +674,15 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_MULTI_CONNECTION_ENBALE=y # CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set # CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set CONFIG_BT_SMP_ENABLE=y CONFIG_BT_SMP_MAX_BONDS=15 # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +# CONFIG_BT_BLE_RPA_SUPPORTED is not set CONFIG_BT_BLE_RPA_TIMEOUT=900 CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_BLE_42_DTM_TEST_EN=y -CONFIG_BT_BLE_42_ADV_EN=y -CONFIG_BT_BLE_42_SCAN_EN=y -CONFIG_BT_BLE_VENDOR_HCI_EN=y # CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set # CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set # end of Bluedroid Options @@ -715,8 +699,8 @@ CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF=0 CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 -CONFIG_BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT_EFF=0 CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y # CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 @@ -750,15 +734,12 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# BLE disconnects when Instant Passed (0x28) occurs +# BLE disconnect when instant passed # # CONFIG_BTDM_BLE_LLCP_CONN_UPDATE is not set # CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE is not set -# end of BLE disconnects when Instant Passed (0x28) occurs +# end of BLE disconnect when instant passed -CONFIG_BTDM_BLE_CHAN_ASS_EN=y -CONFIG_BTDM_BLE_PING_EN=y -# CONFIG_BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 is not set CONFIG_BTDM_RESERVE_DRAM=0xdb5c CONFIG_BTDM_CTRL_HLI=y # end of Controller Options @@ -767,19 +748,6 @@ CONFIG_BTDM_CTRL_HLI=y # Common Options # CONFIG_BT_ALARM_MAX_NUM=50 -CONFIG_BT_SMP_CRYPTO_STACK_NATIVE=y -# CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT is not set -# CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS is not set - -# -# BLE Log -# -# CONFIG_BLE_LOG_ENABLED is not set -# end of BLE Log - -# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set -# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set -# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set # end of Common Options # CONFIG_BT_HCI_LOG_DEBUG_EN is not set @@ -813,7 +781,6 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # CONFIG_ADC_DISABLE_DAC=y # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # # Legacy ADC Calibration Configuration @@ -829,55 +796,42 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # Legacy DAC Driver Configurations # # CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy DAC Driver Configurations # # Legacy MCPWM Driver Configurations # # CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy MCPWM Driver Configurations # # Legacy Timer Group Driver Configurations # # CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy Timer Group Driver Configurations # # Legacy RMT Driver Configurations # # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy RMT Driver Configurations # # Legacy I2S Driver Configurations # # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy I2S Driver Configurations -# -# Legacy I2C Driver Configurations -# -# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set -# end of Legacy I2C Driver Configurations - # # Legacy PCNT Driver Configurations # # CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy PCNT Driver Configurations # # Legacy SDM Driver Configurations # # CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy SDM Driver Configurations # end of Driver Configurations @@ -903,7 +857,6 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set -CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -961,7 +914,6 @@ CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -CONFIG_GPTIMER_OBJ_CACHE_SAFE=y # CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set # end of ESP-Driver:GPTimer Configurations @@ -1040,14 +992,6 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # CONFIG_UART_ISR_IN_IRAM is not set # end of ESP-Driver:UART Configurations -# -# ESP-Driver:UHCI Configurations -# -# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set -# CONFIG_UHCI_ISR_CACHE_SAFE is not set -# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:UHCI Configurations - # # Ethernet # @@ -1086,13 +1030,6 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub -# -# ESP HID -# -CONFIG_ESPHID_TASK_SIZE_BT=2048 -CONFIG_ESPHID_TASK_SIZE_BLE=4096 -# end of ESP HID - # # ESP HTTP client # @@ -1204,7 +1141,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # # Peripheral Control # -# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y # end of Peripheral Control # @@ -1265,11 +1202,8 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 -CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set -CONFIG_ESP_PHY_IRAM_OPT=y -# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -1461,10 +1395,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # # CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set -# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set # end of WPS Configuration Options # CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1520,14 +1454,6 @@ CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set # CONFIG_FATFS_USE_LABEL is not set CONFIG_FATFS_LINK_LOCK=y -# CONFIG_FATFS_USE_DYN_BUFFERS is not set - -# -# File system free space calculation behavior -# -CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 -CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 -# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1610,6 +1536,7 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1786,7 +1713,6 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 -# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set # CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set @@ -1874,7 +1800,6 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y -# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1904,7 +1829,6 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y -CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y # CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y @@ -1986,7 +1910,6 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MBEDTLS_THREADING_C is not set CONFIG_MBEDTLS_ERROR_STRINGS=y CONFIG_MBEDTLS_FS_IO=y -# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -2038,8 +1961,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # # CONFIG_OPENTHREAD_SPINEL_ONLY is not set # end of OpenThread Spinel - -# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -2048,7 +1969,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y -CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -2092,7 +2012,6 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set -# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -2295,6 +2214,7 @@ CONFIG_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BLUEDROID_MEM_DEBUG is not set # CONFIG_CLASSIC_BT_ENABLED is not set CONFIG_GATTS_ENABLE=y # CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set @@ -2302,10 +2222,8 @@ CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 CONFIG_GATTC_ENABLE=y # CONFIG_GATTC_CACHE_NVS_FLASH is not set -CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BLE_SMP_ENABLE=y # CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set -# CONFIG_BLUEDROID_MEM_DEBUG is not set # CONFIG_HCI_TRACE_LEVEL_NONE is not set # CONFIG_HCI_TRACE_LEVEL_ERROR is not set CONFIG_HCI_TRACE_LEVEL_WARNING=y @@ -2467,14 +2385,17 @@ CONFIG_BLUFI_TRACE_LEVEL_WARNING=y # CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set # CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set CONFIG_SMP_ENABLE=y # CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y # CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY is not set # CONFIG_BTDM_CONTROLLER_MODE_BTDM is not set CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y # CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4 is not set @@ -2592,6 +2513,8 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y @@ -2612,6 +2535,7 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y # CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set # CONFIG_WPA_WPS_STRICT is not set # CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y diff --git a/microcontroller/ports/esp32/sdkconfig.old b/microcontroller/ports/esp32/sdkconfig.old index 9eca7b5e..c7ea4e9c 100644 --- a/microcontroller/ports/esp32/sdkconfig.old +++ b/microcontroller/ports/esp32/sdkconfig.old @@ -1,7 +1,10 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Configuration # +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" +CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" +CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y @@ -68,7 +71,6 @@ CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 CONFIG_SOC_ADC_SHARED_POWER=y -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y CONFIG_SOC_CPU_CORES_NUM=2 @@ -77,7 +79,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y @@ -89,13 +91,13 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y CONFIG_SOC_I2C_NUM=2 CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y -CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y @@ -153,7 +155,6 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y -CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y @@ -174,8 +175,6 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y -CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 -CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 @@ -198,13 +197,13 @@ CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 -CONFIG_SOC_MPI_OPERATIONS_NUM=1 +CONFIG_SOC_MPI_OPERATIONS_NUM=y CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y @@ -236,7 +235,6 @@ CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y -CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y @@ -459,24 +457,304 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # Bluetooth # -# CONFIG_BT_ENABLED is not set +CONFIG_BT_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=y +# CONFIG_BT_NIMBLE_ENABLED is not set +# CONFIG_BT_CONTROLLER_ONLY is not set +CONFIG_BT_CONTROLLER_ENABLED=y +# CONFIG_BT_CONTROLLER_DISABLED is not set + +# +# Bluedroid Options +# +CONFIG_BT_BTC_TASK_STACK_SIZE=3072 +CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BT_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y +# CONFIG_BT_CLASSIC_ENABLED is not set +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_GATTS_ENABLE=y +# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set +# CONFIG_BT_BLE_BLUFI_ENABLE is not set +CONFIG_BT_GATT_MAX_SR_PROFILES=8 +CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100 +# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 +# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set +# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set +# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set +CONFIG_BT_GATTC_ENABLE=y +CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 +CONFIG_BT_GATTC_NOTIF_REG_MAX=5 +# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 +CONFIG_BT_BLE_SMP_ENABLE=y +# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set +# CONFIG_BT_STACK_NO_LOG is not set + +# +# BT DEBUG LOG LEVEL +# +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 +# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL=2 +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 +# end of BT DEBUG LOG LEVEL + +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_MULTI_CONNECTION_ENBALE=y +# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set +# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set +CONFIG_BT_SMP_ENABLE=y +CONFIG_BT_SMP_MAX_BONDS=15 +# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 +CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +# CONFIG_BT_BLE_RPA_SUPPORTED is not set +CONFIG_BT_BLE_RPA_TIMEOUT=900 +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set +# CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Bluedroid Options + +# +# Controller Options +# +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +# CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set +# CONFIG_BTDM_CTRL_MODE_BTDM is not set +CONFIG_BTDM_CTRL_BLE_MAX_CONN=3 +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 +CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 +CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y +# CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y +# CONFIG_BTDM_CTRL_HCI_MODE_UART_H4 is not set + +# +# MODEM SLEEP Options +# +CONFIG_BTDM_CTRL_MODEM_SLEEP=y +CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG=y +# CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED is not set +CONFIG_BTDM_CTRL_LPCLK_SEL_MAIN_XTAL=y +# end of MODEM SLEEP Options + +CONFIG_BTDM_BLE_DEFAULT_SCA_250PPM=y +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BTDM_BLE_SCAN_DUPL=y +CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BTDM_SCAN_DUPL_TYPE=0 +CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BTDM_SCAN_DUPL_CACHE_REFRESH_PERIOD=0 +# CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN is not set +CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y +# CONFIG_BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set +# CONFIG_BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS is not set +CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 + +# +# BLE disconnect when instant passed +# +# CONFIG_BTDM_BLE_LLCP_CONN_UPDATE is not set +# CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE is not set +# end of BLE disconnect when instant passed + +CONFIG_BTDM_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_CTRL_HLI=y +# end of Controller Options # # Common Options # - -# -# BLE Log -# -# CONFIG_BLE_LOG_ENABLED is not set -# end of BLE Log - -# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set -# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set -# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +CONFIG_BT_ALARM_MAX_NUM=50 # end of Common Options + +# CONFIG_BT_HCI_LOG_DEBUG_EN is not set # end of Bluetooth +# CONFIG_BLE_MESH is not set + # # Console Library # @@ -503,7 +781,6 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # CONFIG_ADC_DISABLE_DAC=y # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # # Legacy ADC Calibration Configuration @@ -519,55 +796,42 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # Legacy DAC Driver Configurations # # CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy DAC Driver Configurations # # Legacy MCPWM Driver Configurations # # CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy MCPWM Driver Configurations # # Legacy Timer Group Driver Configurations # # CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy Timer Group Driver Configurations # # Legacy RMT Driver Configurations # # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy RMT Driver Configurations # # Legacy I2S Driver Configurations # # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy I2S Driver Configurations -# -# Legacy I2C Driver Configurations -# -# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set -# end of Legacy I2C Driver Configurations - # # Legacy PCNT Driver Configurations # # CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy PCNT Driver Configurations # # Legacy SDM Driver Configurations # # CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy SDM Driver Configurations # end of Driver Configurations @@ -593,7 +857,6 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set -CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -618,6 +881,8 @@ CONFIG_ADC_DISABLE_DAC_OUTPUT=y # Wireless Coexistence # CONFIG_ESP_COEX_ENABLED=y +CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y +# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set # CONFIG_ESP_COEX_GPIO_DEBUG is not set # end of Wireless Coexistence @@ -649,7 +914,6 @@ CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -CONFIG_GPTIMER_OBJ_CACHE_SAFE=y # CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set # end of ESP-Driver:GPTimer Configurations @@ -728,14 +992,6 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # CONFIG_UART_ISR_IN_IRAM is not set # end of ESP-Driver:UART Configurations -# -# ESP-Driver:UHCI Configurations -# -# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set -# CONFIG_UHCI_ISR_CACHE_SAFE is not set -# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:UHCI Configurations - # # Ethernet # @@ -774,13 +1030,6 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub -# -# ESP HID -# -CONFIG_ESPHID_TASK_SIZE_BT=2048 -CONFIG_ESPHID_TASK_SIZE_BLE=4096 -# end of ESP HID - # # ESP HTTP client # @@ -892,7 +1141,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # # Peripheral Control # -# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y # end of Peripheral Control # @@ -953,11 +1202,8 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 -CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set -CONFIG_ESP_PHY_IRAM_OPT=y -# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -1049,8 +1295,7 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP_PANIC_HANDLER_IRAM is not set # CONFIG_ESP_DEBUG_STUBS_ENABLE is not set CONFIG_ESP_DEBUG_OCDAWARE=y -# CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set -CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5=y # # Brownout Detector @@ -1150,10 +1395,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # # CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set -# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set # end of WPS Configuration Options # CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1209,14 +1454,6 @@ CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set # CONFIG_FATFS_USE_LABEL is not set CONFIG_FATFS_LINK_LOCK=y -# CONFIG_FATFS_USE_DYN_BUFFERS is not set - -# -# File system free space calculation behavior -# -CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 -CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 -# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1299,6 +1536,7 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1475,7 +1713,6 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 -# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set # CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set @@ -1563,7 +1800,6 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y -# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1593,7 +1829,6 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y -CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y # CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y @@ -1675,7 +1910,6 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MBEDTLS_THREADING_C is not set CONFIG_MBEDTLS_ERROR_STRINGS=y CONFIG_MBEDTLS_FS_IO=y -# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -1727,8 +1961,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # # CONFIG_OPENTHREAD_SPINEL_ONLY is not set # end of OpenThread Spinel - -# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -1737,7 +1969,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y -CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -1781,7 +2012,6 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set -# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -1928,6 +2158,10 @@ CONFIG_WL_SECTOR_SIZE=4096 # CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_WIFI_PROV_BLE_BONDING is not set +# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_WIFI_PROV_BLE_NOTIFY is not set +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set # end of Wi-Fi Provisioning Manager diff --git a/microcontroller/ports/host/comm.h b/microcontroller/ports/host/comm.h index e7f5ecb1..22f00a1e 100644 --- a/microcontroller/ports/host/comm.h +++ b/microcontroller/ports/host/comm.h @@ -3,7 +3,7 @@ #include -#define MAX_PAYLOAD_SIZE 128 +#define MAX_PAYLOAD_SIZE 256 #define PROTO_SIZE 3 #define PAYLOAD_LEN_SIZE 5 #define HEADER_SIZE PROTO_SIZE + PAYLOAD_LEN_SIZE diff --git a/microcontroller/ports/host/shell.c b/microcontroller/ports/host/shell.c index 0d95d09c..941581d7 100644 --- a/microcontroller/ports/host/shell.c +++ b/microcontroller/ports/host/shell.c @@ -44,6 +44,9 @@ static void load(char* filename) { float start_time = get_time_ms(); #ifndef _WIN32 file_handle = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (file_handle == NULL) { + fprintf(stderr, "Error: failed to load %s\n", filename); + } #else file_handle = (void*)LoadLibraryA(filename); if (file_handle == NULL) { From a1284c4b5d764effd83f6b654f54f1034f2bc63e Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 4 Jul 2026 21:47:30 +0900 Subject: [PATCH 15/33] Fix cli to run run command on windows. --- cli/src/services/ble.ts | 4 +- microcontroller/ports/esp32/main/ble.c | 15 +- microcontroller/ports/esp32/sdkconfig | 132 ++------ microcontroller/ports/esp32/sdkconfig.old | 384 +++++++++++++++++----- 4 files changed, 345 insertions(+), 190 deletions(-) diff --git a/cli/src/services/ble.ts b/cli/src/services/ble.ts index 454b3948..5fbb266a 100644 --- a/cli/src/services/ble.ts +++ b/cli/src/services/ble.ts @@ -7,8 +7,8 @@ import { Protocol, ProtocolPacketBuilder, ProtocolParser } from './device-protoc const MTU = 495; -const SERVICE_UUID = '00ff'; -const CHARACTERISTIC_UUID = 'ff01'; +const SERVICE_UUID = 'b500'; +const CHARACTERISTIC_UUID = 'b501'; export type DeviceServiceEvents = { diff --git a/microcontroller/ports/esp32/main/ble.c b/microcontroller/ports/esp32/main/ble.c index 4ada41a4..83028b31 100644 --- a/microcontroller/ports/esp32/main/ble.c +++ b/microcontroller/ports/esp32/main/ble.c @@ -28,8 +28,8 @@ ///Declare the static function static void gatts_profile_shell_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param); -#define GATTS_SERVICE_UUID_SHELL 0x00FF -#define GATTS_CHAR_UUID_SHELL 0xFF01 +#define GATTS_SERVICE_UUID_SHELL 0xB500 +#define GATTS_CHAR_UUID_SHELL 0xB501 #define GATTS_DESCR_UUID_SHELL 0x3333 #define GATTS_NUM_HANDLE_SHELL 4 @@ -59,11 +59,8 @@ static uint8_t adv_config_done = 0; #define scan_rsp_config_flag (1 << 1) static uint8_t adv_service_uuid128[32] = { - /* LSB <--------------------------------------------------------------------------------> MSB */ - //first uuid, 16bit, [12],[13] is the value - 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00, - //second uuid, 32bit, [12], [13], [14], [15] is the value - 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, + // BlueScript shell service (0xB500). [12],[13] is the value. + 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0xB5, 0x00, 0x00, }; // The length of adv data must be less than 31 bytes @@ -79,7 +76,7 @@ static esp_ble_adv_data_t adv_data = { .p_manufacturer_data = NULL, .service_data_len = 0, .p_service_data = NULL, - .service_uuid_len = 32, + .service_uuid_len = 16, .p_service_uuid = adv_service_uuid128, .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), }; @@ -95,7 +92,7 @@ static esp_ble_adv_data_t scan_rsp_data = { .p_manufacturer_data = NULL, .service_data_len = 0, .p_service_data = NULL, - .service_uuid_len = 32, + .service_uuid_len = 16, .p_service_uuid = adv_service_uuid128, .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT), }; diff --git a/microcontroller/ports/esp32/sdkconfig b/microcontroller/ports/esp32/sdkconfig index 2183722b..add276d4 100644 --- a/microcontroller/ports/esp32/sdkconfig +++ b/microcontroller/ports/esp32/sdkconfig @@ -1,7 +1,10 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Configuration # +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" +CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" +CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y @@ -68,7 +71,6 @@ CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 CONFIG_SOC_ADC_SHARED_POWER=y -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y CONFIG_SOC_CPU_CORES_NUM=2 @@ -77,7 +79,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y @@ -89,13 +91,13 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y CONFIG_SOC_I2C_NUM=2 CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y -CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y @@ -153,7 +155,6 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y -CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y @@ -174,8 +175,6 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y -CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 -CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 @@ -198,13 +197,13 @@ CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 -CONFIG_SOC_MPI_OPERATIONS_NUM=1 +CONFIG_SOC_MPI_OPERATIONS_NUM=y CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y @@ -236,7 +235,6 @@ CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y -CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y @@ -394,13 +392,13 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 # # Partition Table # -CONFIG_PARTITION_TABLE_SINGLE_APP=y +# CONFIG_PARTITION_TABLE_SINGLE_APP is not set # CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set # CONFIG_PARTITION_TABLE_TWO_OTA is not set # CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set -# CONFIG_PARTITION_TABLE_CUSTOM is not set +CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" -CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_MD5=y # end of Partition Table @@ -474,6 +472,7 @@ CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BT_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y # CONFIG_BT_CLASSIC_ENABLED is not set CONFIG_BT_BLE_ENABLED=y @@ -488,28 +487,14 @@ CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 # CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set # CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set # CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set -# CONFIG_BT_GATTS_SECURITY_LEVELS_CHAR is not set -# CONFIG_BT_GATTS_KEY_MATERIAL_CHAR is not set CONFIG_BT_GATTC_ENABLE=y CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 CONFIG_BT_GATTC_NOTIF_REG_MAX=5 # CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 -CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_BLE_SMP_ENABLE=y # CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set # CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set -CONFIG_BT_BLE_SMP_BOND_NVS_FLASH=y -# CONFIG_BT_BLE_RPA_SUPPORTED is not set - -# -# Bluedroid debug option -# -# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set -# CONFIG_BT_BLUEDROID_MEM_STATS is not set -# CONFIG_BT_BLUEDROID_THREAD_DEBUG is not set -# end of Bluedroid debug option - # CONFIG_BT_STACK_NO_LOG is not set # @@ -689,16 +674,15 @@ CONFIG_BT_ACL_CONNECTIONS=4 CONFIG_BT_MULTI_CONNECTION_ENBALE=y # CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set # CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set CONFIG_BT_SMP_ENABLE=y CONFIG_BT_SMP_MAX_BONDS=15 # CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +# CONFIG_BT_BLE_RPA_SUPPORTED is not set CONFIG_BT_BLE_RPA_TIMEOUT=900 CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y -CONFIG_BT_BLE_42_DTM_TEST_EN=y -CONFIG_BT_BLE_42_ADV_EN=y -CONFIG_BT_BLE_42_SCAN_EN=y -CONFIG_BT_BLE_VENDOR_HCI_EN=y # CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set # CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set # end of Bluedroid Options @@ -715,8 +699,8 @@ CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF=0 CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 -CONFIG_BTDM_CTRL_BR_EDR_MIN_ENC_KEY_SZ_DFT_EFF=0 CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y # CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 @@ -750,15 +734,12 @@ CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 # -# BLE disconnects when Instant Passed (0x28) occurs +# BLE disconnect when instant passed # # CONFIG_BTDM_BLE_LLCP_CONN_UPDATE is not set # CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE is not set -# end of BLE disconnects when Instant Passed (0x28) occurs +# end of BLE disconnect when instant passed -CONFIG_BTDM_BLE_CHAN_ASS_EN=y -CONFIG_BTDM_BLE_PING_EN=y -# CONFIG_BTDM_CTRL_CONTROLLER_DEBUG_MODE_1 is not set CONFIG_BTDM_RESERVE_DRAM=0xdb5c CONFIG_BTDM_CTRL_HLI=y # end of Controller Options @@ -767,19 +748,6 @@ CONFIG_BTDM_CTRL_HLI=y # Common Options # CONFIG_BT_ALARM_MAX_NUM=50 -CONFIG_BT_SMP_CRYPTO_STACK_NATIVE=y -# CONFIG_BT_SMP_CRYPTO_STACK_TINYCRYPT is not set -# CONFIG_BT_SMP_CRYPTO_STACK_MBEDTLS is not set - -# -# BLE Log -# -# CONFIG_BLE_LOG_ENABLED is not set -# end of BLE Log - -# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set -# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set -# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set # end of Common Options # CONFIG_BT_HCI_LOG_DEBUG_EN is not set @@ -813,7 +781,6 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # CONFIG_ADC_DISABLE_DAC=y # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # # Legacy ADC Calibration Configuration @@ -829,55 +796,42 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # Legacy DAC Driver Configurations # # CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy DAC Driver Configurations # # Legacy MCPWM Driver Configurations # # CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy MCPWM Driver Configurations # # Legacy Timer Group Driver Configurations # # CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy Timer Group Driver Configurations # # Legacy RMT Driver Configurations # # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy RMT Driver Configurations # # Legacy I2S Driver Configurations # # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy I2S Driver Configurations -# -# Legacy I2C Driver Configurations -# -# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set -# end of Legacy I2C Driver Configurations - # # Legacy PCNT Driver Configurations # # CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy PCNT Driver Configurations # # Legacy SDM Driver Configurations # # CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy SDM Driver Configurations # end of Driver Configurations @@ -903,7 +857,6 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set -CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -961,7 +914,6 @@ CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -CONFIG_GPTIMER_OBJ_CACHE_SAFE=y # CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set # end of ESP-Driver:GPTimer Configurations @@ -1040,14 +992,6 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # CONFIG_UART_ISR_IN_IRAM is not set # end of ESP-Driver:UART Configurations -# -# ESP-Driver:UHCI Configurations -# -# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set -# CONFIG_UHCI_ISR_CACHE_SAFE is not set -# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:UHCI Configurations - # # Ethernet # @@ -1086,13 +1030,6 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub -# -# ESP HID -# -CONFIG_ESPHID_TASK_SIZE_BT=2048 -CONFIG_ESPHID_TASK_SIZE_BLE=4096 -# end of ESP HID - # # ESP HTTP client # @@ -1204,7 +1141,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # # Peripheral Control # -# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y # end of Peripheral Control # @@ -1265,11 +1202,8 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 -CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set -CONFIG_ESP_PHY_IRAM_OPT=y -# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -1461,10 +1395,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # # CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set -# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set # end of WPS Configuration Options # CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1520,14 +1454,6 @@ CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set # CONFIG_FATFS_USE_LABEL is not set CONFIG_FATFS_LINK_LOCK=y -# CONFIG_FATFS_USE_DYN_BUFFERS is not set - -# -# File system free space calculation behavior -# -CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 -CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 -# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1610,6 +1536,7 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1786,7 +1713,6 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 -# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set # CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set @@ -1874,7 +1800,6 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y -# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1904,7 +1829,6 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y -CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y # CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y @@ -1986,7 +1910,6 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MBEDTLS_THREADING_C is not set CONFIG_MBEDTLS_ERROR_STRINGS=y CONFIG_MBEDTLS_FS_IO=y -# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -2038,8 +1961,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # # CONFIG_OPENTHREAD_SPINEL_ONLY is not set # end of OpenThread Spinel - -# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -2048,7 +1969,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y -CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -2092,7 +2012,6 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set -# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -2295,6 +2214,7 @@ CONFIG_BLUEDROID_PINNED_TO_CORE_0=y # CONFIG_BLUEDROID_PINNED_TO_CORE_1 is not set CONFIG_BLUEDROID_PINNED_TO_CORE=0 CONFIG_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BLUEDROID_MEM_DEBUG is not set # CONFIG_CLASSIC_BT_ENABLED is not set CONFIG_GATTS_ENABLE=y # CONFIG_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set @@ -2302,10 +2222,8 @@ CONFIG_GATTS_SEND_SERVICE_CHANGE_AUTO=y CONFIG_GATTS_SEND_SERVICE_CHANGE_MODE=0 CONFIG_GATTC_ENABLE=y # CONFIG_GATTC_CACHE_NVS_FLASH is not set -CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BLE_SMP_ENABLE=y # CONFIG_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set -# CONFIG_BLUEDROID_MEM_DEBUG is not set # CONFIG_HCI_TRACE_LEVEL_NONE is not set # CONFIG_HCI_TRACE_LEVEL_ERROR is not set CONFIG_HCI_TRACE_LEVEL_WARNING=y @@ -2467,14 +2385,17 @@ CONFIG_BLUFI_TRACE_LEVEL_WARNING=y # CONFIG_BLUFI_TRACE_LEVEL_DEBUG is not set # CONFIG_BLUFI_TRACE_LEVEL_VERBOSE is not set CONFIG_BLUFI_INITIAL_TRACE_LEVEL=2 +# CONFIG_BLE_HOST_QUEUE_CONGESTION_CHECK is not set CONFIG_SMP_ENABLE=y # CONFIG_BLE_ACTIVE_SCAN_REPORT_ADV_SCAN_RSP_INDIVIDUALLY is not set +CONFIG_BLE_ESTABLISH_LINK_CONNECTION_TIMEOUT=30 CONFIG_BTDM_CONTROLLER_MODE_BLE_ONLY=y # CONFIG_BTDM_CONTROLLER_MODE_BR_EDR_ONLY is not set # CONFIG_BTDM_CONTROLLER_MODE_BTDM is not set CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN=3 CONFIG_BTDM_CONTROLLER_BLE_MAX_CONN_EFF=3 CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0 CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y # CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4 is not set @@ -2592,6 +2513,8 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y CONFIG_ESP32_WIFI_TX_BA_WIN=6 CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_RX_BA_WIN=6 CONFIG_ESP32_WIFI_NVS_ENABLED=y CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y @@ -2612,6 +2535,7 @@ CONFIG_WPA_MBEDTLS_TLS_CLIENT=y # CONFIG_WPA_WPS_SOFTAP_REGISTRAR is not set # CONFIG_WPA_WPS_STRICT is not set # CONFIG_WPA_DEBUG_PRINT is not set +# CONFIG_WPA_TESTING_OPTIONS is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH is not set # CONFIG_ESP32_ENABLE_COREDUMP_TO_UART is not set CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y diff --git a/microcontroller/ports/esp32/sdkconfig.old b/microcontroller/ports/esp32/sdkconfig.old index 9eca7b5e..c7ea4e9c 100644 --- a/microcontroller/ports/esp32/sdkconfig.old +++ b/microcontroller/ports/esp32/sdkconfig.old @@ -1,7 +1,10 @@ # # Automatically generated file. DO NOT EDIT. -# Espressif IoT Development Framework (ESP-IDF) 5.4.4 Project Configuration +# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Configuration # +CONFIG_SOC_BROWNOUT_RESET_SUPPORTED="Not determined" +CONFIG_SOC_TWAI_BRP_DIV_SUPPORTED="Not determined" +CONFIG_SOC_DPORT_WORKAROUND="Not determined" CONFIG_SOC_CAPS_ECO_VER_MAX=301 CONFIG_SOC_ADC_SUPPORTED=y CONFIG_SOC_DAC_SUPPORTED=y @@ -68,7 +71,6 @@ CONFIG_SOC_ADC_SAMPLE_FREQ_THRES_LOW=20 CONFIG_SOC_ADC_RTC_MIN_BITWIDTH=9 CONFIG_SOC_ADC_RTC_MAX_BITWIDTH=12 CONFIG_SOC_ADC_SHARED_POWER=y -CONFIG_SOC_BROWNOUT_RESET_SUPPORTED=y CONFIG_SOC_SHARED_IDCACHE_SUPPORTED=y CONFIG_SOC_IDCACHE_PER_CORE=y CONFIG_SOC_CPU_CORES_NUM=2 @@ -77,7 +79,7 @@ CONFIG_SOC_CPU_HAS_FPU=y CONFIG_SOC_HP_CPU_HAS_MULTIPLE_CORES=y CONFIG_SOC_CPU_BREAKPOINTS_NUM=2 CONFIG_SOC_CPU_WATCHPOINTS_NUM=2 -CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=0x40 +CONFIG_SOC_CPU_WATCHPOINT_MAX_REGION_SIZE=64 CONFIG_SOC_DAC_CHAN_NUM=2 CONFIG_SOC_DAC_RESOLUTION=8 CONFIG_SOC_DAC_DMA_16BIT_ALIGN=y @@ -89,13 +91,13 @@ CONFIG_SOC_GPIO_OUT_RANGE_MAX=33 CONFIG_SOC_GPIO_VALID_DIGITAL_IO_PAD_MASK=0xEF0FEA CONFIG_SOC_GPIO_CLOCKOUT_BY_IO_MUX=y CONFIG_SOC_GPIO_CLOCKOUT_CHANNEL_NUM=3 +CONFIG_SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP=y CONFIG_SOC_I2C_NUM=2 CONFIG_SOC_HP_I2C_NUM=2 CONFIG_SOC_I2C_FIFO_LEN=32 CONFIG_SOC_I2C_CMD_REG_NUM=16 CONFIG_SOC_I2C_SUPPORT_SLAVE=y CONFIG_SOC_I2C_SUPPORT_APB=y -CONFIG_SOC_I2C_SUPPORT_10BIT_ADDR=y CONFIG_SOC_I2C_STOP_INDEPENDENT=y CONFIG_SOC_I2S_NUM=2 CONFIG_SOC_I2S_HW_VERSION_1=y @@ -153,7 +155,6 @@ CONFIG_SOC_RTCIO_PIN_COUNT=18 CONFIG_SOC_RTCIO_INPUT_OUTPUT_SUPPORTED=y CONFIG_SOC_RTCIO_HOLD_SUPPORTED=y CONFIG_SOC_RTCIO_WAKE_SUPPORTED=y -CONFIG_SOC_RTC_CNTL_NEEDS_ATOMIC_ACCESS=y CONFIG_SOC_SDM_GROUPS=1 CONFIG_SOC_SDM_CHANNELS_PER_GROUP=8 CONFIG_SOC_SDM_CLK_SUPPORT_APB=y @@ -174,8 +175,6 @@ CONFIG_SOC_TIMER_GROUP_TIMERS_PER_GROUP=2 CONFIG_SOC_TIMER_GROUP_COUNTER_BIT_WIDTH=64 CONFIG_SOC_TIMER_GROUP_TOTAL_TIMERS=4 CONFIG_SOC_TIMER_GROUP_SUPPORT_APB=y -CONFIG_SOC_LP_TIMER_BIT_WIDTH_LO=32 -CONFIG_SOC_LP_TIMER_BIT_WIDTH_HI=16 CONFIG_SOC_TOUCH_SENSOR_VERSION=1 CONFIG_SOC_TOUCH_SENSOR_NUM=10 CONFIG_SOC_TOUCH_SAMPLE_CFG_NUM=1 @@ -198,13 +197,13 @@ CONFIG_SOC_SHA_SUPPORT_SHA256=y CONFIG_SOC_SHA_SUPPORT_SHA384=y CONFIG_SOC_SHA_SUPPORT_SHA512=y CONFIG_SOC_MPI_MEM_BLOCKS_NUM=4 -CONFIG_SOC_MPI_OPERATIONS_NUM=1 +CONFIG_SOC_MPI_OPERATIONS_NUM=y CONFIG_SOC_RSA_MAX_BIT_LEN=4096 CONFIG_SOC_AES_SUPPORT_AES_128=y CONFIG_SOC_AES_SUPPORT_AES_192=y CONFIG_SOC_AES_SUPPORT_AES_256=y CONFIG_SOC_SECURE_BOOT_V1=y -CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=1 +CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS=y CONFIG_SOC_FLASH_ENCRYPTED_XTS_AES_BLOCK_MAX=32 CONFIG_SOC_PHY_DIG_REGS_MEM_SIZE=21 CONFIG_SOC_PM_SUPPORT_EXT0_WAKEUP=y @@ -236,7 +235,6 @@ CONFIG_SOC_BLE_MESH_SUPPORTED=y CONFIG_SOC_BT_CLASSIC_SUPPORTED=y CONFIG_SOC_BLUFI_SUPPORTED=y CONFIG_SOC_BT_H2C_ENC_KEY_CTRL_ENH_VSC_SUPPORTED=y -CONFIG_SOC_BLE_MULTI_CONN_OPTIMIZATION=y CONFIG_SOC_ULP_HAS_ADC=y CONFIG_SOC_PHY_COMBO_MODULE=y CONFIG_SOC_EMAC_RMII_CLK_OUT_INTERNAL_LOOPBACK=y @@ -459,24 +457,304 @@ CONFIG_APPTRACE_LOCK_ENABLE=y # # Bluetooth # -# CONFIG_BT_ENABLED is not set +CONFIG_BT_ENABLED=y +CONFIG_BT_BLUEDROID_ENABLED=y +# CONFIG_BT_NIMBLE_ENABLED is not set +# CONFIG_BT_CONTROLLER_ONLY is not set +CONFIG_BT_CONTROLLER_ENABLED=y +# CONFIG_BT_CONTROLLER_DISABLED is not set + +# +# Bluedroid Options +# +CONFIG_BT_BTC_TASK_STACK_SIZE=3072 +CONFIG_BT_BLUEDROID_PINNED_TO_CORE_0=y +# CONFIG_BT_BLUEDROID_PINNED_TO_CORE_1 is not set +CONFIG_BT_BLUEDROID_PINNED_TO_CORE=0 +CONFIG_BT_BTU_TASK_STACK_SIZE=4352 +# CONFIG_BT_BLUEDROID_MEM_DEBUG is not set +CONFIG_BT_BLUEDROID_ESP_COEX_VSC=y +# CONFIG_BT_CLASSIC_ENABLED is not set +CONFIG_BT_BLE_ENABLED=y +CONFIG_BT_GATTS_ENABLE=y +# CONFIG_BT_GATTS_PPCP_CHAR_GAP is not set +# CONFIG_BT_BLE_BLUFI_ENABLE is not set +CONFIG_BT_GATT_MAX_SR_PROFILES=8 +CONFIG_BT_GATT_MAX_SR_ATTRIBUTES=100 +# CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MANUAL is not set +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_AUTO=y +CONFIG_BT_GATTS_SEND_SERVICE_CHANGE_MODE=0 +# CONFIG_BT_GATTS_ROBUST_CACHING_ENABLED is not set +# CONFIG_BT_GATTS_DEVICE_NAME_WRITABLE is not set +# CONFIG_BT_GATTS_APPEARANCE_WRITABLE is not set +CONFIG_BT_GATTC_ENABLE=y +CONFIG_BT_GATTC_MAX_CACHE_CHAR=40 +CONFIG_BT_GATTC_NOTIF_REG_MAX=5 +# CONFIG_BT_GATTC_CACHE_NVS_FLASH is not set +CONFIG_BT_GATTC_CONNECT_RETRY_COUNT=3 +CONFIG_BT_BLE_SMP_ENABLE=y +# CONFIG_BT_SMP_SLAVE_CON_PARAMS_UPD_ENABLE is not set +# CONFIG_BT_BLE_SMP_ID_RESET_ENABLE is not set +# CONFIG_BT_STACK_NO_LOG is not set + +# +# BT DEBUG LOG LEVEL +# +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HCI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HCI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_L2CAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_L2CAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_RFCOMM_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SDP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SDP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GAP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GAP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BNEP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BNEP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_PAN_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_PAN_TRACE_LEVEL=2 +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_A2D_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_A2D_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVDT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVDT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVCT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVCT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_AVRC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_AVRC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_MCA_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_MCA_TRACE_LEVEL=2 +# CONFIG_BT_LOG_HID_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_HID_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_HID_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_HID_TRACE_LEVEL=2 +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_APPL_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_APPL_TRACE_LEVEL=2 +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_GATT_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_GATT_TRACE_LEVEL=2 +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_SMP_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_SMP_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTIF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTIF_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BTC_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BTC_TRACE_LEVEL=2 +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_OSI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_OSI_TRACE_LEVEL=2 +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_NONE is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_ERROR is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_WARNING=y +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_API is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_EVENT is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_DEBUG is not set +# CONFIG_BT_LOG_BLUFI_TRACE_LEVEL_VERBOSE is not set +CONFIG_BT_LOG_BLUFI_TRACE_LEVEL=2 +# end of BT DEBUG LOG LEVEL + +CONFIG_BT_ACL_CONNECTIONS=4 +CONFIG_BT_MULTI_CONNECTION_ENBALE=y +# CONFIG_BT_ALLOCATION_FROM_SPIRAM_FIRST is not set +# CONFIG_BT_BLE_DYNAMIC_ENV_MEMORY is not set +# CONFIG_BT_BLE_HOST_QUEUE_CONG_CHECK is not set +CONFIG_BT_SMP_ENABLE=y +CONFIG_BT_SMP_MAX_BONDS=15 +# CONFIG_BT_BLE_ACT_SCAN_REP_ADV_SCAN is not set +CONFIG_BT_BLE_ESTAB_LINK_CONN_TOUT=30 +CONFIG_BT_MAX_DEVICE_NAME_LEN=32 +# CONFIG_BT_BLE_RPA_SUPPORTED is not set +CONFIG_BT_BLE_RPA_TIMEOUT=900 +CONFIG_BT_BLE_42_FEATURES_SUPPORTED=y +# CONFIG_BT_BLE_HIGH_DUTY_ADV_INTERVAL is not set +# CONFIG_BT_ABORT_WHEN_ALLOCATION_FAILS is not set +# end of Bluedroid Options + +# +# Controller Options +# +CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y +# CONFIG_BTDM_CTRL_MODE_BR_EDR_ONLY is not set +# CONFIG_BTDM_CTRL_MODE_BTDM is not set +CONFIG_BTDM_CTRL_BLE_MAX_CONN=3 +CONFIG_BTDM_CTRL_BR_EDR_SCO_DATA_PATH_EFF=0 +CONFIG_BTDM_CTRL_PCM_ROLE_EFF=0 +CONFIG_BTDM_CTRL_PCM_POLAR_EFF=0 +CONFIG_BTDM_CTRL_PCM_FSYNCSHP_EFF=0 +CONFIG_BTDM_CTRL_BLE_MAX_CONN_EFF=3 +CONFIG_BTDM_CTRL_BR_EDR_MAX_ACL_CONN_EFF=0 +CONFIG_BTDM_CTRL_BR_EDR_MAX_SYNC_CONN_EFF=0 +CONFIG_BTDM_CTRL_PINNED_TO_CORE_0=y +# CONFIG_BTDM_CTRL_PINNED_TO_CORE_1 is not set +CONFIG_BTDM_CTRL_PINNED_TO_CORE=0 +CONFIG_BTDM_CTRL_HCI_MODE_VHCI=y +# CONFIG_BTDM_CTRL_HCI_MODE_UART_H4 is not set + +# +# MODEM SLEEP Options +# +CONFIG_BTDM_CTRL_MODEM_SLEEP=y +CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_ORIG=y +# CONFIG_BTDM_CTRL_MODEM_SLEEP_MODE_EVED is not set +CONFIG_BTDM_CTRL_LPCLK_SEL_MAIN_XTAL=y +# end of MODEM SLEEP Options + +CONFIG_BTDM_BLE_DEFAULT_SCA_250PPM=y +CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 +CONFIG_BTDM_BLE_SCAN_DUPL=y +CONFIG_BTDM_SCAN_DUPL_TYPE_DEVICE=y +# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA is not set +# CONFIG_BTDM_SCAN_DUPL_TYPE_DATA_DEVICE is not set +CONFIG_BTDM_SCAN_DUPL_TYPE=0 +CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE=100 +CONFIG_BTDM_SCAN_DUPL_CACHE_REFRESH_PERIOD=0 +# CONFIG_BTDM_BLE_MESH_SCAN_DUPL_EN is not set +CONFIG_BTDM_CTRL_FULL_SCAN_SUPPORTED=y +# CONFIG_BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX is not set +# CONFIG_BTDM_CTRL_CHECK_CONNECT_IND_ACCESS_ADDRESS is not set +CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_SUPP=y +CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM=100 +CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD=20 + +# +# BLE disconnect when instant passed +# +# CONFIG_BTDM_BLE_LLCP_CONN_UPDATE is not set +# CONFIG_BTDM_BLE_LLCP_CHAN_MAP_UPDATE is not set +# end of BLE disconnect when instant passed + +CONFIG_BTDM_RESERVE_DRAM=0xdb5c +CONFIG_BTDM_CTRL_HLI=y +# end of Controller Options # # Common Options # - -# -# BLE Log -# -# CONFIG_BLE_LOG_ENABLED is not set -# end of BLE Log - -# CONFIG_BT_BLE_LOG_SPI_OUT_ENABLED is not set -# CONFIG_BT_BLE_LOG_UHCI_OUT_ENABLED is not set -# CONFIG_BT_LE_USED_MEM_STATISTICS_ENABLED is not set +CONFIG_BT_ALARM_MAX_NUM=50 # end of Common Options + +# CONFIG_BT_HCI_LOG_DEBUG_EN is not set # end of Bluetooth +# CONFIG_BLE_MESH is not set + # # Console Library # @@ -503,7 +781,6 @@ CONFIG_TWAI_ERRATA_FIX_LISTEN_ONLY_DOM=y # CONFIG_ADC_DISABLE_DAC=y # CONFIG_ADC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_ADC_SKIP_LEGACY_CONFLICT_CHECK is not set # # Legacy ADC Calibration Configuration @@ -519,55 +796,42 @@ CONFIG_ADC_CAL_LUT_ENABLE=y # Legacy DAC Driver Configurations # # CONFIG_DAC_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_DAC_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy DAC Driver Configurations # # Legacy MCPWM Driver Configurations # # CONFIG_MCPWM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_MCPWM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy MCPWM Driver Configurations # # Legacy Timer Group Driver Configurations # # CONFIG_GPTIMER_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_GPTIMER_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy Timer Group Driver Configurations # # Legacy RMT Driver Configurations # # CONFIG_RMT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_RMT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy RMT Driver Configurations # # Legacy I2S Driver Configurations # # CONFIG_I2S_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_I2S_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy I2S Driver Configurations -# -# Legacy I2C Driver Configurations -# -# CONFIG_I2C_SKIP_LEGACY_CONFLICT_CHECK is not set -# end of Legacy I2C Driver Configurations - # # Legacy PCNT Driver Configurations # # CONFIG_PCNT_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_PCNT_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy PCNT Driver Configurations # # Legacy SDM Driver Configurations # # CONFIG_SDM_SUPPRESS_DEPRECATE_WARN is not set -# CONFIG_SDM_SKIP_LEGACY_CONFLICT_CHECK is not set # end of Legacy SDM Driver Configurations # end of Driver Configurations @@ -593,7 +857,6 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y # CONFIG_ESP_TLS_SERVER_MIN_AUTH_MODE_OPTIONAL is not set # CONFIG_ESP_TLS_PSK_VERIFICATION is not set # CONFIG_ESP_TLS_INSECURE is not set -CONFIG_ESP_TLS_DYN_BUF_STRATEGY_SUPPORTED=y # end of ESP-TLS # @@ -618,6 +881,8 @@ CONFIG_ADC_DISABLE_DAC_OUTPUT=y # Wireless Coexistence # CONFIG_ESP_COEX_ENABLED=y +CONFIG_ESP_COEX_SW_COEXIST_ENABLE=y +# CONFIG_ESP_COEX_POWER_MANAGEMENT is not set # CONFIG_ESP_COEX_GPIO_DEBUG is not set # end of Wireless Coexistence @@ -649,7 +914,6 @@ CONFIG_DAC_DMA_AUTO_16BIT_ALIGN=y CONFIG_GPTIMER_ISR_HANDLER_IN_IRAM=y # CONFIG_GPTIMER_CTRL_FUNC_IN_IRAM is not set # CONFIG_GPTIMER_ISR_IRAM_SAFE is not set -CONFIG_GPTIMER_OBJ_CACHE_SAFE=y # CONFIG_GPTIMER_ENABLE_DEBUG_LOG is not set # end of ESP-Driver:GPTimer Configurations @@ -728,14 +992,6 @@ CONFIG_SPI_SLAVE_ISR_IN_IRAM=y # CONFIG_UART_ISR_IN_IRAM is not set # end of ESP-Driver:UART Configurations -# -# ESP-Driver:UHCI Configurations -# -# CONFIG_UHCI_ISR_HANDLER_IN_IRAM is not set -# CONFIG_UHCI_ISR_CACHE_SAFE is not set -# CONFIG_UHCI_ENABLE_DEBUG_LOG is not set -# end of ESP-Driver:UHCI Configurations - # # Ethernet # @@ -774,13 +1030,6 @@ CONFIG_ESP_GDBSTUB_SUPPORT_TASKS=y CONFIG_ESP_GDBSTUB_MAX_TASKS=32 # end of GDB Stub -# -# ESP HID -# -CONFIG_ESPHID_TASK_SIZE_BT=2048 -CONFIG_ESPHID_TASK_SIZE_BLE=4096 -# end of ESP HID - # # ESP HTTP client # @@ -892,7 +1141,7 @@ CONFIG_RTC_CLK_CAL_CYCLES=1024 # # Peripheral Control # -# CONFIG_PERIPH_CTRL_FUNC_IN_IRAM is not set +CONFIG_PERIPH_CTRL_FUNC_IN_IRAM=y # end of Peripheral Control # @@ -953,11 +1202,8 @@ CONFIG_ESP_PHY_RF_CAL_PARTIAL=y # CONFIG_ESP_PHY_RF_CAL_NONE is not set # CONFIG_ESP_PHY_RF_CAL_FULL is not set CONFIG_ESP_PHY_CALIBRATION_MODE=0 -CONFIG_ESP_PHY_PLL_TRACK_PERIOD_MS=1000 # CONFIG_ESP_PHY_PLL_TRACK_DEBUG is not set # CONFIG_ESP_PHY_RECORD_USED_TIME is not set -CONFIG_ESP_PHY_IRAM_OPT=y -# CONFIG_ESP_PHY_DEBUG is not set # end of PHY # @@ -1049,8 +1295,7 @@ CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1=y # CONFIG_ESP_PANIC_HANDLER_IRAM is not set # CONFIG_ESP_DEBUG_STUBS_ENABLE is not set CONFIG_ESP_DEBUG_OCDAWARE=y -# CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 is not set -CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_4=y +CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5=y # # Brownout Detector @@ -1150,10 +1395,10 @@ CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT=y # # CONFIG_ESP_WIFI_WPS_STRICT is not set # CONFIG_ESP_WIFI_WPS_PASSPHRASE is not set -# CONFIG_ESP_WIFI_WPS_RECONNECT_ON_FAIL is not set # end of WPS Configuration Options # CONFIG_ESP_WIFI_DEBUG_PRINT is not set +# CONFIG_ESP_WIFI_TESTING_OPTIONS is not set CONFIG_ESP_WIFI_ENTERPRISE_SUPPORT=y # CONFIG_ESP_WIFI_ENT_FREE_DYNAMIC_BUFFER is not set # end of Wi-Fi @@ -1209,14 +1454,6 @@ CONFIG_FATFS_VFS_FSTAT_BLKSIZE=0 # CONFIG_FATFS_IMMEDIATE_FSYNC is not set # CONFIG_FATFS_USE_LABEL is not set CONFIG_FATFS_LINK_LOCK=y -# CONFIG_FATFS_USE_DYN_BUFFERS is not set - -# -# File system free space calculation behavior -# -CONFIG_FATFS_DONT_TRUST_FREE_CLUSTER_CNT=0 -CONFIG_FATFS_DONT_TRUST_LAST_ALLOC=0 -# end of File system free space calculation behavior # end of FAT Filesystem support # @@ -1299,6 +1536,7 @@ CONFIG_HAL_ASSERTION_EQUALS_SYSTEM=y CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=2 CONFIG_HAL_SPI_MASTER_FUNC_IN_IRAM=y CONFIG_HAL_SPI_SLAVE_FUNC_IN_IRAM=y +# CONFIG_HAL_ECDSA_GEN_SIG_CM is not set # end of Hardware Abstraction Layer (HAL) and Low Level (LL) # @@ -1475,7 +1713,6 @@ CONFIG_LWIP_IPV6_ND6_NUM_NEIGHBORS=5 CONFIG_LWIP_IPV6_ND6_NUM_PREFIXES=5 CONFIG_LWIP_IPV6_ND6_NUM_ROUTERS=3 CONFIG_LWIP_IPV6_ND6_NUM_DESTINATIONS=10 -# CONFIG_LWIP_IPV6_ND6_ROUTE_INFO_OPTION_SUPPORT is not set # CONFIG_LWIP_PPP_SUPPORT is not set # CONFIG_LWIP_SLIP_SUPPORT is not set @@ -1563,7 +1800,6 @@ CONFIG_MBEDTLS_SSL_OUT_CONTENT_LEN=4096 # CONFIG_MBEDTLS_X509_TRUSTED_CERT_CALLBACK is not set # CONFIG_MBEDTLS_SSL_CONTEXT_SERIALIZATION is not set CONFIG_MBEDTLS_SSL_KEEP_PEER_CERTIFICATE=y -# CONFIG_MBEDTLS_SSL_KEYING_MATERIAL_EXPORT is not set CONFIG_MBEDTLS_PKCS7_C=y # end of mbedTLS v3.x related @@ -1593,7 +1829,6 @@ CONFIG_MBEDTLS_HAVE_TIME=y # CONFIG_MBEDTLS_PLATFORM_TIME_ALT is not set # CONFIG_MBEDTLS_HAVE_TIME_DATE is not set CONFIG_MBEDTLS_ECDSA_DETERMINISTIC=y -CONFIG_MBEDTLS_SHA1_C=y CONFIG_MBEDTLS_SHA512_C=y # CONFIG_MBEDTLS_SHA3_C is not set CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y @@ -1675,7 +1910,6 @@ CONFIG_MBEDTLS_ECP_NIST_OPTIM=y # CONFIG_MBEDTLS_THREADING_C is not set CONFIG_MBEDTLS_ERROR_STRINGS=y CONFIG_MBEDTLS_FS_IO=y -# CONFIG_MBEDTLS_ALLOW_WEAK_CERTIFICATE_VERIFICATION is not set # end of mbedTLS # @@ -1727,8 +1961,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y # # CONFIG_OPENTHREAD_SPINEL_ONLY is not set # end of OpenThread Spinel - -# CONFIG_OPENTHREAD_DEBUG is not set # end of OpenThread # @@ -1737,7 +1969,6 @@ CONFIG_NEWLIB_TIME_SYSCALL_USE_RTC_HRT=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_0=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_1=y CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_VERSION_2=y -CONFIG_ESP_PROTOCOMM_SUPPORT_SECURITY_PATCH_VERSION=y # end of Protocomm # @@ -1781,7 +2012,6 @@ CONFIG_SPI_FLASH_BROWNOUT_RESET=y # CONFIG_SPI_FLASH_SUSPEND_TSUS_VAL_US=50 # CONFIG_SPI_FLASH_FORCE_ENABLE_XMC_C_SUSPEND is not set -# CONFIG_SPI_FLASH_FORCE_ENABLE_C6_H2_SUSPEND is not set # end of Optional and Experimental Features (READ DOCS FIRST) # end of Main Flash configuration @@ -1928,6 +2158,10 @@ CONFIG_WL_SECTOR_SIZE=4096 # CONFIG_WIFI_PROV_SCAN_MAX_ENTRIES=16 CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30 +# CONFIG_WIFI_PROV_BLE_BONDING is not set +# CONFIG_WIFI_PROV_BLE_FORCE_ENCRYPTION is not set +# CONFIG_WIFI_PROV_BLE_NOTIFY is not set +# CONFIG_WIFI_PROV_KEEP_BLE_ON_AFTER_PROV is not set CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set # end of Wi-Fi Provisioning Manager From 22406c04af9b13b3ce35b2ddce28b571be3150f0 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sat, 4 Jul 2026 22:34:13 +0900 Subject: [PATCH 16/33] Remove shell true --- cli/src/core/shell.ts | 2 +- cli/src/services/ble.ts | 21 +-------------------- lang/src/compiler/utils.ts | 2 +- 3 files changed, 3 insertions(+), 22 deletions(-) diff --git a/cli/src/core/shell.ts b/cli/src/core/shell.ts index a3490381..45580c4c 100644 --- a/cli/src/core/shell.ts +++ b/cli/src/core/shell.ts @@ -17,7 +17,7 @@ export function exec(command: string, options?: {cwd?: string, silent?: boolean} } return new Promise((resolve, reject) => { - const executeProcess = spawn(command, {shell: true, cwd}); + const executeProcess = spawn(command, {shell: false, cwd}); let stdout = ''; let stderr = ''; diff --git a/cli/src/services/ble.ts b/cli/src/services/ble.ts index 5fbb266a..a8529ca1 100644 --- a/cli/src/services/ble.ts +++ b/cli/src/services/ble.ts @@ -180,9 +180,7 @@ export class BleConnection extends Connection { }; noble.on('discover', this.discoverHandler); }); - console.log("foo") await noble.stopScanningAsync(); - console.log("foo2") this.peripheral = peripheral; this.peripheral.on('disconnect', (event) => { this.emit('disconnected', event); @@ -194,39 +192,22 @@ export class BleConnection extends Connection { this.status = 'connected'; this.emit('connected'); }); - console.log("Foo3") await peripheral.connectAsync(); - console.log("foo4") - const result1 = await peripheral.discoverServicesAsync(); - console.log("foo41") - console.log(result1) - const service = result1.find(s => s.uuid === 'ff'); - console.log('service', service) - const ch1 = await service?.discoverCharacteristicsAsync(); - console.log("foo412") - console.log(ch1) - const result = await peripheral.discoverAllServicesAndCharacteristicsAsync(); - console.log("foo42") - console.log(result) - const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync( [SERVICE_UUID], [CHARACTERISTIC_UUID] ); - console.log("foo5") if (characteristics.length === 0) { throw new Error('Target characteristic not found.'); } - console.log("foo6") this.characteristic = characteristics[0]; this.characteristic.on('data', (data, isNotification) => { if (isNotification) { this.emit('receiveData', data); } }) - console.log("foo7") await this.characteristic.subscribeAsync(); - console.log("foo8") + return; } private async waitForPoweredOn(): Promise { diff --git a/lang/src/compiler/utils.ts b/lang/src/compiler/utils.ts index 04530b09..14bbda44 100644 --- a/lang/src/compiler/utils.ts +++ b/lang/src/compiler/utils.ts @@ -2,7 +2,7 @@ import { spawn } from "child_process"; export function executeCommand(command: string, args: string[], cwd?: string, showStdout = false, showStderr = false): Promise { return new Promise((resolve, reject) => { - const executeProcess = spawn(command, args, { shell: true, cwd }); + const executeProcess = spawn(command, args, { shell: false, cwd }); let stdout = ''; let stderr = ''; From 4032645ad1f0db3cc23ae3fe18a6f542606a4005 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sat, 4 Jul 2026 22:34:53 +0900 Subject: [PATCH 17/33] Fix run with repl. --- cli/src/commands/project/run.ts | 34 +++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/cli/src/commands/project/run.ts b/cli/src/commands/project/run.ts index 47bc29e6..ca20698e 100644 --- a/cli/src/commands/project/run.ts +++ b/cli/src/commands/project/run.ts @@ -128,18 +128,9 @@ class RunHandler extends CommandHandler { } class RunWithReplHandler extends RunHandler { - private rl: readline.Interface; + private rl?: readline.Interface; private readonly taskQueue = new SerialTaskQueue(); - constructor(projectConfigHandler: ProjectConfigHandler) { - super(projectConfigHandler); - this.rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - prompt: chalk.blue.bold('> ') - }); - } - async run() { const interrupted = await super.run(); if (interrupted) { @@ -151,12 +142,23 @@ class RunWithReplHandler extends RunHandler { return false; } + async close() { + this.rl?.close(); + await super.close(); + } + private runRepl() { logger.info("Start REPL. Type 'Ctrl-D' to exit."); - this.rl.prompt(); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + prompt: chalk.blue.bold('> '), + }); + this.rl = rl; + rl.prompt(); return new Promise((resolve, reject) => { - this.rl.on('line', (line) => { - this.rl.pause(); + rl.on('line', (line) => { + rl.pause(); this.taskQueue.enqueue(async () => { try { const output = await this.compiler.compileFragment(line); @@ -170,12 +172,12 @@ class RunWithReplHandler extends RunHandler { return; } } finally { - this.rl.resume(); - this.rl.prompt(); + rl.resume(); + rl.prompt(); } }); }); - this.rl.on('close', () => { + rl.on('close', () => { resolve(); }); }); From 88b3a7ef9511067f1dfc3604770b2c87e008a93f Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 13:57:13 +0900 Subject: [PATCH 18/33] Fix promise bugs on ble. --- cli/src/services/ble.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/cli/src/services/ble.ts b/cli/src/services/ble.ts index a8529ca1..6e1c2cd7 100644 --- a/cli/src/services/ble.ts +++ b/cli/src/services/ble.ts @@ -44,9 +44,8 @@ export class DeviceService extends Service { for (const entryPoint of bin.entryPoints) { builder.jump(entryPoint.isMain ? isMain : 0, entryPoint.address); } - await this.send('execute', builder.build()); let executionTime = 0; - return new Promise((resolve) => { + const p = new Promise((resolve) => { this.on('exectime', (id, time) => { executionTime += time; if (id === isMain) { @@ -55,16 +54,19 @@ export class DeviceService extends Service { } }); }); + await this.send('execute', builder.build()); + return p; } public async init(): Promise { const builder = new ProtocolPacketBuilder(MTU).reset(); - await this.send('init', builder.build()); - return new Promise((resolve) => { + const p = new Promise((resolve) => { this.once('memory', (layout) => { resolve(layout); }); }); + await this.send('init', builder.build()); + return p; } private handleReceivedData(data: Buffer) { @@ -168,8 +170,7 @@ export class BleConnection extends Connection { await this.waitForPoweredOn(); this.foundPeriferals = []; - await noble.startScanningAsync([SERVICE_UUID], false); - const peripheral = await new Promise((resolve) => { + const searchPeriferalPromise = new Promise((resolve) => { this.discoverHandler = (p: Peripheral) => { this.foundPeriferals.push(p); if (p.advertisement.localName === this.deviceName) { @@ -180,6 +181,8 @@ export class BleConnection extends Connection { }; noble.on('discover', this.discoverHandler); }); + await noble.startScanningAsync([SERVICE_UUID], false); + const peripheral = await searchPeriferalPromise; await noble.stopScanningAsync(); this.peripheral = peripheral; this.peripheral.on('disconnect', (event) => { From 1abc4f303727694bf14bb66de8f8183182e8455c Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 14:02:32 +0900 Subject: [PATCH 19/33] Update open url operation for notebook. --- cli/src/commands/project/run.ts | 10 +++------- cli/src/core/shell.ts | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/cli/src/commands/project/run.ts b/cli/src/commands/project/run.ts index ca20698e..cbae5d3e 100644 --- a/cli/src/commands/project/run.ts +++ b/cli/src/commands/project/run.ts @@ -7,7 +7,7 @@ import path from 'path'; import { logger, ProgramOutput, createBoxedOutput, createConsoleOutput, createWebSocketOutput, runStep, LoadStepLogger } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; -import { cwd, exec } from "../../core/shell"; +import { cwd, openUrl } from "../../core/shell"; import { CommandHandler } from "../command"; import { BoardRuntime, CompilerAdapter, createPlatformSession } from "../../platforms"; import { CompileError, CompileOutput } from "@bscript/lang"; @@ -239,13 +239,9 @@ class RunWithNotebookHandler extends RunHandler { } - private openBrowser(port: number|string) { + private async openBrowser(port: number | string) { const url = `http://localhost:${port}`; - const startCommand = - process.platform === 'win32' ? 'start' : - process.platform === 'darwin' ? 'open' : 'xdg-open'; - - exec(`${startCommand} ${url}`, {silent: true}); + await openUrl(url); } private startWebsocket() { diff --git a/cli/src/core/shell.ts b/cli/src/core/shell.ts index 45580c4c..bf2e5a62 100644 --- a/cli/src/core/shell.ts +++ b/cli/src/core/shell.ts @@ -60,4 +60,27 @@ function getErrorMessage(command: string, code: number|null, stdout: string, std message += `> Stdout: ${stdout === '' ? 'N/A' : stdout}\n`; message += `> Stderr: ${stderr === '' ? 'N/A' : stderr}\n`; return message; +} + +export function openUrl(url: string): Promise { + return new Promise((resolve, reject) => { + let cmd: string; + let args: string[]; + if (process.platform === 'win32') { + cmd = 'cmd.exe'; + args = ['/c', 'start', '', url]; + } else if (process.platform === 'darwin') { + cmd = 'open'; + args = [url]; + } else { + cmd = 'xdg-open'; + args = [url]; + } + const child = spawn(cmd, args, { stdio: 'ignore', detached: true }); + child.on('error', reject); + child.on('close', (code) => { + if (code === 0) resolve(); + else reject(new Error(`Failed to open URL (exit code ${code})`)); + }); + }); } \ No newline at end of file From adf98a2798d2db2880ac6365e4fc51b9c47c7fd6 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 14:27:23 +0900 Subject: [PATCH 20/33] Shorten setup messages. --- cli/src/commands/board/setup/base.ts | 2 +- cli/src/commands/board/setup/esp32-darwin.ts | 2 +- cli/src/commands/board/setup/esp32-windows.ts | 2 +- cli/src/commands/board/setup/host-windows.ts | 5 +++-- cli/src/commands/board/setup/utils.ts | 1 + 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cli/src/commands/board/setup/base.ts b/cli/src/commands/board/setup/base.ts index 4f39dcc2..11286c0b 100644 --- a/cli/src/commands/board/setup/base.ts +++ b/cli/src/commands/board/setup/base.ts @@ -24,7 +24,7 @@ export abstract class SetupHandler extends CommandHandler { loadSetupSteps() { this.setupSteps.push({ description: `Download BlueScript runtime from ${this.boardEnv.runtimeZipUrl}.`, - actionMessage: `Downloading BlueScript runtime from ${this.boardEnv.runtimeZipUrl}...`, + actionMessage: `Downloading BlueScript runtime...`, action: this.downloadBlueScriptRuntimeStep.bind(this) }); this.loadBoardSetupSteps(); diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts index 665f4d7c..9844dc17 100644 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -29,7 +29,7 @@ export class Esp32DarwinSetupHandler extends SetupHandler { }); this.setupSteps.push({ description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, - actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}... It may take a while.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, action: this.cloneEspIdfStep.bind(this), }); this.setupSteps.push({ diff --git a/cli/src/commands/board/setup/esp32-windows.ts b/cli/src/commands/board/setup/esp32-windows.ts index 15f01d84..59726bb8 100644 --- a/cli/src/commands/board/setup/esp32-windows.ts +++ b/cli/src/commands/board/setup/esp32-windows.ts @@ -22,7 +22,7 @@ export class Esp32WindowsSetupHandler extends SetupHandler { }); this.setupSteps.push({ description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, - actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}... It may take a while.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, action: this.cloneEspIdfStep.bind(this), }); this.setupSteps.push({ diff --git a/cli/src/commands/board/setup/host-windows.ts b/cli/src/commands/board/setup/host-windows.ts index 2e0075c2..544f0c27 100644 --- a/cli/src/commands/board/setup/host-windows.ts +++ b/cli/src/commands/board/setup/host-windows.ts @@ -16,7 +16,7 @@ export class HostWindowsSetupHandler extends SetupHandler { loadBoardSetupSteps(): void { this.setupSteps.push({ - description: "Verify that MinGW is installed.", // write version + description: "Verify that MinGW is installed.", actionMessage: "Verifying that MinGW is installed...", action: this.verifyMingwIsInstalledStep.bind(this), }); @@ -41,7 +41,7 @@ export class HostWindowsSetupHandler extends SetupHandler { private async verifyMingwIsInstalledStep() { if (await isPackageInstalledOnWindows('gcc')) { - if (!await this.isMingwGccAvailable()) { + if (!(await this.isMingwGccAvailable())) { throw new Error("gcc is not a MinGW compiler. Please install MinGW-w64 and add it to PATH."); } } else { @@ -51,6 +51,7 @@ export class HostWindowsSetupHandler extends SetupHandler { private async isMingwGccAvailable(): Promise { const machine = await this.getGccTargetMachine(); + console.log(machine) return machine?.includes('mingw') ?? false; } diff --git a/cli/src/commands/board/setup/utils.ts b/cli/src/commands/board/setup/utils.ts index f304e066..a0b0a318 100644 --- a/cli/src/commands/board/setup/utils.ts +++ b/cli/src/commands/board/setup/utils.ts @@ -15,6 +15,7 @@ export async function isPackageInstalledOnWindows(name: string) { await exec(`where ${name}`, { silent: true }); return true; } catch (error) { + console.log(error) return false; } } From 7bfa26de46eb9e00ec060145d8063ec406720143 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 15:53:36 +0900 Subject: [PATCH 21/33] Update command execution. --- cli/src/commands/board/flash-runtime.ts | 4 +- cli/src/commands/board/setup/esp32-darwin.ts | 4 +- cli/src/commands/board/setup/host-windows.ts | 5 +- cli/src/commands/board/setup/utils.ts | 19 +- cli/src/commands/project/check.ts | 2 +- cli/src/commands/project/create.ts | 2 +- cli/src/commands/project/install.ts | 7 +- cli/src/commands/project/run.ts | 10 +- cli/src/commands/project/uninstall.ts | 2 +- cli/src/core/command-exec.ts | 148 +++++++++++++++ cli/src/core/shell.ts | 86 --------- cli/src/platforms/board-env/esp32-env.ts | 24 ++- cli/src/platforms/board-env/host-env.ts | 41 +++-- .../commands/board/flash-runtime.test.ts | 14 +- cli/tests/commands/board/setup.test.ts | 168 +++++++++--------- cli/tests/commands/board/update.test.ts | 74 +++++--- cli/tests/commands/mock-helpers.ts | 6 +- cli/tests/commands/project/install.test.ts | 74 ++++---- cli/tests/global-mocks.ts | 2 +- .../integration/project/repl.host.test.ts | 4 +- .../integration/project/run.host.test.ts | 6 +- 21 files changed, 398 insertions(+), 304 deletions(-) create mode 100644 cli/src/core/command-exec.ts delete mode 100644 cli/src/core/shell.ts diff --git a/cli/src/commands/board/flash-runtime.ts b/cli/src/commands/board/flash-runtime.ts index ca256108..4c07335d 100644 --- a/cli/src/commands/board/flash-runtime.ts +++ b/cli/src/commands/board/flash-runtime.ts @@ -5,7 +5,7 @@ import * as os from 'os'; import { SerialPort } from 'serialport' import { BoardName } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; -import { exec } from '../../core/shell'; +import { execShell } from '../../core/command-exec'; import chalk from "chalk"; import { CommandHandler } from "../command"; import { DEFAULT_DEVICE_NAME } from "../../config/project-config"; @@ -53,7 +53,7 @@ class ESP32FlashRuntimeHandler extends FlashRuntimeHandler { const osType = os.platform(); const preCommand = osType === 'win32' ? `call ${exportFile}` : `source ${exportFile}`; - await exec(`${preCommand} && idf.py ${args.join(' ')}`,{ cwd }); + await execShell(`${preCommand} && idf.py ${args.join(' ')}`, { cwd }); } } diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts index 9844dc17..8e72a8be 100644 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -1,5 +1,5 @@ import { SetupHandler } from "./base"; -import { exec } from '../../../core/shell'; +import { execWithLog, simpleExec } from '../../../core/command-exec'; import { skip } from "../../../core/logger"; import * as path from 'path'; import { BoardName } from "../../../config/board-utils"; @@ -75,7 +75,7 @@ export class Esp32DarwinSetupHandler extends SetupHandler { if (packages.length === 0) { return skip('already installed.'); } - await exec(`brew install ${packages.join(' ')}`); + await execWithLog('brew', ['install', ...packages]); } private async cloneEspIdfStep() { diff --git a/cli/src/commands/board/setup/host-windows.ts b/cli/src/commands/board/setup/host-windows.ts index 544f0c27..6c1e644c 100644 --- a/cli/src/commands/board/setup/host-windows.ts +++ b/cli/src/commands/board/setup/host-windows.ts @@ -1,5 +1,5 @@ import { SetupHandler } from "./base"; -import { exec } from '../../../core/shell'; +import { simpleExec } from '../../../core/command-exec'; import { BoardName } from "../../../config/board-utils"; import { HostWindowsEnv } from "../../../platforms/board-env/host-env"; import { isPackageInstalledOnWindows } from "./utils"; @@ -51,13 +51,12 @@ export class HostWindowsSetupHandler extends SetupHandler { private async isMingwGccAvailable(): Promise { const machine = await this.getGccTargetMachine(); - console.log(machine) return machine?.includes('mingw') ?? false; } private async getGccTargetMachine(): Promise { try { - return (await exec('gcc -dumpmachine', { silent: true })).trim(); + return (await simpleExec('gcc', ['-dumpmachine'])).trim(); } catch { return undefined; } diff --git a/cli/src/commands/board/setup/utils.ts b/cli/src/commands/board/setup/utils.ts index a0b0a318..06afe59b 100644 --- a/cli/src/commands/board/setup/utils.ts +++ b/cli/src/commands/board/setup/utils.ts @@ -1,33 +1,32 @@ -import { exec } from '../../../core/shell'; +import { simpleExec } from '../../../core/command-exec'; export async function isPackageInstalledOnUnix(name: string) { try { - await exec(`which ${name}`, { silent: true }); + await simpleExec('which', [name]); return true; - } catch (error) { + } catch { return false; } } export async function isPackageInstalledOnWindows(name: string) { try { - await exec(`where ${name}`, { silent: true }); + await simpleExec('where.exe', [name]); return true; - } catch (error) { - console.log(error) + } catch { return false; } } export async function isPythonVersionGreaterThan3() { try { - const result = await exec( - `python -c "import sys; print(sys.version_info.major)"`, - { silent: true }, + const result = await simpleExec( + 'python', + ['-c', 'import sys; print(sys.version_info.major)'], ); return result.trim() === '3'; } catch { return false; } -} \ No newline at end of file +} diff --git a/cli/src/commands/project/check.ts b/cli/src/commands/project/check.ts index 191bc20b..e33748e4 100644 --- a/cli/src/commands/project/check.ts +++ b/cli/src/commands/project/check.ts @@ -1,7 +1,7 @@ import { Command } from "commander"; import { logger, runStep } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; -import { cwd } from "../../core/shell"; +import { cwd } from "../../core/command-exec"; import { CommandHandler } from "../command"; import { CompilerAdapter, getCompilerAdapter } from "../../platforms"; diff --git a/cli/src/commands/project/create.ts b/cli/src/commands/project/create.ts index 07ab6428..323363b9 100644 --- a/cli/src/commands/project/create.ts +++ b/cli/src/commands/project/create.ts @@ -4,7 +4,7 @@ import chalk from "chalk"; import * as path from 'path'; import { logger } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; -import { cwd } from "../../core/shell"; +import { cwd } from "../../core/command-exec"; import { BOARD_NAMES, BoardName, isValidBoard } from "../../config/board-utils"; import * as fs from '../../core/fs'; import { CommandHandler } from "../command"; diff --git a/cli/src/commands/project/install.ts b/cli/src/commands/project/install.ts index 3b977d06..9e725e46 100644 --- a/cli/src/commands/project/install.ts +++ b/cli/src/commands/project/install.ts @@ -1,7 +1,7 @@ import { Command } from "commander"; import { logger } from "../../core/logger"; import { ProjectConfigHandler, PackageSource ,PROJECT_DEFAULT_PATHS } from "../../config/project-config"; -import { cwd, exec } from "../../core/shell"; +import { cwd, simpleExec } from "../../core/command-exec"; import * as fs from '../../core/fs'; import * as path from 'path'; import { CommandHandler } from "../command"; @@ -65,10 +65,9 @@ class InstallationHandler extends CommandHandler { private async downloadPackage(url: string, version?: string): Promise { logger.log(`Downloading from ${url}...`); const tmpDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-package'); - const branchCmd = version ? `--branch ${version}` : ''; - const cmd = `git clone --depth 1 ${branchCmd} ${url} ${tmpDir}`; + const branchArgs = version ? ['--branch', version] : []; try { - await exec(cmd, {silent: true}); + await simpleExec('git', ['clone', '--depth', '1', ...branchArgs, url, tmpDir]); const gitDir = path.join(tmpDir, '.git'); if (fs.exists(gitDir)) { fs.removeDir(gitDir); diff --git a/cli/src/commands/project/run.ts b/cli/src/commands/project/run.ts index cbae5d3e..ade82149 100644 --- a/cli/src/commands/project/run.ts +++ b/cli/src/commands/project/run.ts @@ -7,7 +7,7 @@ import path from 'path'; import { logger, ProgramOutput, createBoxedOutput, createConsoleOutput, createWebSocketOutput, runStep, LoadStepLogger } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; -import { cwd, openUrl } from "../../core/shell"; +import { cwd, ExecOptions, simpleExec } from "../../core/command-exec"; import { CommandHandler } from "../command"; import { BoardRuntime, CompilerAdapter, createPlatformSession } from "../../platforms"; import { CompileError, CompileOutput } from "@bscript/lang"; @@ -241,7 +241,13 @@ class RunWithNotebookHandler extends RunHandler { private async openBrowser(port: number | string) { const url = `http://localhost:${port}`; - await openUrl(url); + if (process.platform === 'win32') { + await simpleExec('cmd.exe', ['/c', 'start', '', url], { detached: true, stdio: 'ignore' }); + } else if (process.platform === 'darwin') { + await simpleExec('open', [url], { detached: true, stdio: 'ignore' }); + } else { + await simpleExec('xdg-open', [url], { detached: true, stdio: 'ignore' }); + } } private startWebsocket() { diff --git a/cli/src/commands/project/uninstall.ts b/cli/src/commands/project/uninstall.ts index 5aa920aa..20e25d58 100644 --- a/cli/src/commands/project/uninstall.ts +++ b/cli/src/commands/project/uninstall.ts @@ -1,7 +1,7 @@ import { Command } from "commander"; import { logger } from "../../core/logger"; import { ProjectConfigHandler, PROJECT_DEFAULT_PATHS } from "../../config/project-config"; -import { cwd } from "../../core/shell"; +import { cwd } from "../../core/command-exec"; import * as fs from '../../core/fs'; import * as path from 'path'; import { CommandHandler } from "../command"; diff --git a/cli/src/core/command-exec.ts b/cli/src/core/command-exec.ts new file mode 100644 index 00000000..d5235138 --- /dev/null +++ b/cli/src/core/command-exec.ts @@ -0,0 +1,148 @@ +import { spawn, SpawnOptions } from "child_process"; +import { logger } from "./logger"; +import { exists } from "./fs"; + +export function cwd() { + return process.cwd(); +} + +export type ExecOptions = { + cwd?: string; + detached?: boolean; + stdio?: 'ignore' | 'pipe'; +}; + +type ProcessOutput = { + stdout: string; + stderr: string; +}; + +type ProcessStreamHooks = { + onStdoutData?: (chunk: string) => void; + onStderrData?: (chunk: string) => void; +}; + +type FailureMode = 'stderr' | 'detailed'; + +function validateCwd(cwd?: string): void { + if (cwd && !exists(cwd)) { + throw new Error(`${cwd} does not exist.`); + } +} + +function formatCommand(command: string, args: string[]): string { + return [command, ...args].join(' '); +} + +function rejectProcessFailure( + formattedCommand: string, + code: number | null, + stdout: string, + stderr: string, + failureMode: FailureMode, + spawnError?: Error, +): Error { + if (spawnError) { + return new Error(spawnError.message); + } + if (failureMode === 'stderr') { + return new Error(stderr || `Command failed: ${formattedCommand}`); + } + return new Error(getErrorMessage(formattedCommand, code, stdout, stderr)); +} + +function runProcess( + command: string, + args: string[], + options: ExecOptions = {}, + hooks?: ProcessStreamHooks, + failureMode: FailureMode = 'detailed', +): Promise { + const { cwd, detached = false, stdio = 'pipe' } = options; + const formattedCommand = formatCommand(command, args); + + return new Promise((resolve, reject) => { + const spawnOptions: SpawnOptions = { shell: false, cwd, detached, stdio }; + const child = spawn(command, args, spawnOptions); + let stdout = ''; + let stderr = ''; + + if (stdio !== 'ignore' && child.stdout) { + child.stdout.on('data', (data) => { + const chunk = data.toString(); + hooks?.onStdoutData?.(chunk); + stdout += chunk; + }); + } + + if (stdio !== 'ignore' && child.stderr) { + child.stderr.on('data', (data) => { + const chunk = data.toString(); + hooks?.onStderrData?.(chunk); + stderr += chunk; + }); + } + + child.on('error', (err) => { + reject(rejectProcessFailure(formattedCommand, null, stdout, stderr, failureMode, err)); + }); + + child.on('close', (code) => { + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(rejectProcessFailure(formattedCommand, code, stdout, stderr, failureMode)); + } + }); + + if (detached) { + child.unref(); + } + }); +} + +export async function simpleExec( + command: string, + args: string[], + options?: ExecOptions, +): Promise { + validateCwd(options?.cwd); + const { stdout } = await runProcess(command, args, options, undefined, 'stderr'); + return stdout; +} + +export async function execWithLog( + command: string, + args: string[], + options?: ExecOptions, +): Promise { + validateCwd(options?.cwd); + + const formattedCommand = formatCommand(command, args); + logger.log(`Executing ${formattedCommand}`); + + const { stdout } = await runProcess(command, args, options, { + onStdoutData: (chunk) => process.stdout.write(chunk), + onStderrData: (chunk) => process.stderr.write(chunk), + }, 'stderr'); + return stdout; +} + +export async function execShell(command: string, options?: { cwd?: string }): Promise { + validateCwd(options?.cwd); + + if (process.platform === 'win32') { + await execWithLog('cmd.exe', ['/c', command], { cwd: options?.cwd }); + } else { + await execWithLog('/bin/sh', ['-c', command], { cwd: options?.cwd }); + } +} + +function getErrorMessage(command: string, code: number|null, stdout: string, stderr: string) { + let message = `Command failed: ${command}\n`; + if (code) + message += `> Exit code: ${code}\n`; + message += `> Stdout: ${stdout === '' ? 'N/A' : stdout}\n`; + message += `> Stderr: ${stderr === '' ? 'N/A' : stderr}\n`; + return message; +} diff --git a/cli/src/core/shell.ts b/cli/src/core/shell.ts deleted file mode 100644 index bf2e5a62..00000000 --- a/cli/src/core/shell.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { spawn } from "child_process"; -import { logger } from "./logger"; -import { exists } from "./fs"; - -export function cwd() { - return process.cwd(); -} - -export function exec(command: string, options?: {cwd?: string, silent?: boolean}): Promise { - const {cwd, silent = false} = options ?? {}; - - if (cwd && !exists(cwd)) { - throw new Error(`${cwd} does not exist.`); - } - if (!silent) { - logger.log(`Executing ${command}`); - } - - return new Promise((resolve, reject) => { - const executeProcess = spawn(command, {shell: false, cwd}); - let stdout = ''; - let stderr = ''; - - executeProcess.stdout.on('data', (data) => { - const chunk = data.toString(); - if (!silent) { - process.stdout.write(chunk); - } - stdout += chunk; - }); - - executeProcess.stderr.on('data', (data) => { - const chunk = data.toString(); - if (!silent) { - process.stderr.write(chunk); - } - stderr += chunk; - }); - - executeProcess.on('error', (err) => { - const message = getErrorMessage(command, null, stdout, stderr); - reject(new Error(message)); - }); - - executeProcess.on('close', (code) => { - if (code === 0) { - resolve(stdout); - } else { - const message = getErrorMessage(command, code, stdout, stderr); - reject(new Error(message)); - } - }); - }); -} - -function getErrorMessage(command: string, code: number|null, stdout: string, stderr: string) { - let message = `Command failed: ${command}\n`; - if (code) - message += `> Exit code: ${code}\n`; - message += `> Stdout: ${stdout === '' ? 'N/A' : stdout}\n`; - message += `> Stderr: ${stderr === '' ? 'N/A' : stderr}\n`; - return message; -} - -export function openUrl(url: string): Promise { - return new Promise((resolve, reject) => { - let cmd: string; - let args: string[]; - if (process.platform === 'win32') { - cmd = 'cmd.exe'; - args = ['/c', 'start', '', url]; - } else if (process.platform === 'darwin') { - cmd = 'open'; - args = [url]; - } else { - cmd = 'xdg-open'; - args = [url]; - } - const child = spawn(cmd, args, { stdio: 'ignore', detached: true }); - child.on('error', reject); - child.on('close', (code) => { - if (code === 0) resolve(); - else reject(new Error(`Failed to open URL (exit code ${code})`)); - }); - }); -} \ No newline at end of file diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index bb46b21d..9621ec3c 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from "../../config/constants"; -import { exec } from '../../core/shell'; +import { simpleExec, execShell, execWithLog } from '../../core/command-exec'; import { BoardEnv } from './common-env'; const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; @@ -24,9 +24,10 @@ export abstract class Esp32Env extends BoardEnv { abstract getXtensaGccDir(): Promise; async cloneEspIdf() { - await exec( - `git clone --depth 1 -b ${this.idfVersion} --recursive ${this.idfGitRepo}`, - { cwd: this.espRootDir } + await execWithLog( + 'git', + ['clone', '--depth', '1', '-b', this.idfVersion, '--recursive', this.idfGitRepo], + { cwd: this.espRootDir }, ); } @@ -65,7 +66,6 @@ export abstract class Esp32Env extends BoardEnv { } protected resolveXtensaGccDirFromExport(stdout: string, pathLabel: string, pathSeparator: string): string { - console.log(stdout) const env = this.parseKeyValueExport(stdout); const pathValue = env.get(pathLabel); @@ -95,12 +95,15 @@ export class Esp32DarwinEnv extends Esp32Env { get xtensaLdFileName() { return XTENSA_LD_NAME; } async runEspIdfInstallScript() { - await exec(this.idfInstallShFile); + await execShell(`bash ${JSON.stringify(this.idfInstallShFile)}`); } async getXtensaGccDir() { try { - const stdout = await exec(`${this.idfToolsPyFile} export --format key-value`); + const stdout = await simpleExec( + 'python3', + [this.idfToolsPyFile, 'export', '--format', 'key-value'], + ); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ':'); } catch (error) { throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); @@ -117,12 +120,15 @@ export class Esp32WindowsEnv extends Esp32Env { get xtensaLdFileName(): string { return `${XTENSA_LD_NAME}.exe`; } async runEspIdfInstallScript() { - await exec(this.idfInstallBatFile); + await execShell(this.idfInstallBatFile); } async getXtensaGccDir() { try { - const stdout = await exec(`python ${this.idfToolsPyFile} export --format key-value`); + const stdout = await simpleExec( + 'python', + [this.idfToolsPyFile, 'export', '--format', 'key-value'], + ); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ';'); } catch (error) { throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 39a7ed85..0d089fa0 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -1,7 +1,7 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from '../../config/constants'; -import { exec } from '../../core/shell'; +import { simpleExec } from '../../core/command-exec'; import { BoardEnv } from './common-env'; export abstract class HostEnv extends BoardEnv { @@ -36,14 +36,17 @@ export class HostDarwinEnv extends HostEnv { async buildHostRuntime() { fs.makeDir(this.buildDir); try { - await exec( - `cc -DLINUX64 -O2 -shared -fPIC -o "${this.runtimeSoFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, - { silent: true }, - ); - await exec( - `cc -DLINUX64 -O2 -o "${this.shellFile}" "${this.shellCFile}" "${this.runtimeSoFile}" -lm -ldl`, - { silent: true }, - ); + await simpleExec('cc', [ + '-DLINUX64', '-O2', '-shared', '-fPIC', + '-o', this.runtimeSoFile, + this.runtimeCFile, this.builtinModuleCFile, this.commCFile, + ]); + await simpleExec('cc', [ + '-DLINUX64', '-O2', + '-o', this.shellFile, + this.shellCFile, this.runtimeSoFile, + '-lm', '-ldl', + ]); } catch(error) { throw new Error('Failed to compile host runtime.', { cause: error }); } @@ -58,15 +61,17 @@ export class HostWindowsEnv extends HostEnv { async buildHostRuntime() { fs.makeDir(this.buildDir); try { - await exec( - // `gcc -DLINUX64 -O2 -shared -o "${this.runtimeDllFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, - `gcc -DLINUX64 -O2 -shared -o "${this.runtimeDllFile}" "${this.runtimeCFile}" "${this.builtinModuleCFile}" "${this.commCFile}"`, - { silent: true }, - ); - await exec( - `gcc -DLINUX64 -O2 -o "${this.shellFile}" "${this.shellCFile}" "${this.runtimeDllFile}" -lm`, - { silent: true }, - ); + await simpleExec('gcc', [ + '-DLINUX64', '-O2', '-shared', + '-o', this.runtimeDllFile, + this.runtimeCFile, this.builtinModuleCFile, this.commCFile, + ]); + await simpleExec('gcc', [ + '-DLINUX64', '-O2', + '-o', this.shellFile, + this.shellCFile, this.runtimeDllFile, + '-lm', + ]); } catch (error) { throw new Error('Failed to compile host runtime.', { cause: error }); } diff --git a/cli/tests/commands/board/flash-runtime.test.ts b/cli/tests/commands/board/flash-runtime.test.ts index 95ed0c2f..ebc693cb 100644 --- a/cli/tests/commands/board/flash-runtime.test.ts +++ b/cli/tests/commands/board/flash-runtime.test.ts @@ -5,7 +5,7 @@ import { mockedInquirer, mockedLogger, mockProcessExit, - mockedExec, + mockedExecShell, } from '../mock-helpers'; @@ -56,7 +56,7 @@ describe('board flash-runtime command', () => { // --- Assert --- expect(mockedInquirer.prompt).not.toHaveBeenCalled(); - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('build flash -p'), {cwd: expect.stringContaining('esp32')}); + expect(mockedExecShell).toHaveBeenCalledWith(expect.stringContaining('build flash -p'), { cwd: expect.stringContaining('esp32') }); }); it('should show an error and return if no serial ports are found', async () => { @@ -70,7 +70,7 @@ describe('board flash-runtime command', () => { // --- Assert --- expect(mockedLogger.error).toHaveBeenCalled(); expect(mockedInquirer.prompt).not.toHaveBeenCalled(); - expect(mockedExec).not.toHaveBeenCalled(); + expect(mockedExecShell).not.toHaveBeenCalled(); }); it('should exit with an error for an unknown board name', async () => { @@ -105,7 +105,7 @@ describe('board flash-runtime command', () => { await handleFlashRuntimeCommand('esp32', {}); // --- Assert --- - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('build flash'), {cwd: expect.stringContaining('esp32')}); + expect(mockedExecShell).toHaveBeenCalledWith(expect.stringContaining('build flash'), { cwd: expect.stringContaining('esp32') }); expect(mockedLogger.error).not.toHaveBeenCalled(); }); @@ -119,7 +119,7 @@ describe('board flash-runtime command', () => { await handleFlashRuntimeCommand('esp32', { deviceName: 'my-device' }); // --- Assert --- - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('my-device'), {cwd: expect.stringContaining('esp32')}); + expect(mockedExecShell).toHaveBeenCalledWith(expect.stringContaining('my-device'), { cwd: expect.stringContaining('esp32') }); expect(mockedLogger.error).not.toHaveBeenCalled(); }); @@ -133,7 +133,7 @@ describe('board flash-runtime command', () => { // --- Assert --- expect(mockedLogger.warn).toHaveBeenCalledWith(`The environment for esp32 is not set up. Run 'bscript board setup esp32' and try again.`); expect(mockedInquirer.prompt).not.toHaveBeenCalled(); - expect(mockedExec).not.toHaveBeenCalled(); + expect(mockedExecShell).not.toHaveBeenCalled(); }); }); @@ -152,4 +152,4 @@ describe('board flash-runtime command', () => { exitSpy.mockRestore(); }); }); -}); \ No newline at end of file +}); diff --git a/cli/tests/commands/board/setup.test.ts b/cli/tests/commands/board/setup.test.ts index 490ebf53..ccf0f1ea 100644 --- a/cli/tests/commands/board/setup.test.ts +++ b/cli/tests/commands/board/setup.test.ts @@ -2,7 +2,9 @@ import { handleSetupCommand } from '../../../src/commands/board/setup'; import os from 'os'; import { mockedDownloadAndUnzip, - mockedExec, + mockedSimpleExec, + mockedExecWithLog, + mockedExecShell, mockedInquirer, mockedLogger, mockProcessExit, @@ -24,6 +26,50 @@ jest.mock('os', () => ({ export const mockedOs = os as jest.Mocked; mockedOs.platform.mockReturnValue('darwin'); +function mockEsp32ShellCommands(options: { + whichFound?: string[]; + pythonMajor?: string; + gitCloneFails?: boolean; +}) { + mockedSimpleExec.mockImplementation(async (cmd, args) => { + if (cmd === 'which') { + if (options.whichFound?.includes(args[0])) { + return ''; + } + throw new Error('not found'); + } + if (cmd === 'python3' && args.some((arg: string) => arg.includes('export'))) { + return mockXtensaGccFromIdfToolsExport(); + } + if (cmd === 'python' && args[1]?.includes('import sys')) { + return options.pythonMajor ?? '3'; + } + return ''; + }); + mockedExecWithLog.mockImplementation(async (cmd, args) => { + if (cmd === 'git' && options.gitCloneFails) { + throw new Error('git command failed'); + } + if (cmd === 'git' || cmd === 'brew') { + return ''; + } + return ''; + }); + mockedExecShell.mockImplementation(async () => {}); +} + +function mockHostShellCommands(options: { ccMissing?: boolean }) { + mockedSimpleExec.mockImplementation(async (cmd, args) => { + if (cmd === 'which') { + if (options.ccMissing && args[0] === 'cc') { + throw new Error('not found'); + } + return ''; + } + return ''; + }); +} + describe('board setup command', () => { beforeAll(() => { @@ -62,7 +108,9 @@ describe('board setup command', () => { // --- Assert --- expect(mockedLogger.warn).toHaveBeenCalledWith('Setup cancelled by user.'); // No further actions taken - expect(mockedExec).not.toHaveBeenCalled(); + expect(mockedSimpleExec).not.toHaveBeenCalled(); + expect(mockedExecWithLog).not.toHaveBeenCalled(); + expect(mockedExecShell).not.toHaveBeenCalled(); }); it('should exit with an error for an unknown board name', async () => { @@ -83,12 +131,7 @@ describe('board setup command', () => { // --- Arrange --- const exitSpy = mockProcessExit(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); - mockedExec.mockImplementation(async (command) => { - if (command.startsWith('git clone')) { - throw new Error('git command failed');; - } - return ''; - }); + mockEsp32ShellCommands({ gitCloneFails: true }); // --- Act --- await handleSetupCommand('esp32'); @@ -104,20 +147,8 @@ describe('board setup command', () => { it('should perform a full setup if not already set up', async () => { // --- Arrange --- mockedInquirer.prompt.mockResolvedValue({ proceed: true }); - mockedExec.mockImplementation(async (command: string) => { - if (command.startsWith('which')) { - if (command.includes('brew') || command.includes('git')) { - return ''; - } - throw new Error('not found'); - } - if (command.includes('idf_tools.py export --format key-value')) { - return mockXtensaGccFromIdfToolsExport(); - } - if (command.includes('python -c "import sys; print(sys.version_info.major)')) { - return '3'; - } - return ''; + mockEsp32ShellCommands({ + whichFound: ['brew', 'git'], }); setupEmpyGlobalEnv(); @@ -132,11 +163,18 @@ describe('board setup command', () => { expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); // 3. Install required packages via Homebrew - expect(mockedExec).toHaveBeenCalledWith('brew install cmake ninja dfu-util ccache'); - + expect(mockedExecWithLog).toHaveBeenCalledWith( + 'brew', + ['install', 'cmake', 'ninja', 'dfu-util', 'ccache'], + ); + // 4. Clone ESP-IDF and run install script - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('git clone'), expect.any(Object)); - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('install.sh')); + expect(mockedExecWithLog).toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); + expect(mockedExecShell).toHaveBeenCalledWith(expect.stringContaining('install.sh')); // 5. Update and save config expect(Object.keys(getGlobalConfig().boards)).toContain('esp32'); @@ -149,20 +187,8 @@ describe('board setup command', () => { // --- Arrange --- mockedInquirer.prompt.mockResolvedValue({ proceed: true }); setupDefaultGlobalEnv(); - mockedExec.mockImplementation(async (command: string) => { - if (command.startsWith('which')) { - if (command.includes('brew') || command.includes('git')) { - return ''; - } - throw new Error('not found'); - } - if (command.includes('idf_tools.py export --format key-value')) { - return mockXtensaGccFromIdfToolsExport(); - } - if (command.includes('python --version')) { - return 'Python 3.7.18'; - } - return ''; + mockEsp32ShellCommands({ + whichFound: ['brew', 'git'], }); // --- Act --- @@ -172,37 +198,26 @@ describe('board setup command', () => { // Confirm downloads are skipped expect(mockedDownloadAndUnzip).not.toHaveBeenCalled(); // Confirm device setup proceeds - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('git clone'), expect.any(Object)); + expect(mockedExecWithLog).toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); }); it('shold skip install required packages if all packages are installed', async () => { // --- Arrange --- setupEmpyGlobalEnv(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); - mockedExec.mockImplementation(async (command: string) => { - if (command.startsWith('which')) { - if (command.includes('brew') || command.includes('git')) { - return ''; - } - if (command.includes('cmake') || command.includes('ninja') || command.includes('dfu-util') || command.includes('ccache')) { - return ''; - } - throw new Error('not found'); - } - if (command.includes('idf_tools.py export --format key-value')) { - return mockXtensaGccFromIdfToolsExport(); - } - if (command.includes('python --version')) { - return 'Python 3.7.18'; - } - return ''; + mockEsp32ShellCommands({ + whichFound: ['brew', 'git', 'cmake', 'ninja', 'dfu-util', 'ccache'], }); // --- Act --- await handleSetupCommand('esp32'); // --- Assert --- - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('brew install cmake')); + expect(mockedExecWithLog).not.toHaveBeenCalledWith('brew', ['install', 'cmake']); }); it('shold stop if python3 is not installed', async () => { @@ -210,17 +225,9 @@ describe('board setup command', () => { setupEmpyGlobalEnv(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); const exitSpy = mockProcessExit(); - mockedExec.mockImplementation(async (command: string) => { - if (command.startsWith('which')) { - if (command.includes('brew') || command.includes('git')) { - return ''; - } - throw new Error('not found'); - } - if (command.includes('python --version')) { - return 'Python 2.7.18'; - } - return ''; + mockEsp32ShellCommands({ + whichFound: ['brew', 'git'], + pythonMajor: '2', }); // --- Act --- @@ -244,7 +251,9 @@ describe('board setup command', () => { expect(mockedLogger.warn).toHaveBeenCalledWith('The setup for esp32 has already been completed.'); // No further actions taken expect(mockedInquirer.prompt).not.toHaveBeenCalled(); - expect(mockedExec).not.toHaveBeenCalled(); + expect(mockedSimpleExec).not.toHaveBeenCalled(); + expect(mockedExecWithLog).not.toHaveBeenCalled(); + expect(mockedExecShell).not.toHaveBeenCalled(); }); it('should exit with an error for an unsupported OS', async () => { @@ -273,12 +282,7 @@ describe('board setup command', () => { it('should perform a full setup if not already set up', async () => { setupEmpyGlobalEnv(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); - mockedExec.mockImplementation(async (command: string) => { - if (command.startsWith('which')) { - return ''; - } - return ''; - }); + mockHostShellCommands({}); await handleSetupCommand('host'); @@ -295,15 +299,7 @@ describe('board setup command', () => { setupEmpyGlobalEnv(); const exitSpy = mockProcessExit(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); - mockedExec.mockImplementation(async (command: string) => { - if (command.includes('which cc')) { - throw new Error('not found'); - } - if (command.startsWith('which')) { - return ''; - } - return ''; - }); + mockHostShellCommands({ ccMissing: true }); await handleSetupCommand('host'); diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index 884a3450..4c0d4c61 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,9 +1,28 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; -import { mockedDownloadAndUnzip, mockedExec, mockProcessExit } from '../mock-helpers'; +import { mockedDownloadAndUnzip, mockedSimpleExec, mockedExecWithLog, mockedExecShell, mockProcessExit } from '../mock-helpers'; import * as fs from '../../../src/core/fs'; +function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { + mockedSimpleExec.mockImplementation(async (cmd, args) => { + if (cmd === 'python3' && args.some((arg: string) => arg.includes('export'))) { + return mockXtensaGccFromIdfToolsExport(); + } + return ''; + }); + mockedExecWithLog.mockImplementation(async (cmd, args) => { + if (cmd === 'git' && options.gitCloneFails) { + throw new Error('Failed to cloning ESP-IDF'); + } + if (cmd === 'git') { + return ''; + } + return ''; + }); + mockedExecShell.mockImplementation(async () => {}); +} + describe('board update command', () => { beforeAll(() => { spyGlobalSettings('update'); @@ -17,20 +36,19 @@ describe('board update command', () => { it('should update all environments.', async () => { // --- Arrange --- setupGlobalEnvWithEsp32(true, true); - mockedExec.mockImplementation((command: string) => { - if (command.includes('idf_tools.py export --format key-value')) { - return mockXtensaGccFromIdfToolsExport(); - } - return ''; - }); + mockUpdateShellCommands({}); // --- Act --- await handleUpdateCommand(); // --- Assert --- expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); - expect(mockedExec).toHaveBeenCalledWith(expect.stringContaining('install')); + expect(mockedExecWithLog).toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); + expect(mockedExecShell).toHaveBeenCalledWith(expect.stringContaining('install')); expect(getGlobalConfig().version).toMatch(DUMMY_VM_VERSION); expect(getGlobalConfig().boards.esp32.idfVersion).toMatch(DUMMY_ESP_IDF_VERSION); }); @@ -55,7 +73,11 @@ describe('board update command', () => { // --- Assert --- expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); + expect(mockedExecWithLog).not.toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); expect(getGlobalConfig().version).toMatch(DUMMY_VM_VERSION); }); @@ -63,12 +85,7 @@ describe('board update command', () => { // --- Arrange --- const exitSpy = mockProcessExit(); setupGlobalEnvWithEsp32(true, true); - mockedExec.mockImplementation((command: string) => { - if (command.includes('idf_tools.py export --format key-value')) { - return mockXtensaGccFromIdfToolsExport(); - } - return ''; - }); + mockUpdateShellCommands({}); mockedDownloadAndUnzip.mockImplementation(() => { throw new Error('Failed to download.'); }); @@ -78,8 +95,12 @@ describe('board update command', () => { // --- Assert --- expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('install')); + expect(mockedExecWithLog).not.toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); + expect(mockedExecShell).not.toHaveBeenCalledWith(expect.stringContaining('install')); expect(fs.exists(getTestRuntimeDir())).toBe(true); expect(getGlobalConfig().version).toMatch(DUMMY_OLD_VM_VERSION); @@ -91,20 +112,19 @@ describe('board update command', () => { // --- Arrange --- const exitSpy = mockProcessExit(); setupGlobalEnvWithEsp32(true, true); - mockedExec.mockImplementation((command: string) => { - if (command.startsWith('git clone')) { - throw new Error('Failed to cloning ESP-IDF'); - } - return ''; - }); + mockUpdateShellCommands({ gitCloneFails: true }); // --- Act --- await handleUpdateCommand(); // --- Assert --- expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('git clone'),expect.any(Object)); - expect(mockedExec).not.toHaveBeenCalledWith(expect.stringContaining('install')); + expect(mockedExecWithLog).not.toHaveBeenCalledWith( + 'git', + expect.arrayContaining(['clone']), + expect.any(Object), + ); + expect(mockedExecShell).not.toHaveBeenCalledWith(expect.stringContaining('install')); expect(fs.exists(getTestRuntimeDir())).toBe(true); expect(fs.exists(getTestEspRootDir())).toBe(true); expect(getGlobalConfig().version).toMatch(DUMMY_OLD_VM_VERSION); @@ -113,4 +133,4 @@ describe('board update command', () => { // --- Clean up --- exitSpy.mockRestore(); }); -}); \ No newline at end of file +}); diff --git a/cli/tests/commands/mock-helpers.ts b/cli/tests/commands/mock-helpers.ts index c7fa4163..c73a98f9 100644 --- a/cli/tests/commands/mock-helpers.ts +++ b/cli/tests/commands/mock-helpers.ts @@ -1,10 +1,12 @@ -import { exec, cwd } from '../../src/core/shell'; +import { simpleExec, execWithLog, execShell, cwd } from '../../src/core/command-exec'; import inquirer from 'inquirer'; import { logger } from '../../src/core/logger'; import { downloadAndUnzip } from '../../src/core/fs'; -export const mockedExec = exec as jest.Mock; +export const mockedSimpleExec = simpleExec as jest.Mock; +export const mockedExecWithLog = execWithLog as jest.Mock; +export const mockedExecShell = execShell as jest.Mock; export const mockedCwd = cwd as jest.Mock; export const mockedDownloadAndUnzip = downloadAndUnzip as jest.Mock; export const mockedInquirer = inquirer as jest.Mocked; diff --git a/cli/tests/commands/project/install.test.ts b/cli/tests/commands/project/install.test.ts index d9e604ed..d711aa4c 100644 --- a/cli/tests/commands/project/install.test.ts +++ b/cli/tests/commands/project/install.test.ts @@ -3,7 +3,7 @@ import * as fs from '../../../src/core/fs'; import * as path from 'path'; import { mockedCwd, - mockedExec, + mockedSimpleExec, mockedLogger, mockProcessExit, } from '../mock-helpers'; @@ -49,10 +49,11 @@ describe('install command', () => { // --- Arrange --- setupGlobalEnvWithEsp32(); createDummyProject(projectRoot); - mockedExec.mockImplementation((command) => { - if (command.startsWith('git clone')) { - dummyGitClone(command, {}); + mockedSimpleExec.mockImplementation((cmd, args) => { + if (cmd === 'git' && args[0] === 'clone') { + dummyGitClone(args, {}); } + return Promise.resolve(''); }); // --- Act --- @@ -68,16 +69,17 @@ describe('install command', () => { // --- Arrange --- setupGlobalEnvWithEsp32(); createDummyProject(projectRoot); - mockedExec.mockImplementation((command) => { - if (command.startsWith('git clone')) { - if (command.includes('led')) { - dummyGitClone(command, { + mockedSimpleExec.mockImplementation((cmd, args) => { + if (cmd === 'git' && args[0] === 'clone') { + if (args.some((arg: string) => arg.includes('led'))) { + dummyGitClone(args, { 'pkg-gpio-esp32-project': 'https://github.com/bluescript-lang/pkg-gpio-esp32.git' }); - } else if (command.includes('gpio')) { - dummyGitClone(command, {}); + } else if (args.some((arg: string) => arg.includes('gpio'))) { + dummyGitClone(args, {}); } } + return Promise.resolve(''); }); // --- Act --- @@ -94,18 +96,19 @@ describe('install command', () => { // --- Arrange --- setupGlobalEnvWithEsp32(); createDummyProject(projectRoot); - mockedExec.mockImplementation((command) => { - if (command.startsWith('git clone')) { - if (command.includes('led')) { - dummyGitClone(command, { + mockedSimpleExec.mockImplementation((cmd, args) => { + if (cmd === 'git' && args[0] === 'clone') { + if (args.some((arg: string) => arg.includes('led'))) { + dummyGitClone(args, { 'pkg-gpio-esp32-project': 'https://github.com/bluescript-lang/pkg-gpio-esp32.git' }); - } else if (command.includes('gpio')) { - dummyGitClone(command, { + } else if (args.some((arg: string) => arg.includes('gpio'))) { + dummyGitClone(args, { 'pkg-led-esp32-project': 'https://github.com/bluescript-lang/pkg-led-esp32.git' }); } } + return Promise.resolve(''); }); // --- Act --- @@ -124,18 +127,19 @@ describe('install command', () => { 'pkg-led-esp32-project': 'https://github.com/bluescript-lang/pkg-led-esp32.git', 'pkg-pwm-esp32-project': 'https://github.com/bluescript-lang/pkg-pwm-esp32.git#v1.0.0', }); - mockedExec.mockImplementation((command) => { - if (command.startsWith('git clone')) { - if (command.includes('led')) { - dummyGitClone(command, { + mockedSimpleExec.mockImplementation((cmd, args) => { + if (cmd === 'git' && args[0] === 'clone') { + if (args.some((arg: string) => arg.includes('led'))) { + dummyGitClone(args, { 'pkg-gpio-esp32-project': 'https://github.com/bluescript-lang/pkg-gpio-esp32.git' }); - } else if (command.includes('gpio')) { - dummyGitClone(command, {}); - } else if (command.includes('pwm')) { - dummyGitClone(command, {}); + } else if (args.some((arg: string) => arg.includes('gpio'))) { + dummyGitClone(args, {}); + } else if (args.some((arg: string) => arg.includes('pwm'))) { + dummyGitClone(args, {}); } } + return Promise.resolve(''); }); // --- Act --- @@ -152,10 +156,11 @@ describe('install command', () => { const exitSpy = mockProcessExit(); setupDefaultGlobalEnv(); createDummyProject(projectRoot); - mockedExec.mockImplementation((command) => { - if (command.startsWith('git clone')) { - dummyGitClone(command, {}); + mockedSimpleExec.mockImplementation((cmd, args) => { + if (cmd === 'git' && args[0] === 'clone') { + dummyGitClone(args, {}); } + return Promise.resolve(''); }); // --- Act --- @@ -172,22 +177,17 @@ describe('install command', () => { }); -function dummyGitClone(command: string, dependencies: {[name: string]: string}) { - const urlRegex = /(https?:\/\/\S+|git@\S+)/; - const match = command.match(urlRegex); - - if (!match) { +function dummyGitClone(args: string[], dependencies: {[name: string]: string}) { + const url = args.find((arg) => arg.startsWith('http') || arg.startsWith('git@')); + if (!url) { console.error("Could not find git url."); return null; } - const fullUrl = match[0]; + const fullUrl = url; const cleanUrl = fullUrl.replace(/\.git$/, ''); const repoName = cleanUrl.split('/').pop() || ''; - - const urlIndex = command.indexOf(fullUrl); - const textAfterUrl = command.substring(urlIndex + fullUrl.length).trim(); - const targetDir = textAfterUrl.length > 0 ? textAfterUrl : repoName; + const targetDir = args[args.length - 1]; fs.makeDir(targetDir); const bsConfig = { diff --git a/cli/tests/global-mocks.ts b/cli/tests/global-mocks.ts index d2a15341..72254fc9 100644 --- a/cli/tests/global-mocks.ts +++ b/cli/tests/global-mocks.ts @@ -37,6 +37,6 @@ jest.mock('../src/core/fs', () => { }) -jest.mock('../src/core/shell'); +jest.mock('../src/core/command-exec'); // jest.mock('../src/core/fs'); jest.mock('inquirer'); diff --git a/cli/tests/integration/project/repl.host.test.ts b/cli/tests/integration/project/repl.host.test.ts index 0dbfe8d1..08c3616e 100644 --- a/cli/tests/integration/project/repl.host.test.ts +++ b/cli/tests/integration/project/repl.host.test.ts @@ -1,5 +1,5 @@ -jest.mock('../../../src/core/shell', () => ({ - ...jest.requireActual('../../../src/core/shell'), +jest.mock('../../../src/core/command-exec', () => ({ + ...jest.requireActual('../../../src/core/command-exec'), cwd: jest.fn(), })); diff --git a/cli/tests/integration/project/run.host.test.ts b/cli/tests/integration/project/run.host.test.ts index b23a902e..82941a74 100644 --- a/cli/tests/integration/project/run.host.test.ts +++ b/cli/tests/integration/project/run.host.test.ts @@ -1,10 +1,10 @@ -jest.mock('../../../src/core/shell', () => ({ - ...jest.requireActual('../../../src/core/shell'), +jest.mock('../../../src/core/command-exec', () => ({ + ...jest.requireActual('../../../src/core/command-exec'), cwd: jest.fn(), })); import * as path from 'path'; -import { cwd } from '../../../src/core/shell'; +import { cwd } from '../../../src/core/command-exec'; import * as fs from '../../../src/core/fs'; import { handleRunCommand } from '../../../src/commands/project/run'; import { From 6779882e611f6a326f518f94499aefa689965ec0 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 17:06:29 +0900 Subject: [PATCH 22/33] Fixing bugs on windows --- cli/src/services/host-protocol.ts | 5 ++++ cli/src/services/parse-result.txt | 48 +++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 cli/src/services/parse-result.txt diff --git a/cli/src/services/host-protocol.ts b/cli/src/services/host-protocol.ts index 37553bf3..4f447bf8 100644 --- a/cli/src/services/host-protocol.ts +++ b/cli/src/services/host-protocol.ts @@ -57,18 +57,23 @@ export class HostProtocolParser { public parse(line: string): {parsed: HostParseResult[], remain: string} { // The format is [xx yyyy zz...] // xx is protocol, yyyy is payload length, zz... is payload + console.log("line", line) const headerLength = 8; const parsed: HostParseResult[] = []; let remain: string = line; while (remain.length >= headerLength) { try { const protocol = Number(remain.substring(0, 2)); + console.log("protocol", protocol) const payloadLength = Number(remain.substring(3, 7)); + console.log("payloadLength", payloadLength) if (remain.length < headerLength + payloadLength) { return { parsed, remain }; } const payload = remain.substring(headerLength, headerLength + payloadLength); + console.log("payload", payload) remain = remain.substring(headerLength + payloadLength); + console.log("remain", remain, remain.length); parsed.push(this.parsePayload(protocol, payload)); } catch (error) { throw new Error("Failed to parse message.", { cause: error }); diff --git a/cli/src/services/parse-result.txt b/cli/src/services/parse-result.txt new file mode 100644 index 00000000..ab4ccc4a --- /dev/null +++ b/cli/src/services/parse-result.txt @@ -0,0 +1,48 @@ +bscript project run +INFO: Connecting... OK +INFO: Initializing OK +INFO: Compiling... OK +INFO: Loading...line 06 0007 1399.27 +protocol 6 +payloadLength 7 +payload 1399.27 +remain 0 +INFO: Loading... OK +INFO: Start executing program. Type 'Ctrl-D' to exit. + +========================================================================== OUTPUT ========================================================================== +line 03 0015 'Hello world!' +05 0006 0.0142 +protocol 3 +payloadLength 15 +payload 'Hello world!' +remain +05 0006 0.0142 15 +protocol 0 +payloadLength 0 +payload +remain 0.0142 7 +C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:59 + throw new Error("Failed to parse message.", { cause: error }); + ^ + +Error: Failed to parse message. + at HostProtocolParser.parse (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:59:23) + at HostMessageQueue.addChunk (C:\Users\qiand\bluescript\cli\dist\services\process.js:55:48) + ... 6 lines matching cause stack trace ... + at addChunk (node:internal/streams/readable:563:12) + at readableAddChunkPushByteMode (node:internal/streams/readable:514:3) { + [cause]: Error: Failed to parse buffer. The protocol 0 is not parsable. + at HostProtocolParser.parsePayload (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:66:19) + at HostProtocolParser.parse (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:56:34) + at HostMessageQueue.addChunk (C:\Users\qiand\bluescript\cli\dist\services\process.js:55:48) + at C:\Users\qiand\bluescript\cli\dist\services\process.js:14:31 + at C:\Users\qiand\bluescript\cli\dist\services\common.js:34:13 + at Array.forEach () + at ProcessConnection.emit (C:\Users\qiand\bluescript\cli\dist\services\common.js:33:27) + at Socket. (C:\Users\qiand\bluescript\cli\dist\services\process.js:114:18) + at Socket.emit (node:events:509:28) + at addChunk (node:internal/streams/readable:563:12) +} + +Node.js v24.18.0 \ No newline at end of file From 2f8332c8e084a01dd99cc0f4b239efac97db837b Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 17:55:08 +0900 Subject: [PATCH 23/33] Fix parse bugs. --- cli/src/services/ble-result.txt | 102 ------------------ cli/src/services/host-protocol.ts | 5 - cli/src/services/parse-result.txt | 48 --------- .../board-toolchain/host-toolchain.ts | 3 + .../board-toolchain/tools/makefile.ts | 2 +- microcontroller/ports/host/shell.c | 7 ++ 6 files changed, 11 insertions(+), 156 deletions(-) delete mode 100644 cli/src/services/ble-result.txt delete mode 100644 cli/src/services/parse-result.txt diff --git a/cli/src/services/ble-result.txt b/cli/src/services/ble-result.txt deleted file mode 100644 index 14513eb8..00000000 --- a/cli/src/services/ble-result.txt +++ /dev/null @@ -1,102 +0,0 @@ ->bscript project run -INFO: Connecting...foo -foo2 -Foo3 -foo4 -foo41 -[ - Service { - _noble: Noble { - initialized: true, - address: 'unknown', - _state: 'poweredOn', - _bindings: [NobleWinrt], - _peripherals: [Object], - _services: [Object], - _characteristics: [Object], - _descriptors: [Object], - _discoveredPeripheralUUids: [Object], - _events: [Object: null prototype], - _eventsCount: 2, - _allowDuplicates: false - }, - _peripheralId: '083af2438a6a', - uuid: '1801', - name: 'Generic Attribute', - type: 'org.bluetooth.service.generic_attribute', - includedServiceUuids: null, - characteristics: null - }, - Service { - _noble: Noble { - initialized: true, - address: 'unknown', - _state: 'poweredOn', - _bindings: [NobleWinrt], - _peripherals: [Object], - _services: [Object], - _characteristics: [Object], - _descriptors: [Object], - _discoveredPeripheralUUids: [Object], - _events: [Object: null prototype], - _eventsCount: 2, - _allowDuplicates: false - }, - _peripheralId: '083af2438a6a', - uuid: '1800', - name: 'Generic Access', - type: 'org.bluetooth.service.generic_access', - includedServiceUuids: null, - characteristics: null - }, - Service { - _noble: Noble { - initialized: true, - address: 'unknown', - _state: 'poweredOn', - _bindings: [NobleWinrt], - _peripherals: [Object], - _services: [Object], - _characteristics: [Object], - _descriptors: [Object], - _discoveredPeripheralUUids: [Object], - _events: [Object: null prototype], - _eventsCount: 2, - _allowDuplicates: false - }, - _peripheralId: '083af2438a6a', - uuid: 'ff', - name: null, - type: null, - includedServiceUuids: null, - characteristics: null - } -] -service Service { - _noble: Noble { - initialized: true, - address: 'unknown', - _state: 'poweredOn', - _bindings: NobleWinrt { _events: [Object: null prototype], _eventsCount: 25 }, - _peripherals: { '083af2438a6a': [Peripheral] }, - _services: { '083af2438a6a': [Object] }, - _characteristics: { '083af2438a6a': [Object] }, - _descriptors: { '083af2438a6a': [Object] }, - _discoveredPeripheralUUids: { '083af2438a6a': true }, - _events: [Object: null prototype] { - warning: [Function (anonymous)], - newListener: [Function (anonymous)] - }, - _eventsCount: 2, - _allowDuplicates: false - }, - _peripheralId: '083af2438a6a', - uuid: 'ff', - name: null, - type: null, - includedServiceUuids: null, - characteristics: null -} -GetGattServicesForUuidAsync: no service with given id -BLEManager::DiscoverCharacteristics::::operator (): GetService error -^C \ No newline at end of file diff --git a/cli/src/services/host-protocol.ts b/cli/src/services/host-protocol.ts index 4f447bf8..37553bf3 100644 --- a/cli/src/services/host-protocol.ts +++ b/cli/src/services/host-protocol.ts @@ -57,23 +57,18 @@ export class HostProtocolParser { public parse(line: string): {parsed: HostParseResult[], remain: string} { // The format is [xx yyyy zz...] // xx is protocol, yyyy is payload length, zz... is payload - console.log("line", line) const headerLength = 8; const parsed: HostParseResult[] = []; let remain: string = line; while (remain.length >= headerLength) { try { const protocol = Number(remain.substring(0, 2)); - console.log("protocol", protocol) const payloadLength = Number(remain.substring(3, 7)); - console.log("payloadLength", payloadLength) if (remain.length < headerLength + payloadLength) { return { parsed, remain }; } const payload = remain.substring(headerLength, headerLength + payloadLength); - console.log("payload", payload) remain = remain.substring(headerLength + payloadLength); - console.log("remain", remain, remain.length); parsed.push(this.parsePayload(protocol, payload)); } catch (error) { throw new Error("Failed to parse message.", { cause: error }); diff --git a/cli/src/services/parse-result.txt b/cli/src/services/parse-result.txt deleted file mode 100644 index ab4ccc4a..00000000 --- a/cli/src/services/parse-result.txt +++ /dev/null @@ -1,48 +0,0 @@ -bscript project run -INFO: Connecting... OK -INFO: Initializing OK -INFO: Compiling... OK -INFO: Loading...line 06 0007 1399.27 -protocol 6 -payloadLength 7 -payload 1399.27 -remain 0 -INFO: Loading... OK -INFO: Start executing program. Type 'Ctrl-D' to exit. - -========================================================================== OUTPUT ========================================================================== -line 03 0015 'Hello world!' -05 0006 0.0142 -protocol 3 -payloadLength 15 -payload 'Hello world!' -remain -05 0006 0.0142 15 -protocol 0 -payloadLength 0 -payload -remain 0.0142 7 -C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:59 - throw new Error("Failed to parse message.", { cause: error }); - ^ - -Error: Failed to parse message. - at HostProtocolParser.parse (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:59:23) - at HostMessageQueue.addChunk (C:\Users\qiand\bluescript\cli\dist\services\process.js:55:48) - ... 6 lines matching cause stack trace ... - at addChunk (node:internal/streams/readable:563:12) - at readableAddChunkPushByteMode (node:internal/streams/readable:514:3) { - [cause]: Error: Failed to parse buffer. The protocol 0 is not parsable. - at HostProtocolParser.parsePayload (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:66:19) - at HostProtocolParser.parse (C:\Users\qiand\bluescript\cli\dist\services\host-protocol.js:56:34) - at HostMessageQueue.addChunk (C:\Users\qiand\bluescript\cli\dist\services\process.js:55:48) - at C:\Users\qiand\bluescript\cli\dist\services\process.js:14:31 - at C:\Users\qiand\bluescript\cli\dist\services\common.js:34:13 - at Array.forEach () - at ProcessConnection.emit (C:\Users\qiand\bluescript\cli\dist\services\common.js:33:27) - at Socket. (C:\Users\qiand\bluescript\cli\dist\services\process.js:114:18) - at Socket.emit (node:events:509:28) - at addChunk (node:internal/streams/readable:563:12) -} - -Node.js v24.18.0 \ No newline at end of file diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 6f7a3340..9fb665da 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -161,6 +161,9 @@ export class HostWindowsToolchain extends HostToolchain { this.runtimeDll, '-lm', ...keepEntrySymbols, + '-Wl,--export-all-symbols', + '-Wl,--enable-auto-import', + '-Wl,--enable-runtime-pseudo-reloc' ]; await executeCommand(this.config.compilerToolchain.gcc, args); return outputFile; diff --git a/lang/src/compiler/board-toolchain/tools/makefile.ts b/lang/src/compiler/board-toolchain/tools/makefile.ts index 8ffde896..72a068dc 100644 --- a/lang/src/compiler/board-toolchain/tools/makefile.ts +++ b/lang/src/compiler/board-toolchain/tools/makefile.ts @@ -61,7 +61,7 @@ export function hostWindowsMakefilePreset(pkg: PackageForHostWindows, toolchain: objectFiles: pkg.objectFiles.map(toMakePath), headerFilesInDist: pkg.headerFilesInDist.map(toMakePath), includeDirs: [toMakePath(pkg.resolvedDistDir)], - compileFlags: ['-O2', '-w', '-DLINUX64'], + compileFlags: ['-O2', '-w', '-DLINUX64', '-fno-common'], distDir: toMakePath(pkg.resolvedDistDir), buildDir: toMakePath(pkg.resolvedBuildDir), toolchain: { diff --git a/microcontroller/ports/host/shell.c b/microcontroller/ports/host/shell.c index 941581d7..4357c390 100644 --- a/microcontroller/ports/host/shell.c +++ b/microcontroller/ports/host/shell.c @@ -11,6 +11,8 @@ #include #else #include +#include +#include #endif @@ -78,6 +80,11 @@ static void call(char* funcname) { } int main() { +#ifdef _WIN32 + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); +#endif + gc_initialize(); bluescript_main0_(); From 057a8c405a4126c9a16e2c9ef83a2830f0aadf35 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 17:59:00 +0900 Subject: [PATCH 24/33] Fixing link bugs for windows. --- lang/src/compiler/board-toolchain/host-toolchain.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index 9fb665da..a0a8f766 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -117,6 +117,12 @@ export class HostUnixToolchain extends HostToolchain { } export class HostWindowsToolchain extends HostToolchain { + // Import libraries (.dll.a) of previously generated fragment DLLs. + // On Windows, cross-DLL data symbols are only resolved reliably when the + // referencing DLL links against a proper import library rather than the + // DLL file itself, so keep these separate from generatedSharedLibs. + private generatedImportLibs: string[] = []; + get runtimeDll(): string { return path.join(this.runtimeBuildDir, 'c-runtime.dll'); } @@ -153,11 +159,13 @@ export class HostWindowsToolchain extends HostToolchain { (sym) => `-Wl,-u,${sym}`, ); const outputFile = project.mainPackage.dllFile(this.compileId++); + const importLibFile = `${outputFile}.a`; const args = [ '-shared', '-o', outputFile, + `-Wl,--out-implib,${importLibFile}`, ...archiveFiles, - ...this.generatedSharedLibs, + ...this.generatedImportLibs, this.runtimeDll, '-lm', ...keepEntrySymbols, @@ -166,6 +174,7 @@ export class HostWindowsToolchain extends HostToolchain { '-Wl,--enable-runtime-pseudo-reloc' ]; await executeCommand(this.config.compilerToolchain.gcc, args); + this.generatedImportLibs.push(importLibFile); return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, { cause: error }); From 8641a5064dc85f5535a577027aad0fbe6e3393d8 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 18:30:22 +0900 Subject: [PATCH 25/33] Fixing link bugs. --- .../board-toolchain/host-toolchain.ts | 1 + lang/src/compiler/board-toolchain/result.txt | 147 ++++++++++++++++++ 2 files changed, 148 insertions(+) create mode 100644 lang/src/compiler/board-toolchain/result.txt diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index a0a8f766..ff8020d0 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -173,6 +173,7 @@ export class HostWindowsToolchain extends HostToolchain { '-Wl,--enable-auto-import', '-Wl,--enable-runtime-pseudo-reloc' ]; + console.log('[bs][win-link]', this.config.compilerToolchain.gcc, args.join(' ')) await executeCommand(this.config.compilerToolchain.gcc, args); this.generatedImportLibs.push(importLibFile); return outputFile; diff --git a/lang/src/compiler/board-toolchain/result.txt b/lang/src/compiler/board-toolchain/result.txt new file mode 100644 index 00000000..a91a575c --- /dev/null +++ b/lang/src/compiler/board-toolchain/result.txt @@ -0,0 +1,147 @@ +link command + +[bs][win-link] gcc -shared -o C:\Users\qiand\.bluescript\temp\dist\build\temp1.dll -Wl,--out-implib,C:\Users\qiand\.bluescript\temp\dist\build\temp1.dll.a C:\Users\qiand\.bluescript\temp\dist\build\libtemp.a C:\Users\qiand\.bluescript\temp\dist\build\temp0.dll.a C:\Users\qiand\bluescript\microcontroller\ports\host\build\c-runtime.dll -lm -Wl,-u,bluescript_main2_ -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc + +objdump -x temp0.dll | findstr /i "Export _a" +Entry 0 0000000000008000 00000075 Export Directory [.edata (or where ever we found it)] + 00009180 00b6 _amsg_exit +There is an export table in .edata at 0x196c8000 +The Export Tables (interpreted .edata section contents) +Export Flags 0 + Export Address Table 00000003 + Export Address Table 0000000000008028 +Export Address Table -- Ordinal Base 1 + [ 0] +base[ 1] 00007030 Export RVA + [ 1] +base[ 2] 00001340 Export RVA + [ 2] +base[ 3] 00007020 Export RVA + [ 0] +base[ 1] 0000 _a + 10 .debug_aranges 00000050 00000003196cc000 00000003196cc000 00003000 2**0 + 12 .debug_abbrev 000000ca 00000003196cf000 00000003196cf000 00004600 2**0 +[ 4](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000018 __proc_attached +[ 12](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000280 .rdata$.refptr.__xi_a +[ 16](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000260 .rdata$.refptr.__xc_a +[ 23](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000220 .rdata$.refptr.__mingw_app_type +[102](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000358 __xd_a +[190](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000000af0 ___w64_mingwthr_add_key_dtor +[261](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_abbrev +[273](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_aranges +[289](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000014 .debug_abbrev +[291](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000030 .debug_aranges +[327](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000000011b0 __acrt_iob_func +[603](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a0 __imp_abort +[604](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000378 __lib64_libkernel32_a_iname +[610](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000014 _head_lib64_libmsvcrt_def_a +[615](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000338 __xl_a +[620](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000030 _a +[632](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000180 __imp__amsg_exit +[646](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 .refptr.__mingw_app_type +[658](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000280 .refptr.__xi_a +[660](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000001000 __section_alignment__ +[670](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003c0 __lib64_libmsvcrt_def_a_iname +[674](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _head_lib64_libkernel32_a +[692](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000200 __file_alignment__ +[703](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000328 __xi_a +[707](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000318 __xc_a +[711](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000001358 _amsg_exit +[726](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000050 __imp___acrt_iob_func +[736](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000260 .refptr.__xc_a +[747](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000070 __mingw_app_type + +C:\Users\qiand\.bluescript\temp\dist\build>nm temp0.dll | findstr /i "_a" +00000003196cf014 N .debug_abbrev +00000003196cf000 N .debug_abbrev +00000003196cc030 N .debug_aranges +00000003196cc000 N .debug_aranges +00000003196c4220 r .rdata$.refptr.__mingw_app_type +00000003196c4260 r .rdata$.refptr.__xc_a +00000003196c4280 r .rdata$.refptr.__xi_a +00000003196c4220 R .refptr.__mingw_app_type +00000003196c4260 R .refptr.__xc_a +00000003196c4280 R .refptr.__xi_a +00000003196c1af0 T ___w64_mingwthr_add_key_dtor +00000003196c21b0 T __acrt_iob_func +0000000000000200 A __file_alignment__ +00000003196c3050 D __imp___acrt_iob_func +00000003196c9180 I __imp__amsg_exit +00000003196c91a0 I __imp_abort +00000003196c9378 I __lib64_libkernel32_a_iname +00000003196c93c0 I __lib64_libmsvcrt_def_a_iname +00000003196c7070 B __mingw_app_type +00000003196c7018 b __proc_attached +0000000000001000 A __section_alignment__ +00000003196c4318 R __xc_a +00000003196c4358 r __xd_a +00000003196c4328 R __xi_a +00000003196c4338 R __xl_a +00000003196c7030 B _a +00000003196c2358 T _amsg_exit +00000003196c9000 I _head_lib64_libkernel32_a +00000003196c9014 I _head_lib64_libmsvcrt_def_a + +C:\Users\qiand\.bluescript\temp\dist\build>objdump -x temp1.dll | findstr /i "temp0 _a __imp" + 00009198 00b6 _amsg_exit + [ 0] +base[ 1] 0000 _a + 10 .debug_aranges 00000050 000000033e4ec000 000000033e4ec000 00003400 2**0 + 12 .debug_abbrev 000000ca 000000033e4ef000 000000033e4ef000 00004a00 2**0 +[ 4](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000018 __proc_attached +[ 12](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000290 .rdata$.refptr.__xi_a +[ 16](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000270 .rdata$.refptr.__xc_a +[ 23](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000230 .rdata$.refptr.__mingw_app_type +[ 59](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000000002b0 .rdata$.refptr._a +[124](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000410 __xd_a +[212](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000000b50 ___w64_mingwthr_add_key_dtor +[283](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_abbrev +[295](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_aranges +[311](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000014 .debug_abbrev +[313](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000030 .debug_aranges +[349](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x0000000000001210 __acrt_iob_func +[644](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001b8 __imp_abort +[645](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003e4 __lib64_libkernel32_a_iname +[646](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000040 __imp__initterm_e +[649](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a8 __imp__lock +[651](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000014 _head_lib64_libmsvcrt_def_a +[652](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001c0 __imp_calloc +[657](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003f0 __xl_a +[663](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000040 _a +[669](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000140 __imp_DeleteCriticalSection +[675](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000198 __imp__amsg_exit +[682](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000208 __imp_gc_init_rootset +[687](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000150 __imp_GetLastError +[689](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001d0 __imp_free +[690](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000230 .refptr.__mingw_app_type +[694](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000210 __imp_gc_method_lookup +[696](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000160 __imp_LeaveCriticalSection +[703](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000290 .refptr.__xi_a +[705](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000001000 __section_alignment__ +[712](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001d8 __imp_memcpy +[716](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000000000000042c __lib64_libmsvcrt_def_a_iname +[718](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000002b0 .refptr._a +[721](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _head_lib64_libkernel32_a +[729](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000148 __imp_EnterCriticalSection +[736](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000068 __imp__register_onexit_function +[740](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001e8 __imp_strlen +[741](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000200 __file_alignment__ +[742](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000158 __imp_InitializeCriticalSection +[743](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001e0 __imp_realloc +[745](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001f8 __imp_vfprintf +[751](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000070 __imp__initialize_onexit_table +[752](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003e0 __xi_a +[753](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000168 __imp_Sleep +[756](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003d0 __xc_a +[760](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000000013b8 _amsg_exit +[761](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000170 __imp_TlsGetValue +[762](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000060 __imp__execute_onexit_table +[763](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001c8 __imp_fprintf +[765](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000178 __imp_VirtualProtect +[766](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 __imp_global_rootset0 +[769](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000180 __imp_VirtualQuery +[770](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a0 __imp__initterm +[772](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000190 __imp___iob_func +[775](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001f0 __imp_strncmp +[776](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000218 __imp_gc_root_set_head +[777](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000050 __imp___acrt_iob_func +[786](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001b0 __imp__unlock +[788](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000270 .refptr.__xc_a +[792](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 __imp_global_rootset0 +[796](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000218 __imp_gc_root_set_head +[801](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000080 __mingw_app_type \ No newline at end of file From 56948bf5dbbeba889591c59d677a4f9acfed74f7 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 18:35:50 +0900 Subject: [PATCH 26/33] Fixing link bugs for windows. --- .../compiler/board-toolchain/host-toolchain.ts | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index ff8020d0..c76282e7 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -117,12 +117,6 @@ export class HostUnixToolchain extends HostToolchain { } export class HostWindowsToolchain extends HostToolchain { - // Import libraries (.dll.a) of previously generated fragment DLLs. - // On Windows, cross-DLL data symbols are only resolved reliably when the - // referencing DLL links against a proper import library rather than the - // DLL file itself, so keep these separate from generatedSharedLibs. - private generatedImportLibs: string[] = []; - get runtimeDll(): string { return path.join(this.runtimeBuildDir, 'c-runtime.dll'); } @@ -159,13 +153,11 @@ export class HostWindowsToolchain extends HostToolchain { (sym) => `-Wl,-u,${sym}`, ); const outputFile = project.mainPackage.dllFile(this.compileId++); - const importLibFile = `${outputFile}.a`; const args = [ '-shared', '-o', outputFile, - `-Wl,--out-implib,${importLibFile}`, ...archiveFiles, - ...this.generatedImportLibs, + ...this.generatedSharedLibs, this.runtimeDll, '-lm', ...keepEntrySymbols, @@ -173,9 +165,10 @@ export class HostWindowsToolchain extends HostToolchain { '-Wl,--enable-auto-import', '-Wl,--enable-runtime-pseudo-reloc' ]; - console.log('[bs][win-link]', this.config.compilerToolchain.gcc, args.join(' ')) - await executeCommand(this.config.compilerToolchain.gcc, args); - this.generatedImportLibs.push(importLibFile); + // TEMPORARY (diagnostic): print the exact linker invocation and + // surface gcc/ld stdout+stderr while debugging cross-DLL data sharing. + console.log('[bs][win-link]', this.config.compilerToolchain.gcc, args.join(' ')); + await executeCommand(this.config.compilerToolchain.gcc, args, undefined, true, true); return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, { cause: error }); From 8511f5107b47e345aa888409ffa4248e747e6282 Mon Sep 17 00:00:00 2001 From: maejima-fumika Date: Sun, 5 Jul 2026 18:42:42 +0900 Subject: [PATCH 27/33] Fixing link bugs. --- lang/src/compiler/board-toolchain/result.txt | 118 +------------------ 1 file changed, 6 insertions(+), 112 deletions(-) diff --git a/lang/src/compiler/board-toolchain/result.txt b/lang/src/compiler/board-toolchain/result.txt index a91a575c..52a6d79a 100644 --- a/lang/src/compiler/board-toolchain/result.txt +++ b/lang/src/compiler/board-toolchain/result.txt @@ -1,84 +1,9 @@ -link command - -[bs][win-link] gcc -shared -o C:\Users\qiand\.bluescript\temp\dist\build\temp1.dll -Wl,--out-implib,C:\Users\qiand\.bluescript\temp\dist\build\temp1.dll.a C:\Users\qiand\.bluescript\temp\dist\build\libtemp.a C:\Users\qiand\.bluescript\temp\dist\build\temp0.dll.a C:\Users\qiand\bluescript\microcontroller\ports\host\build\c-runtime.dll -lm -Wl,-u,bluescript_main2_ -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--enable-runtime-pseudo-reloc - -objdump -x temp0.dll | findstr /i "Export _a" -Entry 0 0000000000008000 00000075 Export Directory [.edata (or where ever we found it)] - 00009180 00b6 _amsg_exit -There is an export table in .edata at 0x196c8000 -The Export Tables (interpreted .edata section contents) -Export Flags 0 - Export Address Table 00000003 - Export Address Table 0000000000008028 -Export Address Table -- Ordinal Base 1 - [ 0] +base[ 1] 00007030 Export RVA - [ 1] +base[ 2] 00001340 Export RVA - [ 2] +base[ 3] 00007020 Export RVA - [ 0] +base[ 1] 0000 _a - 10 .debug_aranges 00000050 00000003196cc000 00000003196cc000 00003000 2**0 - 12 .debug_abbrev 000000ca 00000003196cf000 00000003196cf000 00004600 2**0 -[ 4](sec 6)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000018 __proc_attached -[ 12](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000280 .rdata$.refptr.__xi_a -[ 16](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000260 .rdata$.refptr.__xc_a -[ 23](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000220 .rdata$.refptr.__mingw_app_type -[102](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 0) 0x0000000000000358 __xd_a -[190](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000000af0 ___w64_mingwthr_add_key_dtor -[261](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_abbrev -[273](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000000 .debug_aranges -[289](sec 13)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000014 .debug_abbrev -[291](sec 11)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x0000000000000030 .debug_aranges -[327](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x00000000000011b0 __acrt_iob_func -[603](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a0 __imp_abort -[604](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000378 __lib64_libkernel32_a_iname -[610](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000014 _head_lib64_libmsvcrt_def_a -[615](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000338 __xl_a -[620](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000030 _a -[632](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000180 __imp__amsg_exit -[646](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 .refptr.__mingw_app_type -[658](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000280 .refptr.__xi_a -[660](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000001000 __section_alignment__ -[670](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003c0 __lib64_libmsvcrt_def_a_iname -[674](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _head_lib64_libkernel32_a -[692](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000200 __file_alignment__ -[703](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000328 __xi_a -[707](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000318 __xc_a -[711](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x0000000000001358 _amsg_exit -[726](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000050 __imp___acrt_iob_func -[736](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000260 .refptr.__xc_a -[747](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000070 __mingw_app_type - -C:\Users\qiand\.bluescript\temp\dist\build>nm temp0.dll | findstr /i "_a" -00000003196cf014 N .debug_abbrev -00000003196cf000 N .debug_abbrev -00000003196cc030 N .debug_aranges -00000003196cc000 N .debug_aranges -00000003196c4220 r .rdata$.refptr.__mingw_app_type -00000003196c4260 r .rdata$.refptr.__xc_a -00000003196c4280 r .rdata$.refptr.__xi_a -00000003196c4220 R .refptr.__mingw_app_type -00000003196c4260 R .refptr.__xc_a -00000003196c4280 R .refptr.__xi_a -00000003196c1af0 T ___w64_mingwthr_add_key_dtor -00000003196c21b0 T __acrt_iob_func -0000000000000200 A __file_alignment__ -00000003196c3050 D __imp___acrt_iob_func -00000003196c9180 I __imp__amsg_exit -00000003196c91a0 I __imp_abort -00000003196c9378 I __lib64_libkernel32_a_iname -00000003196c93c0 I __lib64_libmsvcrt_def_a_iname -00000003196c7070 B __mingw_app_type -00000003196c7018 b __proc_attached -0000000000001000 A __section_alignment__ -00000003196c4318 R __xc_a -00000003196c4358 r __xd_a -00000003196c4328 R __xi_a -00000003196c4338 R __xl_a -00000003196c7030 B _a -00000003196c2358 T _amsg_exit -00000003196c9000 I _head_lib64_libkernel32_a -00000003196c9014 I _head_lib64_libmsvcrt_def_a +C:\Users\qiand\.bluescript\temp\dist\build>objdump -x temp1.dll | findstr /i "__imp__a temp0 .refptr._a" +[ 59](sec 3)(fl 0x00)(ty 0)(scl 3) (nx 1) 0x00000000000002b0 .rdata$.refptr._a +[675](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000198 __imp__amsg_exit +[718](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000002b0 .refptr._a -C:\Users\qiand\.bluescript\temp\dist\build>objdump -x temp1.dll | findstr /i "temp0 _a __imp" +C:\Users\qiand\.bluescript\temp\dist\build>objdump -x temp1.dll | findstr /i "_a" 00009198 00b6 _amsg_exit [ 0] +base[ 1] 0000 _a 10 .debug_aranges 00000050 000000033e4ec000 000000033e4ec000 00003400 2**0 @@ -97,51 +22,20 @@ C:\Users\qiand\.bluescript\temp\dist\build>objdump -x temp1.dll | findstr /i "te [349](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 1) 0x0000000000001210 __acrt_iob_func [644](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001b8 __imp_abort [645](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003e4 __lib64_libkernel32_a_iname -[646](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000040 __imp__initterm_e -[649](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a8 __imp__lock [651](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000014 _head_lib64_libmsvcrt_def_a -[652](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001c0 __imp_calloc [657](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003f0 __xl_a [663](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000040 _a -[669](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000140 __imp_DeleteCriticalSection [675](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000198 __imp__amsg_exit -[682](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000208 __imp_gc_init_rootset -[687](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000150 __imp_GetLastError -[689](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001d0 __imp_free [690](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000230 .refptr.__mingw_app_type -[694](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000210 __imp_gc_method_lookup -[696](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000160 __imp_LeaveCriticalSection [703](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000290 .refptr.__xi_a [705](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000001000 __section_alignment__ -[712](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001d8 __imp_memcpy [716](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x000000000000042c __lib64_libmsvcrt_def_a_iname [718](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000002b0 .refptr._a [721](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000000 _head_lib64_libkernel32_a -[729](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000148 __imp_EnterCriticalSection -[736](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000068 __imp__register_onexit_function -[740](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001e8 __imp_strlen [741](sec -1)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000200 __file_alignment__ -[742](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000158 __imp_InitializeCriticalSection -[743](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001e0 __imp_realloc -[745](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001f8 __imp_vfprintf -[751](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000070 __imp__initialize_onexit_table [752](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003e0 __xi_a -[753](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000168 __imp_Sleep [756](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000003d0 __xc_a [760](sec 1)(fl 0x00)(ty 20)(scl 2) (nx 0) 0x00000000000013b8 _amsg_exit -[761](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000170 __imp_TlsGetValue -[762](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000060 __imp__execute_onexit_table -[763](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001c8 __imp_fprintf -[765](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000178 __imp_VirtualProtect -[766](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 __imp_global_rootset0 -[769](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000180 __imp_VirtualQuery -[770](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001a0 __imp__initterm -[772](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000190 __imp___iob_func -[775](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001f0 __imp_strncmp -[776](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000218 __imp_gc_root_set_head [777](sec 2)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000050 __imp___acrt_iob_func -[786](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x00000000000001b0 __imp__unlock [788](sec 3)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000270 .refptr.__xc_a -[792](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000220 __imp_global_rootset0 -[796](sec 8)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000218 __imp_gc_root_set_head -[801](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000080 __mingw_app_type \ No newline at end of file +[801](sec 6)(fl 0x00)(ty 0)(scl 2) (nx 0) 0x0000000000000080 __mingw_app_type From a1b32e574f11a0e943e9f5ae541a6cba0acd757a Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 18:56:28 +0900 Subject: [PATCH 28/33] Fixing link bugs for windows. --- .../compiler/board-toolchain/host-toolchain.ts | 12 ++++++++---- lang/src/compiler/package.ts | 17 +++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/lang/src/compiler/board-toolchain/host-toolchain.ts b/lang/src/compiler/board-toolchain/host-toolchain.ts index c76282e7..cebdcbe0 100644 --- a/lang/src/compiler/board-toolchain/host-toolchain.ts +++ b/lang/src/compiler/board-toolchain/host-toolchain.ts @@ -44,6 +44,11 @@ export abstract class HostToolchain

implements BoardToolchain archiveFiles.push(await this.compilePackage(project.mainPackage)); const sharedLib = await this.link(project, archiveFiles, entryPoints); this.generatedSharedLibs.push(sharedLib); + // Prevent the main package's generated C from being recompiled into the + // next (fragment) shared library. Otherwise each fragment statically + // redefines all prior globals, which breaks cross-fragment variable + // access on platforms without symbol interposition (e.g. Windows). + project.mainPackage.removeGeneratedCFiles(); return { filePath: sharedLib, entryNames: entryPoints.map(name => ({isMain: name === project.mainPackage.name, name})), @@ -56,11 +61,13 @@ export abstract class HostToolchain

implements BoardToolchain if (!this.compiledPackages.has(pkg.name)) { archiveFiles.push(await this.compilePackage(pkg)); this.compiledPackages.add(pkg.name); + pkg.removeGeneratedCFiles(); } } archiveFiles.push(await this.compilePackage(project.mainPackage)); const sharedLib = await this.link(project, archiveFiles, entryPoints); this.generatedSharedLibs.push(sharedLib); + project.mainPackage.removeGeneratedCFiles(); return { filePath: sharedLib, entryNames: entryPoints.map(name => ({isMain: name === project.mainPackage.name, name})), @@ -165,10 +172,7 @@ export class HostWindowsToolchain extends HostToolchain { '-Wl,--enable-auto-import', '-Wl,--enable-runtime-pseudo-reloc' ]; - // TEMPORARY (diagnostic): print the exact linker invocation and - // surface gcc/ld stdout+stderr while debugging cross-DLL data sharing. - console.log('[bs][win-link]', this.config.compilerToolchain.gcc, args.join(' ')); - await executeCommand(this.config.compilerToolchain.gcc, args, undefined, true, true); + await executeCommand(this.config.compilerToolchain.gcc, args); return outputFile; } catch (error) { throw new Error(`Failed to link: ${getErrorMessage(error)}`, { cause: error }); diff --git a/lang/src/compiler/package.ts b/lang/src/compiler/package.ts index 527e0e8f..4e6b7c1e 100644 --- a/lang/src/compiler/package.ts +++ b/lang/src/compiler/package.ts @@ -122,6 +122,23 @@ export class Package { fs.writeFileSync(filePath, data); return filePath; } + + // Removes the transpiler-generated C files (bs_*.c) from the dist dir. + // Used for incremental (REPL) builds so that each fragment is compiled into + // a shared library containing only its own object, referencing symbols of + // previous fragments from their shared libraries instead of statically + // redefining them. Native (user-provided) C files are left untouched. + removeGeneratedCFiles() { + if (!fs.existsSync(this.resolvedDistDir)) { + return; + } + const generatedCFilePattern = /^bs_.*\.c$/; + this.walkFiles(this.resolvedDistDir, (name, fullPath) => { + if (generatedCFilePattern.test(name)) { + fs.rmSync(fullPath, { force: true }); + } + }, [this.resolvedBuildDir]); + } protected walkFiles(dir: string, handler: (name: string, fullPath: string) => void, ignorDirs?: string[]) { for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { From c94530c184e51966f746e3c1a61495d9eaaa35d2 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 19:53:40 +0900 Subject: [PATCH 29/33] Fixing unit tests. --- cli/tests/commands/board/setup.test.ts | 4 ++-- cli/tests/commands/board/update.test.ts | 5 +++-- cli/tests/commands/global-env-helper.ts | 11 +++++++++-- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cli/tests/commands/board/setup.test.ts b/cli/tests/commands/board/setup.test.ts index ccf0f1ea..b4cb9cbc 100644 --- a/cli/tests/commands/board/setup.test.ts +++ b/cli/tests/commands/board/setup.test.ts @@ -9,7 +9,7 @@ import { mockedLogger, mockProcessExit, } from '../mock-helpers'; -import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings, getTestRuntimeDir, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings, getTestRuntimeDir, getEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { HostDarwinEnv } from '../../../src/platforms/board-env/host-env'; import * as path from 'path'; @@ -38,7 +38,7 @@ function mockEsp32ShellCommands(options: { } throw new Error('not found'); } - if (cmd === 'python3' && args.some((arg: string) => arg.includes('export'))) { + if (cmd === getEsp32IdfToolsExportPythonCommand() && args.some((arg: string) => arg.includes('export'))) { return mockXtensaGccFromIdfToolsExport(); } if (cmd === 'python' && args[1]?.includes('import sys')) { diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index 4c0d4c61..f977bbfc 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,12 +1,13 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; -import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, getEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { mockedDownloadAndUnzip, mockedSimpleExec, mockedExecWithLog, mockedExecShell, mockProcessExit } from '../mock-helpers'; import * as fs from '../../../src/core/fs'; function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { + const pythonCmd = getEsp32IdfToolsExportPythonCommand(); mockedSimpleExec.mockImplementation(async (cmd, args) => { - if (cmd === 'python3' && args.some((arg: string) => arg.includes('export'))) { + if (cmd === pythonCmd && args.some((arg: string) => arg.includes('export'))) { return mockXtensaGccFromIdfToolsExport(); } return ''; diff --git a/cli/tests/commands/global-env-helper.ts b/cli/tests/commands/global-env-helper.ts index bc268551..58e4b915 100644 --- a/cli/tests/commands/global-env-helper.ts +++ b/cli/tests/commands/global-env-helper.ts @@ -112,14 +112,21 @@ export function setupGlobalEnvWithEsp32(isOldVersion = false, isEspIdfOldVersion fs.makeDir(getTestRuntimeDir()); } +export function getEsp32IdfToolsExportPythonCommand(): string { + return os.platform() === 'win32' ? 'python' : 'python3'; +} + export function mockXtensaGccFromIdfToolsExport(): string { + const isWin = os.platform() === 'win32'; + const gccName = isWin ? 'xtensa-esp32-elf-gcc.exe' : 'xtensa-esp32-elf-gcc'; + const pathSep = isWin ? ';' : ':'; const gccDir = path.join( GLOBAL_SETTINGS.BLUESCRIPT_DIR, '.espressif/tools/xtensa-esp-elf/bin', ); fs.makeDir(gccDir); - fs.writeFile(path.join(gccDir, 'xtensa-esp32-elf-gcc'), ''); - return `PATH=${gccDir}:/xtensa-esp-elf-gdb/bin`; + fs.writeFile(path.join(gccDir, gccName), ''); + return `PATH=${gccDir}${pathSep}/xtensa-esp-elf-gdb/bin`; } export function getGlobalConfig(): any { From 84665c65e724aaaf96c796e72bb124af7db0f78b Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Sun, 5 Jul 2026 21:00:13 +0900 Subject: [PATCH 30/33] Fix python command usage. --- cli/src/commands/board/setup/esp32-darwin.ts | 21 +++++++++++++------ cli/src/commands/board/setup/esp32-windows.ts | 17 +++++++++++---- cli/src/commands/board/update.ts | 5 +++-- cli/src/config/global-config.ts | 1 + cli/src/platforms/board-env/esp32-env.ts | 10 ++++----- cli/tests/commands/board/setup.test.ts | 14 ++++++------- cli/tests/commands/board/update.test.ts | 5 ++--- cli/tests/commands/global-env-helper.ts | 5 +++++ cli/tests/config/global-config.test.ts | 1 + 9 files changed, 52 insertions(+), 27 deletions(-) diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts index 8e72a8be..fcdfc90b 100644 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ b/cli/src/commands/board/setup/esp32-darwin.ts @@ -1,5 +1,5 @@ import { SetupHandler } from "./base"; -import { execWithLog, simpleExec } from '../../../core/command-exec'; +import { execWithLog } from '../../../core/command-exec'; import { skip } from "../../../core/logger"; import * as path from 'path'; import { BoardName } from "../../../config/board-utils"; @@ -10,6 +10,7 @@ import { isPackageInstalledOnUnix, isPythonVersionGreaterThan3 } from "./utils"; export class Esp32DarwinSetupHandler extends SetupHandler { boardName: BoardName = "esp32"; boardEnv: Esp32DarwinEnv; + pythonCommand?: string; constructor() { super(); @@ -18,7 +19,7 @@ export class Esp32DarwinSetupHandler extends SetupHandler { loadBoardSetupSteps(): void { this.setupSteps.push({ - description: "Verify that git, python3 and brew are installed.", + description: "Verify that git, python3, brew and make are installed.", actionMessage: "Verifying that git, python3 and brew are installed...", action: this.verifyPrerequisitsInstalledStep.bind(this), }); @@ -40,7 +41,7 @@ export class Esp32DarwinSetupHandler extends SetupHandler { } async setBoardConfig() { - const xtensaGccDir = await this.boardEnv.getXtensaGccDir(); + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); this.globalConfigHandler.updateBoardConfig(this.boardName, { idfVersion: this.boardEnv.idfVersion, rootDir: this.boardEnv.espRootDir, @@ -49,7 +50,8 @@ export class Esp32DarwinSetupHandler extends SetupHandler { gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), - make: 'make' + make: 'make', + python: this.pythonCommand! }, }); } @@ -61,8 +63,15 @@ export class Esp32DarwinSetupHandler extends SetupHandler { if (!await isPackageInstalledOnUnix("brew")) { throw new Error("Cannot find brew command. Please install Homebrew and try again."); } - if (!(await isPythonVersionGreaterThan3()) && !(await isPackageInstalledOnUnix('python3'))) { - throw new Error("Cannot find python3. Please install Python3 and try again."); + if (await isPythonVersionGreaterThan3()) { + this.pythonCommand = 'python'; + } else if (await isPackageInstalledOnUnix('python3')) { + this.pythonCommand = 'python3'; + } else { + throw new Error("Cannot find Python3. Please install Python3 and try again."); + } + if (!await isPackageInstalledOnUnix("make")) { + throw new Error("Cannot find make command. Please install make and try again."); } } diff --git a/cli/src/commands/board/setup/esp32-windows.ts b/cli/src/commands/board/setup/esp32-windows.ts index 59726bb8..bfc99278 100644 --- a/cli/src/commands/board/setup/esp32-windows.ts +++ b/cli/src/commands/board/setup/esp32-windows.ts @@ -8,6 +8,7 @@ export class Esp32WindowsSetupHandler extends SetupHandler { boardName: BoardName = "esp32"; boardEnv: Esp32WindowsEnv; makeCommand?: string; + pythonCommand?: string; constructor() { super(); @@ -33,7 +34,7 @@ export class Esp32WindowsSetupHandler extends SetupHandler { } async setBoardConfig() { - const xtensaGccDir = await this.boardEnv.getXtensaGccDir(); + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); this.globalConfigHandler.updateBoardConfig(this.boardName, { idfVersion: this.boardEnv.idfVersion, rootDir: this.boardEnv.espRootDir, @@ -42,17 +43,25 @@ export class Esp32WindowsSetupHandler extends SetupHandler { gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), - make: this.makeCommand! + make: this.makeCommand!, + python: this.pythonCommand! }, }); } private async verifyPrerequisitsInstalledStep() { + // git command if (!await isPackageInstalledOnWindows("git")) { throw new Error("Cannot find git command. Please install git and try again."); } - if (!(await isPythonVersionGreaterThan3()) && !(await isPackageInstalledOnWindows('python3'))) { - throw new Error("Cannot find python3. Please install Python3 and try again."); + + // python command + if (await isPythonVersionGreaterThan3()) { + this.pythonCommand = 'python'; + } else if (await isPackageInstalledOnWindows('python3')) { + this.pythonCommand = 'python3'; + } else { + throw new Error("Cannot find Python3. Please install Python3 and try again."); } // make command diff --git a/cli/src/commands/board/update.ts b/cli/src/commands/board/update.ts index 512a8013..c5e75cf5 100644 --- a/cli/src/commands/board/update.ts +++ b/cli/src/commands/board/update.ts @@ -115,7 +115,7 @@ class UpdateHandler extends CommandHandler { await esp32Env.cloneEspIdf(); await esp32Env.runEspIdfInstallScript(); - const xtensaGccDir = await esp32Env.getXtensaGccDir(); + const xtensaGccDir = await esp32Env.getXtensaGccDir(boardConfig.toolchain.python); this.globalConfigHandler.updateBoardConfig('esp32', { idfVersion: esp32Env.idfVersion, rootDir: esp32Env.espRootDir, @@ -124,7 +124,8 @@ class UpdateHandler extends CommandHandler { gcc: path.join(xtensaGccDir, esp32Env.xtensaGccFileName), ar: path.join(xtensaGccDir, esp32Env.xtensaArFileName), ld: path.join(xtensaGccDir, esp32Env.xtensaLdFileName), - make: boardConfig.toolchain.make + make: boardConfig.toolchain.make, + python: boardConfig.toolchain.python }, }); } diff --git a/cli/src/config/global-config.ts b/cli/src/config/global-config.ts index c4931c63..7b77906b 100644 --- a/cli/src/config/global-config.ts +++ b/cli/src/config/global-config.ts @@ -13,6 +13,7 @@ const esp32BoardSchema = z.object({ ar: z.string(), ld: z.string(), make: z.string(), + python: z.string(), }), }); diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 9621ec3c..5eb79227 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -21,7 +21,7 @@ export abstract class Esp32Env extends BoardEnv { abstract get xtensaLdFileName(): string; abstract runEspIdfInstallScript(): Promise; - abstract getXtensaGccDir(): Promise; + abstract getXtensaGccDir(pythonCommand: string): Promise; async cloneEspIdf() { await execWithLog( @@ -98,10 +98,10 @@ export class Esp32DarwinEnv extends Esp32Env { await execShell(`bash ${JSON.stringify(this.idfInstallShFile)}`); } - async getXtensaGccDir() { + async getXtensaGccDir(pythonCommand: string) { try { const stdout = await simpleExec( - 'python3', + pythonCommand, [this.idfToolsPyFile, 'export', '--format', 'key-value'], ); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ':'); @@ -123,10 +123,10 @@ export class Esp32WindowsEnv extends Esp32Env { await execShell(this.idfInstallBatFile); } - async getXtensaGccDir() { + async getXtensaGccDir(pythonCommand: string) { try { const stdout = await simpleExec( - 'python', + pythonCommand, [this.idfToolsPyFile, 'export', '--format', 'key-value'], ); return super.resolveXtensaGccDirFromExport(stdout, 'PATH', ';'); diff --git a/cli/tests/commands/board/setup.test.ts b/cli/tests/commands/board/setup.test.ts index b4cb9cbc..ef6637d5 100644 --- a/cli/tests/commands/board/setup.test.ts +++ b/cli/tests/commands/board/setup.test.ts @@ -9,7 +9,7 @@ import { mockedLogger, mockProcessExit, } from '../mock-helpers'; -import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings, getTestRuntimeDir, getEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { deleteGlobalEnv, getGlobalConfig, setupDefaultGlobalEnv, setupEmpyGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, spyGlobalSettings, getTestRuntimeDir, isEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { HostDarwinEnv } from '../../../src/platforms/board-env/host-env'; import * as path from 'path'; @@ -38,7 +38,7 @@ function mockEsp32ShellCommands(options: { } throw new Error('not found'); } - if (cmd === getEsp32IdfToolsExportPythonCommand() && args.some((arg: string) => arg.includes('export'))) { + if (isEsp32IdfToolsExportPythonCommand(cmd) && args.some((arg: string) => arg.includes('export'))) { return mockXtensaGccFromIdfToolsExport(); } if (cmd === 'python' && args[1]?.includes('import sys')) { @@ -148,7 +148,7 @@ describe('board setup command', () => { // --- Arrange --- mockedInquirer.prompt.mockResolvedValue({ proceed: true }); mockEsp32ShellCommands({ - whichFound: ['brew', 'git'], + whichFound: ['brew', 'git', 'make'], }); setupEmpyGlobalEnv(); @@ -188,7 +188,7 @@ describe('board setup command', () => { mockedInquirer.prompt.mockResolvedValue({ proceed: true }); setupDefaultGlobalEnv(); mockEsp32ShellCommands({ - whichFound: ['brew', 'git'], + whichFound: ['brew', 'git', 'make'], }); // --- Act --- @@ -210,7 +210,7 @@ describe('board setup command', () => { setupEmpyGlobalEnv(); mockedInquirer.prompt.mockResolvedValue({ proceed: true }); mockEsp32ShellCommands({ - whichFound: ['brew', 'git', 'cmake', 'ninja', 'dfu-util', 'ccache'], + whichFound: ['brew', 'git', 'cmake', 'ninja', 'dfu-util', 'ccache', 'make'], }); // --- Act --- @@ -226,7 +226,7 @@ describe('board setup command', () => { mockedInquirer.prompt.mockResolvedValue({ proceed: true }); const exitSpy = mockProcessExit(); mockEsp32ShellCommands({ - whichFound: ['brew', 'git'], + whichFound: ['brew', 'git', 'make'], pythonMajor: '2', }); @@ -234,7 +234,7 @@ describe('board setup command', () => { await handleSetupCommand('esp32'); // --- Assert --- - expect(mockedLogger.showError).toHaveBeenCalledWith(new Error('Cannot find python3. Please install Python3 and try again.')); + expect(mockedLogger.showError).toHaveBeenCalledWith(new Error('Cannot find Python3. Please install Python3 and try again.')); expect(process.exit).toHaveBeenCalledWith(1); exitSpy.mockRestore(); }) diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index f977bbfc..88e336b1 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,13 +1,12 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; -import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, getEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, isEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { mockedDownloadAndUnzip, mockedSimpleExec, mockedExecWithLog, mockedExecShell, mockProcessExit } from '../mock-helpers'; import * as fs from '../../../src/core/fs'; function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { - const pythonCmd = getEsp32IdfToolsExportPythonCommand(); mockedSimpleExec.mockImplementation(async (cmd, args) => { - if (cmd === pythonCmd && args.some((arg: string) => arg.includes('export'))) { + if (isEsp32IdfToolsExportPythonCommand(cmd) && args.some((arg: string) => arg.includes('export'))) { return mockXtensaGccFromIdfToolsExport(); } return ''; diff --git a/cli/tests/commands/global-env-helper.ts b/cli/tests/commands/global-env-helper.ts index 58e4b915..030de6c8 100644 --- a/cli/tests/commands/global-env-helper.ts +++ b/cli/tests/commands/global-env-helper.ts @@ -104,6 +104,7 @@ export function setupGlobalEnvWithEsp32(isOldVersion = false, isEspIdfOldVersion ar: '/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-ar', ld: '/.espressif/tools/xtensa-esp-elf/esp-14.2.0_20241119/xtensa-esp-elf/bin/xtensa-esp32-elf-ld', make: 'make', + python: 'python' }, } } @@ -116,6 +117,10 @@ export function getEsp32IdfToolsExportPythonCommand(): string { return os.platform() === 'win32' ? 'python' : 'python3'; } +export function isEsp32IdfToolsExportPythonCommand(cmd: string): boolean { + return cmd === 'python' || cmd === 'python3'; +} + export function mockXtensaGccFromIdfToolsExport(): string { const isWin = os.platform() === 'win32'; const gccName = isWin ? 'xtensa-esp32-elf-gcc.exe' : 'xtensa-esp32-elf-gcc'; diff --git a/cli/tests/config/global-config.test.ts b/cli/tests/config/global-config.test.ts index dba84fb7..81c78381 100644 --- a/cli/tests/config/global-config.test.ts +++ b/cli/tests/config/global-config.test.ts @@ -49,6 +49,7 @@ describe('GlobalConfigHandler', () => { ar: 'ar', ld: 'ld', make: 'make', + python: 'python3', }, } const handler = GlobalConfigHandler.load(); From 412aecb27470a524c5d9caa46c91f8f3f426f5ce Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Mon, 6 Jul 2026 22:06:56 +0900 Subject: [PATCH 31/33] Fix update command. --- cli/README.md | 2 + cli/docs/manual-test.md | 10 +- cli/src/commands/board/flash-runtime.ts | 4 +- cli/src/commands/board/full-clean.ts | 2 +- cli/src/commands/board/list.ts | 4 +- cli/src/commands/board/remove.ts | 4 +- cli/src/commands/board/setup/base.ts | 4 +- cli/src/commands/board/setup/esp32-darwin.ts | 97 ----------- cli/src/commands/board/setup/esp32-windows.ts | 84 ---------- cli/src/commands/board/setup/esp32.ts | 152 ++++++++++++++++++ cli/src/commands/board/setup/host-darwin.ts | 53 ------ cli/src/commands/board/setup/host-windows.ts | 68 -------- cli/src/commands/board/setup/host.ts | 100 ++++++++++++ cli/src/commands/board/setup/index.ts | 6 +- cli/src/commands/board/setup/utils.ts | 32 ---- cli/src/commands/board/update.ts | 98 ++++++----- cli/src/commands/command.ts | 11 +- cli/src/commands/project/check.ts | 4 +- cli/src/commands/project/create.ts | 4 +- cli/src/commands/project/install.ts | 4 +- cli/src/commands/project/run.ts | 4 +- cli/src/commands/project/uninstall.ts | 4 +- cli/src/commands/repl.ts | 4 +- cli/src/config/global-config.ts | 26 ++- cli/src/platforms/board-env/common-env.ts | 44 ++++- cli/src/platforms/board-env/esp32-env.ts | 39 ++++- cli/src/platforms/board-env/host-env.ts | 71 +++++++- cli/tests/commands/board/update.test.ts | 83 +++++++++- cli/tests/integration/host-run-helper.ts | 6 +- 29 files changed, 607 insertions(+), 417 deletions(-) delete mode 100644 cli/src/commands/board/setup/esp32-darwin.ts delete mode 100644 cli/src/commands/board/setup/esp32-windows.ts create mode 100644 cli/src/commands/board/setup/esp32.ts delete mode 100644 cli/src/commands/board/setup/host-darwin.ts delete mode 100644 cli/src/commands/board/setup/host-windows.ts create mode 100644 cli/src/commands/board/setup/host.ts delete mode 100644 cli/src/commands/board/setup/utils.ts diff --git a/cli/README.md b/cli/README.md index 996c40d9..5f6efa83 100644 --- a/cli/README.md +++ b/cli/README.md @@ -32,6 +32,8 @@ npm run test:all # unit + integration **Integration test requirements:** macOS (`cc`) or Windows (MinGW-w64: `gcc`, `mingw32-make`), and the `microcontroller/` tree at the repository root. On first run, tests build `microcontroller/ports/host/build/shell` (or `shell.exe`) and `c-runtime.so` (or `c-runtime.dll`) if missing. Tests are skipped automatically on Linux and other unsupported platforms. +**Supported platforms:** macOS and Windows for `host` and `esp32` board setup. Linux is not supported. On Windows, install the Visual C++ Build Environment before `npm install` (node-gyp), and MinGW-w64 for the host runtime. See [Windows prerequisites](https://csg-tokyo.github.io/bluescript/docs/tutorial/get-started/setup-environment-windows) on the website. + **Integration coverage (14 tests):** - `tests/integration/project/run.host.test.ts` — `project run` on host: normal output, built-in library, functions/variables, local import, local package import, inline C, `.c` / `.h` includes, compile error diff --git a/cli/docs/manual-test.md b/cli/docs/manual-test.md index 426088f6..332a40f2 100644 --- a/cli/docs/manual-test.md +++ b/cli/docs/manual-test.md @@ -39,9 +39,11 @@ Use a clean working directory for project commands (no existing `bsconfig.json` | Profile | OS | Node.js | Additional requirements | | :--- | :--- | :--- | :--- | | **host** | macOS | v18+ (v20+ recommended) | `cc`, `make` | -| **esp32** | macOS | v18+ (v20+ recommended) | ESP32 board, USB cable, Bluetooth enabled | +| **host** | Windows | v18+ (v20+ recommended) | Visual C++ Build Environment (for npm install), MinGW-w64 (`gcc`, `mingw32-make`) | +| **esp32** | macOS | v18+ (v20+ recommended) | Homebrew, Git, Python 3, ESP32 board, USB cable, Bluetooth enabled | +| **esp32** | Windows | v18+ (v20+ recommended) | Visual C++ Build Environment (for npm install), Git, Python 3, `make` or `mingw32-make`, ESP32 board, USB cable, Bluetooth enabled | -> **Note:** The host runtime currently requires **macOS**. ESP32 setup is also macOS-only in the current CLI implementation. +> ESP32 on Windows (setup, flash, BLE `project run`) has been manually verified. Linux is not supported by the CLI. ### Automated integration tests (host) @@ -65,7 +67,7 @@ CLI log output is suppressed during integration runs (`tests/integration-setup.t ## Quick smoke (host only, ~15 min) -Run this before merging most CLI PRs. No hardware required. +Run this before merging most CLI PRs. No hardware required. Run on **macOS** or **Windows** (MinGW-w64 for host). The same steps apply on both platforms. 1. **MT-SMOKE-01** — `bscript -v` prints the expected version 2. **MT-SMOKE-02** — `bscript board list` shows `esp32` and `host` @@ -738,7 +740,7 @@ Jest **unit** tests in `cli/tests/` mock filesystem, network, and device I/O. ** | Area | Unit tests | Integration tests (host, macOS/Windows) | Manual testing still needed | | :--- | :--- | :--- | :--- | -| `board setup` | Handler logic, macOS paths, skip-if-done | — | Real download, ESP-IDF install, host runtime build | +| `board setup` | Handler logic, macOS/Windows paths, skip-if-done | — | Real download, ESP-IDF install, host runtime build | | `board flash-runtime` | ESP32 handler, host rejection, port prompt mocked, `deviceName` passed to build | — | Actual USB flash on hardware; BLE advertised name after flash | | `board remove` / `fullclean` | File removal, prompts mocked | — | Confirm disk state after real removal | | `board update` | Update steps, rollback logic | — | End-to-end after real version bump | diff --git a/cli/src/commands/board/flash-runtime.ts b/cli/src/commands/board/flash-runtime.ts index 4c07335d..3fc04fb3 100644 --- a/cli/src/commands/board/flash-runtime.ts +++ b/cli/src/commands/board/flash-runtime.ts @@ -7,13 +7,13 @@ import { BoardName } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; import { execShell } from '../../core/command-exec'; import chalk from "chalk"; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; import { DEFAULT_DEVICE_NAME } from "../../config/project-config"; const RUNTIME_ESP_PORT_DIR = (runtimeDir: string) => path.join(runtimeDir, 'ports/esp32'); -abstract class FlashRuntimeHandler extends CommandHandler { +abstract class FlashRuntimeHandler extends CommandHandlerWithUpdateCheck { abstract isSetup(): boolean; abstract flashRuntime(port: string, deviceName?: string): Promise; diff --git a/cli/src/commands/board/full-clean.ts b/cli/src/commands/board/full-clean.ts index 13981cc5..4cb2f3c4 100644 --- a/cli/src/commands/board/full-clean.ts +++ b/cli/src/commands/board/full-clean.ts @@ -7,7 +7,7 @@ import { CommonBoardEnv } from "../../platforms/board-env"; class FullcleanHandler extends CommandHandler { constructor() { - super(false); + super(); } fullclean() { diff --git a/cli/src/commands/board/list.ts b/cli/src/commands/board/list.ts index dc384d68..943256e8 100644 --- a/cli/src/commands/board/list.ts +++ b/cli/src/commands/board/list.ts @@ -2,10 +2,10 @@ import { Command } from "commander"; import chalk from 'chalk'; import { BOARD_NAMES } from "../../config/board-utils"; import { logger } from "../../core/logger"; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; -class ListHandler extends CommandHandler { +class ListHandler extends CommandHandlerWithUpdateCheck { list() { const supportedBoards = BOARD_NAMES; logger.log('Available boards:'); diff --git a/cli/src/commands/board/remove.ts b/cli/src/commands/board/remove.ts index 574b76a4..44ff3b82 100644 --- a/cli/src/commands/board/remove.ts +++ b/cli/src/commands/board/remove.ts @@ -2,11 +2,11 @@ import { Command } from "commander"; import inquirer from 'inquirer'; import { BoardName, isValidBoard } from "../../config/board-utils"; import { logger, runStep } from "../../core/logger"; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; import { BoardEnv, createBoardEnv } from "../../platforms/board-env"; -class RemoveHandler extends CommandHandler { +class RemoveHandler extends CommandHandlerWithUpdateCheck { boardName: BoardName; boardEnv: BoardEnv; diff --git a/cli/src/commands/board/setup/base.ts b/cli/src/commands/board/setup/base.ts index 11286c0b..c4f5dbe7 100644 --- a/cli/src/commands/board/setup/base.ts +++ b/cli/src/commands/board/setup/base.ts @@ -1,6 +1,6 @@ import { runStep, skip } from "../../../core/logger"; import { StepSkip } from "../../../core/logger/step-runner"; -import { CommandHandler } from "../../command"; +import { CommandHandlerWithUpdateCheck } from "../../command"; import { BoardName } from "../../../config/board-utils"; import { CommonBoardEnv } from "../../../platforms/board-env/common-env"; @@ -12,7 +12,7 @@ export interface Step { } -export abstract class SetupHandler extends CommandHandler { +export abstract class SetupHandler extends CommandHandlerWithUpdateCheck { abstract boardName: BoardName; abstract boardEnv: CommonBoardEnv; protected setupSteps: Step[] = []; diff --git a/cli/src/commands/board/setup/esp32-darwin.ts b/cli/src/commands/board/setup/esp32-darwin.ts deleted file mode 100644 index fcdfc90b..00000000 --- a/cli/src/commands/board/setup/esp32-darwin.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { SetupHandler } from "./base"; -import { execWithLog } from '../../../core/command-exec'; -import { skip } from "../../../core/logger"; -import * as path from 'path'; -import { BoardName } from "../../../config/board-utils"; -import { Esp32DarwinEnv } from "../../../platforms/board-env/esp32-env"; -import { isPackageInstalledOnUnix, isPythonVersionGreaterThan3 } from "./utils"; - - -export class Esp32DarwinSetupHandler extends SetupHandler { - boardName: BoardName = "esp32"; - boardEnv: Esp32DarwinEnv; - pythonCommand?: string; - - constructor() { - super(); - this.boardEnv = new Esp32DarwinEnv(); - } - - loadBoardSetupSteps(): void { - this.setupSteps.push({ - description: "Verify that git, python3, brew and make are installed.", - actionMessage: "Verifying that git, python3 and brew are installed...", - action: this.verifyPrerequisitsInstalledStep.bind(this), - }); - this.setupSteps.push({ - description: "Install required packages via brew if they are not installed (cmake, ninja, dfu-util, and ccache).", - actionMessage: "Installing required packages...", - action: this.installRequiredPackagesStep.bind(this), - }); - this.setupSteps.push({ - description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, - actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, - action: this.cloneEspIdfStep.bind(this), - }); - this.setupSteps.push({ - description: "Run ESP-IDF install script.", - actionMessage: "Running ESP-IDF install script...", - action: this.runEspIdfInstallScriptStep.bind(this), - }); - } - - async setBoardConfig() { - const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); - this.globalConfigHandler.updateBoardConfig(this.boardName, { - idfVersion: this.boardEnv.idfVersion, - rootDir: this.boardEnv.espRootDir, - exportFile: this.boardEnv.idfExportFile, - toolchain: { - gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), - ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), - ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), - make: 'make', - python: this.pythonCommand! - }, - }); - } - - private async verifyPrerequisitsInstalledStep() { - if (!await isPackageInstalledOnUnix("git")) { - throw new Error("Cannot find git command. Please install git and try again."); - } - if (!await isPackageInstalledOnUnix("brew")) { - throw new Error("Cannot find brew command. Please install Homebrew and try again."); - } - if (await isPythonVersionGreaterThan3()) { - this.pythonCommand = 'python'; - } else if (await isPackageInstalledOnUnix('python3')) { - this.pythonCommand = 'python3'; - } else { - throw new Error("Cannot find Python3. Please install Python3 and try again."); - } - if (!await isPackageInstalledOnUnix("make")) { - throw new Error("Cannot find make command. Please install make and try again."); - } - } - - private async installRequiredPackagesStep() { - let packages: string[] = []; - if (!(await isPackageInstalledOnUnix('cmake'))) { packages.push('cmake'); } - if (!(await isPackageInstalledOnUnix('ninja'))) { packages.push('ninja'); } - if (!(await isPackageInstalledOnUnix('dfu-util'))) { packages.push('dfu-util'); } - if (!(await isPackageInstalledOnUnix('ccache'))) { packages.push('ccache'); } - if (packages.length === 0) { - return skip('already installed.'); - } - await execWithLog('brew', ['install', ...packages]); - } - - private async cloneEspIdfStep() { - await this.boardEnv.cloneEspIdf(); - } - - private async runEspIdfInstallScriptStep() { - await this.boardEnv.runEspIdfInstallScript(); - } -} \ No newline at end of file diff --git a/cli/src/commands/board/setup/esp32-windows.ts b/cli/src/commands/board/setup/esp32-windows.ts deleted file mode 100644 index bfc99278..00000000 --- a/cli/src/commands/board/setup/esp32-windows.ts +++ /dev/null @@ -1,84 +0,0 @@ -import { SetupHandler } from "./base"; -import * as path from 'path'; -import { BoardName } from "../../../config/board-utils"; -import { Esp32WindowsEnv } from "../../../platforms/board-env/esp32-env"; -import { isPackageInstalledOnWindows, isPythonVersionGreaterThan3 } from "./utils"; - -export class Esp32WindowsSetupHandler extends SetupHandler { - boardName: BoardName = "esp32"; - boardEnv: Esp32WindowsEnv; - makeCommand?: string; - pythonCommand?: string; - - constructor() { - super(); - this.boardEnv = new Esp32WindowsEnv(); - } - - loadBoardSetupSteps(): void { - this.setupSteps.push({ - description: "Verify that git, python3 and make are installed.", - actionMessage: "Verifying that git and python3 are installed...", - action: this.verifyPrerequisitsInstalledStep.bind(this), - }); - this.setupSteps.push({ - description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, - actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, - action: this.cloneEspIdfStep.bind(this), - }); - this.setupSteps.push({ - description: "Run ESP-IDF install script.", - actionMessage: "Running ESP-IDF install script...", - action: this.runEspIdfInstallScriptStep.bind(this), - }); - } - - async setBoardConfig() { - const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); - this.globalConfigHandler.updateBoardConfig(this.boardName, { - idfVersion: this.boardEnv.idfVersion, - rootDir: this.boardEnv.espRootDir, - exportFile: this.boardEnv.idfExportFile, - toolchain: { - gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), - ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), - ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), - make: this.makeCommand!, - python: this.pythonCommand! - }, - }); - } - - private async verifyPrerequisitsInstalledStep() { - // git command - if (!await isPackageInstalledOnWindows("git")) { - throw new Error("Cannot find git command. Please install git and try again."); - } - - // python command - if (await isPythonVersionGreaterThan3()) { - this.pythonCommand = 'python'; - } else if (await isPackageInstalledOnWindows('python3')) { - this.pythonCommand = 'python3'; - } else { - throw new Error("Cannot find Python3. Please install Python3 and try again."); - } - - // make command - if (await isPackageInstalledOnWindows('make')) { - this.makeCommand = 'make'; - } else if (await isPackageInstalledOnWindows('mingw32-make')) { - this.makeCommand = 'mingw32-make'; - } else { - throw new Error("Cannot find make or mingw32-make command. Please install make or mingw32-make and try again."); - } - } - - private async cloneEspIdfStep() { - await this.boardEnv.cloneEspIdf(); - } - - private async runEspIdfInstallScriptStep() { - await this.boardEnv.runEspIdfInstallScript(); - } -} \ No newline at end of file diff --git a/cli/src/commands/board/setup/esp32.ts b/cli/src/commands/board/setup/esp32.ts new file mode 100644 index 00000000..03f846ae --- /dev/null +++ b/cli/src/commands/board/setup/esp32.ts @@ -0,0 +1,152 @@ +import { SetupHandler } from "./base"; +import { execWithLog } from '../../../core/command-exec'; +import { skip } from "../../../core/logger"; +import * as path from 'path'; +import { BoardName } from "../../../config/board-utils"; +import { Esp32DarwinEnv, Esp32WindowsEnv } from "../../../platforms/board-env/esp32-env"; + + +export class Esp32DarwinSetupHandler extends SetupHandler { + boardName: BoardName = "esp32"; + boardEnv: Esp32DarwinEnv; + pythonCommand?: string; + makeCommand?: string; + + constructor() { + super(); + this.boardEnv = new Esp32DarwinEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that git, python3, brew and make are installed.", + actionMessage: "Verifying that git, python3 and brew are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: "Install required packages via brew if they are not installed (cmake, ninja, dfu-util, and ccache).", + actionMessage: "Installing required packages...", + action: this.installRequiredPackagesStep.bind(this), + }); + this.setupSteps.push({ + description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, + action: this.cloneEspIdfStep.bind(this), + }); + this.setupSteps.push({ + description: "Run ESP-IDF install script.", + actionMessage: "Running ESP-IDF install script...", + action: this.runEspIdfInstallScriptStep.bind(this), + }); + } + + async setBoardConfig() { + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); + this.globalConfigHandler.updateBoardConfig(this.boardName, { + idfVersion: this.boardEnv.idfVersion, + rootDir: this.boardEnv.espRootDir, + exportFile: this.boardEnv.idfExportFile, + toolchain: { + gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), + ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), + ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), + make: this.makeCommand!, + python: this.pythonCommand! + }, + }); + } + + private async verifyPrerequisitsInstalledStep() { + if (!await this.boardEnv.isPackageInstalled("git")) { + throw new Error("Cannot find git command. Please install git and try again."); + } + if (!await this.boardEnv.isPackageInstalled("brew")) { + throw new Error("Cannot find brew command. Please install Homebrew and try again."); + } + this.pythonCommand = await this.boardEnv.getPythonCommand(); + this.makeCommand = await this.boardEnv.getMakeCommand(); + } + + private async installRequiredPackagesStep() { + let packages: string[] = []; + if (!(await this.boardEnv.isPackageInstalled('cmake'))) { packages.push('cmake'); } + if (!(await this.boardEnv.isPackageInstalled('ninja'))) { packages.push('ninja'); } + if (!(await this.boardEnv.isPackageInstalled('dfu-util'))) { packages.push('dfu-util'); } + if (!(await this.boardEnv.isPackageInstalled('ccache'))) { packages.push('ccache'); } + if (packages.length === 0) { + return skip('already installed.'); + } + await execWithLog('brew', ['install', ...packages]); + } + + private async cloneEspIdfStep() { + await this.boardEnv.cloneEspIdf(); + } + + private async runEspIdfInstallScriptStep() { + await this.boardEnv.runEspIdfInstallScript(); + } +} + +export class Esp32WindowsSetupHandler extends SetupHandler { + boardName: BoardName = "esp32"; + boardEnv: Esp32WindowsEnv; + makeCommand?: string; + pythonCommand?: string; + + constructor() { + super(); + this.boardEnv = new Esp32WindowsEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that git, python3 and make are installed.", + actionMessage: "Verifying that git and python3 are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: `Clone ESP-IDF ${this.boardEnv.idfVersion} from ${this.boardEnv.idfGitRepo}.`, + actionMessage: `Cloning ESP-IDF ${this.boardEnv.idfVersion}... It may take a while.`, + action: this.cloneEspIdfStep.bind(this), + }); + this.setupSteps.push({ + description: "Run ESP-IDF install script.", + actionMessage: "Running ESP-IDF install script...", + action: this.runEspIdfInstallScriptStep.bind(this), + }); + } + + async setBoardConfig() { + const xtensaGccDir = await this.boardEnv.getXtensaGccDir(this.pythonCommand!); + this.globalConfigHandler.updateBoardConfig(this.boardName, { + idfVersion: this.boardEnv.idfVersion, + rootDir: this.boardEnv.espRootDir, + exportFile: this.boardEnv.idfExportFile, + toolchain: { + gcc: path.join(xtensaGccDir, this.boardEnv.xtensaGccFileName), + ar: path.join(xtensaGccDir, this.boardEnv.xtensaArFileName), + ld: path.join(xtensaGccDir, this.boardEnv.xtensaLdFileName), + make: this.makeCommand!, + python: this.pythonCommand! + }, + }); + } + + private async verifyPrerequisitsInstalledStep() { + // git command + if (!await this.boardEnv.isPackageInstalled("git")) { + throw new Error("Cannot find git command. Please install git and try again."); + } + this.pythonCommand = await this.boardEnv.getPythonCommand(); + this.makeCommand = await this.boardEnv.getMakeCommand(); + } + + private async cloneEspIdfStep() { + await this.boardEnv.cloneEspIdf(); + } + + private async runEspIdfInstallScriptStep() { + await this.boardEnv.runEspIdfInstallScript(); + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-darwin.ts b/cli/src/commands/board/setup/host-darwin.ts deleted file mode 100644 index 6ef2b9c2..00000000 --- a/cli/src/commands/board/setup/host-darwin.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { SetupHandler } from "./base"; -import { BoardName } from "../../../config/board-utils"; -import { HostDarwinEnv } from "../../../platforms/board-env/host-env"; -import { isPackageInstalledOnUnix } from "./utils"; - - -export class HostDarwinSetupHandler extends SetupHandler { - boardName: BoardName = 'host'; - boardEnv: HostDarwinEnv; - - constructor() { - super(); - this.boardEnv = new HostDarwinEnv(); - } - - loadBoardSetupSteps(): void { - this.setupSteps.push({ - description: "Verify that cc and make are installed.", - actionMessage: "Verifying that cc and make are installed...", - action: this.verifyPrerequisitsInstalledStep.bind(this), - }); - this.setupSteps.push({ - description: "Build host runtime.", - actionMessage: "Building host runtime...", - action: this.buildHostRuntimeStep.bind(this), - }); - } - - async setBoardConfig() { - this.globalConfigHandler.updateBoardConfig('host', { - rootDir: this.boardEnv.hostRootDir, - shellFile: this.boardEnv.shellFile, - toolchain: { - gcc: 'cc', - ar: 'ar', - make: 'make' - }, - }) - } - - private async verifyPrerequisitsInstalledStep() { - if (!await isPackageInstalledOnUnix("cc")) { - throw new Error("Cannot find cc command. Please install cc and try again."); - } - if (!await isPackageInstalledOnUnix("make")) { - throw new Error("Cannot find make command. Please install make and try again."); - } - } - - private async buildHostRuntimeStep() { - await this.boardEnv.buildHostRuntime(); - } -} \ No newline at end of file diff --git a/cli/src/commands/board/setup/host-windows.ts b/cli/src/commands/board/setup/host-windows.ts deleted file mode 100644 index 6c1e644c..00000000 --- a/cli/src/commands/board/setup/host-windows.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { SetupHandler } from "./base"; -import { simpleExec } from '../../../core/command-exec'; -import { BoardName } from "../../../config/board-utils"; -import { HostWindowsEnv } from "../../../platforms/board-env/host-env"; -import { isPackageInstalledOnWindows } from "./utils"; - - -export class HostWindowsSetupHandler extends SetupHandler { - boardName: BoardName = 'host'; - boardEnv: HostWindowsEnv; - - constructor() { - super(); - this.boardEnv = new HostWindowsEnv(); - } - - loadBoardSetupSteps(): void { - this.setupSteps.push({ - description: "Verify that MinGW is installed.", - actionMessage: "Verifying that MinGW is installed...", - action: this.verifyMingwIsInstalledStep.bind(this), - }); - this.setupSteps.push({ - description: "Build host runtime.", - actionMessage: "Building host runtime...", - action: this.buildHostRuntimeStep.bind(this), - }); - } - - async setBoardConfig() { - this.globalConfigHandler.updateBoardConfig('host', { - rootDir: this.boardEnv.hostRootDir, - shellFile: this.boardEnv.shellFile, - toolchain: { - gcc: 'gcc', - ar: 'ar', - make: 'mingw32-make' - }, - }) - } - - private async verifyMingwIsInstalledStep() { - if (await isPackageInstalledOnWindows('gcc')) { - if (!(await this.isMingwGccAvailable())) { - throw new Error("gcc is not a MinGW compiler. Please install MinGW-w64 and add it to PATH."); - } - } else { - throw new Error("Cannot find gcc command. Please install MinGW-w64 and add it to PATH."); - } - } - - private async isMingwGccAvailable(): Promise { - const machine = await this.getGccTargetMachine(); - return machine?.includes('mingw') ?? false; - } - - private async getGccTargetMachine(): Promise { - try { - return (await simpleExec('gcc', ['-dumpmachine'])).trim(); - } catch { - return undefined; - } - } - - private async buildHostRuntimeStep() { - await this.boardEnv.buildHostRuntime(); - } -} \ No newline at end of file diff --git a/cli/src/commands/board/setup/host.ts b/cli/src/commands/board/setup/host.ts new file mode 100644 index 00000000..1b930b81 --- /dev/null +++ b/cli/src/commands/board/setup/host.ts @@ -0,0 +1,100 @@ +import { SetupHandler } from "./base"; +import { BoardName } from "../../../config/board-utils"; +import { HostDarwinEnv, HostWindowsEnv } from "../../../platforms/board-env/host-env"; + + +export class HostDarwinSetupHandler extends SetupHandler { + boardName: BoardName = 'host'; + boardEnv: HostDarwinEnv; + gccCommand?: string; + arCommand?: string; + makeCommand?: string; + + constructor() { + super(); + this.boardEnv = new HostDarwinEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that cc and make are installed.", + actionMessage: "Verifying that cc and make are installed...", + action: this.verifyPrerequisitsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: "Build host runtime.", + actionMessage: "Building host runtime...", + action: this.buildHostRuntimeStep.bind(this), + }); + } + + async setBoardConfig() { + this.globalConfigHandler.setBoardConfig('host', { + rootDir: this.boardEnv.hostRootDir, + shellFile: this.boardEnv.shellFile, + toolchain: { + gcc: this.gccCommand!, + ar: this.arCommand!, + make: this.makeCommand! + }, + }) + } + + private async verifyPrerequisitsInstalledStep() { + this.gccCommand = await this.boardEnv.getGccCommand(); + this.arCommand = await this.boardEnv.getArCommand(); + this.makeCommand = await this.boardEnv.getMakeCommand(); + } + + private async buildHostRuntimeStep() { + await this.boardEnv.buildHostRuntime(); + } +} + +export class HostWindowsSetupHandler extends SetupHandler { + boardName: BoardName = 'host'; + boardEnv: HostWindowsEnv; + gccCommand?: string; + arCommand?: string; + makeCommand?: string; + + constructor() { + super(); + this.boardEnv = new HostWindowsEnv(); + } + + loadBoardSetupSteps(): void { + this.setupSteps.push({ + description: "Verify that MinGW is installed.", + actionMessage: "Verifying that MinGW is installed...", + action: this.verifyMingwIsInstalledStep.bind(this), + }); + this.setupSteps.push({ + description: "Build host runtime.", + actionMessage: "Building host runtime...", + action: this.buildHostRuntimeStep.bind(this), + }); + } + + async setBoardConfig() { + this.globalConfigHandler.setBoardConfig('host', { + rootDir: this.boardEnv.hostRootDir, + shellFile: this.boardEnv.shellFile, + toolchain: { + gcc: this.gccCommand!, + ar: this.arCommand!, + make: this.makeCommand! + }, + }); + } + + private async verifyMingwIsInstalledStep() { + this.gccCommand = await this.boardEnv.getGccCommand(); + this.arCommand = await this.boardEnv.getArCommand(); + this.makeCommand = await this.boardEnv.getMakeCommand(); + } + + private async buildHostRuntimeStep() { + await this.boardEnv.buildHostRuntime(); + } +} \ No newline at end of file diff --git a/cli/src/commands/board/setup/index.ts b/cli/src/commands/board/setup/index.ts index e209be40..9570c1df 100644 --- a/cli/src/commands/board/setup/index.ts +++ b/cli/src/commands/board/setup/index.ts @@ -4,10 +4,8 @@ import inquirer from 'inquirer'; import { logger } from "../../../core/logger"; import chalk from "chalk"; import { SetupHandler } from "./base"; -import { Esp32DarwinSetupHandler } from "./esp32-darwin"; -import { HostDarwinSetupHandler } from "./host-darwin"; -import { Esp32WindowsSetupHandler } from "./esp32-windows"; -import { HostWindowsSetupHandler } from "./host-windows"; +import { Esp32DarwinSetupHandler, Esp32WindowsSetupHandler } from "./esp32"; +import { HostDarwinSetupHandler, HostWindowsSetupHandler } from "./host"; function getSetupHandler(board: string): SetupHandler { diff --git a/cli/src/commands/board/setup/utils.ts b/cli/src/commands/board/setup/utils.ts deleted file mode 100644 index 06afe59b..00000000 --- a/cli/src/commands/board/setup/utils.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { simpleExec } from '../../../core/command-exec'; - - -export async function isPackageInstalledOnUnix(name: string) { - try { - await simpleExec('which', [name]); - return true; - } catch { - return false; - } -} - -export async function isPackageInstalledOnWindows(name: string) { - try { - await simpleExec('where.exe', [name]); - return true; - } catch { - return false; - } -} - -export async function isPythonVersionGreaterThan3() { - try { - const result = await simpleExec( - 'python', - ['-c', 'import sys; print(sys.version_info.major)'], - ); - return result.trim() === '3'; - } catch { - return false; - } -} diff --git a/cli/src/commands/board/update.ts b/cli/src/commands/board/update.ts index c5e75cf5..85634deb 100644 --- a/cli/src/commands/board/update.ts +++ b/cli/src/commands/board/update.ts @@ -5,19 +5,43 @@ import { GLOBAL_SETTINGS } from "../../config/constants"; import * as fs from '../../core/fs'; import * as path from 'path'; import { CommonBoardEnv, createBoardEnv, Esp32Env } from "../../platforms/board-env"; -import { Esp32BoardConfig } from "../../config/global-config"; +import { Esp32BoardConfig, GlobalConfig, GlobalConfigHandler } from "../../config/global-config"; +import chalk from "chalk"; class UpdateHandler extends CommandHandler { + private oldGlobalConfig?: GlobalConfig; + private globalConfigHandler: GlobalConfigHandler; private existingRuntimeDir: string | undefined; private existingEspDir: string | undefined; - private existingHostDir: string | undefined; private tmpRuntimeDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-runtime'); private tmpEspDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-esp'); - private tmpHostDir = path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'tmp-host'); constructor() { - super(false); + super(); + const { handler, oldConfig } = this.getOldGlobalConfigAndHandler(); + this.oldGlobalConfig = oldConfig; + this.globalConfigHandler = handler; + } + + private getOldGlobalConfigAndHandler() { + if (!GlobalConfigHandler.isGlobalConfigFileExists()) { + logger.warn("The BlueScript environment is not setup."); + process.exit(1); + } + try { + const handler = GlobalConfigHandler.load(); + const oldConfig = structuredClone(handler.getConfig()); + if (oldConfig.version === GLOBAL_SETTINGS.VM_VERSION) { + logger.warn("Update is not needed."); + process.exit(0); + } + return { handler, oldConfig }; + } catch (error) { + const handler = GlobalConfigHandler.loadEmpty(); + const oldConfig = GlobalConfigHandler.getConfigWithoutCheck(); + return { handler, oldConfig }; + } } async update() { @@ -26,17 +50,15 @@ class UpdateHandler extends CommandHandler { await this.updateEsp32Step(); await this.updateHostStep(); this.globalConfigHandler.setVersion(GLOBAL_SETTINGS.VM_VERSION); + this.globalConfigHandler.save(); } catch (error) { // Restore - if (this.existingRuntimeDir) { + if (this.existingRuntimeDir && fs.exists(this.tmpRuntimeDir)) { fs.moveDir(this.tmpRuntimeDir, this.existingRuntimeDir); } - if (this.existingEspDir) { + if (this.existingEspDir && fs.exists(this.tmpEspDir)) { fs.moveDir(this.tmpEspDir, this.existingEspDir); } - if (this.existingHostDir) { - fs.moveDir(this.tmpHostDir, this.existingHostDir); - } throw error; } finally { if (fs.exists(this.tmpRuntimeDir)) { @@ -45,17 +67,12 @@ class UpdateHandler extends CommandHandler { if (fs.exists(this.tmpEspDir)) { fs.removeDir(this.tmpEspDir); } - if (fs.exists(this.tmpHostDir)) { - fs.removeDir(this.tmpHostDir); - } - this.globalConfigHandler.save(); } } private updateRuntimeStep() { return runStep('Updating Runtime...', async () => { - const globalConfig = this.globalConfigHandler.getConfig(); - if (globalConfig.runtimeDir === undefined || globalConfig.version === GLOBAL_SETTINGS.VM_VERSION) { + if (this.oldGlobalConfig?.runtimeDir === undefined) { return skip('not needed'); } await this.updateRuntime(); @@ -64,27 +81,20 @@ class UpdateHandler extends CommandHandler { private updateEsp32Step() { return runStep('Updating the environment for esp32...', async () => { - if (!this.globalConfigHandler.isBoardSetup('esp32')) { + if (!("esp32" in (this.oldGlobalConfig?.boards ?? {}))) { return skip('not setup'); } - const esp32Config = this.globalConfigHandler.getBoardConfig('esp32')!; + const esp32Config = this.oldGlobalConfig?.boards.esp32; const esp32Env = createBoardEnv('esp32'); - if (esp32Config.idfVersion === esp32Env.idfVersion) { - return skip('not needed'); - } await this.updateEsp32(esp32Env, esp32Config); }); } private updateHostStep() { return runStep('Updating the environment for host...', async () => { - if (!this.globalConfigHandler.isBoardSetup('host')) { + if (!("host" in (this.oldGlobalConfig?.boards ?? {}))) { return skip('not setup'); } - const globalConfig = this.globalConfigHandler.getConfig(); - if (globalConfig.runtimeDir === undefined || globalConfig.version === GLOBAL_SETTINGS.VM_VERSION) { - return skip('not needed'); - } await this.updateHost(); }); } @@ -101,22 +111,34 @@ class UpdateHandler extends CommandHandler { private async updateHost() { const hostEnv = createBoardEnv('host'); await hostEnv.buildHostRuntime(); - const boardConfig = this.globalConfigHandler.getBoardConfig('host')!; - this.globalConfigHandler.updateBoardConfig('host', { + const boardConfig = this.oldGlobalConfig?.boards.host; + let gccCommand = boardConfig?.toolchain.gcc ?? await hostEnv.getGccCommand(); + let arCommand = boardConfig?.toolchain.ar ?? await hostEnv.getArCommand(); + let makeCommand = boardConfig?.toolchain.make ??await hostEnv.getMakeCommand(); + this.globalConfigHandler.setBoardConfig('host', { + rootDir: hostEnv.hostRootDir, shellFile: hostEnv.shellFile, - toolchain: boardConfig.toolchain, + toolchain: { + gcc: gccCommand, + ar: arCommand, + make: makeCommand, + }, }); } - private async updateEsp32(esp32Env: Esp32Env, boardConfig: Esp32BoardConfig) { + private async updateEsp32(esp32Env: Esp32Env, boardConfig?: Esp32BoardConfig) { this.existingEspDir = esp32Env.espRootDir; - fs.moveDir(esp32Env.espRootDir, this.tmpEspDir); - esp32Env.refreshBoardRoot(); - await esp32Env.cloneEspIdf(); - await esp32Env.runEspIdfInstallScript(); - const xtensaGccDir = await esp32Env.getXtensaGccDir(boardConfig.toolchain.python); - this.globalConfigHandler.updateBoardConfig('esp32', { + if (boardConfig?.idfVersion !== esp32Env.idfVersion) { + fs.moveDir(esp32Env.espRootDir, this.tmpEspDir); + esp32Env.refreshBoardRoot(); + await esp32Env.cloneEspIdf(); + await esp32Env.runEspIdfInstallScript(); + } + let pythonCommand = boardConfig?.toolchain.python ?? await esp32Env.getPythonCommand(); + let makeCommand = boardConfig?.toolchain.make ?? await esp32Env.getMakeCommand(); + const xtensaGccDir = await esp32Env.getXtensaGccDir(pythonCommand); + this.globalConfigHandler.setBoardConfig('esp32', { idfVersion: esp32Env.idfVersion, rootDir: esp32Env.espRootDir, exportFile: esp32Env.idfExportFile, @@ -124,8 +146,8 @@ class UpdateHandler extends CommandHandler { gcc: path.join(xtensaGccDir, esp32Env.xtensaGccFileName), ar: path.join(xtensaGccDir, esp32Env.xtensaArFileName), ld: path.join(xtensaGccDir, esp32Env.xtensaLdFileName), - make: boardConfig.toolchain.make, - python: boardConfig.toolchain.python + make: makeCommand, + python: pythonCommand }, }); } @@ -143,7 +165,7 @@ export async function handleUpdateCommand() { logger.error(`Failed to update board environments.`); logger.showError(error); - logger.info(`Remove ${GLOBAL_SETTINGS.BLUESCRIPT_DIR} and setup boards one by one.`); + logger.info(`If you cannot update, run ${chalk.yellow('bscript board fullclean')} and setup boards from the beginning.`); process.exit(1); } } diff --git a/cli/src/commands/command.ts b/cli/src/commands/command.ts index 925d6efe..97b5331f 100644 --- a/cli/src/commands/command.ts +++ b/cli/src/commands/command.ts @@ -4,13 +4,14 @@ import chalk from "chalk"; import { GLOBAL_SETTINGS } from "../config/constants"; import * as fs from '../core/fs'; -export abstract class CommandHandler { +export abstract class CommandHandler {} + +export abstract class CommandHandlerWithUpdateCheck extends CommandHandler { protected globalConfigHandler: GlobalConfigHandler; - constructor(checkUpdate = true) { - if (checkUpdate) { - this.checkUpdate(); - } + constructor() { + super(); + this.checkUpdate(); this.globalConfigHandler = GlobalConfigHandler.load(); } diff --git a/cli/src/commands/project/check.ts b/cli/src/commands/project/check.ts index e33748e4..0049e428 100644 --- a/cli/src/commands/project/check.ts +++ b/cli/src/commands/project/check.ts @@ -2,10 +2,10 @@ import { Command } from "commander"; import { logger, runStep } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; import { cwd } from "../../core/command-exec"; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; import { CompilerAdapter, getCompilerAdapter } from "../../platforms"; -class CheckHandler extends CommandHandler { +class CheckHandler extends CommandHandlerWithUpdateCheck { private compilerAdapter: CompilerAdapter; constructor(private projectConfigHandler: ProjectConfigHandler) { diff --git a/cli/src/commands/project/create.ts b/cli/src/commands/project/create.ts index 323363b9..20c43c72 100644 --- a/cli/src/commands/project/create.ts +++ b/cli/src/commands/project/create.ts @@ -7,7 +7,7 @@ import { ProjectConfigHandler } from "../../config/project-config"; import { cwd } from "../../core/command-exec"; import { BOARD_NAMES, BoardName, isValidBoard } from "../../config/board-utils"; import * as fs from '../../core/fs'; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; const ENTRY_FILE_CONTENTS = `console.log("Hello world!");\n`; @@ -16,7 +16,7 @@ const GIT_IGNORE_CONTENTS = `\ **/packages/ `; -class CreateHandler extends CommandHandler { +class CreateHandler extends CommandHandlerWithUpdateCheck { private board: BoardName; private projectRoot: string; private projectConfigHandler: ProjectConfigHandler; diff --git a/cli/src/commands/project/install.ts b/cli/src/commands/project/install.ts index 9e725e46..60b10fd0 100644 --- a/cli/src/commands/project/install.ts +++ b/cli/src/commands/project/install.ts @@ -4,11 +4,11 @@ import { ProjectConfigHandler, PackageSource ,PROJECT_DEFAULT_PATHS } from "../. import { cwd, simpleExec } from "../../core/command-exec"; import * as fs from '../../core/fs'; import * as path from 'path'; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; import { GLOBAL_SETTINGS } from "../../config/constants"; -class InstallationHandler extends CommandHandler { +class InstallationHandler extends CommandHandlerWithUpdateCheck { private projectConfigHandler: ProjectConfigHandler; private projectRootDir: string; private packagesDir: string; diff --git a/cli/src/commands/project/run.ts b/cli/src/commands/project/run.ts index ade82149..19288f14 100644 --- a/cli/src/commands/project/run.ts +++ b/cli/src/commands/project/run.ts @@ -8,13 +8,13 @@ import { logger, ProgramOutput, createBoxedOutput, createConsoleOutput, createWe runStep, LoadStepLogger } from "../../core/logger"; import { ProjectConfigHandler } from "../../config/project-config"; import { cwd, ExecOptions, simpleExec } from "../../core/command-exec"; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; import { BoardRuntime, CompilerAdapter, createPlatformSession } from "../../platforms"; import { CompileError, CompileOutput } from "@bscript/lang"; import { WebSocketConnection } from "../../services/websocket"; import { SerialTaskQueue } from "../../core/serial-task-queue"; -class RunHandler extends CommandHandler { +class RunHandler extends CommandHandlerWithUpdateCheck { protected compiler: CompilerAdapter; protected runtime: BoardRuntime; protected programOutput: ProgramOutput; diff --git a/cli/src/commands/project/uninstall.ts b/cli/src/commands/project/uninstall.ts index 20e25d58..16483a1b 100644 --- a/cli/src/commands/project/uninstall.ts +++ b/cli/src/commands/project/uninstall.ts @@ -4,10 +4,10 @@ import { ProjectConfigHandler, PROJECT_DEFAULT_PATHS } from "../../config/projec import { cwd } from "../../core/command-exec"; import * as fs from '../../core/fs'; import * as path from 'path'; -import { CommandHandler } from "../command"; +import { CommandHandlerWithUpdateCheck } from "../command"; -class UninstallHandler extends CommandHandler { +class UninstallHandler extends CommandHandlerWithUpdateCheck { private projectDir: string; private projectConfigHandler: ProjectConfigHandler; diff --git a/cli/src/commands/repl.ts b/cli/src/commands/repl.ts index dfec3d4c..235f3cd9 100644 --- a/cli/src/commands/repl.ts +++ b/cli/src/commands/repl.ts @@ -6,7 +6,7 @@ import * as path from 'path'; import * as readline from 'readline'; import chalk from "chalk"; import * as fs from '../core/fs'; -import { CommandHandler } from "./command"; +import { CommandHandlerWithUpdateCheck } from "./command"; import { GLOBAL_SETTINGS } from "../config/constants"; import { CompileContext, createPlatformSession } from "../platforms"; import { BoardName } from "../config/board-utils"; @@ -23,7 +23,7 @@ function defaultReplReadlineFactory(): readline.Interface { }); } -class ReplHandler extends CommandHandler { +class ReplHandler extends CommandHandlerWithUpdateCheck { static readonly TEMP_PROJECT_NAME = 'temp'; static get tempProjectDir(): string { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, ReplHandler.TEMP_PROJECT_NAME); diff --git a/cli/src/config/global-config.ts b/cli/src/config/global-config.ts index 7b77906b..9074a870 100644 --- a/cli/src/config/global-config.ts +++ b/cli/src/config/global-config.ts @@ -51,8 +51,8 @@ export class GlobalConfigHandler { } static load() { - if (!fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE)) { - return new GlobalConfigHandler(globalConfigSchema.parse({version: GLOBAL_SETTINGS.VM_VERSION})); + if (!this.isGlobalConfigFileExists()) { + return this.loadEmpty() } try { const fileContent = fs.readFile(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE); @@ -79,6 +79,19 @@ export class GlobalConfigHandler { } } + static loadEmpty() { + return new GlobalConfigHandler(globalConfigSchema.parse({ version: GLOBAL_SETTINGS.VM_VERSION })); + } + + static getConfigWithoutCheck() { + const fileContent = fs.readFile(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE); + return JSON.parse(fileContent) as GlobalConfig; + } + + static isGlobalConfigFileExists() { + return fs.exists(GLOBAL_SETTINGS.BLUESCRIPT_CONFIG_FILE); + } + update(config: Partial) { try { this.config = globalConfigSchema.parse({ @@ -129,6 +142,15 @@ export class GlobalConfigHandler { return this.config.boards?.[boardName]; } + setBoardConfig(boardName: K, boardConfig: BoardConfig[K]) { + this.update({ + boards: { + ...this.config.boards, + [boardName]: boardConfig + } + }); + } + updateBoardConfig(boardName: K, boardConfig: Partial) { const existingBoardConfig = this.config.boards[boardName] ?? {}; const mergedBoardConfig = { diff --git a/cli/src/platforms/board-env/common-env.ts b/cli/src/platforms/board-env/common-env.ts index cea7865e..3890ce81 100644 --- a/cli/src/platforms/board-env/common-env.ts +++ b/cli/src/platforms/board-env/common-env.ts @@ -1,6 +1,7 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from '../../config/constants'; +import { simpleExec } from '../../core/command-exec'; export abstract class BoardEnv { @@ -26,8 +27,12 @@ export abstract class BoardEnv { } abstract removeBoardRoot(): void; - abstract refreshBoardRoot(): void; + abstract isPackageInstalled(name: string): Promise; + + isPythonVersionGreaterThan3(): Promise { + return isPythonVersionGreaterThan3(); + }; async downloadBlueScriptRuntime() { if (fs.exists(this.runtimeDir)) { @@ -50,4 +55,41 @@ export abstract class BoardEnv { export class CommonBoardEnv extends BoardEnv { removeBoardRoot(): void {} refreshBoardRoot(): void {} + async isPackageInstalled(name: string): Promise { + return false; + } + async isPythonVersionGreaterThan3(): Promise { + return false; + } } + +export async function isPackageInstalledOnUnix(name: string) { + try { + await simpleExec('which', [name]); + return true; + } catch { + return false; + } +} + +export async function isPackageInstalledOnWindows(name: string) { + try { + await simpleExec('where.exe', [name]); + return true; + } catch { + return false; + } +} + +export async function isPythonVersionGreaterThan3() { + try { + const result = await simpleExec( + 'python', + ['-c', 'import sys; print(sys.version_info.major)'], + ); + return result.trim() === '3'; + } catch { + return false; + } +} + diff --git a/cli/src/platforms/board-env/esp32-env.ts b/cli/src/platforms/board-env/esp32-env.ts index 5eb79227..702446cd 100644 --- a/cli/src/platforms/board-env/esp32-env.ts +++ b/cli/src/platforms/board-env/esp32-env.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from "../../config/constants"; import { simpleExec, execShell, execWithLog } from '../../core/command-exec'; -import { BoardEnv } from './common-env'; +import { BoardEnv, isPackageInstalledOnUnix, isPackageInstalledOnWindows } from './common-env'; const XTENSA_TOOLCHAIN_DIR = 'xtensa-esp-elf'; const XTENSA_GCC_NAME = 'xtensa-esp32-elf-gcc'; @@ -22,6 +22,7 @@ export abstract class Esp32Env extends BoardEnv { abstract runEspIdfInstallScript(): Promise; abstract getXtensaGccDir(pythonCommand: string): Promise; + abstract getMakeCommand(): Promise; async cloneEspIdf() { await execWithLog( @@ -85,6 +86,16 @@ export abstract class Esp32Env extends BoardEnv { throw new Error(`${XTENSA_TOOLCHAIN_DIR} not found in exported PATH`); } + + async getPythonCommand(): Promise { + if (await this.isPythonVersionGreaterThan3()) { + return 'python'; + } else if (await this.isPackageInstalled('python3')) { + return 'python3'; + } else { + throw new Error("Cannot find Python3. Please install Python3 and try again."); + } + } } export class Esp32DarwinEnv extends Esp32Env { @@ -109,6 +120,18 @@ export class Esp32DarwinEnv extends Esp32Env { throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); } } + + isPackageInstalled(name: string): Promise { + return isPackageInstalledOnUnix(name); + } + + async getMakeCommand(): Promise { + if (await this.isPackageInstalled('make')) { + return 'make'; + } else { + throw new Error('Cannot find make command. Please install make.'); + } + } } export class Esp32WindowsEnv extends Esp32Env { @@ -134,4 +157,18 @@ export class Esp32WindowsEnv extends Esp32Env { throw new Error(`Failed to find ${XTENSA_TOOLCHAIN_DIR}.`, { cause: error }); } } + + isPackageInstalled(name: string): Promise { + return isPackageInstalledOnWindows(name); + } + + async getMakeCommand(): Promise { + if (await this.isPackageInstalled('make')) { + return 'make'; + } else if (await this.isPackageInstalled('mingw32-make')) { + return 'mingw32-make'; + } else { + throw new Error("Cannot find make or mingw32-make command. Please install make or mingw32-make and try again."); + } + } } diff --git a/cli/src/platforms/board-env/host-env.ts b/cli/src/platforms/board-env/host-env.ts index 0d089fa0..bbedf514 100644 --- a/cli/src/platforms/board-env/host-env.ts +++ b/cli/src/platforms/board-env/host-env.ts @@ -2,7 +2,7 @@ import * as path from 'path'; import * as fs from '../../core/fs'; import { GLOBAL_SETTINGS } from '../../config/constants'; import { simpleExec } from '../../core/command-exec'; -import { BoardEnv } from './common-env'; +import { BoardEnv, isPackageInstalledOnUnix, isPackageInstalledOnWindows } from './common-env'; export abstract class HostEnv extends BoardEnv { get hostRootDir() { return path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'); } @@ -27,6 +27,10 @@ export abstract class HostEnv extends BoardEnv { removeBuildDir() { fs.removeDir(this.buildDir); } + + abstract getGccCommand(): Promise; + abstract getArCommand(): Promise; + abstract getMakeCommand(): Promise; } export class HostDarwinEnv extends HostEnv { @@ -52,6 +56,34 @@ export class HostDarwinEnv extends HostEnv { } } + + isPackageInstalled(name: string): Promise { + return isPackageInstalledOnUnix(name); + } + + async getGccCommand(): Promise { + if (await this.isPackageInstalled('cc')) { + return 'cc'; + } else { + throw new Error('Cannot find cc command. Please install cc.'); + } + } + + async getArCommand(): Promise { + if (await this.isPackageInstalled('ar')) { + return 'ar'; + } else { + throw new Error('Cannot find ar command. Please install ar.'); + } + } + + async getMakeCommand(): Promise { + if (await this.isPackageInstalled('make')) { + return 'make'; + } else { + throw new Error('Cannot find make command. Please install make.'); + } + } } export class HostWindowsEnv extends HostEnv { @@ -76,4 +108,41 @@ export class HostWindowsEnv extends HostEnv { throw new Error('Failed to compile host runtime.', { cause: error }); } } + + isPackageInstalled(name: string): Promise { + return isPackageInstalledOnWindows(name); + } + + async getGccCommand(): Promise { + if (await this.isPackageInstalled('gcc') && await this.isMingwGccAvailable()) { + return 'gcc'; + } else { + throw new Error('Cannot find gcc command. Please install MinGW-w64 and add it to PATH.'); + } + } + + private async isMingwGccAvailable(): Promise { + try { + const machine = (await simpleExec('gcc', ['-dumpmachine'])).trim(); + return machine.includes('mingw'); + } catch { + return false; + } + } + + async getArCommand(): Promise { + if (await this.isPackageInstalled('ar')) { + return 'ar'; + } else { + throw new Error('Cannot find ar command. Please install MinGW-w64 and add it to PATH.'); + } + } + + async getMakeCommand(): Promise { + if (await this.isPackageInstalled('mingw32-make')) { + return 'mingw32-make'; + } else { + throw new Error('Cannot find mingw32-make command. Please install MinGW-w64 and add it to PATH.'); + } + } } diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index 88e336b1..ae5be595 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,7 +1,22 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; -import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, isEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, isEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; import { mockedDownloadAndUnzip, mockedSimpleExec, mockedExecWithLog, mockedExecShell, mockProcessExit } from '../mock-helpers'; +import { HostDarwinEnv } from '../../../src/platforms/board-env/host-env'; import * as fs from '../../../src/core/fs'; +import * as path from 'path'; +import os from 'os'; + +jest.mock('os', () => ({ + ...jest.requireActual('os'), + platform: jest.fn(), +})); + +const mockedOs = os as jest.Mocked; +const mockedBuildHostRuntime = jest.spyOn(HostDarwinEnv.prototype, 'buildHostRuntime'); + +function getTestHostShellFile() { + return path.join(getTestRuntimeDir(), 'ports/host/build', 'shell'); +} function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { @@ -26,10 +41,14 @@ function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { describe('board update command', () => { beforeAll(() => { spyGlobalSettings('update'); + mockedOs.platform.mockReturnValue('darwin'); + mockedBuildHostRuntime.mockResolvedValue(); }); afterEach(() => { jest.clearAllMocks(); + mockedDownloadAndUnzip.mockResolvedValue(undefined); + mockedBuildHostRuntime.mockResolvedValue(); deleteGlobalEnv(); }); @@ -55,13 +74,17 @@ describe('board update command', () => { it('should skip updating runtime if version mismatch does not exist.', async () => { // --- Arrange --- + const exitSpy = mockProcessExit(); setupDefaultGlobalEnv(); // --- Act --- await handleUpdateCommand(); // --- Assert --- - expect(mockedDownloadAndUnzip).not.toHaveBeenCalledTimes(1); + expect(process.exit).toHaveBeenCalledWith(0); + + // --- Clean up --- + exitSpy.mockRestore(); }); it('should skip updating ESP-IDF if version mismatch of ESP-IDF does not exist.', async () => { @@ -119,7 +142,7 @@ describe('board update command', () => { // --- Assert --- expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); - expect(mockedExecWithLog).not.toHaveBeenCalledWith( + expect(mockedExecWithLog).toHaveBeenCalledWith( 'git', expect.arrayContaining(['clone']), expect.any(Object), @@ -133,4 +156,58 @@ describe('board update command', () => { // --- Clean up --- exitSpy.mockRestore(); }); + + describe('for host board', () => { + it('should update host environment.', async () => { + // --- Arrange --- + setupGlobalEnvWithHost(true); + + // --- Act --- + await handleUpdateCommand(); + + // --- Assert --- + expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); + expect(mockedBuildHostRuntime).toHaveBeenCalledTimes(1); + expect(getGlobalConfig().version).toMatch(DUMMY_VM_VERSION); + expect(getGlobalConfig().boards.host.shellFile).toBe(getTestHostShellFile()); + expect(getGlobalConfig().boards.host.toolchain).toEqual({ + gcc: 'cc', + ar: 'ar', + make: 'make', + }); + }); + + it('should skip updating host if host is not setup.', async () => { + // --- Arrange --- + setupDefaultGlobalEnv(true); + + // --- Act --- + await handleUpdateCommand(); + + // --- Assert --- + expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); + expect(mockedBuildHostRuntime).not.toHaveBeenCalled(); + }); + + it('should restore old runtime if error occures during updating host', async () => { + // --- Arrange --- + const exitSpy = mockProcessExit(); + setupGlobalEnvWithHost(true); + mockedBuildHostRuntime.mockRejectedValueOnce( + new Error('Failed to compile host runtime.'), + ); + + // --- Act --- + await handleUpdateCommand(); + + // --- Assert --- + expect(mockedDownloadAndUnzip).toHaveBeenCalledTimes(1); + expect(mockedBuildHostRuntime).toHaveBeenCalledTimes(1); + expect(fs.exists(getTestRuntimeDir())).toBe(true); + expect(getGlobalConfig().version).toMatch(DUMMY_OLD_VM_VERSION); + + // --- Clean up --- + exitSpy.mockRestore(); + }); + }); }); diff --git a/cli/tests/integration/host-run-helper.ts b/cli/tests/integration/host-run-helper.ts index 23e9ba76..38dbc0b9 100644 --- a/cli/tests/integration/host-run-helper.ts +++ b/cli/tests/integration/host-run-helper.ts @@ -5,7 +5,6 @@ import * as fs from '../../src/core/fs'; import { ProjectConfigHandler } from '../../src/config/project-config'; import { PROJECT_DEFAULT_PATHS } from '../../src/config/project-config'; import { BoardEnv, createBoardEnv } from '../../src/platforms/board-env'; -import { isPackageInstalledOnWindows } from '../../src/commands/board/setup/utils'; import { logger } from '../../src/core/logger'; const isHostPlatform = os.platform() === 'darwin' || os.platform() === 'win32'; @@ -165,12 +164,13 @@ export async function assertHostIntegrationPrerequisites(): Promise { if (process.platform !== 'win32') { return; } - if (!await isPackageInstalledOnWindows('gcc')) { + const hostEnv = createBoardEnv('host'); + if (!await hostEnv.isPackageInstalled('gcc')) { throw new Error( 'MinGW-w64 gcc is required for host integration tests on Windows.', ); } - if (!await isPackageInstalledOnWindows('mingw32-make')) { + if (!await hostEnv.isPackageInstalled('mingw32-make')) { throw new Error( 'mingw32-make is required for host integration tests on Windows.', ); From 5cc444e9304bb9d0500dd92f1901c4c832cbc8b6 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Tue, 7 Jul 2026 09:45:54 +0900 Subject: [PATCH 32/33] Fix update test. --- cli/tests/commands/board/update.test.ts | 45 +++++++++++----------- cli/tests/commands/global-env-helper.ts | 33 +++++++++++----- cli/tests/commands/project/create.test.ts | 14 +++---- cli/tests/commands/project/install.test.ts | 7 ++-- 4 files changed, 56 insertions(+), 43 deletions(-) diff --git a/cli/tests/commands/board/update.test.ts b/cli/tests/commands/board/update.test.ts index ae5be595..2ba51408 100644 --- a/cli/tests/commands/board/update.test.ts +++ b/cli/tests/commands/board/update.test.ts @@ -1,23 +1,29 @@ import { handleUpdateCommand } from '../../../src/commands/board/update'; -import { deleteGlobalEnv, DUMMY_ESP_IDF_VERSION, getGlobalConfig, getTestEspRootDir, getTestRuntimeDir, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, setupGlobalEnvWithHost, DUMMY_VM_VERSION, spyGlobalSettings, DUMMY_OLD_VM_VERSION, DUMMY_OLD_ESP_IDF_VERSION, isEsp32IdfToolsExportPythonCommand, mockXtensaGccFromIdfToolsExport } from '../global-env-helper'; +import { + deleteGlobalEnv, + DUMMY_ESP_IDF_VERSION, + getGlobalConfig, + getExpectedHostToolchain, + getTestEspRootDir, + getTestHostShellFile, + getTestRuntimeDir, + setupDefaultGlobalEnv, + setupGlobalEnvWithEsp32, + setupGlobalEnvWithHost, + DUMMY_VM_VERSION, + spyGlobalSettings, + DUMMY_OLD_VM_VERSION, + DUMMY_OLD_ESP_IDF_VERSION, + isEsp32IdfToolsExportPythonCommand, + mockXtensaGccFromIdfToolsExport, +} from '../global-env-helper'; import { mockedDownloadAndUnzip, mockedSimpleExec, mockedExecWithLog, mockedExecShell, mockProcessExit } from '../mock-helpers'; -import { HostDarwinEnv } from '../../../src/platforms/board-env/host-env'; +import { HostDarwinEnv, HostWindowsEnv } from '../../../src/platforms/board-env/host-env'; import * as fs from '../../../src/core/fs'; -import * as path from 'path'; -import os from 'os'; - -jest.mock('os', () => ({ - ...jest.requireActual('os'), - platform: jest.fn(), -})); - -const mockedOs = os as jest.Mocked; -const mockedBuildHostRuntime = jest.spyOn(HostDarwinEnv.prototype, 'buildHostRuntime'); - -function getTestHostShellFile() { - return path.join(getTestRuntimeDir(), 'ports/host/build', 'shell'); -} +import * as os from 'os'; +const HostEnvClass = os.platform() === 'win32' ? HostWindowsEnv : HostDarwinEnv; +const mockedBuildHostRuntime = jest.spyOn(HostEnvClass.prototype, 'buildHostRuntime'); function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { mockedSimpleExec.mockImplementation(async (cmd, args) => { @@ -41,7 +47,6 @@ function mockUpdateShellCommands(options: { gitCloneFails?: boolean }) { describe('board update command', () => { beforeAll(() => { spyGlobalSettings('update'); - mockedOs.platform.mockReturnValue('darwin'); mockedBuildHostRuntime.mockResolvedValue(); }); @@ -170,11 +175,7 @@ describe('board update command', () => { expect(mockedBuildHostRuntime).toHaveBeenCalledTimes(1); expect(getGlobalConfig().version).toMatch(DUMMY_VM_VERSION); expect(getGlobalConfig().boards.host.shellFile).toBe(getTestHostShellFile()); - expect(getGlobalConfig().boards.host.toolchain).toEqual({ - gcc: 'cc', - ar: 'ar', - make: 'make', - }); + expect(getGlobalConfig().boards.host.toolchain).toEqual(getExpectedHostToolchain()); }); it('should skip updating host if host is not setup.', async () => { diff --git a/cli/tests/commands/global-env-helper.ts b/cli/tests/commands/global-env-helper.ts index 030de6c8..2ce6eac5 100644 --- a/cli/tests/commands/global-env-helper.ts +++ b/cli/tests/commands/global-env-helper.ts @@ -2,7 +2,8 @@ import * as path from "path"; import * as os from "os"; import * as fs from '../../src/core/fs'; import { GLOBAL_SETTINGS } from "../../src/config/constants"; -import { CommonBoardEnv, Esp32DarwinEnv, HostDarwinEnv } from "../../src/platforms/board-env"; +import { CommonBoardEnv, Esp32DarwinEnv, Esp32WindowsEnv } from "../../src/platforms/board-env"; +import { HostDarwinEnv, HostWindowsEnv } from "../../src/platforms/board-env/host-env"; const TEMP_DIR = path.join(__dirname, '../../temp-files'); const DUMMY_BLUESCRIPT_DIR = (suffix: string) => path.join(TEMP_DIR, `.bluescript-${suffix}`); @@ -13,10 +14,24 @@ export const DUMMY_ESP_IDF_VERSION = 'v5.4'; export const DUMMY_OLD_ESP_IDF_VERSION = 'v5.3'; function commonBoardEnv() { return new CommonBoardEnv(); } -function esp32BoardEnv() { return new Esp32DarwinEnv(); } + +function esp32BoardEnv() { + return os.platform() === 'win32' ? new Esp32WindowsEnv() : new Esp32DarwinEnv(); +} + +function hostBoardEnv() { + return os.platform() === 'win32' ? new HostWindowsEnv() : new HostDarwinEnv(); +} export function getTestRuntimeDir() { return commonBoardEnv().runtimeDir; } export function getTestEspRootDir() { return esp32BoardEnv().espRootDir; } export function getTestEspIdfExportFile() { return esp32BoardEnv().idfExportFile; } +export function getTestHostShellFile() { return hostBoardEnv().shellFile; } + +export function getExpectedHostToolchain() { + return os.platform() === 'win32' + ? { gcc: 'gcc', ar: 'ar', make: 'mingw32-make' } + : { gcc: 'cc', ar: 'ar', make: 'make' }; +} export function spyGlobalSettings(globalDirSuffix: string) { jest.spyOn(GLOBAL_SETTINGS, 'BLUESCRIPT_DIR', 'get').mockReturnValue(DUMMY_BLUESCRIPT_DIR(globalDirSuffix)); @@ -55,15 +70,16 @@ export function setupDefaultGlobalEnv(isOldVersion = false) { } export function setupGlobalEnvWithHost(isOldVersion = false, buildDir?: string) { + const hostEnv = hostBoardEnv(); const resolvedBuildDir = buildDir ?? path.join(getTestRuntimeDir(), 'ports/host/build'); setupGlobalEnv({ version: isOldVersion ? DUMMY_OLD_VM_VERSION : DUMMY_VM_VERSION, runtimeDir: getTestRuntimeDir(), boards: { host: { - rootDir: path.join(GLOBAL_SETTINGS.BLUESCRIPT_DIR, 'host'), - shellFile: path.join(resolvedBuildDir, 'shell'), - toolchain: { gcc: 'cc', ar: 'ar', make: 'make' }, + rootDir: hostEnv.hostRootDir, + shellFile: hostEnv.shellFile, + toolchain: getExpectedHostToolchain(), } }, }); @@ -122,15 +138,14 @@ export function isEsp32IdfToolsExportPythonCommand(cmd: string): boolean { } export function mockXtensaGccFromIdfToolsExport(): string { - const isWin = os.platform() === 'win32'; - const gccName = isWin ? 'xtensa-esp32-elf-gcc.exe' : 'xtensa-esp32-elf-gcc'; - const pathSep = isWin ? ';' : ':'; + const esp32Env = esp32BoardEnv(); + const pathSep = esp32Env instanceof Esp32WindowsEnv ? ';' : ':'; const gccDir = path.join( GLOBAL_SETTINGS.BLUESCRIPT_DIR, '.espressif/tools/xtensa-esp-elf/bin', ); fs.makeDir(gccDir); - fs.writeFile(path.join(gccDir, gccName), ''); + fs.writeFile(path.join(gccDir, esp32Env.xtensaGccFileName), ''); return `PATH=${gccDir}${pathSep}/xtensa-esp-elf-gdb/bin`; } diff --git a/cli/tests/commands/project/create.test.ts b/cli/tests/commands/project/create.test.ts index 7e15eeb6..c50a939c 100644 --- a/cli/tests/commands/project/create.test.ts +++ b/cli/tests/commands/project/create.test.ts @@ -10,7 +10,7 @@ import { import { deleteGlobalEnv, setupDefaultGlobalEnv, setupGlobalEnvWithEsp32, spyGlobalSettings } from '../global-env-helper'; describe('create project command', () => { - const DUMMY_CWD = path.join(__dirname, '../../../temp-files'); + const DUMMY_CWD = path.join(__dirname, '../../../temp-files/create'); const projectName = 'test-project'; const projectDir = path.join(DUMMY_CWD, projectName); const projectBsconfig = path.join(projectDir, 'bsconfig.json'); @@ -22,10 +22,11 @@ describe('create project command', () => { } beforeAll(() => { - spyGlobalSettings('create'); + fs.makeDir(DUMMY_CWD, true); }); beforeEach(() => { + spyGlobalSettings('create'); mockedCwd.mockReturnValue(DUMMY_CWD); deleteGlobalEnv(); deleteDummyProject(); @@ -33,13 +34,8 @@ describe('create project command', () => { afterEach(() => { jest.clearAllMocks(); - // deleteGlobalEnv(); - // deleteDummyProject(); - }); - - afterAll(() => { - // deleteGlobalEnv(); - // deleteDummyProject(); + deleteGlobalEnv(); + deleteDummyProject(); }); it('should show warning and exit if update is needed', async () => { diff --git a/cli/tests/commands/project/install.test.ts b/cli/tests/commands/project/install.test.ts index d711aa4c..ab8dd7cf 100644 --- a/cli/tests/commands/project/install.test.ts +++ b/cli/tests/commands/project/install.test.ts @@ -13,13 +13,14 @@ import { PROJECT_DEFAULT_PATHS } from '../../../src/config/project-config'; describe('install command', () => { - const projectRoot = path.join(__dirname, '../../../temp-files/test-project'); + const projectRoot = path.join(__dirname, '../../../temp-files/install/test-project'); beforeAll(() => { - spyGlobalSettings('install'); - }) + fs.makeDir(path.dirname(projectRoot), true); + }); beforeEach(() => { + spyGlobalSettings('install'); mockedCwd.mockReturnValue(projectRoot); }); From 0072757684eec18c313c6f784d387726de8ef746 Mon Sep 17 00:00:00 2001 From: maejimafumika Date: Tue, 7 Jul 2026 10:57:26 +0900 Subject: [PATCH 33/33] Update document. --- website/docs/reference/cli.md | 17 +- .../get-started/setup-environment-windows.md | 365 ++++++++++++++++++ .../tutorial/get-started/setup-environment.md | 63 ++- website/docs/tutorial/guides/repl.md | 30 +- .../guides/try-without-microcontroller.md | 32 +- website/src/components/OsTabs/index.tsx | 54 +++ 6 files changed, 517 insertions(+), 44 deletions(-) create mode 100644 website/docs/tutorial/get-started/setup-environment-windows.md create mode 100644 website/src/components/OsTabs/index.tsx diff --git a/website/docs/reference/cli.md b/website/docs/reference/cli.md index 3f1bd65d..dd695e9f 100644 --- a/website/docs/reference/cli.md +++ b/website/docs/reference/cli.md @@ -8,6 +8,12 @@ The BlueScript CLI (`bscript`) is the primary tool for managing projects, settin npm install -g @bscript/cli ``` +:::info Supported platforms +BlueScript CLI supports **macOS** and **Windows**. **Linux is not supported.** + +On Windows, install the Visual C++ Build Environment before `npm install -g @bscript/cli` (required by node-gyp for native dependencies such as `serialport`). See [Windows prerequisites](../tutorial/get-started/setup-environment-windows.md). +::: + ## Project Management ### `bscript project create` @@ -150,7 +156,14 @@ bscript board setup **Arguments:** * ``: The target board identifier (`esp32` or `host`). -For `esp32`, this downloads ESP-IDF and related tools. For `host`, this builds the local runtime process and requires a C compiler toolchain (`cc` and `make`). See [Try Without Microcontroller](../tutorial/guides/try-without-microcontroller.md). +**Platform requirements:** + +| Board | macOS | Windows | +| :--- | :--- | :--- | +| `host` | `cc`, `make` | MinGW-w64: `gcc`, `mingw32-make` | +| `esp32` | Homebrew, Git, Python 3, `make` | Git, Python 3, `make` or `mingw32-make`. See [Windows prerequisites](../tutorial/get-started/setup-environment-windows.md). | + +For `host`, see [Try Without Microcontroller](../tutorial/guides/try-without-microcontroller.md). --- @@ -170,7 +183,7 @@ bscript board flash-runtime [options] | Option | Alias | Description | | :--- | :--- | :--- | -| `--port` | `-p` | Specify the serial port connected to the device (e.g., `COM3`, `/dev/ttyUSB0`). If omitted, the CLI will list available ports for selection. | +| `--port` | `-p` | Serial port (e.g. macOS: `/dev/tty.usbserial-xxxx`; Windows: `COM3`). If omitted, the CLI lists available ports for selection. | | `--device-name` | `-d` | Bluetooth device name advertised by the runtime after flashing (default: `"BLUESCRIPT"`). Must match `deviceName` in your project's `bsconfig.json` when connecting wirelessly. | **Example:** diff --git a/website/docs/tutorial/get-started/setup-environment-windows.md b/website/docs/tutorial/get-started/setup-environment-windows.md new file mode 100644 index 00000000..52cc6bcc --- /dev/null +++ b/website/docs/tutorial/get-started/setup-environment-windows.md @@ -0,0 +1,365 @@ +--- +slug: /tutorial/get-started/setup-environment-windows +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Windows prerequisites + +This page walks you through installing the software BlueScript needs on **Windows**. + +## Node.js and Visual C++ Build Environment {#nodejs-and-visual-c-build-environment} + +`@bscript/cli` depends on native Node.js add-ons (for example `serialport` and Bluetooth libraries). On Windows, `npm install -g @bscript/cli` uses **node-gyp**, which compiles those add-ons and requires a **Visual C++ Build Environment** in addition to Node.js. + +Install **both** before running `npm install -g @bscript/cli`. + +### Node.js {#nodejs} + +**What it is:** The JavaScript runtime that powers `npm` and the BlueScript CLI. + +**Version:** v20 or later (LTS recommended). + + + + +1. Download the **LTS** installer from [nodejs.org](https://nodejs.org/). +2. Run the installer and accept the defaults. The option to **add Node.js to PATH** is enabled by default — leave it on. +3. Close any open terminals and open a **new** one. + + + + +If [winget](https://learn.microsoft.com/en-us/windows/package-manager/winget/) is available: + +```powershell +winget install OpenJS.NodeJS.LTS +``` + +Then open a **new** terminal. + + + + +If [Chocolatey](https://chocolatey.org/install) is installed: + +```powershell +choco install nodejs-lts -y +``` + +Then open a **new** terminal. + + + + +**Verify:** + +```powershell +node --version +npm --version +``` + +You should see version numbers (for example `v22.x.x` and `10.x.x`), not "command not found". + +### Visual C++ Build Environment {#visual-c-build-environment} + +**What it is:** Microsoft’s C++ compiler and Windows SDK. **node-gyp** uses them to build native Node.js modules during `npm install`. + +**You do not need to add anything to PATH manually** — the installer registers the build tools with Visual Studio’s locator, which node-gyp finds automatically. + + + + +1. Download [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) (free). +2. Run the installer. On the **Workloads** tab, check **"Desktop development with C++"** (C++ によるデスクトップ開発). +3. Click **Install** and wait until it finishes (several GB; may take a while). +4. Open a **new** terminal. + +You can use full **Visual Studio** (Community edition is fine) instead of Build Tools, with the same **"Desktop development with C++"** workload. + + + + +If Chocolatey is installed: + +```powershell +choco install visualstudio2022buildtools --package-parameters "--add Microsoft.VisualStudio.Workload.VCTools --includeRecommended" -y +``` + +Then open a **new** terminal. + + + + +**Verify:** There is no single `cl` command guaranteed on PATH in a normal terminal. The practical check is to install the CLI (after Node.js and the build tools are installed): + +```powershell +npm install -g @bscript/cli +bscript --version +``` + +If `npm install` fails with `gyp ERR! find VS`, the C++ workload is missing or the terminal was opened before installation finished — reinstall the workload and use a **new** terminal. + +--- + +## Git {#git} + +**What it is:** Version control used by ESP-IDF setup to clone repositories. + +**Required for:** `bscript board setup esp32` only. + + + + +1. Download [Git for Windows](https://git-scm.com/download/win). +2. Run the installer. When asked about **Adjusting your PATH environment**, choose **"Git from the command line and also from 3rd-party software"** so `git` works in PowerShell and Command Prompt. +3. Other options can stay at defaults. Open a **new** terminal after installation. + + + + +```powershell +winget install Git.Git +``` + +Open a **new** terminal. If `git` is not found, re-run the official installer and ensure PATH integration is enabled. + + + + +```powershell +choco install git -y +``` + +Open a **new** terminal. + + + + +**Verify:** + +```powershell +git --version +``` + +--- + +## Python 3 {#python-3} + +**What it is:** A programming language runtime. ESP-IDF’s Windows installer (`install.bat`) uses Python to set up its own tool environment. + +**Required for:** `bscript board setup esp32` (install **before** that command). + +**Version:** 3.8 or later; 3.11+ recommended. + + + + +1. Download Python from [python.org/downloads/windows](https://www.python.org/downloads/windows/). +2. Run the installer. At the bottom of the first screen, enable **"Add python.exe to PATH"** — this is important. +3. Choose **Install Now** (or **Customize** if you prefer). Open a **new** terminal after installation. + + + + +```powershell +winget install Python.Python.3.12 +``` + +Open a **new** terminal. + + + + +```powershell +choco install python -y +``` + +Open a **new** terminal. + + + + +**Verify:** + +```powershell +python --version +``` + +If `python` is not found, try: + +```powershell +python3 --version +``` + +BlueScript accepts either `python` or `python3` on PATH. + +--- + +## MinGW-w64 {#mingw-w64} + +**What it is:** A GCC-based C/C++ toolchain for Windows (`gcc`, `ar`, and often `mingw32-make`). + +**Required for:** [Host runtime](../guides/try-without-microcontroller.md) — `bscript board setup host` compiles native code with **MinGW’s** `gcc` and `mingw32-make`, not Visual Studio’s compiler. + +:::info Visual C++ vs MinGW +- **Visual C++ Build Environment** → needed for `npm install` (Node native modules). +- **MinGW-w64** → needed for `bscript board setup host` (BlueScript host runtime). + +They serve different purposes; host development on Windows needs **both**. +::: + + + + +[MSYS2](https://www.msys2.org/) provides a maintained MinGW-w64 environment. + +1. Download and run the MSYS2 installer from [msys2.org](https://www.msys2.org/). +2. Open **MSYS2 UCRT64** from the Start menu (not the plain "MSYS" shell). +3. Update the package database (first time only): + +```bash +pacman -Syu +``` + +Close the window when prompted, reopen **MSYS2 UCRT64**, and run `pacman -Syu` again if needed. + +4. Install the toolchain and make: + +```bash +pacman -S --needed mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-make +``` + +5. Add MinGW to your **Windows** PATH (not only inside MSYS2): + + - Typical folder: `C:\msys64\ucrt64\bin` (adjust if you installed MSYS2 elsewhere). + - **Settings → System → About → Advanced system settings → Environment Variables** + - Under **User variables** or **System variables**, edit **Path**, click **New**, paste the `ucrt64\bin` path, and confirm. + +6. Open a **new** PowerShell or Command Prompt window. + + + + +```powershell +choco install mingw -y +``` + +Chocolatey usually adds MinGW’s `bin` folder to PATH. Open a **new** terminal. + +If `gcc -dumpmachine` does not contain `mingw`, use the MSYS2 method instead. + + + + +**Verify** (in PowerShell or Command Prompt, not only inside MSYS2): + +```powershell +gcc --version +ar --version +mingw32-make --version +``` + +For host setup, `gcc` must be MinGW (not another vendor). Check with: + +```powershell +gcc -dumpmachine +``` + +The output should include `mingw` (for example `x86_64-w64-mingw32`). + +--- + +## make or mingw32-make {#make-or-mingw32-make} + +**What it is:** A build automation tool. ESP-IDF uses `make` or `mingw32-make` when compiling firmware. + +**Required for:** `bscript board setup esp32` and related ESP32 builds. + +:::tip Already installed? +If you followed [MinGW-w64](#mingw-w64) via MSYS2 with `mingw-w64-ucrt-x86_64-make`, **`mingw32-make` is already available** — run the verify commands below and skip a separate make install unless `make` is also required by your workflow. +::: + +BlueScript accepts **either** `make` **or** `mingw32-make` on PATH for ESP32. + + + + +In **MSYS2 UCRT64**: + +```bash +pacman -S make +``` + +Or for `mingw32-make` only: + +```bash +pacman -S mingw-w64-ucrt-x86_64-make +``` + +Add `C:\msys64\ucrt64\bin` (and optionally `C:\msys64\usr\bin` if you installed `make` from the `make` package) to Windows PATH. Open a **new** terminal. + + + + +Install GNU make: + +```powershell +choco install make -y +``` + +Open a **new** terminal. + + + + +**Verify:** + +```powershell +make --version +``` + +If `make` is not found: + +```powershell +mingw32-make --version +``` + +At least one of these must succeed before `bscript board setup esp32`. + +--- + +## USB-to-UART drivers {#usb-to-uart-drivers} + +**When you need this:** Your ESP32 does not show up as a COM port when you run `bscript board flash-runtime esp32`. + +Many ESP32 boards use a USB–serial bridge chip. Windows needs a driver before the port appears in Device Manager. + +1. Identify the chip on your board (common types: **CP2102**, **CH340**, **FT232**). +2. Install the matching driver: + - [CP210x (Silicon Labs)](https://www.silabs.com/software-and-tools/usb-to-uart-bridge-vcp-drivers) + - [FTDI VCP](https://ftdichip.com/drivers/vcp-drivers/) + - CH340: search for "CH340 driver Windows" from your board vendor or [WCH](http://www.wch-ic.com/downloads/CH341SER_EXE.html) +3. Connect the board via USB. Open **Device Manager** (Win + X → Device Manager). +4. Under **Ports (COM & LPT)**, you should see something like **USB Serial Port (COM3)**. Note the COM number — the CLI lists it when flashing. + +If the port still does not appear, try another USB cable (some cables are charge-only) or a different USB port. + +See also [Establish Serial Connection with ESP32](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/establish-serial-connection.html) in the ESP-IDF documentation. + +--- + +## Troubleshooting + +| Problem | What to try | +| :--- | :--- | +| `'node' is not recognized` | Reinstall Node.js with PATH enabled; open a new terminal | +| `gyp ERR! find VS` during `npm install` | Install **Desktop development with C++** workload; new terminal | +| `'python' is not recognized` | Reinstall Python with **Add to PATH**; try `python3` | +| `'gcc' is not recognized` | Add MSYS2 `ucrt64\bin` to PATH; new terminal | +| `gcc` found but host setup fails | Run `gcc -dumpmachine` — must show `mingw`, not `msvc` | +| `'make' is not recognized` | Install `make` or ensure `mingw32-make` is on PATH | +| ESP32 COM port missing | Install USB-to-UART driver; check cable and Device Manager | + +--- diff --git a/website/docs/tutorial/get-started/setup-environment.md b/website/docs/tutorial/get-started/setup-environment.md index 70d00368..fbc0b488 100644 --- a/website/docs/tutorial/get-started/setup-environment.md +++ b/website/docs/tutorial/get-started/setup-environment.md @@ -1,31 +1,72 @@ +import OsTabs from '@site/src/components/OsTabs'; +import TabItem from '@theme/TabItem'; + # Set up your environment -:::danger macOS Only -Currently, BlueScript strictly requires **macOS**. Windows and Linux support is under development. +:::danger Linux not supported +BlueScript supports **macOS** and **Windows**. **Linux is not supported** at this time. ::: In this guide, we will install the BlueScript CLI and flash the runtime environment to your ESP32 microcontroller. ## Prerequisites -Before we begin, ensure you have the following: +### Hardware + +- **Host PC:** macOS or Windows +- **Microcontroller:** An ESP32 development board (e.g., ESP32-DevKitC) +- **USB cable** to connect your host PC and the microcontroller + +### Software + + + + +- [Node.js](https://nodejs.org/) v20 or later +- [Homebrew](https://brew.sh/) +- **Git** (`git`) +- **Python 3** (`python` or `python3`) +- **make** (`make`) + + + + +- [Node.js](https://nodejs.org/) v20 or later +- **Visual C++ Build Environment** (required for `npm install -g @bscript/cli`; see [Windows prerequisites](./setup-environment-windows.md#nodejs-and-visual-c-build-environment)) +- **Git** (`git`) +- **Python 3** (`python` or `python3`) +- **make** or **mingw32-make** + +For step-by-step installation instructions, see **[Windows prerequisites](./setup-environment-windows.md)**. + + + -- **Hardware:** - - **Host PC:** A laptop running **macOS** (Windows and Linux are currently **not** supported). - - **Micocontroller:** An ESP32 development board (e.g., ESP32-DevKitC) - - **USB cable** to connect your host PC and the microcontroller -- **Software:** - - [Node.js](https://nodejs.org/) (v20 or later) installed on your host PC. --- ## Step 1: Install the CLI -BlueScript provides a command-line interface (CLI) to manage projects and communicate with your device. Install it globally using npm: +BlueScript provides a command-line interface (CLI) to manage projects and communicate with your device. + + + + +```bash +npm install -g @bscript/cli +``` + + + + +Install the [Visual C++ Build Environment](./setup-environment-windows.md#nodejs-and-visual-c-build-environment) first, then: ```bash npm install -g @bscript/cli ``` + + + Verify the installation: ```bash @@ -58,7 +99,7 @@ Connect your ESP32 to your computer via USB and flash the runtime: bscript board flash-runtime esp32 ``` -The CLI will display a list of detected serial ports. Use the arrow keys to select the one corresponding to your ESP32 (e.g., /dev/tty.usbserial-xxxx). +The CLI will display a list of detected serial ports. Use the arrow keys to select the one corresponding to your ESP32 (e.g., /dev/tty.usbserial-xxxx on macOS or COMX on Windows). :::info Device not found? If your device does not appear in the list, you may need to install USB-to-UART drivers (e.g., [CP210x](https://www.silabs.com/software-and-tools/usb-to-uart-bridge-vcp-drivers) or [FTDI](https://ftdichip.com/drivers/vcp-drivers/)). diff --git a/website/docs/tutorial/guides/repl.md b/website/docs/tutorial/guides/repl.md index a47c52f2..5fdae3e5 100644 --- a/website/docs/tutorial/guides/repl.md +++ b/website/docs/tutorial/guides/repl.md @@ -6,23 +6,6 @@ sidebar_label: REPL & Notebook After your program runs on the device, you can send **more BlueScript code** without editing files and running `bscript project run` again. -The easiest way is the **Notebook**: a browser UI where you run code in cells. You can also use a **REPL** in the terminal (one line at a time). - -## Which mode should I use? - -| Mode | Command | When to use it | -| :--- | :--- | :--- | -| **Notebook** | `bscript project run --with-notebook` | You have a project and want to try code in cells (recommended) | -| **Project REPL** | `bscript project run --with-repl` | Same as above, but you prefer the terminal | -| **Global REPL** | `bscript repl -b esp32` or `bscript repl -b host` | No project yet—language syntax only (use `-d` to specify device name on ESP32) | -| **Normal run** | `bscript project run` | You are writing the full app in `index.bs` | - -**Notebook vs REPL:** The Notebook supports multi-line cells (**Shift+Enter** to run) and shows output on the side. The REPL accepts **one line per Enter**. - -Hardware libraries (e.g. GPIO) work in the Notebook and Project REPL only if you ran `bscript project install` in that project. The global REPL cannot use them. - ---- - ## Try the Notebook This walkthrough continues from [Blink LED](../get-started/blink-led.md) (GPIO package installed, LED wired). @@ -70,7 +53,7 @@ console.log("LED off"); led.write(PinLevel.Low); ``` -Compile errors appear under the cell. Press **`Ctrl+D`** in the terminal to exit. +Press **`Ctrl+D`** in the terminal to exit. --- @@ -82,7 +65,7 @@ Compile errors appear under the cell. Press **`Ctrl+D`** in the terminal to exit bscript project run --with-repl ``` -After `index.bs` runs, type one line at the `>` prompt. Installed packages (e.g. `gpio`) can be imported here. Exit with **`Ctrl+D`**. Do not combine `--with-repl` and `--with-notebook`. +After `index.bs` runs, type one line at the `>` prompt. Installed packages (e.g. `gpio`) can be imported here. Exit with **`Ctrl+D`**. ### Global REPL @@ -94,18 +77,9 @@ bscript repl -b host Use this for quick syntax checks without a project. **GPIO and other installed libraries are not available.** Exit with **`Ctrl+D`**. -:::note Host runtime -The host runtime must be set up first. See [Try Without Microcontroller](./try-without-microcontroller.md) for setup. -::: - -:::note -A global Notebook (without a project) is planned for a future release. -::: - --- ## Good to know * **Device name:** Notebook and Project REPL connect using `deviceName` in `bsconfig.json`. Global REPL uses the `-d` flag instead. The name must match what was set during `bscript board flash-runtime`. See [bsconfig.json](../../reference/bsconfig.md#esp32-fields). * Code on the device is **lost after a reboot**—run the command again to re-upload. -* Variables and functions from earlier cells or REPL lines **stay available** until you disconnect. diff --git a/website/docs/tutorial/guides/try-without-microcontroller.md b/website/docs/tutorial/guides/try-without-microcontroller.md index 011d6e70..0ea85cc6 100644 --- a/website/docs/tutorial/guides/try-without-microcontroller.md +++ b/website/docs/tutorial/guides/try-without-microcontroller.md @@ -2,6 +2,9 @@ sidebar_label: Try Without Microcontroller --- +import OsTabs from '@site/src/components/OsTabs'; +import TabItem from '@theme/TabItem'; + # Try Without Microcontroller BlueScript is designed primarily for microcontroller development (ESP32). @@ -9,14 +12,35 @@ If you do not have hardware yet—or want a faster path for language and compile For the main ESP32 workflow, see [Get Started](../get-started/introduction.md). -:::danger macOS Only -The host runtime currently requires **macOS**. Windows and Linux support is under development. +:::danger Linux not supported +The host runtime supports **macOS** and **Windows**. **Linux is not supported** at this time. ::: ## Prerequisites + + + - [Node.js](https://nodejs.org/) v20+ -- C compiler toolchain (`cc` and `make`) +- C compiler toolchain: **Xcode Command Line Tools** (`cc` and `make`) +- **Git** (`git`) + +Install Command Line Tools if needed: + +```bash +xcode-select --install +``` + + + + +- [Node.js](https://nodejs.org/) v20+ +- **Visual C++ Build Environment** (for `npm install -g @bscript/cli`; see [Windows prerequisites for ESP32](../get-started/setup-environment-windows.md#nodejs-and-visual-c-build-environment)) +- [MinGW-w64](https://www.mingw-w64.org/) on `PATH`: `gcc` and `mingw32-make` +- **Git** (`git`) + + + ## Quickstart @@ -28,6 +52,8 @@ If you have not installed the CLI yet: npm install -g @bscript/cli ``` +On Windows, install the [Visual C++ Build Environment](../get-started/setup-environment-windows.md#nodejs-and-visual-c-build-environment) before running this command. + ### 2. Set up the host runtime ```bash diff --git a/website/src/components/OsTabs/index.tsx b/website/src/components/OsTabs/index.tsx new file mode 100644 index 00000000..c5c6a331 --- /dev/null +++ b/website/src/components/OsTabs/index.tsx @@ -0,0 +1,54 @@ +import {useState} from 'react'; +import useIsomorphicLayoutEffect from '@docusaurus/useIsomorphicLayoutEffect'; +import Tabs from '@theme/Tabs'; +import type {Props as TabsProps} from '@theme/Tabs'; + +const GROUP_ID = 'os'; +const STORAGE_KEY = `docusaurus.tab.${GROUP_ID}`; + +export type OsTabValue = 'macos' | 'windows'; + +export function detectOsTabValue(): OsTabValue { + if (typeof navigator === 'undefined') { + return 'macos'; + } + + try { + const stored = localStorage.getItem(STORAGE_KEY); + if (stored === 'macos' || stored === 'windows') { + return stored; + } + } catch { + // ignore + } + + const ua = navigator.userAgent; + if (/Win/i.test(ua)) { + return 'windows'; + } + if (/Mac/i.test(ua)) { + return 'macos'; + } + + return 'macos'; +} + +type OsTabsProps = Omit; + +export default function OsTabs({children, ...props}: OsTabsProps) { + const [defaultValue, setDefaultValue] = useState(null); + + useIsomorphicLayoutEffect(() => { + setDefaultValue(detectOsTabValue()); + }, []); + + if (defaultValue === null) { + return