@@ -78,7 +78,7 @@ import { ArrayDelRepetition } from '../lib/node-utility/Utility';
7878import {
7979 copyObject , downloadFileWithProgress , getDownloadUrlFromGitea ,
8080 runShellCommand , redirectHost , readGithubRepoFolder , FileCache ,
81- genGithubHash , md5
81+ genGithubHash , md5 , toArray
8282} from './utility' ;
8383import { concatSystemEnvPath , DeleteDir , exeSuffix , kill } from './Platform' ;
8484import { KeilARMOption , KeilC51Option , KeilParser , KeilRteDependence } from './KeilXmlParser' ;
@@ -96,6 +96,8 @@ import {
9696import * as eclipseParser from './EclipseProjectParser' ;
9797import { isArray } from 'util' ;
9898import { parseIarCompilerLog , CompilerDiagnostics , parseGccCompilerLog , parseArmccCompilerLog , parseKeilc51CompilerLog } from './ProblemMatcher' ;
99+ import * as iarParser from './IarProjectParser' ;
100+ import * as ArmCpuUtils from './ArmCpuUtils' ;
99101
100102enum 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 ) ;
0 commit comments