From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  offline version generated on 04-Aug-2010 21:08 UTC  

RTSC Packaging Primer/Lesson 7

Program Configuration — selecting charlie.sqrtlib libraries

Having finally built and released the charlie.sqrtlib function libraries—one pair per RTSC target—we'll turn now to the task of selecting the appropriate library from this set during program configuration at the client's site. While the configuration process in general affords packages many opportunities to become active participants in building client applications—which we'll highlight towards the end of this lesson—selecting the appropriate function libraries that satisfy a particular set of program requirements becomes another "sweet spot" of RTSC packaging.

As you may recall from the flow introduced in Lesson 3, program configuration requires that the client designate a particular RTSC target as an input to the process—clearly one factor in guiding library selection. But you may also recall that the client configured the optimize parameter of the charlie.sqrtlib.Settings module in prog.cfg—an additional piece of data used internally by the package when choosing between the isqrt_loop and isqrt_unroll libraries for the current target.

Contents

Specifying the Settings module

From the very outset, we've exposed you to a wide range of RTSC modules used in a variety of contexts:

As a rule, content suppliers will explicitly declare the public (client-visible) features of a RTSC module—its constants, types, parameters, functions—through a separate XDCspec source file found in the corresponding package directory. Applying a simple physical design pattern borrowed from Java, the specification for the charlie.sqrtlib.Settings module must reside in a file named Settings.xdc housed in the charlie/sqrtlib package directory.

charlie/sqrtlib/package.xdc
 
 
1
 
/*! Library of square-root functions */
package charlie.sqrtlib {
    module Settings;
}

charlie/sqrtlib/Settings.xdc
 
2
 
3
 
 
 
 
4
 
/*! Controls library selection during program configuration */
metaonly module Settings {
 
    enum OptType {
        OPTIMIZE_FOR_SPACE,
        OPTIMIZE_FOR_TIME
    };
 
    config OptType optimize = OPTIMIZE_FOR_TIME;
}

To complete the picture, we've also listed the package.xdc specification file for charlie.sqrtlib which first introduces the Settings module within the scope of this package at line 1.

Even more suggestive of a header file—but clearly expressed in a higher-level language than C—Settings.xdc like package.xdc before it defines its own namespace that in turns scopes other programmatic identifiers. In the case of the module declaration beginning at line 2—again, using a notation suggestive of a C struct—we've then introduced OptType and optimize within the scope of Settings itself.

The enum declaration at line 3 mirrors the syntax and semantics of C, and merits no further explanation at this point. As for the config declaration at line 4—a new keyword to match a new construct—suffice it to say that optimize becomes a property of the XDCscript object representing the Settings module with the client's prog.cfg file, with OPTIMIZE_FOR_TIME serving as its initial (default) value. Not unlike variables or fields in C, config declarations will effectively constrain the type of values this parameter can receive during assignment.

As a practical matter, virtually any sort of declaration normally placed within a C language header file—constants, types, functions—can appear within an XDCspec module specification with little or no change. Suffice it to say that you'd find const, typedef, struct, and extern amongst the keywords of the XDCspec language; a cursory scan through some of the module specifications bundled with the XDCtools product—viewed using xdc.tools.cdoc.sg or else by browsing rtsc.eclipse.org—would also reveal an XDCspec type system that effectively supersets standard C.

Implementation domain.  Whereas all RTSC modules will uniformly define their public client-visible features through a corresponding XDCspec source file—invariably found within the containing package directory, and viewable through client documentation utilities such as xdc.tools.cdoc.sg—internal implementation strategies can vary considerably from one module to the next:

  • acme.utils.Bench has C-based implementations for its begin and end functions, callable from within executable target programs at runtime; whereas

  • xdc.bld.PackageContents has an XDCscript-based implementation for its addLibrary function, callable from within hosted scripts generally running in a very specific context.

Our charlie.sqrtlib.Settings module of course has no functions at all, just a configuration parameter plus some supporting types and constants; practically speaking, the module does not require a private implementation in either programming language. Still, to reinforce the fact that its features remain limited to the client's configuration meta-program—as opposed to also having a presence in the client's executable target-program—we've qualified the declaration back at line 2 with the metaonly keyword.

By contrast, a module like acme.utils.Bench—whose XDCspec specification omits the metaonly keyword—maintains a presence in the domain of XDCscript and C. In particular, the final value held by the assignable Bench.enable parameter at configuration-time becomes the initial value of the Bench_enable const at run-time—used internally within the C implementation of the Bench_begin and Bench_end functions. The concept of a single XDCspec specification—one set of constant, type, parameter, or function declarations in a C-based notation—driving a realization within the XDCscript meta-language as well as the C target-language remains a basic premise of RTSC.

Implementing the getLibs function

Back to the task at hand—selecting the appropriate set of libraries during program configuration—RTSC packages can explicitly participate at this stage of the process by implementing a special meta-function named getLibs. Sourced in XDCscript and found in a special file named package.xs within the corresponding package directory, the getLibs function returns a string naming each library actually used further downstream when linking the current program.

The makefile and prog.cfg script used to build and configure the client application in Lesson 3 respectively selected ti.targets.C64P as the program's target and assigned OPTIMIZE_FOR_TIME to the Settings.optimize configuration parameter. As you'd discover by inspecting the program linker.cmd file generated through the RTSC configuration process, this particular combination of inputs selects lib/isqrt_loop.a64P as the library contribution from the charlie.sqrtlib package.

charlie/sqrtlib/package.xs
 
 
1
2
 
3
 
 
4
 
 
 
 
 
 
 
 
 
5
 
 
 
 
 
function getLibs( prog )
{
    var pkg = this;
    var Settings = pkg.Settings;
 
    var suffix = prog.build.target.findSuffix(pkg);
    var name;
 
    switch (Settings.optimize) {
        case Settings.OPTIMIZE_FOR_SPACE:
            name = "isqrt_loop";
            break;
        case Settings.OPTIMIZE_FOR_TIME:
            name = "isqrt_unroll";
            break;
    }
 
    if (suffix && name) {
        return "lib/" + name + ".a" + suffix;
    }
    else {
        return null;
    }
}

Automatically invoked during the final stages of RTSC configuration—well after first executing the client's prog.cfg script—the getLibs function has access to two important XDCscript objects used when constructing the list of libraries contributed by this package:

  • prog (an explicitly named argument to getLibs) references an object whose properties characterize the program as a whole—including information about the current target extracted at line 3; and

  • this (an implicit argument to getLibs) references an object representing the charlie.sqrtlib package per se—bound here to the local variable pkg at line 1 to improve readability.

In object-oriented languages such as XDCscript, calls of the form «object».«function»( «args» )—sometimes termed a method invocation—would here bind the distinguished variable this to the value of «object» once inside the body of «function». Said another way, the configuration process automatically invokes the getLibs method on each XDCscript «package-object» corresponding to some RTSC package contributing directly or indirectly to the current program.

Working backwards now, the string returned at line 5 relies on earlier assignments to suffix and name—which would here assume the values "isqrt_loop" and "64P" in light of our client application from Lesson 3. In general, the string returned by getLibs can name multiple libraries with ";" as a delimiter; and, in cases where a particular package has no libraries to contribute, getLibs can return an empty string "" or else the special value null.

Moving up the page, the switch statement beginning at line 4 discriminates amongst the set of possible values currently held by Settings.optimize—values of type OptType specified earlier at line 3 of Settings.xdc—and then appropriately assigns the local variable name. As for the binding of Settings at line 2 of getLibs, we've accessed the XDCscript object representing this module using a «package-object».«module-name» idiom, where pkg (alias this) here references the charlie.sqrtlib package object.

As an alternative, we could have called xdc.useModule('charlie.sqrtlib.Settings') at line 2 to retrieve the corresponding module object, though somehow leveraging the package object already available to getLibs seems more self-contained in this example.

Completing the story now, the assignment to suffix at line 3 starts with the object bound to the prog argument of getLibs and then eventually navigates to a findSuffix function defined on targets; taking the current package object as its argument, findSuffix reflects on all targets used when building this package and returns the suffix "most compatible" with the target selected for this program configuration. Internally, findSuffix comprehends the rather rich backward-compatibility relationships that often exist amongst targets—for instance, "newer" targets (like ti.targets.C64P) can often link libraries compiled with "older" targets (like ti.targets.C62).

To test your understanding, the value of this within the body of the findSuffix function would here reference an XDCscript object corresponding to the ti.targets.C64P target—the same meta-module we've configured earlier within the config.bld script prepared at the producer's site and executed prior to building the charlie.sqrtlib package.

The xdc.IPackage interface

Besides getLibs, package producers can elect to implement other meta-functions in package.xs called at different points within the program configuration process—from when the package first enters the current configuration through final generation of the linker.cmd output file.

init
called upon importing this package into the current configuration, usually via xdc.useModule
close
called when the client's script completes its contribution to the current configuration
validate
called before generation of output files begins, giving the package one last opportunity to issue errors/warnings
exit
called after the current configuration has been successfully validated, immediately before generation
getSects
called during generation, to elicit contributions to linker.cmd beyond the libraries returned by getLibs

Like virtually everything within the world of RTSC, this set of functions ultimately belongs to a larger programmatic entity specified within an XDCspec source file—in this case, a RTSC interface named xdc.IPackage. Following the same pattern introduced earlier with the charlie.sqrtlib.Settings module, the special xdc package—bundled with the XDCtools product—indeed contains an XDCspec source file named IPackage.xdc.

xdc/package.xdc
 
1
 
package xdc {
    interface IPackage;
}

xdc/IPackage.xdc
2
 
 
 
3
 
 
 
 
metaonly interface IPackage {
        ...
    function close();
    function exit();
    function getLibs(prog);
    function getSects();
    function init();
    function validate();
}

Here again, line 1 of xdc/package.xdc first introduces IPackage within the scope of the xdc package per se, followed then with a more comprehensive specification in IPackage.xdc; and not unlike Settings.xdc, the metaonly keyword at line 2 implies that none of the xdc.IPackage features specified here have a presence within the target-program during execution. Note also how the function keyword in the XDCspec declaration at line 3 mirrors the syntax of its XDCscript implementation back in package.xs. Needless to say, the "real" xdc.IPackage.xdc interface specification bundled with the XDCtools product contains considerably more detail than shown here.

Similar to the modules we've already encountered, a RTSC interface defines a programmatic contract that aggregates a related set of constants, types, parameters, and functions. But unlike a RTSC module—which couples a client-visible specification with a distinct supplier-proprietary implementation at any point in time—a RTSC interface can simultaneously support multiple implementations. Said a little differently, any package producer can elect to furnish a specific implementation of the xdc.IPackage functions within their package.xs file—effectively superseding default implementations otherwise invoked during the program configuration process.

In the same vein, the xdc.bld.ITarget interface specifies a collection of features shared by all RTSC targets; reviewing the current config.bld script, you'll recall that ti.targets.C64P and gnu.targets.Mingw each have an assignable rootDir property. In general, RTSC (meta-)modules like ti.targets.C64P can inherit client-visible features specified elsewhere within a RTSC (meta-)interface, can extend these features on a per-module basis, and can override default parameter values or function implementations as appropriate.

See also

Writing getLibs() Guidelines for package getLibs() functions
xdc.IPackage Client documentation for xdc.IPackage

[printable version]  offline version generated on 04-Aug-2010 21:08 UTC  
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Views
Personal tools
package reference