diff --git a/src/env/index.ts b/src/env/index.ts index 7883856..0980027 100644 --- a/src/env/index.ts +++ b/src/env/index.ts @@ -1,48 +1,58 @@ -import LISA from '@listenai/lisa_core'; -import { Bundle, Flasher } from '@lisa-env/type'; -import { Binary } from '@binary/type'; -import { delimiter, join } from 'path'; -import { uniq, defaults } from 'lodash'; -import { pathExists, readJson, outputJson, remove } from 'fs-extra'; +import LISA from "@listenai/lisa_core"; +import { Bundle, Flasher } from "@lisa-env/type"; +import { Binary } from "@binary/type"; +import { delimiter, join } from "path"; +import { uniq, defaults } from "lodash"; +import { pathExists, readJson, outputJson, remove } from "fs-extra"; -import { KEY_OF_PATH, SYSTEM_PATHS, makePath, splitPath } from '../utils/path'; -import typedImport from '../utils/typedImport'; +import { KEY_OF_PATH, SYSTEM_PATHS, makePath, splitPath } from "../utils/path"; +import typedImport from "../utils/typedImport"; -import { PLUGIN_HOME, get } from './config'; +import { PLUGIN_HOME, get } from "./config"; -export const PACKAGE_HOME = join(PLUGIN_HOME, 'packages'); -const PACKAGE_MODULES_DIR = join(PACKAGE_HOME, 'node_modules'); +export const PACKAGE_HOME = join(PLUGIN_HOME, "packages"); +const PACKAGE_MODULES_DIR = join(PACKAGE_HOME, "node_modules"); -const CONFIG_DIR = join(PLUGIN_HOME, 'config'); -const WEST_CONFIG_GLOBAL = join(CONFIG_DIR, 'westconfig'); +const CONFIG_DIR = join(PLUGIN_HOME, "config"); +const WEST_CONFIG_GLOBAL = join(CONFIG_DIR, "westconfig"); -const ENV_CACHE_DIR = join(PLUGIN_HOME, 'envs'); +const ENV_CACHE_DIR = join(PLUGIN_HOME, "envs"); -const PIP_INDEX_URL = process.env.PIP_INDEX_URL || 'https://pypi.tuna.tsinghua.edu.cn/simple'; +const PIP_INDEX_URL = + process.env.PIP_INDEX_URL || "https://pypi.tuna.tsinghua.edu.cn/simple"; const BUILTIN_BINARIES = [ - '../venv', - '@binary/cmake', - '@binary/dtc', - '@binary/gperf', - '@binary/mklfs', - '@binary/ninja', - '@binary/protoc', - '@binary/xz', + "../venv", + "@binary/cmake", + "@binary/dtc", + "@binary/gperf", + "@binary/mklfs", + "@binary/ninja", + "@binary/protoc", + "@binary/xz", ]; -export async function getEnv(override?: string): Promise> { - const escape = (name: string) => name.replaceAll('/', '_').replaceAll('\\', '_'); - const cacheName = override ? `cache_${escape(override)}.json` : 'cache.json'; +export async function getEnv( + override?: string +): Promise> { + const escape = (name: string) => + name.replaceAll("/", "_").replaceAll("\\", "_"); + const cacheName = override ? `cache_${escape(override)}.json` : "cache.json"; const cacheFile = join(ENV_CACHE_DIR, cacheName); if (await pathExists(cacheFile)) { const env = await readJson(cacheFile); - Object.assign(env, makePath([...splitPath(env[KEY_OF_PATH]), ...SYSTEM_PATHS])); + Object.assign( + env, + makePath([...splitPath(env[KEY_OF_PATH]), ...SYSTEM_PATHS]) + ); return env; } else { const env = await makeEnv(override); await outputJson(cacheFile, env); - Object.assign(env, makePath([...splitPath(env[KEY_OF_PATH]), ...SYSTEM_PATHS])); + Object.assign( + env, + makePath([...splitPath(env[KEY_OF_PATH]), ...SYSTEM_PATHS]) + ); return env; } } @@ -51,8 +61,10 @@ export async function invalidateEnv(): Promise { await remove(ENV_CACHE_DIR); } -export async function getFlasher(override?: string): Promise { - const envs = await get('env') || []; +export async function getFlasher( + override?: string +): Promise { + const envs = (await get("env")) || []; if (override) envs.unshift(override); const bundles = await loadBundles(uniq(envs)); if (bundles.length == 0) return undefined; @@ -62,21 +74,29 @@ export async function getFlasher(override?: string): Promise { if (!envs) return []; try { - return await Promise.all(envs.map(name => typedImport(`${PACKAGE_MODULES_DIR}/@lisa-env/${name}`))); + return await Promise.all( + envs.map((name) => + typedImport(`${PACKAGE_MODULES_DIR}/@lisa-env/${name}`) + ) + ); } catch (e) { return []; } } -export async function loadBinaries(bundles?: Bundle[]): Promise> { +export async function loadBinaries( + bundles?: Bundle[] +): Promise> { const binaries: Record = {}; for (const name of BUILTIN_BINARIES) { - const unprefixedName = name.split('/').slice(1).join('/'); + const unprefixedName = name.split("/").slice(1).join("/"); binaries[unprefixedName] = await typedImport(name); } for (const bundle of bundles || []) { for (const name of bundle.binaries || []) { - binaries[name] = await typedImport(`${PACKAGE_MODULES_DIR}/@binary/${name}`); + binaries[name] = await typedImport( + `${PACKAGE_MODULES_DIR}/@binary/${name}` + ); } } return binaries; @@ -87,7 +107,7 @@ async function makeEnv(override?: string): Promise> { const binaries: string[] = []; const libraries: string[] = []; - const envs = await get('env') || []; + const envs = (await get("env")) || []; if (override) envs.unshift(override); const bundles = await loadBundles(uniq(envs)); @@ -101,9 +121,9 @@ async function makeEnv(override?: string): Promise> { } } - const sdk = await get('sdk'); + const sdk = await get("sdk"); if (sdk) { - env['ZEPHYR_BASE'] = sdk; + env["ZEPHYR_BASE"] = sdk; } Object.assign(env, { @@ -121,29 +141,39 @@ async function makeEnv(override?: string): Promise> { Object.assign(env, makePath(binaries)); - if (libraries.length > 0 && process.platform == 'linux') { + if (libraries.length > 0 && process.platform == "linux") { const { LD_LIBRARY_PATH } = process.env; - env['LD_LIBRARY_PATH'] = [ + env["LD_LIBRARY_PATH"] = [ ...libraries, - ...LD_LIBRARY_PATH ? LD_LIBRARY_PATH.split(delimiter) : [], + ...(LD_LIBRARY_PATH ? LD_LIBRARY_PATH.split(delimiter) : []), ].join(delimiter); } - if (process.platform == 'linux') { + if (process.platform == "linux") { try { const dirs: string[] = []; - const { stdout } = await LISA.cmd('infocmp', ['-D'], { shell: true }); - LISA.application.debug('infocmp -D', stdout); - for (const dir of stdout.split('\n')) { - if (dir && await pathExists(dir)) { + const { stdout } = await LISA.cmd("infocmp", ["-D"], { shell: true }); + LISA.application.debug("infocmp -D", stdout); + for (const dir of stdout.split("\n")) { + if (dir && (await pathExists(dir))) { dirs.push(dir); } } - env['TERMINFO_DIRS'] = dirs.join(delimiter); - LISA.application.debug('TERMINFO_DIRS', env['TERMINFO_DIRS']); - } catch (e) { - } + env["TERMINFO_DIRS"] = dirs.join(delimiter); + LISA.application.debug("TERMINFO_DIRS", env["TERMINFO_DIRS"]); + } catch (e) {} } return env; } + +export async function getBinarie(name: string): Promise { + const envs = (await get("env")) || []; + const bundles = await loadBundles(uniq(envs)); + const binaries = await loadBinaries(bundles); + for (const binary of Object.keys(binaries)) { + if (name === binary.toString()) { + return binaries[binary]; + } + } +} diff --git a/src/tasks/initVs.ts b/src/tasks/initVs.ts index f741501..2e588c3 100644 --- a/src/tasks/initVs.ts +++ b/src/tasks/initVs.ts @@ -1,64 +1,108 @@ -import { LisaType, job } from '../utils/lisa_ex'; -import { join, resolve } from 'path'; +import { LisaType, job } from "../utils/lisa_ex"; +import { join, resolve } from "path"; import { - readFile, copy, writeFile, readJson, pathExists, writeJson -} from 'fs-extra'; + readFile, + copy, + writeFile, + readJson, + pathExists, + remove, + rename, + mkdir, +} from "fs-extra"; -import { getEnv } from '../env'; -import { get } from '../env/config'; -import parseArgs from '../utils/parseArgs'; -import { testLog } from '../utils/testLog'; +import { getEnv, getBinarie } from "../env"; +import { get } from "../env/config"; +import parseArgs from "../utils/parseArgs"; +import { testLog } from "../utils/testLog"; +import { platform } from "os"; export default ({ application, cmd }: LisaType) => { - - job('init-vs', { - title: '生成vscode debug runner', + job("init-vs", { + title: "生成vscode debug runner", async task(ctx, task) { - const { args, printHelp } = parseArgs(application.argv, { - 'env': { arg: 'name', help: '指定编译环境' }, - }); - const current = await get('env'); + const availableSdks = ["csk6-dsp", "csk6"]; + const current = await get("env"); const env = await getEnv(); - let XTENSA_TOOL: string = ''; - if (!args['env']) { - if (!current) { - throw new Error(`需要设置 编译环境 (lisa zep use-env [path])`); - } else if (!current.includes('csk6-dsp')) { - throw new Error(`暂不支持其他SDK`); - } - } else if (args['env'] !== 'csk6-dsp') { + let XTENSA_TOOL: string = ""; + let JLINK_TOOL: string = ""; + let JLinkGDBServerCL: string = ""; + if (platform() !== "win32") { + throw new Error("该命令暂只支持在 windows 下执行"); + } + const { args } = parseArgs(application.argv, { + env: { arg: "name", help: "生成vscode debug runner" }, + }); + if (!current) { + throw new Error(`需要设置 编译环境 (lisa zep use-env [path])`); + } + if (!args["env"]) { + throw new Error(`需要指定编译环境 (--env [env])`); + } else if (!availableSdks.includes(args["env"])) { throw new Error(`暂不支持其他SDK`); } - - const XTENSA_SYSTEM = env.XTENSA_SYSTEM; - if (!XTENSA_SYSTEM) { - throw new Error(`需要设置 XTENSA_SYSTEM`); - } else { - XTENSA_TOOL = join(XTENSA_SYSTEM.split('venus_hifi4')[0], 'XtensaTools/bin/xt-gdb.exe') - if (!(await pathExists(XTENSA_TOOL))) { - throw new Error(`xt-gdb不存在: ${XTENSA_TOOL}`); + if (args["env"] === "csk6-dsp") { + const XTENSA_SYSTEM = env.XTENSA_SYSTEM; + if (!XTENSA_SYSTEM) { + throw new Error(`需要设置 XTENSA_SYSTEM`); + } else { + XTENSA_TOOL = join( + XTENSA_SYSTEM.split("venus_hifi4")[0], + "XtensaTools/bin/xt-gdb.exe" + ); + if (!(await pathExists(XTENSA_TOOL))) { + throw new Error(`xt-gdb不存在: ${XTENSA_TOOL}`); + } + } + } + if (args["env"] === "csk6") { + const JLINK = await getBinarie("jlink-venus"); + JLINK_TOOL = JLINK && JLINK.homeDir; + if (!JLINK_TOOL || !(await pathExists(JLINK_TOOL))) { + throw new Error(`需要设置 jlink-venus`); + } else { + JLinkGDBServerCL = join(JLINK.homeDir, "JLinkGDBServerCL.exe"); + if (!(await pathExists(JLinkGDBServerCL))) { + throw new Error(`缺少必要文件:${JLinkGDBServerCL}`); + } } } - const jlinkSNcode = ctx.jlinkSNcode || await task.prompt({ - type: 'input', - name: 'value', - message: '请输入jlink 的 `SN` 码', - initial: '.', - }) - ctx.jlinkSNcode = jlinkSNcode; - const targetDir = join(process.cwd(), '.vscode'); - const formDir = join(__dirname, '..', '..', 'vscode'); - await copy(formDir, targetDir); - const configFIle = join(targetDir, 'xt-ocd-config.xml'); - const Launchfile = join(targetDir, 'launch.json'); - const configFileStr = await readFile(configFIle, 'utf8'); - const result = configFileStr.replace(/###usbser###/g, jlinkSNcode); - await writeFile(configFIle, result, 'utf-8'); - const launchJson = await readJson(Launchfile); - launchJson.configurations[0].linux.miDebuggerPath = XTENSA_TOOL || ''; - await writeFile(Launchfile, JSON.stringify(launchJson, null, "\t")); - testLog(task, '成功') + const targetDir = join(process.cwd(), ".vscode"); + const formDir = join(__dirname, "..", "..", "vscode"); + const Launchfile = join(formDir, `launch_${args["env"]}.json`); + await remove(targetDir); + if (args["env"] === "csk6-dsp") { + const jlinkSNcode = + ctx.jlinkSNcode || + (await task.prompt({ + type: "input", + name: "value", + message: "请输入jlink 的 `SN` 码", + initial: ".", + })); + ctx.jlinkSNcode = jlinkSNcode; + await mkdir(targetDir); + const configFIle = join(formDir, "xt-ocd-config.xml"); + const configFileStr = await readFile(configFIle, "utf8"); + const result = configFileStr.replace(/###usbser###/g, jlinkSNcode); + await writeFile(join(targetDir, "xt-ocd-config.xml"), result, "utf-8"); + const launchJson = await readJson(Launchfile); + launchJson.configurations[0].linux.miDebuggerPath = XTENSA_TOOL || ""; + await writeFile( + join(targetDir, `launch.json`), + JSON.stringify(launchJson, null, "\t") + ); + } else { + await mkdir(targetDir); + const launchJson = await readJson(Launchfile); + launchJson.configurations[0].serverpath = JLinkGDBServerCL || ""; + launchJson.configurations[0].armToolchainPath = JLINK_TOOL || ""; + await writeFile( + join(targetDir, `launch.json`), + JSON.stringify(launchJson, null, "\t") + ); + } + testLog(task, "成功"); }, - }); -} +}; diff --git a/vscode/launch.json b/vscode/launch_csk6-dsp.json similarity index 100% rename from vscode/launch.json rename to vscode/launch_csk6-dsp.json diff --git a/vscode/launch_csk6.json b/vscode/launch_csk6.json new file mode 100644 index 0000000..2b3b833 --- /dev/null +++ b/vscode/launch_csk6.json @@ -0,0 +1,43 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "cortex-debug", + "request": "launch", + "cwd": "${workspaceRoot}", + "name": "Venus_demo_lisa_test", + "executable": "${workspaceFolder}/zephyr/build/zephyr/zephyr.elf", + "device": "Cortex-M33", + "servertype": "jlink", + "rtos": "Zephyr", + "serverpath": "C:\\Users\\alex\\mylistenai\\jlink-venus\\binary\\JLinkGDBServerCL.exe", + "armToolchainPath": "C:\\Users\\alex\\mylistenai\\jlink-venus\\bin", + "toolchainPrefix": "arm-none-eabi", + "interface": "swd", + "showDevDebugOutput": false, + "runToMain": false, + "runToEntryPoint": "__start", + "serverArgs": [ + "-timeout", + "0", + "-strict", + "-singlerun", + "-vd", + "-ir", + "-localhostonly", + "1", + "-endian", + "little" + ], + "preLaunchCommands": [ + "monitor flash erase", + "monitor clrbp", + "monitor reset" + ], + "preRestartCommands": [ + "file ${workspaceFolder}/zephyr/build/zephyr/zephyr.elf", + "load" + ] + } + ] +} \ No newline at end of file