| /* --COPYRIGHT--,EPL | 
 |  *  Copyright (c) 2008 Texas Instruments and others. | 
 |  *  All rights reserved. This program and the accompanying materials | 
 |  *  are made available under the terms of the Eclipse Public License v1.0 | 
 |  *  which accompanies this distribution, and is available at | 
 |  *  http://www.eclipse.org/legal/epl-v10.html | 
 |  *  | 
 |  *  Contributors: | 
 |  *      Texas Instruments - initial implementation | 
 |  *  | 
 |  * --/COPYRIGHT--*/ | 
 | var debug; | 
 | if (debug == null) { | 
 |     debug = function (msg) {}; | 
 | } | 
 |  | 
 | var _bldUtils = xdc.useModule('xdc.bld.Utils'); | 
 |  | 
 | /* | 
 |  *  ======== _targetCmds ======== | 
 |  *  Hash table of commands (indexed by target.suffix).  Commands are | 
 |  *  themselves hashtables (indexed by file type: "asm", "c", ...) that | 
 |  *  define the commands for cc, asm , etc. | 
 |  */ | 
 | var _targetCmds = null; | 
 |  | 
 | /* | 
 |  *  ======== _targetEnvs ======== | 
 |  *  Environment variable settings required for the compile/link/archive | 
 |  *  commands. | 
 |  */ | 
 | var _targetEnvs = "LD_LIBRARY_PATH="; | 
 |  | 
 | /* | 
 |  *  ======== _thisPkg ======== | 
 |  *  This variable is initialized by this package's init method to the | 
 |  *  package containing this file.  We use this in lieu of hard coding | 
 |  *  this package's name in this file. | 
 |  */ | 
 | var _thisPkg = null; | 
 |  | 
 | /* | 
 |  *  ======== ITarget.archive ======== | 
 |  */ | 
 | function archive(goal) | 
 | { | 
 |     var target = this; | 
 |     _initTab(target); | 
 |      | 
 |     var result = null; | 
 |     var tool2cmd = _targetCmds[target.suffix]; | 
 |  | 
 |     if (tool2cmd != null) { | 
 | 	result = new xdc.om['xdc.bld'].ITarget.CommandSet; | 
 | 	result.msg = "archiving " + goal.files + " into $@ ..."; | 
 | 	result.envs = _targetEnvs.split("\n"); | 
 | 	result.cmds = _bldUtils.expandString(tool2cmd["ar"], { | 
 | 	    AROPTS_P:	target.arOpts.prefix, | 
 | 	    AROPTS_S:	target.arOpts.suffix, | 
 |             VERS:       target.VERS, | 
 |             TARG:       target.TARG, | 
 | 	    aropts:	goal.opts, | 
 | 	    files:	goal.files | 
 | 	}); | 
 |     } | 
 |  | 
 |     return (result); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== ITarget.compile ======== | 
 |  */ | 
 | function compile(goal) { | 
 |     return (_compile(this, goal, false)); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== ITarget.link ======== | 
 |  */ | 
 | function link(goal) | 
 | { | 
 |     var target = this; | 
 |     _initTab(target); | 
 |      | 
 |     var result = null; | 
 |     var tool2cmd = _targetCmds[target.suffix]; | 
 |  | 
 |     if (tool2cmd != null) { | 
 |         /* add --via option in front of linker command file */ | 
 | 	var fileList = goal.files.replace(/(^|\s+)([\/\w\\\.]+\.xdl)($|\s+)/, | 
 | 					  " --via $2 "); | 
 |  | 
 | 	result = new xdc.om['xdc.bld'].ITarget.CommandSet; | 
 | 	result.msg = "lnk" + target.suffix + " $@ ..."; | 
 | 	result.envs = _targetEnvs.split("\n"); | 
 | 	result.cmds = _bldUtils.expandString(tool2cmd["link"], { | 
 | 	    LOPTS_P:	target.lnkOpts == null ? "" : target.lnkOpts.prefix, | 
 | 	    LOPTS_S:	target.lnkOpts == null ? "" : target.lnkOpts.suffix, | 
 |             VERS:       target.VERS, | 
 |             TARG:       target.TARG, | 
 | 	    lopts:	goal.opts, | 
 | 	    files:	fileList | 
 | 	}); | 
 |     } | 
 |  | 
 |     return (result); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== ITarget.getVersion ======== | 
 |  */ | 
 | function getVersion() | 
 | { | 
 |     var target = this; | 
 |      | 
 |     _initTab(target); | 
 |  | 
 |     var result = target.$name + "{"; | 
 |     var key; | 
 |  | 
 |     if ((key = target.versionMap["arm" + target.$private.vers]) == null) { | 
 | 	/* map 2.3.4 to "1,0,2.3,4", 2.3 to "1,0,2.3", and 2 to "1,0,2" */ | 
 | 	key = "1,0"; | 
 | 	var va = target.$private.vers.split('.'); | 
 | 	for (var i = 0; i < va.length; i++) { | 
 | 	    key += (i == 1 ? '.' : ',') + va[i]; | 
 | 	} | 
 |     } | 
 |     result += key; | 
 |  | 
 |     return (result); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== ITarget.scompile ======== | 
 |  */ | 
 | function scompile(goal) { | 
 |     return (_compile(this, goal, true)); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _compile ======== | 
 |  */ | 
 | function _compile(target, goal, asm) | 
 | { | 
 |     var result = null; | 
 |  | 
 |     _initTab(target); | 
 |  | 
 |     var tool2cmd = _targetCmds[target.suffix];	/* get tool to template map */ | 
 |      | 
 |     if (tool2cmd != null) { | 
 | 	var ext = target.extensions[goal.srcSuffix]; | 
 | 	if (ext != null) { | 
 | 	    if (asm == true && ext.typ == "asm") { | 
 | 		return (null); | 
 | 	    } | 
 |  | 
 | 	    result = new xdc.om['xdc.bld'].ITarget.CommandSet; | 
 | 	    result.msg = (ext.typ == "c" ? "cl" : ext.typ) | 
 | 			    + target.suffix | 
 | 			    + (asm == true ? " -S $< ..." : " $< ..."); | 
 |      | 
 | 	    var dstDir = goal.dstPrefix + goal.base; | 
 | 	    dstDir = dstDir.replace(/[^\/\\]*$/, ""); | 
 |      | 
 | 	    result.envs = _targetEnvs.split("\n"); | 
 |      | 
 |             var ccoptsPre = target.ccOpts.prefix; | 
 |             var ccoptsSuf = target.ccOpts.suffix; | 
 |             /* If the target defines ccConfigOpts, they should be used | 
 |              * instead of ccOpts. The string expansion has to be done here, | 
 |              * in the case ccConfigOpts contains COPTS. If the expansion was | 
 |              * left for the end of the function, there would be an infinite | 
 |              * recursion. | 
 |              */ | 
 | 	    if ("ccConfigOpts" in target  | 
 | 		&& dstDir.match(/package\/cfg[\/]*$/) != null) { | 
 |                 ccoptsPre = _bldUtils.expandString(target.ccConfigOpts.prefix, | 
 |                     {"ccOpts.prefix": target.ccOpts.prefix}); | 
 |                 ccoptsSuf = _bldUtils.expandString(target.ccConfigOpts.suffix, | 
 |                     {"ccOpts.suffix": target.ccOpts.suffix}); | 
 |             } | 
 |  | 
 | 	    result.cmds = _bldUtils.expandString(tool2cmd[ext.typ], { | 
 |                 VERS:       target.VERS, | 
 |                 TARG:       target.TARG, | 
 | 		COPTS_P:    ccoptsPre, | 
 | 		COPTS_S:    ccoptsSuf, | 
 | 		AOPTS_P:    target.asmOpts.prefix, | 
 | 		AOPTS_S:    target.asmOpts.suffix, | 
 | 		ASMONLY:    asm ? "-S" : "", | 
 | 		dstDir:	    dstDir, | 
 | 		srcExt:	    goal.srcSuffix, | 
 | 		copts:	    goal.opts.copts, | 
 | 		aopts:	    goal.opts.aopts, | 
 | 		defs:	    _getDefs(ext.typ, goal.opts.defs), | 
 | 		incs:	    goal.opts.incs | 
 | 	    }); | 
 | 	} | 
 |     } | 
 |      | 
 |     return (result); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _getDefs ======== | 
 |  *  translate C-like -D options into assembler --predefine options | 
 |  *  | 
 |  * Note this translation is simplistic; it does not handle values with  | 
 |  * embedded spaces, strings, ... | 
 |  */ | 
 | function _getDefs(type, cDefs) | 
 | { | 
 |     if (type != "asm") { | 
 | 	return (cDefs); | 
 |     } | 
 |  | 
 |     /* eliminate C only xdc definitions: | 
 |      *     -Dxdc_cfg__header__='arm/targets/tests/package/cfg/hello_xea8.h'   | 
 |      *     -Dxdc_target_name__=CortexA8  | 
 |      *     -Dxdc_target_types__=arm/targets/std.h  | 
 |      */ | 
 |     var defs = cDefs.replace(/-Dxdc_(cfg__header|target_name|target_types)__=[^\s]+($|\s+)/g, ""); | 
 |      | 
 |     /* translate -Dxxx to --predefine 'xxx SETL {TRUE}' */ | 
 |     defs = defs.replace(/-D(\w+)($|\s+)/g, | 
 |         "--predefine \"$1 SETL {TRUE}\"$2"); | 
 |  | 
 |     /* translate -Dxxx=yyy to --predefine 'xxx SETA yyy' */ | 
 |     defs = defs.replace(/-D(\w+)=([^\s]+)/g, | 
 |         "--predefine \"$1 SETA $2\""); | 
 |  | 
 |     /* translate -Dxxx= to --predefine 'xxx SETA ""' */ | 
 |     defs = defs.replace(/-D(\w+)=($|\s)/g, | 
 |         "--predefine \"$1 SETA ''\""); | 
 |  | 
 |     return (defs); | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _init ======== | 
 |  *  Initialize this capsule at package init time. | 
 |  */ | 
 | function _init(pkg) | 
 | { | 
 |     _thisPkg = pkg; | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _initTab ======== | 
 |  *  Check if the target command map is already initialized, and if not  | 
 |  *  initialize it. | 
 |  */ | 
 | function _initTab(target) | 
 | { | 
 |     if (_targetCmds == null) { | 
 | 	_targetCmds = {}; | 
 |     } | 
 |  | 
 |     if (_targetCmds[target.suffix] == undefined) { | 
 |         _initVers(target); | 
 | 	_mkCmds(target); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _initVers ======== | 
 |  *  Initialize target.$private.vers if they are not already | 
 |  *  initialized by a previous call to _initVers() or by the user via | 
 |  *  the config.bld script. | 
 |  */ | 
 | function _initVers(target) | 
 | { | 
 |     if (target.$private.vers != null || target.rootDir == null) { | 
 | 	return; | 
 |     } | 
 |  | 
 |     if (target.$private.vers == null) { | 
 |         target.$private.vers = ""; | 
 |  | 
 |         if (target.VERS != null) { | 
 |             /* user specified version */ | 
 |             target.$private.vers = target.VERS.replace(/\//, '.'); | 
 |         } | 
 |         else { | 
 |             /* call compiler to get its version */ | 
 |             var result = _askcc(target); | 
 |             if (result == "") { | 
 |                 print(target.$name | 
 |                     + ": warning: can't determine armcc version; "); | 
 |                 print("Check if " + target.rootDir + "/.../armcc can run on "); | 
 |                 print(xdc.om['xdc.bld'].BuildEnvironment.hostOSName + ". "); | 
 |             } | 
 |             /* parse its ouptut */ | 
 |             var ma = result.match(/.*RVCT([\d\.]+).*\[Build ([\d]+)\].*/); | 
 |             if (ma != null) { | 
 |                 // print("arm version: " + result + ", ma = " + ma); | 
 |                 target.$private.vers = ma[1] + "." + ma[2]; | 
 |                 target.VERS = ma[1] + "/" + ma[2]; | 
 |             } | 
 |         } | 
 |  | 
 |         _check(target); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _mkCmds ======== | 
 |  */ | 
 | function _mkCmds(target) | 
 | { | 
 |     var cmd, cmdOpts; | 
 |     var tool2cmd = {}; | 
 |      | 
 |     var ccCmd = target.cc.cmd; | 
 |  | 
 |     /* define assemble command template */ | 
 |     cmdOpts = " $(AOPTS_P) " | 
 |         + target.asm.opts | 
 | 	+ " $(AOPTS_S) $(defs) $(aopts) $(incs) $(XDCINCS) " | 
 |         + target.includeOpts; | 
 |     cmd  = target.asm.cmd + cmdOpts + " -o $@ $<"; | 
 |     tool2cmd["asm"] = cmd; | 
 |  | 
 |     /* define the C compile command template */ | 
 |     cmdOpts = "$(COPTS_P) " + target.cc.opts | 
 | 	+ " $(COPTS_S) $(defs) $(copts) $(incs) $(XDCINCS) " | 
 | 	+ target.includeOpts; | 
 |     cmd = ccCmd | 
 |         + " --c99 $(ASMONLY) " + cmdOpts + " -o $@ $<"; | 
 |     tool2cmd["c"] = cmd; | 
 |  | 
 |     /* define the C++ compile command template */ | 
 |     cmd = ccCmd | 
 |         + " --cpp $(ASMONLY) " + cmdOpts + " -o $@ $<"; | 
 |     tool2cmd["cpp"] = cmd; | 
 |  | 
 |     /* define the link command template */ | 
 |     cmd = target.lnk.cmd | 
 | 	+ " $(LOPTS_P) $(lopts) -o $@ $(files) " + target.lnk.opts | 
 | 	+ " $(LOPTS_S)\n"; | 
 |     tool2cmd["link"] = cmd; | 
 |  | 
 |     /* define the ar command template */ | 
 |     cmd  = target.ar.cmd | 
 | 	+ " $(AROPTS_P) " + target.ar.opts | 
 | 	+ " $@ $(AROPTS_S) $(aropts) $(files)"; | 
 |     tool2cmd["ar"] = cmd; | 
 |  | 
 |     /* add command template set to _targetCmds */ | 
 |     _targetCmds[target.suffix] = tool2cmd; | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _check ======== | 
 |  */ | 
 | function _check(target) | 
 | { | 
 |     var err = null; | 
 |      | 
 |     /* check that VERS and TARG have been set */ | 
 |     if (target.VERS == null) { | 
 |         err = target.name + ".VERS has not been set. "; | 
 |     } | 
 |     if (target.TARG == null) { | 
 |         err += target.name + ".TARG has not been set. "; | 
 |     } | 
 |  | 
 |     /* If the armcc executable cannot be found | 
 |      * it's probably a misspelled directory path. | 
 |      */ | 
 |     if (err == null) { | 
 |         var ccCmd = target.rootDir + "/Programs/" | 
 |             + target.VERS + "/" + target.TARG + "/armcc"; | 
 |         var file = new java.io.File(ccCmd); | 
 |         if (!file.exists() | 
 |             && !(new java.io.File(ccCmd + ".exe").exists())) { | 
 |             err = ccCmd + " cannot be found. "; | 
 |         } | 
 |     } | 
 |  | 
 |     if (err != null) { | 
 |         err += "Ensure that rootDir, TARG, and VERS for the " | 
 |             + target.name + " target are set correctly in " | 
 |             + java.lang.System.getenv("XDCBUILDCFG"); | 
 |         throw new Error(err); | 
 |     } | 
 | } | 
 |  | 
 | /* | 
 |  *  ======== _askcc ======== | 
 |  */ | 
 | function _askcc(target) | 
 | { | 
 |     var opt = "--vsn"; | 
 |     if (target.LONGNAME == null) { | 
 |         throw new Error(target.name | 
 |             + ".LONGNAME is not defined. You must set either " | 
 |             + target.name + ".VERS or " + target.name + ".LONGNAME."); | 
 |     } | 
 |  | 
 |     /* If the armcc executable cannot be found | 
 |      * it's probably a misspelled directory path. | 
 |      */ | 
 |     var ccCmd = target.rootDir + "/" + target.LONGNAME; | 
 |     var file = new java.io.File(ccCmd); | 
 |     if (!file.exists() | 
 |         && !(new java.io.File(ccCmd + ".exe").exists())) { | 
 |         throw new Error(ccCmd + " cannot be found. Ensure" | 
 |             + " that rootDir and LONGNAME for the " + target.name | 
 |             + " target are set correctly in " | 
 |             + java.lang.System.getenv("XDCBUILDCFG")); | 
 |     } | 
 |  | 
 |     var licFile = java.lang.System.getenv("ARMLMD_LICENSE_FILE"); | 
 |     if (licFile == null) { | 
 |         licFile = "/apps/flames/data/arm.flames-usa1.lic:/apps/flames/data/arm.flames-eur0.lic:/apps/flames/data/arm.flames-ind2.lic"; | 
 |     } | 
 |     var attrs = { | 
 |         envs: ["ARMLMD_LICENSE_FILE=" + licFile] | 
 |     }; | 
 |     var cmd = ccCmd + " " + opt; | 
 |     var status = {}; | 
 |     if (xdc.exec(cmd, attrs, status) >= 0) { | 
 |         var va = status.output.match(/^.*RVCT[\d\.]+[^\n]+/); | 
 |         if (va != null) { | 
 |             return (va[0]); | 
 |         } | 
 |         else { | 
 |             print(target.$name + ": warning: failed to parse '" | 
 |                 + opt + "' output (= '" + status.output  | 
 |                 + "'); check compiler options"); | 
 |         } | 
 |     } | 
 |     else { | 
 |         print(target.$name + ": warning: exec of '" + cmd + "' failed:" | 
 |             + status.output + "; check tools installation"); | 
 |     } | 
 |  | 
 |     return (""); | 
 | } | 
 |  |