| /* --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 (""); |
| } |
| |