Skip to content

Commit 770734b

Browse files
committed
support import iar arm eww workbench
1 parent 374524d commit 770734b

9 files changed

Lines changed: 845 additions & 26 deletions

lang/arm.iar.verify.json

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@
232232
"type": "string",
233233
"default": "Extended-EC++",
234234
"enum": [
235+
"C++",
235236
"Embedded-C++",
236237
"Extended-EC++"
237238
]
@@ -302,12 +303,17 @@
302303
false
303304
]
304305
},
305-
"floating-point": {
306-
"description": "Floating Point",
307-
"type": "boolean",
306+
"floating-point-semantics": {
307+
"description": "Floating Point Semantics",
308+
"type": "string",
309+
"default": "strict",
308310
"enum": [
309-
true,
310-
false
311+
"strict",
312+
"relaxed"
313+
],
314+
"enumDescriptions": [
315+
"Strict Conformance",
316+
"Relaxed (smaller or faster)"
311317
]
312318
},
313319
"multibyte-support": {
@@ -448,6 +454,13 @@
448454
"type": "string"
449455
}
450456
},
457+
"LIB_FLAGS": {
458+
"description": "Additional Libraries",
459+
"type": "array",
460+
"items": {
461+
"type": "string"
462+
}
463+
},
451464
"program-entry": {
452465
"readable_name": "Program Entry",
453466
"readable_name.zh-cn": "程序入口",

lib/node-utility

Submodule node-utility updated 1 file

src/EIDEProjectExplorer.ts

Lines changed: 287 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ import { ArrayDelRepetition } from '../lib/node-utility/Utility';
7878
import {
7979
copyObject, downloadFileWithProgress, getDownloadUrlFromGitea,
8080
runShellCommand, redirectHost, readGithubRepoFolder, FileCache,
81-
genGithubHash, md5
81+
genGithubHash, md5, toArray
8282
} from './utility';
8383
import { concatSystemEnvPath, DeleteDir, exeSuffix, kill } from './Platform';
8484
import { KeilARMOption, KeilC51Option, KeilParser, KeilRteDependence } from './KeilXmlParser';
@@ -96,6 +96,8 @@ import {
9696
import * as eclipseParser from './EclipseProjectParser';
9797
import { isArray } from 'util';
9898
import { parseIarCompilerLog, CompilerDiagnostics, parseGccCompilerLog, parseArmccCompilerLog, parseKeilc51CompilerLog } from './ProblemMatcher';
99+
import * as iarParser from './IarProjectParser';
100+
import * as ArmCpuUtils from './ArmCpuUtils';
99101

100102
enum TreeItemType {
101103
SOLUTION,
@@ -1420,11 +1422,295 @@ class ProjectDataProvider implements vscode.TreeDataProvider<ProjTreeItem> {
14201422
case 'eclipse':
14211423
this.ImportEclipseProject(option).catch(err => catchErr(err));
14221424
break;
1425+
case 'iar':
1426+
this.ImportIarProject(option).catch(err => catchErr(err));
1427+
break;
14231428
default:
14241429
break;
14251430
}
14261431
}
14271432

1433+
private async ImportIarProject(option: ImportOptions) {
1434+
1435+
if (!ToolchainManager.getInstance().isToolchainPathReady('IAR_ARM')) {
1436+
const msg = `Your 'IAR_ARM' toolchain path is invalid, we suggest that you set it before start to import !`;
1437+
const ans = await vscode.window.showWarningMessage(msg, `Ok`, 'Skip');
1438+
if (ans != 'Skip') {
1439+
if (ans == 'Ok') { // jump to setup toolchain
1440+
vscode.commands.executeCommand('eide.operation.install_toolchain');
1441+
}
1442+
return;
1443+
}
1444+
}
1445+
1446+
const ewwInfo = await iarParser.parseIarWorkbench(
1447+
new File(option.projectFile.path), SettingManager.GetInstance().getIarForArmDir());
1448+
const ewwRoot = new File(option.projectFile.dir);
1449+
1450+
let projectnum = 0;
1451+
for (const _ in ewwInfo.projects) projectnum++;
1452+
1453+
if (projectnum == 0)
1454+
throw new Error(`Not found any project in this IAR workbench ! [path]: ${option.projectFile.path}`);
1455+
1456+
// store vscode workspace
1457+
const vscWorkspaceFile = File.fromArray([ewwRoot.path, `${ewwInfo.name}.code-workspace`]);
1458+
{
1459+
const vscWorkspace = {
1460+
"folders": <any[]>[]
1461+
};
1462+
1463+
for (const projpath in ewwInfo.projects) {
1464+
const repath = ewwRoot.ToRelativePath(projpath) || projpath;
1465+
const project = ewwInfo.projects[projpath];
1466+
vscWorkspace.folders.push({
1467+
name: project.name,
1468+
path: NodePath.dirname(repath)
1469+
});
1470+
}
1471+
1472+
fs.writeFileSync(vscWorkspaceFile.path, JSON.stringify(vscWorkspace, undefined, 4));
1473+
}
1474+
1475+
const toolchainType: ToolchainName = 'IAR_ARM';
1476+
1477+
//
1478+
let project0workspacefile: File = <any>undefined;
1479+
for (const path_ in ewwInfo.projects) {
1480+
1481+
const iarproj = ewwInfo.projects[path_];
1482+
const prjRoot = new File(NodePath.dirname(path_));
1483+
1484+
const basePrj = AbstractProject.NewProject().createBase({
1485+
name: iarproj.name,
1486+
projectName: iarproj.name,
1487+
type: 'ARM',
1488+
outDir: prjRoot
1489+
}, false);
1490+
1491+
if (!project0workspacefile)
1492+
project0workspacefile = basePrj.workspaceFile;
1493+
1494+
const eidePrjCfg = basePrj.prjConfig.config;
1495+
const eideFolder = File.fromArray([prjRoot.path, AbstractProject.EIDE_DIR]);
1496+
1497+
// set project env
1498+
{
1499+
const envFile = File.fromArray([eideFolder.path, 'env.ini']);
1500+
const envCont = [
1501+
`###########################################################`,
1502+
`# project environment variables`,
1503+
`###########################################################`,
1504+
``,
1505+
];
1506+
for (const key in iarproj.envs) {
1507+
envCont.push(`${key} = ${iarproj.envs[key]}`);
1508+
}
1509+
envFile.Write(envCont.join(os.EOL));
1510+
}
1511+
1512+
// file groups
1513+
eidePrjCfg.virtualFolder = iarproj.fileGroups;
1514+
eidePrjCfg.outDir = 'build';
1515+
basePrj.prjConfig.setToolchain(toolchainType);
1516+
1517+
// targets
1518+
let firstTargetName: string = '';
1519+
for (const tname in iarproj.targets) {
1520+
1521+
if (!firstTargetName)
1522+
firstTargetName = tname;
1523+
1524+
const targetName = tname;
1525+
const iarTarget = iarproj.targets[tname];
1526+
1527+
const nEideTarget: ProjectTargetInfo = <any>{
1528+
excludeList: iarTarget.excludeList,
1529+
toolchain: eidePrjCfg.toolchain,
1530+
compileConfig: copyObject(eidePrjCfg.compileConfig),
1531+
uploader: eidePrjCfg.uploader,
1532+
uploadConfig: copyObject(eidePrjCfg.uploadConfig),
1533+
uploadConfigMap: copyObject(eidePrjCfg.uploadConfigMap)
1534+
};
1535+
1536+
eidePrjCfg.targets[targetName] = nEideTarget;
1537+
1538+
nEideTarget.custom_dep = {
1539+
name: 'default',
1540+
incList: [],
1541+
defineList: [],
1542+
sourceDirList: [],
1543+
libList: []
1544+
};
1545+
1546+
nEideTarget.custom_dep.defineList = toArray(iarTarget.settings['ICCARM.CCDefines']);
1547+
nEideTarget.custom_dep.incList = toArray(iarTarget.settings['ICCARM.CCIncludePath2']);
1548+
1549+
//
1550+
// compiler base config
1551+
//
1552+
const compilerMod = <ArmBaseCompileConfigModel>basePrj.prjConfig.compileConfigModel;
1553+
const compilerOpt = <ArmBaseCompileData>nEideTarget.compileConfig;
1554+
1555+
if (iarTarget.core) {
1556+
const expname = iarTarget.core;
1557+
const cpus = compilerMod.getValidCpus();
1558+
const idx = cpus.findIndex(n => expname == n || expname.toLowerCase().startsWith(n.toLowerCase()));
1559+
if (idx != -1) {
1560+
compilerOpt.cpuType = cpus[idx];
1561+
}
1562+
}
1563+
1564+
if (ArmCpuUtils.hasFpu(compilerOpt.cpuType)) {
1565+
if (iarTarget.settings['General.FPU2'] != '0') {
1566+
compilerOpt.floatingPointHardware =
1567+
ArmCpuUtils.hasFpu(compilerOpt.cpuType, true) ? 'double' : 'single';
1568+
}
1569+
}
1570+
1571+
compilerOpt.scatterFilePath = iarTarget.icfPath;
1572+
1573+
//
1574+
// builder options
1575+
//
1576+
const toolchain = ToolchainManager.getInstance().getToolchain(eidePrjCfg.type, eidePrjCfg.toolchain);
1577+
const builderConfig = toolchain.getDefaultConfig();
1578+
const builderConfigFile = File.fromArray([eideFolder.path, `${targetName.toLowerCase()}.${toolchain.configName}`]);
1579+
1580+
const iar2eideOptsMap = iarParser.IAR2EIDE_OPTS_MAP;
1581+
1582+
// set iar compiler options
1583+
for (const cfgGroupName in iar2eideOptsMap) {
1584+
1585+
const optsGrp = iar2eideOptsMap[cfgGroupName];
1586+
1587+
for (const iarsname in iar2eideOptsMap[cfgGroupName]) {
1588+
1589+
if (typeof iarTarget.settings[iarsname] != 'string')
1590+
continue;
1591+
1592+
const iarOptVal = <string>iarTarget.settings[iarsname];
1593+
1594+
for (const fieldname in optsGrp[iarsname]) {
1595+
const eideOptVal = optsGrp[iarsname][fieldname][iarOptVal];
1596+
if (eideOptVal) {
1597+
(<any>builderConfig)[cfgGroupName][fieldname] = eideOptVal;
1598+
}
1599+
}
1600+
}
1601+
}
1602+
1603+
// copy string options
1604+
1605+
const optToString = (obj: string | string[]): string => {
1606+
if (isArray(obj)) {
1607+
return obj[0];
1608+
} else {
1609+
return obj;
1610+
}
1611+
};
1612+
1613+
// linker
1614+
{
1615+
builderConfig.linker['LIB_FLAGS'] = toArray(iarTarget.settings['ILINK.IlinkAdditionalLibs']);
1616+
1617+
if (iarTarget.settings['ILINK.IlinkOverrideProgramEntryLabel'] == '1') {
1618+
builderConfig.linker['program-entry'] = optToString(iarTarget.settings['ILINK.IlinkProgramEntryLabel']);
1619+
}
1620+
1621+
builderConfig.linker['config-defines'] = toArray(iarTarget.settings['ILINK.IlinkConfigDefines']);
1622+
1623+
const extraOpts: string[] = [];
1624+
1625+
toArray(iarTarget.settings['ILINK.IlinkKeepSymbols'])
1626+
.forEach(s => extraOpts.push(`--keep ${s}`));
1627+
1628+
toArray(iarTarget.settings['ILINK.IlinkDefines'])
1629+
.forEach(s => extraOpts.push(`--define_symbol ${s}`));
1630+
1631+
if (iarTarget.settings['ILINK.IlinkUseExtraOptions'] == '1') {
1632+
toArray(iarTarget.settings['ILINK.IlinkExtraOptions'])
1633+
.forEach(opt => extraOpts.push(opt));
1634+
}
1635+
1636+
builderConfig.linker['misc-controls'] = extraOpts.join(' ');
1637+
}
1638+
1639+
// asm
1640+
{
1641+
builderConfig["asm-compiler"]['defines'] = toArray(iarTarget.settings['AARM.ADefines']);
1642+
1643+
if (iarTarget.settings['AARM.AExtraOptionsCheckV2'] == '1') {
1644+
builderConfig["asm-compiler"]['misc-controls'] =
1645+
toArray(iarTarget.settings['AARM.AExtraOptionsV2']);
1646+
}
1647+
}
1648+
1649+
// cpp
1650+
{
1651+
const extraOpts: string[] = [];
1652+
1653+
toArray(iarTarget.settings['ICCARM.PreInclude'])
1654+
.forEach(s => extraOpts.push(`--preinclude ${s}`));
1655+
1656+
if (iarTarget.settings['ICCARM.IExtraOptionsCheck'] == '1') {
1657+
toArray(iarTarget.settings['ICCARM.IExtraOptions'])
1658+
.forEach(s => extraOpts.push(s));
1659+
}
1660+
1661+
builderConfig["c/cpp-compiler"]['misc-controls'] = extraOpts.join(' ');
1662+
}
1663+
1664+
// builder tasks
1665+
{
1666+
if (iarTarget.builderActions.prebuild) {
1667+
builderConfig.beforeBuildTasks?.push({
1668+
name: 'iar prebuild',
1669+
command: iarTarget.builderActions.prebuild,
1670+
stopBuildAfterFailed: true,
1671+
});
1672+
}
1673+
1674+
if (iarTarget.builderActions.postbuild) {
1675+
builderConfig.afterBuildTasks?.push({
1676+
name: 'iar postbuild',
1677+
command: iarTarget.builderActions.postbuild
1678+
});
1679+
}
1680+
}
1681+
1682+
builderConfigFile.Write(JSON.stringify(builderConfig, undefined, 4));
1683+
}
1684+
1685+
// init current target
1686+
1687+
const tname = firstTargetName;
1688+
const curTarget: any = eidePrjCfg.targets[tname];
1689+
eidePrjCfg.mode = tname; // set current target name
1690+
for (const key in curTarget) {
1691+
if (key === 'custom_dep') {
1692+
eidePrjCfg.dependenceList =
1693+
[{ groupName: 'custom', depList: [curTarget[key]] }];
1694+
continue;
1695+
}
1696+
(<any>eidePrjCfg)[key] = curTarget[key];
1697+
}
1698+
1699+
// save all config
1700+
1701+
basePrj.prjConfig.Save();
1702+
}
1703+
1704+
// switch project
1705+
const selection = await vscode.window.showInformationMessage(
1706+
view_str$operation$import_done, continue_text, cancel_text);
1707+
if (selection === continue_text) {
1708+
WorkspaceManager.getInstance().openWorkspace(projectnum > 1
1709+
? vscWorkspaceFile
1710+
: project0workspacefile);
1711+
}
1712+
}
1713+
14281714
private async ImportEclipseProject(option: ImportOptions) {
14291715

14301716
const ePrjInfo = await eclipseParser.parseEclipseProject(option.projectFile.path);

src/EIDEProjectModules.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ export abstract class ArmBaseCompileConfigModel
536536
{ name: 'double', desc: 'double precision' }
537537
];
538538

539+
getValidCpus(): string[] {
540+
return this.cpuTypeList.filter(n => !n.startsWith(this.DIV_TAG));
541+
}
542+
539543
onPropertyChanged(key: string) {
540544
switch (key) {
541545
case 'cpuType':
@@ -985,7 +989,7 @@ export class GccCompileConfigModel extends ArmBaseCompileConfigModel {
985989
cpuType: 'Cortex-M3',
986990
floatingPointHardware: 'none',
987991
scatterFilePath: 'undefined.lds',
988-
useCustomScatterFile: false,
992+
useCustomScatterFile: true,
989993
storageLayout: { RAM: [], ROM: [] },
990994
options: 'null'
991995
};
@@ -996,7 +1000,7 @@ export class GccCompileConfigModel extends ArmBaseCompileConfigModel {
9961000
}
9971001
}
9981002

999-
export class IarArmCompileConfigModel extends ArmBaseCompileConfigModel {
1003+
class IarArmCompileConfigModel extends ArmBaseCompileConfigModel {
10001004

10011005
protected cpuTypeList = [
10021006
'ARM7EJ-S',
@@ -1040,7 +1044,7 @@ export class IarArmCompileConfigModel extends ArmBaseCompileConfigModel {
10401044
cpuType: 'Cortex-M3',
10411045
floatingPointHardware: 'none',
10421046
scatterFilePath: '${ToolchainRoot}/config/linker/ST/stm32f103x8.icf',
1043-
useCustomScatterFile: false,
1047+
useCustomScatterFile: true,
10441048
storageLayout: { RAM: [], ROM: [] },
10451049
options: 'null'
10461050
};

0 commit comments

Comments
 (0)