From adf69fe9879e3c0bc057b2a4b84bc85f56c7b2dc Mon Sep 17 00:00:00 2001 From: null Date: Mon, 17 Apr 2023 14:55:14 +0800 Subject: [PATCH 01/15] fix string spelling --- src/StringTable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/StringTable.ts b/src/StringTable.ts index 82933ca9..e4066736 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -431,7 +431,7 @@ export const view_str$prompt$setupToolchainPrefix = [ export const view_str$prompt$requestAndActivateLicence = [ `获取并激活许可证`, - `Obtain And Active Licence` + `Obtain And Activate Licence` ][langIndex]; export const view_str$prompt$requestAndActivateLicence_warn_setupPath = [ From e14bc8b3a3a76be348355b603c59a836b820cde9 Mon Sep 17 00:00:00 2001 From: null Date: Thu, 20 Apr 2023 20:42:38 +0800 Subject: [PATCH 02/15] refresh ui after reload project --- src/EIDEProjectExplorer.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index a4de289c..147f6466 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3751,9 +3751,12 @@ export class ProjectExplorer implements CustomConfigurationProvider { return; } + // close and reopen project this.dataProvider.Close(idx); - this.dataProvider.OpenProject(workspaceFile.path, true); + + // refresh explorer tree view + this.Refresh(); } private async onProjectClosed(uid: string | undefined) { From c25fc618c1a9005cdc758f355912f60f3edb10a3 Mon Sep 17 00:00:00 2001 From: null Date: Thu, 20 Apr 2023 20:46:54 +0800 Subject: [PATCH 03/15] need to confirm before remove src folder --- src/EIDEProjectExplorer.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index 147f6466..b4904fb9 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -4716,9 +4716,14 @@ export class ProjectExplorer implements CustomConfigurationProvider { } async Virtual_removeFolder(item: ProjTreeItem) { + const project = this.dataProvider.GetProjectByIndex(item.val.projectIndex); const curFolder = item.val.obj; - project.getVirtualSourceManager().removeFolder(curFolder.path); + + const answer = await vscode.window.showInformationMessage(view_str$prompt$removeSrcDir.replace('{}', curFolder.path), txt_yes, txt_no); + if (answer == txt_yes) { + project.getVirtualSourceManager().removeFolder(curFolder.path); + } } async Virtual_renameFolder(item: ProjTreeItem) { From 3f3606abd0ed47d403648950d89503772825fb8b Mon Sep 17 00:00:00 2001 From: null Date: Thu, 20 Apr 2023 20:48:00 +0800 Subject: [PATCH 04/15] fix string spelling --- src/extension.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/extension.ts b/src/extension.ts index caddc241..56add36f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -932,7 +932,7 @@ async function checkAndInstallRuntime() { if (pkgReady && pkgFile.IsFile()) { try { ChildProcess.execFileSync(pkgFile.path); - const sel = await vscode.window.showInformationMessage(`Ok ! Now you need relaunch VsCode !`, txt_yes); + const sel = await vscode.window.showInformationMessage(`Ok ! Now you need to relaunch VsCode !`, txt_yes); if (sel) { vscode.commands.executeCommand('workbench.action.reloadWindow'); } From 79bd75c66d2b31337835aa2f8333725b46a0b7ca Mon Sep 17 00:00:00 2001 From: null Date: Thu, 20 Apr 2023 21:01:29 +0800 Subject: [PATCH 05/15] compare content before save project --- src/EIDETypeDefine.ts | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index d7ee0eea..7a154699 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -245,7 +245,21 @@ export abstract class Configuration { } Save(force?: boolean): void { - this.cfgFile.Write(this.ToJson()); + + let oldContent: string | undefined; + let newContent: string | undefined = this.ToJson(); + + try { + if (this.cfgFile.IsExist()) { + oldContent = this.cfgFile.Read(); + } + } catch (error) { + GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Warning')); + } + + if (oldContent != newContent) { + this.cfgFile.Write(newContent); + } } protected afterInitConfigData() { @@ -1221,10 +1235,25 @@ export class ProjectConfiguration }; setProjectUsrCtx(data: ProjectUserContextData) { + + const usrCtxFile = this.getProjectUsrCtxFile(); + + let oldUsrCtxCont: string | undefined; + if (usrCtxFile.IsExist()) { + try { + oldUsrCtxCont = usrCtxFile.Read(); + } catch (error) { + GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Warning')); + } + } + try { - this.getProjectUsrCtxFile().Write(JSON.stringify(data, undefined, 4)); + let newUsrCtxCont = JSON.stringify(data, undefined, 4); + if (oldUsrCtxCont != newUsrCtxCont) { + usrCtxFile.Write(newUsrCtxCont); + } } catch (error) { - GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Warning')); + GlobalEvent.emit('globalLog', ExceptionToMessage(error, 'Error')); } } From eda76f0799edf0c04a38b24f9df9f0e229e78aef Mon Sep 17 00:00:00 2001 From: null Date: Thu, 20 Apr 2023 21:15:25 +0800 Subject: [PATCH 06/15] copy source options file if it's not existed when switch target --- src/EIDEProject.ts | 17 +++++++++++++++-- src/EIDETypeDefine.ts | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 7ffd066f..7bec2bc3 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -1421,8 +1421,9 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr targets[targetName] = prjConfig.cloneCurrentTarget(); } - const oldBuilderOptsFile = prjConfig.compileConfigModel + const prevBuilderOptsFile = prjConfig.compileConfigModel .getOptionsFile(this.getEideDir().path, prjConfig.config); + const prevSourcesOptsFile = this.getSourceExtraArgsCfgFile(true); // update current target name prjConfigData.mode = targetName; @@ -1485,12 +1486,24 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr .getOptionsFile(this.getEideDir().path, prjConfig.config, true); if (!optsFile.IsFile()) { try { - fs.copyFileSync(oldBuilderOptsFile.path, optsFile.path); + fs.copyFileSync(prevBuilderOptsFile.path, optsFile.path); } catch (error) { // nothing todo } } + // if source options file is not existed, copy it. + if (prevSourcesOptsFile.IsFile()) { + const srcOptsFile = File.fromArray([this.getEideDir().path, `${targetName.toLowerCase()}.files.options.yml`]); + if (!srcOptsFile.IsFile()) { + try { + fs.copyFileSync(prevSourcesOptsFile.path, srcOptsFile.path); + } catch (error) { + // nothing todo + } + } + } + this.sourceRoots.forceUpdateAllFolders(); this.virtualSource.forceUpdateAllFolders(); diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 7a154699..63d098b1 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -365,7 +365,7 @@ export interface ProjectConfigData { type: ProjectType; // cur target info (virtual node) - mode: string; // target name + mode: string; // target name (And for historical reasons, that's what it's called) excludeList: string[]; toolchain: ToolchainName; compileConfig: T; From 93b3b4786050ea98f617e22b896d9e02d8cb3273 Mon Sep 17 00:00:00 2001 From: null Date: Sat, 22 Apr 2023 19:42:39 +0800 Subject: [PATCH 07/15] no hash for template files --- src/EIDEProjectExplorer.ts | 54 +++----------------------------------- 1 file changed, 3 insertions(+), 51 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index b4904fb9..db50205d 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -3100,37 +3100,6 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco targetDir.CreateDir(true); - let templateShaStr: string | undefined; - let isVerified: boolean | undefined; - - // get template sha str - const li = templateFile.noSuffixName.split('.'); - if (li.length > 1) { - templateShaStr = li[li.length - 1]; - } - - // verify template zip - if (templateShaStr) { - const sha256 = compresser.sha256(templateFile); - if (sha256) { - const sha = md5(sha256); - isVerified = templateShaStr == sha; - } - } - - // if verify failed, notify to user - if (templateShaStr && !isVerified) { - if (templateFile.suffix != '.ewt') { // it's eide template project - const selTxt = await vscode.window.showWarningMessage( - view_str$msg$err_ept_hash, 'Yes', 'No'); - if (selTxt !== 'Yes') { - return; // user canceled - } - } else { // it's eide template workspace - vscode.window.showWarningMessage(view_str$msg$err_ewt_hash); - } - } - const err = await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: `Creating project` @@ -3163,17 +3132,6 @@ class ProjectDataProvider implements vscode.TreeDataProvider, vsco // convert .EIDE to .eide this.toLowercaseEIDEFolder(targetDir); - // if not verified, del *.sh - if (!isVerified) { - const eideFolder = File.fromArray([targetDir.path, AbstractProject.EIDE_DIR]); - if (eideFolder.IsDir()) { - eideFolder.GetList([/\-install\.sh$/i], File.EXCLUDE_ALL_FILTER) - .forEach((f) => { - try { fs.unlinkSync(f.path); } catch (err) { } - }); - } - } - // init project { const prjFile = File.fromArray([targetDir.path, AbstractProject.EIDE_DIR, AbstractProject.prjConfigName]); @@ -4491,16 +4449,10 @@ export class ProjectExplorer implements CustomConfigurationProvider { progress.report({ message: 'zipping ...' }); const err = await compresser.Zip(prjRootDir, option, distDir); - if (!err) { // export done, set hash str - const sha256 = compresser.sha256(tFile); - if (sha256) { - const hash = md5(sha256); - const name = `${tFile.dir}/${tFile.noSuffixName}.${hash}${tFile.suffix}`; - try { fs.renameSync(tFile.path, name); } catch (err) { } - } - progress.report({ message: 'export done !' }); - } else { // export failed + if (err) { GlobalEvent.emit('msg', ExceptionToMessage(err, 'Warning')); + } else { + progress.report({ message: 'export done !' }); } setTimeout(() => resolve(err), 1500); From ba967c8216351c76664bd5f911dc810bf78ec36d Mon Sep 17 00:00:00 2001 From: null Date: Mon, 24 Apr 2023 22:18:42 +0800 Subject: [PATCH 08/15] support 'global' locationType for custom flasher --- src/EIDEProjectExplorer.ts | 21 ++++++++++++++++----- src/WebInterface/WebInterface.ts | 4 ++-- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/EIDEProjectExplorer.ts b/src/EIDEProjectExplorer.ts index db50205d..f64dd0f4 100644 --- a/src/EIDEProjectExplorer.ts +++ b/src/EIDEProjectExplorer.ts @@ -6516,13 +6516,22 @@ export class ProjectExplorer implements CustomConfigurationProvider { let needReload = false; if (tarFlasher.resources[osType()]) { - if (cancel.isCancellationRequested) return; + if (cancel.isCancellationRequested) + return; const res = tarFlasher.resources[osType()]; - let installDir = res.locationType == 'global' ? new File(resManager.getEideToolsInstallDir()) : project.getRootDir(); - if (res.locationType == 'workspace') installDir = File.fromArray([project.getRootDir().path, res.location]); - if (res.zipType != 'none') { + let installDir: File; + let isFirstInstall: boolean = false; + + if (res.locationType == 'workspace') + installDir = File.fromArray([project.getRootDir().path, res.location]); + else // global + installDir = File.fromArray([resManager.getEideToolsInstallDir(), res.location]); + + // if have a resource and not install, download it + if (res.zipType != 'none' && installDir.IsDir() == false) { + reporter.report({ message: 'downloading resources' }); const buf = await downloadFile(redirectHost(res.url)); if (!(buf instanceof Buffer)) throw buf || new Error('Cannot download resource'); @@ -6534,6 +6543,8 @@ export class ProjectExplorer implements CustomConfigurationProvider { const szip = new SevenZipper(); const r = szip.UnzipSync(new File(tmpPath), installDir); GlobalEvent.emit('globalLog', newMessage('Info', r)); + + isFirstInstall = true; } if (res.setupCommand) { @@ -6549,7 +6560,7 @@ export class ProjectExplorer implements CustomConfigurationProvider { } } - needReload = res.locationType == 'global'; + needReload = isFirstInstall && res.locationType == 'global'; } if (cancel.isCancellationRequested) { diff --git a/src/WebInterface/WebInterface.ts b/src/WebInterface/WebInterface.ts index 0ae12700..f14c7eec 100644 --- a/src/WebInterface/WebInterface.ts +++ b/src/WebInterface/WebInterface.ts @@ -163,9 +163,9 @@ export interface ShellFlasherIndexItem { locationType: 'workspace' | 'global'; /** - * if 'locationType' == 'workspace', this field means tool install path + * if 'locationType' == 'workspace', Install Dir is '${workspaceFolder}/' * - * if 'locationType' == 'global', this field means tool exe file dir path + * if 'locationType' == 'global', Install Dir is '${userHome}/.eide/tools/' */ location: string; From 1ba6b48a1ad1116fa51d2e965ffb185c29054d00 Mon Sep 17 00:00:00 2001 From: null Date: Mon, 24 Apr 2023 22:22:08 +0800 Subject: [PATCH 09/15] fix incompatible options for cpptools --- src/EIDEProject.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 7bec2bc3..566442c9 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -2986,7 +2986,8 @@ class EIDEProject extends AbstractProject { settings['C_Cpp.default.configurationProvider'] = this.extensionId; } - if (settings['C_Cpp.errorSquiggles'] === undefined) { + if (settings['C_Cpp.errorSquiggles'] == undefined || + settings['C_Cpp.errorSquiggles'] == 'Disabled') { settings['C_Cpp.errorSquiggles'] = "disabled"; } From a3367aebccf92232da009e12151e4ab1faec9951 Mon Sep 17 00:00:00 2001 From: null Date: Tue, 25 Apr 2023 21:39:06 +0800 Subject: [PATCH 10/15] add some system vars --- src/EIDEProject.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/EIDEProject.ts b/src/EIDEProject.ts index 566442c9..f71b5325 100644 --- a/src/EIDEProject.ts +++ b/src/EIDEProject.ts @@ -2259,6 +2259,14 @@ export abstract class AbstractProject implements CustomConfigurationProvider, Pr this.registerBuiltinVar('ConfigName', () => this.GetConfiguration().config.mode); this.registerBuiltinVar('ProjectRoot', () => this.getRootDir().path); this.registerBuiltinVar('ExecutableName', () => this.getExecutablePathWithoutSuffix()); + + // system vars + this.registerBuiltinVar('SYS_Platform', () => platform.osType()); + this.registerBuiltinVar('SYS_DirSep', () => File.sep); + this.registerBuiltinVar('SYS_DirSeparator', () => File.sep); + this.registerBuiltinVar('SYS_PathSep', () => platform.osType() != 'win32' ? ':' : ';'); + this.registerBuiltinVar('SYS_PathSeparator', () => platform.osType() != 'win32' ? ':' : ';'); + this.registerBuiltinVar('SYS_EOL', () => os.EOL); } private RegisterEvent(): void { From cfa484b1aefd305e99af0f2b2bc34b43ba27116b Mon Sep 17 00:00:00 2001 From: magmell Date: Thu, 20 Apr 2023 14:15:19 +0800 Subject: [PATCH 11/15] feat: add MIPS toolchain support - Implement MIPS (MTI) toolchain support for *nix and MinGW64 platforms as the MTI_GCC (MIPS MTI GCC Compiler) project type. - Default to a baseline set of MIPS compiler flags. - Add barebones GCC Model data in /res/data/models/*/mips.gcc.model.json. Co-authored-by: Yu Shen Signed-off-by: Mingcong Bai --- lang/mips.mti.gcc.verify.json | 376 ++++++++++++++++++++++ package.json | 16 + package.nls.json | 5 +- package.nls.zh-CN.json | 3 + res/data/models/unix/mips.gcc.model.json | 305 ++++++++++++++++++ res/data/models/win32/mips.gcc.model.json | 305 ++++++++++++++++++ res/tools/linux/7z/7za | Bin src/CodeBuilder.ts | 28 ++ src/EIDEProjectModules.ts | 102 ++++++ src/EIDETypeDefine.ts | 67 ++-- src/OperationExplorer.ts | 15 +- src/SettingManager.ts | 14 + src/StringTable.ts | 5 + src/ToolchainManager.ts | 238 +++++++++++++- 14 files changed, 1452 insertions(+), 27 deletions(-) create mode 100644 lang/mips.mti.gcc.verify.json create mode 100644 res/data/models/unix/mips.gcc.model.json create mode 100644 res/data/models/win32/mips.gcc.model.json mode change 100644 => 100755 res/tools/linux/7z/7za diff --git a/lang/mips.mti.gcc.verify.json b/lang/mips.mti.gcc.verify.json new file mode 100644 index 00000000..e6f31967 --- /dev/null +++ b/lang/mips.mti.gcc.verify.json @@ -0,0 +1,376 @@ +{ + "title": "MIPS GCC Options", + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "object", + "definitions": { + "FLAGS": { + "markdownDescription": "Other Options", + "description.zh-cn": "其他选项", + "size": "huge", + "type": [ + "string", + "array" + ], + "items": { + "type": "string" + }, + "default": [] + } + }, + "properties": { + "beforeBuildTasks": { + "markdownDescription": "List of commands to execute before build", + "description.zh-cn": "构建前要执行的命令列表", + "type": "array", + "default": [ + { + "name": "clean", + "command": "del /Q \"${OutDir}\\*.*\"" + } + ], + "items": { + "type": "object", + "required": [ + "name", + "command" + ], + "properties": { + "name": { + "markdownDescription": "A readable name for display", + "description.zh-cn": "用于显示的可读名称", + "type": "string" + }, + "command": { + "markdownDescription": "Shell command line", + "description.zh-cn": "Shell 命令行", + "type": "string" + }, + "disable": { + "markdownDescription": "Disable this command", + "description.zh-cn": "禁用此命令", + "type": "boolean", + "enum": [ + true, + false + ] + }, + "abortAfterFailed": { + "markdownDescription": "Whether to skip subsequent commands if this command failed", + "description.zh-cn": "是否在此命令失败时,跳过后续的命令", + "type": "boolean", + "enum": [ + true, + false + ] + }, + "stopBuildAfterFailed": { + "markdownDescription": "Whether to stop compiling directly when this command failed", + "description.zh-cn": "是否在此命令失败时,直接停止编译", + "type": "boolean", + "enum": [ + true, + false + ] + } + } + } + }, + "afterBuildTasks": { + "markdownDescription": "List of commands to execute after build", + "description.zh-cn": "构建结束后要执行的命令列表", + "type": "array", + "default": [ + { + "name": "clean", + "command": "del \"${OutDir}\\*._*\"" + } + ], + "items": { + "type": "object", + "required": [ + "name", + "command" + ], + "properties": { + "name": { + "markdownDescription": "A readable name for display", + "description.zh-cn": "用于显示的可读名称", + "type": "string" + }, + "command": { + "markdownDescription": "Shell command line", + "description.zh-cn": "Shell 命令行", + "type": "string" + }, + "disable": { + "markdownDescription": "Disable this command", + "description.zh-cn": "禁用此命令", + "type": "boolean", + "enum": [ + true, + false + ] + }, + "abortAfterFailed": { + "markdownDescription": "Whether to skip subsequent commands if this command failed", + "description.zh-cn": "是否在此命令失败时,跳过后续的命令", + "type": "boolean", + "enum": [ + true, + false + ] + } + } + } + }, + "global": { + "markdownDescription": "Global Options", + "description.zh-cn": "全局选项", + "type": "object", + "properties": { + "output-debug-info": { + "markdownDescription": "Output debug information", + "description.zh-cn": "输出调试信息", + "type": "string", + "default": "disable", + "enum": [ + "disable", + "enable", + "dwarf-2", + "dwarf-3" + ] + }, + "$float-abi-type": { + "markdownDescription": "Hardware floating-point ABI", + "description.zh-cn": "硬件浮点 ABI", + "type": "string", + "default": "softfp", + "enum": [ + "soft-float", + "hard-float" + ] + }, + "arch": { + "markdownDescription": "Arch", + "description.zh-cn": "指令集(arch)", + "size": "small", + "type": "string", + "auto_complete_ctx": "gcc.compiler.archs" + }, + "abi": { + "readable_name": "ABI", + "readable_name.zh-cn": "调用约定(abi)", + "markdownDescription": "Integer and floating-point calling convention", + "description.zh-cn": "整数和浮点调用约定", + "size": "small", + "auto_complete_ctx": "gcc.compiler.abis" + }, + "misc-control": { + "markdownDescription": "Other Global Options", + "description.zh-cn": "编译器附加选项(全局)", + "$ref": "#/definitions/FLAGS", + "default": "" + } + } + }, + "c/cpp-compiler": { + "markdownDescription": "C/C++ Compiler Options", + "description.zh-cn": "C/C++ 编译器选项", + "type": "object", + "properties": { + "language-c": { + "markdownDescription": "C Standard", + "description.zh-cn": "C 标准", + "type": "string", + "default": "c11", + "enum": [ + "c89", + "c90", + "c99", + "c11", + "c17", + "gnu89", + "gnu90", + "gnu99", + "gnu11", + "gnu17" + ] + }, + "language-cpp": { + "markdownDescription": "C++ Standard", + "description.zh-cn": "C++ 标准", + "type": "string", + "default": "c++11", + "enum": [ + "c++98", + "gnu++98", + "c++11", + "gnu++11", + "c++14", + "gnu++14", + "c++17", + "gnu++17" + ] + }, + "optimization": { + "markdownDescription": "Optimization Level", + "description.zh-cn": "代码优化级别", + "type": "string", + "default": "level-0", + "enum": [ + "level-0", + "level-1", + "level-2", + "level-3", + "level-size", + "level-fast", + "level-debug" + ], + "enumDescriptions": [ + "-O0 (default)", + "-O1", + "-O2", + "-O3", + "-Os", + "-Ofast", + "-Og" + ] + }, + "warnings": { + "markdownDescription": "Warning Level", + "description.zh-cn": "警告等级", + "type": "string", + "default": "all-warnings", + "enum": [ + "no-warnings", + "all-warnings" + ] + }, + "turn-warning-into-errors": { + "markdownDescription": "Turn warnings into errors", + "description.zh-cn": "将警告转化为错误", + "type": "boolean" + }, + "one-elf-section-per-function": { + "markdownDescription": "One ELF Section per Function", + "type": "boolean" + }, + "one-elf-section-per-data": { + "markdownDescription": "One ELF Section per Data", + "type": "boolean" + }, + "C_FLAGS": { + "markdownDescription": "Other C Compiler Options", + "description.zh-cn": "C 编译器附加选项", + "$ref": "#/definitions/FLAGS", + "default": "" + }, + "CXX_FLAGS": { + "markdownDescription": "Other C++ Compiler Options", + "description.zh-cn": "C++ 编译器附加选项", + "$ref": "#/definitions/FLAGS", + "default": "" + } + } + }, + "asm-compiler": { + "markdownDescription": "Assembler Options", + "description.zh-cn": "汇编器选项", + "type": "object", + "properties": { + "defines": { + "readable_name": "Preprocessor Definitions", + "readable_name.zh-cn": "预处理器定义", + "markdownDescription": "Preprocessor Definitions", + "description.zh-cn": "预处理器定义", + "type": "array", + "items": { + "type": "string" + } + }, + "ASM_FLAGS": { + "markdownDescription": "Other Assembler Options", + "description.zh-cn": "汇编器附加选项", + "$ref": "#/definitions/FLAGS", + "default": "" + } + } + }, + "linker": { + "markdownDescription": "Linker Options", + "description.zh-cn": "链接器选项", + "type": "object", + "properties": { + "output-format": { + "type": "string", + "default": "elf", + "description": "Output Format", + "description.zh-cn": "输出格式", + "enum": [ + "elf", + "lib" + ], + "enumDescriptions": [ + "ELF", + "LIB" + ] + }, + "$disableOutputTask": { + "type": "boolean", + "markdownDescription": "Not Output Hex/Bin File", + "description.zh-cn": "不生成 Hex/Bin 文件", + "enum": [ + true, + false + ] + }, + "remove-unused-input-sections": { + "markdownDescription": "Remove Unused Input Sections", + "type": "boolean" + }, + "not-print-mem-usage": { + "markdownDescription": "Not Print Memory Usage (disable: -Wl,--print-memory-usage)", + "type": "boolean" + }, + "LD_FLAGS": { + "readable_name": "Other Linker Options", + "readable_name.zh-cn": "链接器附加选项", + "markdownDescription": "Use '-Wl[,option]...' pass options to the linker", + "description.zh-cn": "使用 '-Wl[,option]...' 传递链接器选项", + "$ref": "#/definitions/FLAGS", + "default": "" + }, + "LIB_FLAGS": { + "readable_name": "Lib Flags", + "readable_name.zh-cn": "链接库选项", + "markdownDescription": "Lib Flags, like: -lxxx", + "description.zh-cn": "链接库选项,例如:-lxxx", + "$ref": "#/definitions/FLAGS", + "default": "" + }, + "object-order": { + "type": "array", + "readable_name": "Object Order", + "readable_name.zh-cn": "Object Order", + "markdownDescription": "Object Order (used to determine the order in which object files are linked)", + "description.zh-cn": "Object Order(用于决定某些 obj 文件的链接顺序)", + "default": [], + "properties": { + "pattern": { + "type": "string", + "readable_name": "Pattern", + "description": "A glob pattern (https://github.com/dazinator/DotNet.Glob) to match a object (*.o) file", + "default": "**/your/pattern/for/object/file/path/*.o" + }, + "order": { + "type": "number", + "readable_name": "Order", + "description": "An integer number (The smaller the value, the higher the priority)", + "default": 0 + } + } + } + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 0a1c3ee2..3e120228 100644 --- a/package.json +++ b/package.json @@ -442,6 +442,18 @@ "markdownDescription": "%settings.riscv.gcc.prefix%", "default": "riscv-none-embed-" }, + "EIDE.MIPS.InstallDirectory": { + "type": "string", + "scope": "resource", + "markdownDescription": "%settings.mips.gcc.install.folder%", + "default": "${userRoot}/.eide/tools/mips_mti" + }, + "EIDE.MIPS.ToolPrefix": { + "type": "string", + "scope": "resource", + "markdownDescription": "%settings.mips.gcc.prefix%", + "default": "mips-mti-elf-" + }, "EIDE.Toolchain.AnyGcc.InstallDirectory": { "type": "string", "scope": "resource", @@ -1566,6 +1578,10 @@ "fileMatch": "**/*riscv.gcc.options.json", "url": "./lang/riscv.gcc.verify.json" }, + { + "fileMatch": "**/*mips.mti.gcc.options.json", + "url": "./lang/mips.mti.gcc.verify.json" + }, { "fileMatch": "**/*.any.gcc.json", "url": "./lang/any.gcc.verify.json" diff --git a/package.nls.json b/package.nls.json index e596668d..96d4dbd0 100644 --- a/package.nls.json +++ b/package.nls.json @@ -136,7 +136,10 @@ "settings.armcc.ini": "Keil MDK-ARM `UV4.exe` or `TOOLS.INI` file path [`example: C:\\Keil_v5\\UV4\\UV4.exe`]", "settings.armcc.convert.axf": "Convert `.axf` to `.elf` for ARMCC compiler", - + + "settings.mips.gcc.install.folder": "MIPS toolchain install folder [`example: D:\\mips-mti-elf-mingw64`]", + "settings.mips.gcc.prefix": "MIPS toolchain prefix, like: `mips-mti-elf-`", + "settings.riscv.gcc.install.folder": "RISC-V toolchain install folder [`example: D:\\xpack-riscv-none-embed-gcc-8.3.0-2.3`]", "settings.riscv.gcc.prefix": "RISC-V toolchain prefix, like: `riscv-none-embed-`", diff --git a/package.nls.zh-CN.json b/package.nls.zh-CN.json index 584af732..9f5adb3b 100644 --- a/package.nls.zh-CN.json +++ b/package.nls.zh-CN.json @@ -127,6 +127,9 @@ "settings.armcc.ini": "Keil MDK-ARM `UV4.exe` 或 `TOOLS.INI` 文件路径 [`example: C:\\Keil_v5\\UV4\\UV4.exe`]", "settings.armcc.convert.axf": "编译完成后将 `.axf` 转换为 `.elf`", + "settings.mips.gcc.install.folder": "MIPS Toolchain 安装目录 [`example: D:\\mips-mti-elf-mingw64`]", + "settings.mips.gcc.prefix": "MIPS toolchain 编译器前缀,例如:`mips-mti-elf-`", + "settings.riscv.gcc.install.folder": "RISC-V Toolchain 安装目录 [`example: D:\\xpack-riscv-none-embed-gcc-8.3.0-2.3`]", "settings.riscv.gcc.prefix": "RISC-V Toolchain 编译器前缀,例如:`riscv-none-embed-`", diff --git a/res/data/models/unix/mips.gcc.model.json b/res/data/models/unix/mips.gcc.model.json new file mode 100644 index 00000000..bc8b7598 --- /dev/null +++ b/res/data/models/unix/mips.gcc.model.json @@ -0,0 +1,305 @@ +{ + "name": "MIPS GCC", + "id": "GCC", + "toolPrefix": "mips-mti-elf-", + "useUnixPath": true, + "version": { + "args": "--version", + "matcher": "\\((?.*?)\\) (?\\d+\\.\\d+\\.\\d+)" + }, + "global": { + "arch": { + "type": "value", + "command": "-march=", + "group": [ + "c", + "cpp", + "asm", + "linker" + ], + "location": "first" + }, + "abi": { + "type": "value", + "command": "-mabi=", + "group": [ + "c", + "cpp", + "asm", + "linker" + ], + "location": "first" + }, + "optimization": { + "type": "selectable", + "command": { + "false": "-O0", + "level-0": "-O0", + "level-1": "-O1", + "level-2": "-O2", + "level-3": "-O3", + "level-size": "-Os", + "level-fast": "-Ofast", + "level-debug": "-Og" + }, + "group": [ + "c", + "cpp" + ] + }, + "turn-warning-into-errors": { + "type": "selectable", + "command": { + "true": "-Werror", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "warnings": { + "type": "selectable", + "command": { + "false": "", + "no-warnings": "-w", + "all-warnings": "-Wall" + }, + "group": [ + "c", + "cpp" + ] + }, + "output-debug-info": { + "type": "selectable", + "command": { + "enable": "-g", + "disable": "", + "dwarf-2": "-g -gdwarf-2", + "dwarf-3": "-g -gdwarf-3", + "false": "" + }, + "group": [ + "c", + "cpp", + "asm" + ] + }, + "C_FLAGS": { + "type": "list", + "command": "", + "group": [ + "c" + ] + }, + "CXX_FLAGS": { + "type": "list", + "command": "", + "group": [ + "cpp" + ] + }, + "ASM_FLAGS": { + "type": "list", + "command": "", + "group": [ + "asm" + ] + }, + "LD_FLAGS": { + "type": "list", + "command": "", + "group": [ + "linker" + ] + }, + "misc-control": { + "type": "list", + "command": "", + "group": [ + "c", + "cpp", + "asm", + "linker" + ] + }, + "one-elf-section-per-function": { + "type": "selectable", + "command": { + "true": "-ffunction-sections", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "one-elf-section-per-data": { + "type": "selectable", + "command": { + "true": "-fdata-sections", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "remove-unused-input-sections": { + "type": "selectable", + "command": { + "true": "-Wl,--gc-sections", + "false": "" + }, + "group": [ + "linker" + ] + } + }, + "groups": { + "c": { + "$path": "bin/${toolPrefix}gcc", + "$includes": { + "body": "-I${value}" + }, + "$defines": { + "body": "-D${key}=\"${value}\"" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$default": [ + "-c", + "-xc" + ], + "$language-c": { + "type": "keyValue", + "command": "-std=", + "enum": { + "default": "c11", + "c89": "c89", + "c90": "c90", + "c99": "c99", + "c11": "c11", + "c1x": "c1x", + "c17": "c17", + "gnu89": "gnu89", + "gnu90": "gnu90", + "gnu99": "gnu99", + "gnu11": "gnu11", + "gnu1x": "gnu1x", + "gnu17": "gnu17" + } + } + }, + "cpp": { + "$path": "bin/${toolPrefix}gcc", + "$includes": { + "body": "-I${value}" + }, + "$defines": { + "body": "-D${key}=\"${value}\"" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$default": [ + "-c", + "-xc++" + ], + "$language-cpp": { + "type": "keyValue", + "command": "-std=", + "enum": { + "default": "c++11", + "c++98": "c++98", + "gnu++98": "gnu++98", + "c++11": "c++11", + "gnu++11": "gnu++11", + "c++14": "c++14", + "gnu++14": "gnu++14", + "c++17": "c++17", + "gnu++17": "gnu++17" + } + } + }, + "asm": { + "$path": "bin/${toolPrefix}gcc", + "$includes": { + "body": "-I${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$default": [ + "-c", + "-x assembler-with-cpp" + ], + "defines": { + "type": "list", + "command": "-D" + } + }, + "linker": { + "$path": "bin/${toolPrefix}gcc", + "$libs": { + "body": "-L${value}" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$default": [], + "$output": "-o ${out} ${in} ${lib_flags}", + "$outputSuffix": ".elf", + "$linkMap": { + "type": "value", + "command": "-Wl,-Map=${mapPath}" + }, + "$LIB_FLAGS": { + "type": "list", + "command": "" + }, + "linker-script": { + "type": "list", + "command": "-T " + }, + "not-print-mem-usage": { + "type": "selectable", + "command": { + "true": "", + "false": "-Wl,--print-memory-usage" + } + }, + "$outputBin": [ + { + "name": "output hex file", + "toolPath": "bin/${toolPrefix}objcopy", + "outputSuffix": ".hex", + "command": "-O ihex ${linkerOutput} ${output}" + }, + { + "name": "output bin file", + "toolPath": "bin/${toolPrefix}objcopy", + "outputSuffix": ".bin", + "command": "-O binary ${linkerOutput} ${output}" + } + ] + }, + "linker-lib": { + "$path": "bin/${toolPrefix}ar", + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-rcv ${out} ${in}", + "$outputSuffix": ".a" + } + } +} \ No newline at end of file diff --git a/res/data/models/win32/mips.gcc.model.json b/res/data/models/win32/mips.gcc.model.json new file mode 100644 index 00000000..2df7c3ac --- /dev/null +++ b/res/data/models/win32/mips.gcc.model.json @@ -0,0 +1,305 @@ +{ + "name": "MIPS GCC", + "id": "GCC", + "toolPrefix": "mips-mti-elf-", + "useUnixPath": true, + "version": { + "args": "--version", + "matcher": "\\((?.*?)\\) (?\\d+\\.\\d+\\.\\d+)" + }, + "global": { + "arch": { + "type": "value", + "command": "-march=", + "group": [ + "c", + "cpp", + "asm", + "linker" + ], + "location": "first" + }, + "abi": { + "type": "value", + "command": "-mabi=", + "group": [ + "c", + "cpp", + "asm", + "linker" + ], + "location": "first" + }, + "optimization": { + "type": "selectable", + "command": { + "false": "-O0", + "level-0": "-O0", + "level-1": "-O1", + "level-2": "-O2", + "level-3": "-O3", + "level-size": "-Os", + "level-fast": "-Ofast", + "level-debug": "-Og" + }, + "group": [ + "c", + "cpp" + ] + }, + "turn-warning-into-errors": { + "type": "selectable", + "command": { + "true": "-Werror", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "warnings": { + "type": "selectable", + "command": { + "false": "", + "no-warnings": "-w", + "all-warnings": "-Wall" + }, + "group": [ + "c", + "cpp" + ] + }, + "output-debug-info": { + "type": "selectable", + "command": { + "enable": "-g", + "disable": "", + "dwarf-2": "-g -gdwarf-2", + "dwarf-3": "-g -gdwarf-3", + "false": "" + }, + "group": [ + "c", + "cpp", + "asm" + ] + }, + "C_FLAGS": { + "type": "list", + "command": "", + "group": [ + "c" + ] + }, + "CXX_FLAGS": { + "type": "list", + "command": "", + "group": [ + "cpp" + ] + }, + "ASM_FLAGS": { + "type": "list", + "command": "", + "group": [ + "asm" + ] + }, + "LD_FLAGS": { + "type": "list", + "command": "", + "group": [ + "linker" + ] + }, + "misc-control": { + "type": "list", + "command": "", + "group": [ + "c", + "cpp", + "asm", + "linker" + ] + }, + "one-elf-section-per-function": { + "type": "selectable", + "command": { + "true": "-ffunction-sections", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "one-elf-section-per-data": { + "type": "selectable", + "command": { + "true": "-fdata-sections", + "false": "" + }, + "group": [ + "c", + "cpp" + ] + }, + "remove-unused-input-sections": { + "type": "selectable", + "command": { + "true": "-Wl,--gc-sections", + "false": "" + }, + "group": [ + "linker" + ] + } + }, + "groups": { + "c": { + "$path": "bin\\${toolPrefix}gcc.exe", + "$includes": { + "body": "-I${value}" + }, + "$defines": { + "body": "-D${key}=\"${value}\"" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$default": [ + "-c", + "-xc" + ], + "$language-c": { + "type": "keyValue", + "command": "-std=", + "enum": { + "default": "c11", + "c89": "c89", + "c90": "c90", + "c99": "c99", + "c11": "c11", + "c1x": "c1x", + "c17": "c17", + "gnu89": "gnu89", + "gnu90": "gnu90", + "gnu99": "gnu99", + "gnu11": "gnu11", + "gnu1x": "gnu1x", + "gnu17": "gnu17" + } + } + }, + "cpp": { + "$path": "bin\\${toolPrefix}gcc.exe", + "$includes": { + "body": "-I${value}" + }, + "$defines": { + "body": "-D${key}=\"${value}\"" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$default": [ + "-c", + "-xc++" + ], + "$language-cpp": { + "type": "keyValue", + "command": "-std=", + "enum": { + "default": "c++11", + "c++98": "c++98", + "gnu++98": "gnu++98", + "c++11": "c++11", + "gnu++11": "gnu++11", + "c++14": "c++14", + "gnu++14": "gnu++14", + "c++17": "c++17", + "gnu++17": "gnu++17" + } + } + }, + "asm": { + "$path": "bin\\${toolPrefix}gcc.exe", + "$includes": { + "body": "-I${value}" + }, + "$output": "-o ${out} -MMD ${in}", + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$default": [ + "-c", + "-x assembler-with-cpp" + ], + "defines": { + "type": "list", + "command": "-D" + } + }, + "linker": { + "$path": "bin\\${toolPrefix}gcc.exe", + "$libs": { + "body": "-L${value}" + }, + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$default": [], + "$output": "-o ${out} ${in} ${lib_flags}", + "$outputSuffix": ".elf", + "$linkMap": { + "type": "value", + "command": "-Wl,-Map=${mapPath}" + }, + "$LIB_FLAGS": { + "type": "list", + "command": "" + }, + "linker-script": { + "type": "list", + "command": "-T " + }, + "not-print-mem-usage": { + "type": "selectable", + "command": { + "true": "", + "false": "-Wl,--print-memory-usage" + } + }, + "$outputBin": [ + { + "name": "output hex file", + "toolPath": "bin\\${toolPrefix}objcopy.exe", + "outputSuffix": ".hex", + "command": "-O ihex ${linkerOutput} ${output}" + }, + { + "name": "output bin file", + "toolPath": "bin\\${toolPrefix}objcopy.exe", + "outputSuffix": ".bin", + "command": "-O binary ${linkerOutput} ${output}" + } + ] + }, + "linker-lib": { + "$path": "bin\\${toolPrefix}ar.exe", + "$invoke": { + "useFile": true, + "body": "@${value}" + }, + "$output": "-rcv ${out} ${in}", + "$outputSuffix": ".a" + } + } +} \ No newline at end of file diff --git a/res/tools/linux/7z/7za b/res/tools/linux/7z/7za old mode 100644 new mode 100755 diff --git a/src/CodeBuilder.ts b/src/CodeBuilder.ts index 0937e3d8..473e37ac 100644 --- a/src/CodeBuilder.ts +++ b/src/CodeBuilder.ts @@ -577,6 +577,8 @@ export abstract class CodeBuilder { return new AnyGccCodeBuilder(_project); case 'C51': return new C51CodeBuilder(_project); + case 'MIPS': + return new MipsCodeBuilder(_project); default: throw new Error(`not support this project type: '${_project.GetConfiguration().config.type}'`); } @@ -1057,6 +1059,32 @@ class RiscvCodeBuilder extends CodeBuilder { } } +class MipsCodeBuilder extends CodeBuilder { + + protected getMcuMemorySize(): MemorySize | undefined { + return undefined; + } + + protected preHandleOptions(options: ICompileOptions) { + + const config = this.project.GetConfiguration().config; + + const ldFileList: string[] = []; + config.compileConfig.linkerScriptPath.split(',') + .filter(s => s.trim() != '') + .forEach((sctPath) => { + ldFileList.push(`"${File.ToUnixPath(this.project.ToAbsolutePath(sctPath))}"`); + }); + + if (!options['linker']) { + options.linker = Object.create(null); + } + + // set linker script + options.linker['linker-script'] = ldFileList; + } +} + class AnyGccCodeBuilder extends CodeBuilder { protected getMcuMemorySize(): MemorySize | undefined { diff --git a/src/EIDEProjectModules.ts b/src/EIDEProjectModules.ts index f7fa3147..f31fc56e 100644 --- a/src/EIDEProjectModules.ts +++ b/src/EIDEProjectModules.ts @@ -432,6 +432,8 @@ export abstract class CompileConfigModel extends ConfigModel { return new AnyGccCompileConfigModel(prjConfigData); case 'GNU_SDCC_STM8': return new SdccGnuStm8CompileConfigModel(prjConfigData); + case 'MTI_GCC': + return new MipsCompileConfigModel(prjConfigData); default: throw new Error('Unsupported toolchain: ' + prjConfigData.toolchain); } @@ -1169,6 +1171,106 @@ export class RiscvCompileConfigModel extends CompileConfigModel { + + GetKeyDescription(key: string): string { + switch (key) { + case 'linkerScriptPath': + return view_str$compile$scatterFilePath; + case 'options': + return view_str$compile$options; + default: + return view_str$compile$deprecated; + } + } + + getKeyValue(key: string): string { + switch (key) { + case 'options': + return 'Object {...}'; + default: + return (this.data)[key] || 'null'; + } + } + + getKeyIcon(key: string): KeyIcon | undefined { + switch (key) { + case 'options': + return 'ConfigurationEditor_16x.svg'; + default: + return 'Property_16x.svg'; + } + } + + protected GetKeyType(key: string): FieldType { + switch (key) { + case 'linkerScriptPath': + return 'INPUT'; + case 'options': + return 'EVENT'; + default: + return 'Disable'; + } + } + + protected IsOpenFileCanSelectMany(key: string): boolean { + switch (key) { + case 'linkerScriptPath': + return true; + default: + return super.IsOpenFileCanSelectMany(key); + } + } + + protected GetOpenFileFilters(key: string): OpenFileFilter | undefined { + switch (key) { + case 'linkerScriptPath': + return { + 'linker script': ['ld', 'lds'], + 'any files': ['*'] + }; + default: + return undefined; + } + } + + protected VerifyString(key: string, input: string): string | undefined { + return undefined; + } + + protected GetSelectionList(key: string): CompileConfigPickItem[] | undefined { + return undefined; + } + + protected getEventData(key: string): EventData | undefined { + switch (key) { + case 'options': + return { + event: 'openCompileOptions' + }; + default: + return undefined; + } + } + + static getDefaultConfig(): MipsCompileData { + return { + linkerScriptPath: 'undefined.lds', + options: 'null' + }; + } + + GetDefault(): MipsCompileData { + return MipsCompileConfigModel.getDefaultConfig(); + } +} + // -------- ANY-GCC --------- // deprecated diff --git a/src/EIDETypeDefine.ts b/src/EIDETypeDefine.ts index 63d098b1..fa96c27f 100644 --- a/src/EIDETypeDefine.ts +++ b/src/EIDETypeDefine.ts @@ -1,25 +1,25 @@ /* - MIT License - - Copyright (c) 2019 github0null - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. + MIT License + + Copyright (c) 2019 github0null + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. */ import * as events from 'events'; @@ -42,7 +42,7 @@ import { ToolchainName } from './ToolchainManager'; import { HexUploaderType } from "./HexUploader"; import { VirtualSource } from "./EIDEProject"; import * as utility from './utility'; -import { CompileConfigModel, UploadConfigModel, SdccCompileConfigModel, GccCompileConfigModel, RiscvCompileConfigModel, AnyGccCompileConfigModel } from './EIDEProjectModules'; +import { CompileConfigModel, UploadConfigModel, SdccCompileConfigModel, GccCompileConfigModel, RiscvCompileConfigModel, AnyGccCompileConfigModel, MipsCompileConfigModel } from './EIDEProjectModules'; //////////////////////////////////////////////////////// @@ -77,7 +77,7 @@ export interface ProjectFileGroup extends FileGroup { // 'RISC-V': RISCV Project // 'ANY-GCC': Any GCC Toolchain Project // -export type ProjectType = 'C51' | 'ARM' | 'RISC-V' | 'ANY-GCC'; +export type ProjectType = 'C51' | 'ARM' | 'RISC-V' | 'ANY-GCC' | 'MIPS'; export interface CreateOptions { name: string; // project folder name @@ -587,6 +587,27 @@ export class ProjectConfiguration targets: {}, version: EIDE_CONF_VERSION }; + case 'MIPS': + return { + name: 'undefined', + type: type, + mode: 'Debug', + toolchain: 'MTI_GCC', + dependenceList: [], + compileConfig: MipsCompileConfigModel.getDefaultConfig(), + uploader: 'Custom', + srcDirs: [], + virtualFolder: { name: VirtualSource.rootName, files: [], folders: [] }, + excludeList: [], + outDir: 'build', + deviceName: null, + packDir: null, + uploadConfig: null, + uploadConfigMap: {}, + miscInfo: {}, + targets: {}, + version: EIDE_CONF_VERSION + }; case 'ANY-GCC': return { name: 'undefined', diff --git a/src/OperationExplorer.ts b/src/OperationExplorer.ts index 5139ee38..37f2b98c 100644 --- a/src/OperationExplorer.ts +++ b/src/OperationExplorer.ts @@ -46,7 +46,8 @@ import { view_str$prompt$setupToolchainPrefix, view_str$prompt$needReloadToUpdateEnv, view_str$operation$create_prj_done, - view_str$prompt$requestAndActivateLicence + view_str$prompt$requestAndActivateLicence, + view_str$operation$empty_mips_prj } from './StringTable'; import { CreateOptions, ImportOptions, ProjectType } from './EIDETypeDefine'; import { File } from '../lib/node-utility/File'; @@ -355,6 +356,11 @@ export class OperationExplorer { detail: 'for risc-v chips', type: 'RISC-V' }, + { + label: view_str$operation$empty_mips_prj, + detail: 'for mips chips', + type: 'MIPS' + }, { label: view_str$operation$empty_anygcc_prj, detail: 'for any gcc famliy toolchains', @@ -715,6 +721,13 @@ export class OperationExplorer { } ] }, + { + label: 'MIPS MTI GCC Compiler', + type: 'MTI_GCC', + description: this.getStatusTxt(toolchainManager.isToolchainPathReady('MTI_GCC')) + + ` Loc: ${toolchainManager.getToolchainExecutableFolder('MTI_GCC')?.path}`, + detail: view_str$operation$setToolchainInstallDir.replace('${name}', 'MTI_GCC'), + }, /* { label: 'SDCC With GNU Patch For STM8 (Only for stm8)', type: 'GNU_SDCC_STM8', diff --git a/src/SettingManager.ts b/src/SettingManager.ts index c78ede83..39d93224 100644 --- a/src/SettingManager.ts +++ b/src/SettingManager.ts @@ -591,6 +591,20 @@ export class SettingManager { return this.getConfiguration().get('RISCV.ToolPrefix') || ''; } + //------------------------------- MTI GCC ---------------------------------- + + getMipsToolFolder(): File { + return new File( + this.getFullPathByPluginConfig('MIPS.InstallDirectory') || + this.findGccCompilerRootInSystemEnv(`${this.getMipsToolPrefix()}gcc`) || + 'null' + ); + } + + getMipsToolPrefix(): string { + return this.getConfiguration().get('MIPS.ToolPrefix') || ''; + } + //------------------------------- Any GCC ---------------------------------- getAnyGccToolFolder(): File { diff --git a/src/StringTable.ts b/src/StringTable.ts index e4066736..f00b6570 100644 --- a/src/StringTable.ts +++ b/src/StringTable.ts @@ -754,6 +754,11 @@ export const view_str$operation$empty_riscv_prj = [ 'RISC-V Project' ][langIndex]; +export const view_str$operation$empty_mips_prj = [ + 'MIPS 项目', + 'MIPS Project' +][langIndex]; + export const view_str$operation$empty_anygcc_prj = [ '通用的 GCC 项目', 'Universal GCC Project' diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index e21fd8a6..1a27ba01 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -42,7 +42,7 @@ import { ICompileOptions, ArmBaseBuilderConfigData } from "./EIDEProjectModules" export type ToolchainName = 'SDCC' | 'Keil_C51' | 'IAR_STM8' | 'GNU_SDCC_STM8' | 'COSMIC_STM8' | 'AC5' | 'AC6' | 'GCC' | 'IAR_ARM' | - 'RISCV_GCC' | 'ANY_GCC' | 'None'; + 'RISCV_GCC' | 'ANY_GCC' | 'MTI_GCC' | 'None'; export interface IProjectInfo { @@ -160,6 +160,7 @@ export class ToolchainManager { 'C51': ['Keil_C51', 'SDCC', 'IAR_STM8', 'COSMIC_STM8'], 'ARM': ['AC5', 'AC6', 'GCC', 'IAR_ARM'], 'RISC-V': ['RISCV_GCC'], + 'MIPS': ['MTI_GCC'], 'ANY-GCC': ['ANY_GCC'] }; @@ -191,6 +192,7 @@ export class ToolchainManager { this.add(new RISCV_GCC()); this.add(new AnyGcc()); this.add(new IARARM()); + this.add(new MTI_GCC()); } on(event: 'onChanged', listener: (toolchainName: ToolchainName) => void): void; @@ -250,6 +252,9 @@ export class ToolchainManager { } } break; + case 'MIPS': + res = this.toolchainMap.get('MTI_GCC'); + break; default: throw new Error('Invalid project type \'' + prjType + '\''); } @@ -293,6 +298,8 @@ export class ToolchainManager { return 'Any GNU Toolchain'; case 'COSMIC_STM8': return 'COSMIC STM8 C Compiler'; + case 'MTI_GCC': + return 'MIPS MTI GCC Compiler'; default: return ''; } @@ -415,6 +422,8 @@ export class ToolchainManager { return File.fromArray([settingManager.getSdccDir().path, 'bin']); case 'RISCV_GCC': return File.fromArray([settingManager.getRiscvToolFolder().path, 'bin']); + case 'MTI_GCC': + return File.fromArray([settingManager.getMipsToolFolder().path, 'bin']); case 'GNU_SDCC_STM8': return File.fromArray([settingManager.getGnuSdccStm8Dir().path, 'bin']); case 'ANY_GCC': @@ -1088,7 +1097,7 @@ class COSMIC_STM8 implements IToolchian { } updateCppIntellisenceCfg(builderOpts: ICompileOptions, cppToolsConfig: CppConfigItem): void { - cppToolsConfig.cStandard = 'c99'; + cppToolsConfig.cStandard = 'c99'; cppToolsConfig.cppStandard = 'c++98'; } @@ -2141,6 +2150,230 @@ class IARSTM8 implements IToolchian { } } +class MTI_GCC implements IToolchian { + readonly version = 1; + + readonly settingName: string = 'EIDE.MIPS.InstallDirectory'; + + readonly categoryName: string = 'GCC'; + + readonly name: ToolchainName = 'MTI_GCC'; + + readonly modelName: string = 'mips.mti.gcc.model.json'; + + readonly configName: string = 'mips.mti.gcc.options.json'; + + readonly verifyFileName: string = 'mips.mti.gcc.verify.json'; + + constructor() { + // nothing todo + } + + private getToolPrefix(): string { + return SettingManager.GetInstance().getMipsToolPrefix(); + } + + //----------- + + newInstance(): IToolchian { + return new MTI_GCC(); + } + + private __lastActivedTargetInfo: ToolchainTargetSupportedInfo | undefined; + getGccCompilerTargetInfo(): ToolchainTargetSupportedInfo | undefined { + + if (this.__lastActivedTargetInfo) + return this.__lastActivedTargetInfo; + + const compilerPath = this.getGccFamilyCompilerPathForCpptools(); + if (!compilerPath) + return undefined; + + try { + const machine = child_process.execFileSync(compilerPath, ['-dumpmachine']).toString().trim(); + const sysroot = child_process.execFileSync(compilerPath, ['-print-sysroot']).toString().trim(); + const libpath = `${sysroot}/lib`; + + const archs: string[] = fs.readdirSync(libpath) + .filter(n => n.startsWith('micromipsel-r2') || n.startsWith('mips-r2') || n.startsWith('mipsel-r2')) + .map(n => n.toLowerCase()); + + const lines = child_process.execFileSync(compilerPath, ['-Q', '--help=target']) + .toString().trim().split(/\r\n|\n/); + + let abis: string[] = []; + let mods: string[] = []; + + for (let index = 0; index < lines.length; index++) { + const line = lines[index]; + if (/^\s* Known MIPS ABIs/.test(line)) { + abis = lines[index + 1].trim().split(/\s+/); + } else if (/^\s*Known code models/.test(line)) { + mods = lines[index + 1].trim().split(/\s+/); + } + } + + const targetInfo: ToolchainTargetSupportedInfo = { + machine: machine, + archs: archs, + abis: abis, + rv_codeModels: mods + }; + + this.__lastActivedTargetInfo = targetInfo; + + return targetInfo; + + } catch (error) { + GlobalEvent.emit('msg', ExceptionToMessage(error, 'Hidden')); + return undefined; + } + } + + getGccFamilyCompilerPathForCpptools(): string | undefined { + const gcc = File.fromArray([this.getToolchainDir().path, 'bin', this.getToolPrefix() + `gcc${platform.exeSuffix()}`]); + return gcc.path; + } + + getToolchainPrefix(): string { + return this.getToolPrefix(); + } + + updateCppIntellisenceCfg(builderOpts: ICompileOptions, cppToolsConfig: CppConfigItem): void { + + cppToolsConfig.cStandard = 'c11'; + cppToolsConfig.cppStandard = 'c++11'; + + cppToolsConfig.compilerArgs = ['-std=${c_cppStandard}']; + + if (builderOpts.global) { + + if (builderOpts.global['arch']) { + cppToolsConfig.compilerArgs.push(`-march=${builderOpts.global['arch']}`); + } + + if (builderOpts.global['abi']) { + cppToolsConfig.compilerArgs.push(`-mabi=${builderOpts.global['abi']}`); + } + + if (typeof builderOpts.global['$float-abi-type'] == 'string') { + const abiType = builderOpts.global['$float-abi-type']; + if (abiType === 'soft-float') { + cppToolsConfig.compilerArgs.push("-msoft-float"); + } else if (abiType === 'hard-float') { + cppToolsConfig.compilerArgs.push("-mhard-float"); + } + } + + + // pass global args for cpptools + if (typeof builderOpts.global['misc-control'] == 'string') { + const pList = builderOpts.global['misc-control'].trim().split(/\s+/); + pList.forEach((p) => cppToolsConfig.compilerArgs?.push(p)); + } + } + + if (builderOpts["c/cpp-compiler"]) { + + if (builderOpts["c/cpp-compiler"]['language-c']) { + cppToolsConfig.cStandard = builderOpts["c/cpp-compiler"]['language-c']; + } + + if (builderOpts["c/cpp-compiler"]['language-cpp']) { + cppToolsConfig.cppStandard = builderOpts["c/cpp-compiler"]['language-cpp']; + } + + if (typeof builderOpts["c/cpp-compiler"]['C_FLAGS'] == 'string') { + const pList = builderOpts['c/cpp-compiler']['C_FLAGS'].trim().split(/\s+/); + cppToolsConfig.cCompilerArgs = pList; + } + + if (typeof builderOpts["c/cpp-compiler"]['CXX_FLAGS'] == 'string') { + const pList = builderOpts['c/cpp-compiler']['CXX_FLAGS'].trim().split(/\s+/); + cppToolsConfig.cppCompilerArgs = pList; + } + } + } + + preHandleOptions(prjInfo: IProjectInfo, options: ICompileOptions): void { + + // convert output lib commmand + if (options['linker'] && options['linker']['output-format'] === 'lib') { + options['linker']['$use'] = 'linker-lib'; + } + + // if region 'global' is not exist, create it + if (typeof options['global'] !== 'object') { + options['global'] = {}; + } + + // set tool prefix + options['global'].toolPrefix = this.getToolPrefix(); + } + + getToolchainDir(): File { + return SettingManager.GetInstance().getMipsToolFolder(); + } + + getInternalDefines(builderCfg: T, builderOpts: ICompileOptions): string[] { + return []; + } + + getCustomDefines(): string[] | undefined { + return undefined; + } + + getSystemIncludeList(builderOpts: ICompileOptions): string[] { + return []; + } + + getForceIncludeHeaders(): string[] | undefined { + return [ + ResManager.GetInstance().getGccForceIncludeHeaders().path + ]; + } + + getDefaultIncludeList(): string[] { + return []; + } + + getLibDirs(): string[] { + return []; + } + + getDefaultConfig(): ICompileOptions { + return { + version: this.version, + beforeBuildTasks: [], + afterBuildTasks: [], + global: { + "output-debug-info": 'enable', + "arch": "mips32r5", + "abi": "32" + }, + 'c/cpp-compiler': { + "language-c": "c11", + "language-cpp": "c++11", + "optimization": 'level-debug', + "warnings": "all-warnings", + "one-elf-section-per-function": false, + "one-elf-section-per-data": false, + "C_FLAGS": "", + "CXX_FLAGS": "" + }, + 'asm-compiler': { + "ASM_FLAGS": "" + }, + linker: { + "output-format": "elf", + "remove-unused-input-sections": true, + "LD_FLAGS": "-nostdlib -Wcast-align=strict", + "LIB_FLAGS": "-lm -lgcc" + } + }; + } +} + class RISCV_GCC implements IToolchian { readonly version = 1; @@ -2160,6 +2393,7 @@ class RISCV_GCC implements IToolchian { constructor() { // nothing todo } + /* private getIncludeList(gccDir: string): string[] | undefined { try { From 2afddeaa0135a3a723dc4a13034fdf9e1d42c98d Mon Sep 17 00:00:00 2001 From: magmell Date: Fri, 5 May 2023 14:11:11 +0800 Subject: [PATCH 12/15] fix: fix mips gcc model filename --- .../models/unix/{mips.gcc.model.json => mips.mti.gcc.model.json} | 0 .../models/win32/{mips.gcc.model.json => mips.mti.gcc.model.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename res/data/models/unix/{mips.gcc.model.json => mips.mti.gcc.model.json} (100%) rename res/data/models/win32/{mips.gcc.model.json => mips.mti.gcc.model.json} (100%) diff --git a/res/data/models/unix/mips.gcc.model.json b/res/data/models/unix/mips.mti.gcc.model.json similarity index 100% rename from res/data/models/unix/mips.gcc.model.json rename to res/data/models/unix/mips.mti.gcc.model.json diff --git a/res/data/models/win32/mips.gcc.model.json b/res/data/models/win32/mips.mti.gcc.model.json similarity index 100% rename from res/data/models/win32/mips.gcc.model.json rename to res/data/models/win32/mips.mti.gcc.model.json From afe3707a0f422e654ac20fb69392789f36a1975c Mon Sep 17 00:00:00 2001 From: magmell Date: Fri, 5 May 2023 15:02:42 +0800 Subject: [PATCH 13/15] fix: improve default parameters for MIPS MTI projects Now it compiles a simple C hello-world program successfully with an empty template. like: int main() { printf("hello"); return 0; } --- src/EIDEProjectModules.ts | 2 +- src/ToolchainManager.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EIDEProjectModules.ts b/src/EIDEProjectModules.ts index f31fc56e..93ec9659 100644 --- a/src/EIDEProjectModules.ts +++ b/src/EIDEProjectModules.ts @@ -1261,7 +1261,7 @@ export class MipsCompileConfigModel extends CompileConfigModel static getDefaultConfig(): MipsCompileData { return { - linkerScriptPath: 'undefined.lds', + linkerScriptPath: '', options: 'null' }; } diff --git a/src/ToolchainManager.ts b/src/ToolchainManager.ts index 1a27ba01..e38f0a14 100644 --- a/src/ToolchainManager.ts +++ b/src/ToolchainManager.ts @@ -2358,7 +2358,7 @@ class MTI_GCC implements IToolchian { "warnings": "all-warnings", "one-elf-section-per-function": false, "one-elf-section-per-data": false, - "C_FLAGS": "", + "C_FLAGS": "-EL", "CXX_FLAGS": "" }, 'asm-compiler': { @@ -2367,7 +2367,7 @@ class MTI_GCC implements IToolchian { linker: { "output-format": "elf", "remove-unused-input-sections": true, - "LD_FLAGS": "-nostdlib -Wcast-align=strict", + "LD_FLAGS": "-EL", "LIB_FLAGS": "-lm -lgcc" } }; From 79832e64936fd252e45cd1eae50888ae4e3754fb Mon Sep 17 00:00:00 2001 From: null Date: Fri, 5 May 2023 22:10:00 +0800 Subject: [PATCH 14/15] remove auto-gen '-I' include options for iar arm asm --- res/data/models/unix/arm.iar.model.json | 3 --- res/data/models/win32/arm.iar.model.json | 3 --- 2 files changed, 6 deletions(-) diff --git a/res/data/models/unix/arm.iar.model.json b/res/data/models/unix/arm.iar.model.json index 97355900..d2427b3c 100644 --- a/res/data/models/unix/arm.iar.model.json +++ b/res/data/models/unix/arm.iar.model.json @@ -332,9 +332,6 @@ }, "asm": { "$path": "bin/iasmarm", - "$includes": { - "body": "-I${value}" - }, "$invoke": { "useFile": true, "body": "-f ${value}" diff --git a/res/data/models/win32/arm.iar.model.json b/res/data/models/win32/arm.iar.model.json index 96632608..1d642fa3 100644 --- a/res/data/models/win32/arm.iar.model.json +++ b/res/data/models/win32/arm.iar.model.json @@ -332,9 +332,6 @@ }, "asm": { "$path": "bin\\iasmarm.exe", - "$includes": { - "body": "-I${value}" - }, "$invoke": { "useFile": true, "body": "-f ${value}" From 7280cc98b4a58bdbc36963d8e79a04324389e422 Mon Sep 17 00:00:00 2001 From: RainSlide Date: Mon, 8 May 2023 15:24:35 +0800 Subject: [PATCH 15/15] fix & optimize eide icon set 's cx from 80.285 to 80; merge paths with same color (#878787); remove unnessary rect/path. --- res/icon/icon.png | Bin 2992 -> 1299 bytes res/icon/icon.svg | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/res/icon/icon.png b/res/icon/icon.png index 630fb8115a29ed38a2086f3b9ffcd995e7c520c3..29a17dd1ab9abc631160418cc36e12ccbba24fa7 100644 GIT binary patch delta 1291 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 \ No newline at end of file + \ No newline at end of file