blob: 4922ae2072bdea6c8dd5984703f00e05e11af13d [file] [log] [blame]
/* --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 ("");
}