blob: 90e9bd4f08cad305a0554adaca25962ff9b32afe [file] [log] [blame]
/* --COPYRIGHT--,EPL
* Copyright (c) 2008-2019 Texas Instruments Incorporated
* 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 bldPkg = xdc.om["xdc.bld"];
var _Clock = xdc.module("xdc.services.global.Clock");
/*
* ======== initializeModel ========
*/
function initializeModel(args)
{
xdc.$$make_om('bld'); /* create and name this object model */
/* load build model's modules and interfaces */
xdc.loadPackage('xdc.bld');
/* init global objects */
xdc.global.Pkg = xdc.om['xdc.bld.PackageContents'];
xdc.global.Build = xdc.om['xdc.bld.BuildEnvironment'];
/* bind the root object for this model in the generic "OM" */
xdc.om.$$bind('$root', Pkg);
/* scan the package's modules and interfaces */
Build.$private.scanPkg(Pkg);
/* run the config.bld script */
var $save = xdc.global.arguments;
xdc.global.arguments = args;
Build.$private.sourceCfg(args[0]);
xdc.global.arguments = $save;
}
/*
* ======== BuildEnvironment.onInit ========
* Called when the singleton Build Module Value is first
* created.
*
* Context:
* this the Build Module Value
* Params:
* Returns:
* void
*/
function onInit() {
/*
* ======== scanPkg ========
* Read package.xdc and populate the pkg object with the
* information declared there:
* pkg.name string name of package
* pkg.modules array of modules in this package
* pkg.interfaces array of interface in this package
*
* Params:
* pkg xdc.bld.PackageContents module
*
* Returns
* void
*
* Throws
* exceptions thrown are for fatal errors
*/
function scanPkg(pkg)
{
var file = new java.io.File("package.xdc");
if (file.exists()) {
var scan = new Packages.xdc.services.intern.cmd.Scan(
xdc.$$private.Env
);
pkg.name = "" + scan.read("package.xdc", false);
pkg.$seal("name");
pkg.version = "" + scan.getKey();
pkg.$seal("version");
var a = scan.getModules();
for (var i = 0; i < a.length; i++) {
pkg.modules[pkg.modules.length++] = "" + a[i];
}
pkg.modules.$seal();
var a = scan.getInterfaces();
for (var i = 0; i < a.length; i++) {
pkg.interfaces[pkg.interfaces.length++] = "" + a[i];
}
pkg.interfaces.$seal();
var a = scan.getImports();
for (var i = 0; i < a.length; i++) {
pkg.imports[pkg.imports.length++] = "" + a[i];
}
pkg.imports.$seal();
}
}
/*
* ======== sourceCfg ========
* Source global build configuration file and do light semantic
* processing prior to running package specific build script.
* This script typically loads packages of targets and configures
* the targets for the build environment.
*
* The sourced file may set useTargets and excludeTargets and
* configure various targets. sourceCfg checks that all targets
* included have their rootDir set and propagates the rootDir
* setting to any target that declares another as its base (see
* ITarget).
*
* Params:
* file string naming the file to load and execute.
* This file is searched for along the import path
* (which includes the package path)
* Returns
* void
* Throws
* exceptions thrown are for fatal errors
*/
function sourceCfg(cfgFile)
{
/* import the user's "global" configuration of the target tools */
/* we expand to an absolute file name to ensure that importFile()
* doesn't find the file in the current script directory (which in
* this case is the bld package directory); e.g., "./config.bld"
* should be found along the import path rather than in bld/.
*/
cfgFile = (new java.io.File(cfgFile)).getAbsolutePath() + "";
xdc.$$trace("xdc.bld loading " + cfgFile, 1, ["xdccore"]);
utils.importFile(cfgFile);
/* This case, where config.bld caused an error but there is no
* exception can't be reproduced. This is most likely a leftover from
* an older error handling architecture.
*/
if (utils.hasReportedError()) {
throw xdc.$$XDCException("xdc.bld.TARGET_CONFIG_ERROR",
"Error in configuration. Check '" + cfgFile + "'");
}
_Clock.print("bld: config.bld loaded.");
/* initialize build model's native target (if necessary) */
var nativeName;
if (this.bld.nativeTarget == null) {
if (this.bld.hostOSName == "Windows") {
nativeName = "microsoft.targets.Win64";
}
else if (this.bld.hostOSName == "Linux") {
nativeName = "gnu.targets.Linux86_64";
}
else if (this.bld.hostOSName == "MacOS") {
nativeName = "gnu.targets.Mac86_64";
}
if (nativeName != null && (nativeName in xdc.om)) {
this.bld.nativeTarget = xdc.om[nativeName];
}
}
/* initialize build model's targets array (if necessary) */
if (this.bld.targets.length == 0) {
var inc, xcl;
if ((inc = this.bld.useTargets) === undefined) {
if ((inc = environment["xdc.bld.targets"]) == null) {
inc = "";
}
}
if (inc == "") {
inc = "native";
}
if (inc != null) {
if (this.bld.excludeTargets != null) {
xcl = this.bld.excludeTargets;
}
_exportTargets(this.bld.targets, inc, xcl, true);
}
}
_Clock.print("bld: exported targets.");
/* initialize all targets */
for (var i = 0; i < this.bld.targets.length; i++) {
var targ = this.bld.targets[i];
if (targ == undefined) {
throw xdc.$$XDCException("xdc.bld.TARGET_CONFIG_ERROR",
"Undefined target found in Build.targets (at index = "
+ i + "). "
+ this.bld.printBuildTargets());
}
if (targ instanceof this.bld.$package.ITarget.Module) {
var index = this.targsTab[targ.suffix];
/* check for duplicate suffixes in the target array */
if (index != null) {
var otarg = this.bld.targets[index];
var msg;
if (otarg.$name != targ.$name) {
msg = "The target '" + targ.$name
+ "' has the same suffix as the target '"
+ otarg.$name + "'";
}
else {
msg = "The target '" + targ.$name
+ "' appears more than once in the Build.targets array";
}
throw xdc.$$XDCException("xdc.bld.DUPLICATE_TARGET_ERROR",
msg);
}
this.targsTab[targ.suffix] = i; /* fill in targsTab hash */
/* white space support for Windows (CQ18010) */
if (targ.rootDir != null && targ.rootDir.match(/\s+/) &&
this.bld.hostOSName == "Windows") {
var file = xdc.module('xdc.services.io.File');
targ.rootDir = file.getDOSPath(targ.rootDir);
}
/* patch targets that fail to initialize t_Size */
var t = targ.stdTypes["t_Size"];
if (t == null || t.align == null || t.size == null) {
// print("patching target " + targ.name + "'s t_Size ...");
targ.stdTypes.$unseal();
targ.stdTypes["t_Size"] = targ.stdTypes["t_Int"];
targ.stdTypes.$seal();
}
/* propagate rootDir to targets that don't have it defined */
if (targ.rootDir == null && targ.base != null) {
targ.rootDir = targ.base.rootDir;
}
if (targ.rootDir == null) {
throw xdc.$$XDCException("xdc.bld.ROOTDIR_NOT_SET",
"'rootDir' has not been set for the target "
+ targ.$name + "; define 'rootDir' in "
+ java.lang.System.getenv("XDCBUILDCFG"));
}
/* initialize target's and platforms array and default plat */
if (targ.platforms == null) {
targ.platforms = [];
}
if (targ.platform == null) {
if (targ.platforms.length > 0) {
targ.platform = targ.platforms[0];
}
}
if (targ.platforms.length == 0) {
if (targ.platform != null) {
targ.platforms.length = 1;
targ.platforms[0] = targ.platform;
}
}
}
}
_Clock.print("bld: initialized targets defaults.");
/* seal target to prevent user from changing in package.bld */
for (var i = 0; i < this.bld.targets.length; i++) {
var targ = this.bld.targets[i];
targ.$seal(); /* must do this in a separate loop from above
* because seal follows references. A seal of
* targ will also seal targ.base; e.g., sealing
* C64 will seal the C62 before the C62 is
* initialized!
*/
}
_Clock.print("bld: targets sealed.");
/* BUG?: should we fail if bld.targets is empty? */
/* seal (make readonly) the fields that should not be modified
* by package.bld scripts
*/
this.bld.targets.$seal();
this.bld.$seal("useTargets");
this.bld.$seal("platformTable");
this.bld.$seal("excludeTargets");
this.bld.$seal("nativeTarget");
}
/* initialize private state */
var priv = this.$private; /* private Build Module state */
/* private methods/data that we don't want scripts to see */
priv.scanPkg = scanPkg;
priv.sourceCfg = sourceCfg;
priv.bld = this;
priv.targsTab = {};
}
/*
* ======== BuildEnvironment.usePlatform ========
*/
function usePlatform(platformName)
{
if (!(typeof platformName == "string")) {
throw xdc.$$XDCException("xdc.bld.PARAMETER_MISMATCH",
"Parameter must be a string: was passed " + platformName);
}
var plat = this.platforms[platformName];
if (plat == null) {
var pa = platformName.split(':');
/* load platform package */
var pkg = xdc.loadPackage(pa[0]);
/* create platform instance */
var args = this.platformTable[platformName];
plat = pkg.Platform.create(
platformName.substring(pa[0].length + 1),
args == null ? {} : args);
this.platforms[platformName] = plat;
}
return (plat);
}
/*
* ======== BuildEnvironment.printBuildTargets ========
*/
function printBuildTargets()
{
if (this.targets.length == 0) {
return ("No target modules were loaded.\n");
}
var str = "Valid Build Targets:\n";
for (var i = 0; i < this.targets.length; i++) {
if (this.targets[i] != undefined) {
str = str + this.targets[i].$name + "\n";
}
}
return str;
}
/*
* ======== BuildEnvironment.isInTargetsArray ========
*/
function isInTargetsArray(targ)
{
return (this.$private.targsTab[targ.suffix] == null ? false : true);
}
/*
* ======== BuildEnvironment.getReleaseDescs ========
*/
function getReleaseDescs(pname)
{
var result = [];
/* locate the package.bld.xml file (which describes a package's releases */
var xname = xdc.getPackageBase(pname) + "/package/package.bld.xml";
var xfile = new java.io.File(xname);
if (!xfile.exists()) {
throw xdc.$$XDCException("xdc.bld.PACKAGE_NOT_BUILT", "The package '"
+ pname + "' has not been built. Try re-building the package.");
}
/* parse the XML file */
var doc = Packages.xdc.services.global.XML.parse(xname);
if (doc == null) {
throw xdc.$$XDCException("xdc.bld.INVALID_PACKAGE", "The package '"
+ pname + "' has an invalid package.bld.xml file (" + xname
+ "). Try re-building the package.");
}
/* extract from this file the release information */
var rels = Packages.xdc.services.global.XML.getHMaps(doc, "releases",
["name", "label", "pname"]); /* pname stands for "physical name" */
/* create the release description objects */
for (var i = 0; i < rels.length; i++) {
var obj = rels[i];
var desc = new xdc.om['xdc.bld.Release'].Desc({
name: obj.get("name"),
aname: obj.get("pname"),
label: obj.get("label")
});
result.push(desc);
}
return (result);
}
/*
* ======== _exportTargets ========
* Given the names (or patterns) of modules that implement ITarget, add
* each to the array of targets in build.
*/
function _exportTargets(targArray, list, exclude, warnings)
{
var ta = list.split(/[,;:\s]+/);
var ma = xdc.om.$modules;
var targets = [];
var ep = exclude == null ? null : new RegExp(exclude);
/* put all matching targets into local targets array */
for (var j = 0; j < ta.length; j++) {
/* check for "native" target */
if (ta[j] == "native" && bldPkg.BuildEnvironment.nativeTarget != null) {
targArray[targArray.length++] = bldPkg.BuildEnvironment.nativeTarget;
continue;
}
/* match name against target module names */
var pattern = new RegExp(ta[j]);
var found = false;
var tmp;
for (var i = 0; i < ma.length; i++) {
var sname = ma[i].$name;
if ((tmp = sname.match(pattern)) != null && tmp[0] == sname) {
if (ep != null
&& (tmp = sname.match(ep)) != null && tmp[0] == sname) {
continue;
}
if (ma[i] instanceof bldPkg.ITarget.Module) {
targArray[targArray.length++] = ma[i];
found = true;
}
}
}
/* try appending the TI package prefix to the target specification */
if (found == false) {
for (var i = 0; i < ma.length; i++) {
var sname = ma[i].$name;
if (("ti.targets." + ta[j]) == sname
&& ma[i] instanceof bldPkg.ITarget.Module) {
if (ep != null
&& (tmp = sname.match(ep)) != null && tmp[0] == sname){
continue;
}
targArray[targArray.length++] = ma[i];
found = true;
break;
}
}
}
/* if no match is found for a pattern, print a warning */
if (found == false && warnings == true) {
print("Warning: Target specification '" + ta[j] +
"' does not match any loaded target module.\n" +
xdc.module('xdc.bld.BuildEnvironment').printBuildTargets());
}
}
}