From RTSC-Pedia

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

RTSC Module Primer/Lesson 5

Packages — revisiting "Hello World"

At this juncture, we'll begin a transition from the client programmer's perspective of a RTSC module—a specified set of public constants, types, and functions—to the more internal perspective of the module supplier. As we mentioned from the outset, all RTSC modules ultimately reside within RTSC packages: the xdc.runtime package contains the System module; the acme.utils package contains the Bench module; the bravo.math package contains the RandGen module; and so forth.

Before turning to the internal implementation of the latter pair of modules, however, we'll start by building a rather minimal package—one that in fact contains no modules at all, but rather serves to introduce some important idioms for producing packages. And once again, we'll turn to "Hello World".

Contents

Introducing the package

We've chosen to name our minimal package simply lesson5—a bit unusual, since most packages will typically have longer (globally-unique) names of the form vendor.name1.name2.… . As a rule, all source files associated with a package named vendor.name1.name2.… must reside in a corresponding directory named vendor/name1/name2/… . Applying this rule to our minimal lesson5 package, its sources would reside in the directory «examples»/lesson5.

Beyond the prog.c and prog.cfg sources found in the lesson5 directory—absolutely identical to the target-program and meta-program we already examined back in Lesson 1—this example introduces two specially named source files found in all RTSC packages:

  • package.xdc, which first and foremost declares a canonical name for this package; and
  • package.bld, which prescribes a recipe for building the contents of this package.

Consider, then, the realization of these two special files for our lesson5 package:

lesson5/package.xdc
1
 
 
package lesson5 {
    /* module declarations normally go here */
};
 
lesson5/package.bld
2
3
 
4
5
 
var Build = xdc.useModule('xdc.bld.BuildEnvironment');
var Pkg = xdc.useModule('xdc.bld.PackageContents');
 
for each (var targ in Build.targets) {
    Pkg.addExecutable("prog", targ, targ.platform).addObjects(["prog.c"]);
}

Not unlike a struct declaration in standard C that in turn declares named fields within its scope, the package declaration at line 1 specifies the canonical name of this package (in this case, just lesson5) as well as the names of any modules contained within its programmatic scope (in this case, none). Needless to say, package.xdc is not written in standard C but rather in XDCspec—RTSC's C-like specification language which will play an even more prominent role once we begin developing modules in the lessons to come.

Consistent with the mapping between canonical module names and directory paths we've already encountered when working with #include directives—xdc.runtime.System becomes <xdc/runtime/System.h>—you can start to appreciate why a package named lesson5 must without exception reside in a directory of the same name. You should also note that while all packages are directories, the converse is by no means the case; the directory «examples»/lesson4 for example is not a package—for one, it lacks the special package.xdc found in all RTSC packages.

Turning now to package.bld—written in a language you should certainly recognize by now—this XDCscript recipe represents a more readable and a more general alternative to using a makefile to orchestrate the build flow. Just as the sources to our "Hello World" program—prog.c and prog.cfg—would presumably remain unchanged when rebuilt for different hardware using a different C compiler, so too does package.bld represent a portable recipe for building this package's contents for one (or more that one) RTSC target and platform.

The config.bld file prepared back in Lesson 0—also written in XDCscript, though you may not have realized it at that time—plays an essential role in keeping individual package.bld scripts portable by centralizing information specific to your environment within one file. In practice, config.bld will typically reside in one of the directories found along the RTSC package-path—reflected in the XDCPATH environment variable also assigned back in Lesson 0. As you'll come to appreciate more and more in the world of RTSC, virtually everything worth finding—C headers/libraries, XDCscript scripts, XDCspec specs, and of course config.bld itself—will be found along the RTSC package-path.

Prescribing "what" to build

The pair of special modules introduced at lines 2 and 3 of package.bld form the backbone of the RTSC package build model:

  • The Build module provides various (readonly) properties that capture the current environment in which the package.bld script executes. For example, the targets property used at line 4 tracks its earlier assignment in the special config.bld file back in Lesson 0.

  • The Pkg module provides various functions that add information about different buildable artifacts contained in this package. For example, the addExecutable function used at line 5 prescribes everything needed to build our (portable) "Hello World" program for an arbitrary target and platform.

Indeed, the generality of this package.bld script over (say) a more declarative makefile results from something that lies at the very core of programming itself—the for loop. By embedding a call to addExecutable (line 5) inside an XDCscript for each loop (line 4)—which successively binds the local variable targ to each element of the Build.targets collection—we have effectively arrived at a closed expression of "what" we want to build that remains independent of any particular target(s).

Looking closer at the addExecutable call on line 5, its first argument designates the basename of the target-program's executable file as well as the basename of its corresponding .cfg meta-program. The remaining two arguments designate the RTSC target and RTSC platform used with this program, not unlike how we passed -t and -p options to configuro in our earlier examples (Lesson 2). Note that each RTSC target has a platform property that returns a reasonable default—one which you can actually alter through the special config.bld file prepared back in Lesson 0. Finally, the addExecutable function returns a different type of XDCscript object, one supporting another function (somewhat oddly) named addObject whose sole argument enumerates a set of target-domain source files requiring compilation into object (sic!) files used when linking this executable.

Building the package

We've already introduced one special command bundled with XDCtools—the xs command used to launch host-based applications written in XDCscript; we're now about to introduce another one—the xdc command used to build RTSC packages. And for all practical purposes, you'll need nothing more than just this pair of special commands going forward in the world of RTSC.

The xdc command operates very much like gmake used to build our earlier examples, in that both commands take "goals" as their arguments to designate a particular end-result. For example, invoking xdc clean from within any package directory («examples»/lesson5 for the current example) will remove all generated files resulting from any prior use of the xdc command. Similarly, invoking xdc all (or just xdc by itself) will rebuild the contents of the current package according to the prescription laid out in package.bld, yielding the following output for this example:

 

 
2a
 
 
 
2b
 
 
 
 
>> xdc all
making package.mak (because of package.bld) ...
generating interfaces for package lesson5 (because package/package.xdc.xml is older than package.xdc) ...
configuring prog.x64P from package/cfg/prog_x64P.cfg ...
cl64P package/cfg/prog_x64P.c ...
cl64P prog.c ...
lnk64P prog.x64P ...
configuring prog.x86GW from package/cfg/prog_x86GW.cfg ...
cl86GW prog.c ...
cl86GW package/cfg/prog_x86GW.c ...
lnk86GW prog.x86GW ...
all files complete.

Since we originally assigned Build.targets a list of two RTSC targets in our special config.bld file back in Lesson 0 (ti.targets.C64P and gnu.targets.Mingw in this case) invoking xdc on this package will repetitively perform the same sequence of build steps—configure, compile, and then link—on the same set of portable source files—prog.cfg and prog.c. Were you to add more targets to the Build.targets list, the pattern of build steps beginning at lines 2a and 2b would continue in an obvious way.

If you should encounter any problems when building this example, refer back to Lesson 0 and double-check that your config.bld file correctly references the installation directories for both compilers—directories referred to as «c6xtools» and «gcctools» respectively.

Running the (two) programs built with this package is equally straightforward—invoking the command xdc test loads and runs each program on its respective RTSC platform, using information encapsulated within the platform to guide the process.

 
 
 
 
 
>> xdc test
running prog.x64P ...
Hello World
running prog.x86GW ...
Hello World

Note that each RTSC target defines a (unique) suffix used in all generated files produced by the underlying tool-chain, certainly to eliminate potential filename conflicts (both programs can't be named prog.out in our example) but also to enable an expanded set of target-specific goals for use with the xdc command. For example, invoking xdc test,64P will only run prog.x64P; and invoking xdc test,86GW will only run prog.x86GW. Similarly, invoking xdc all,64P will perform only the first set of build steps beginning at line 2a in the earlier output.

For all intent and purposes, the xdc command is gmake—invoking xdc will quickly transfer control in a very specific manner to a very specific revision of gmake bundled with the XDCtools product. But unlike our earlier examples that each contained a hand-crafted makefile, the xdc command instructs gmake to operate on a generated package.mak file found in all RTSC packages; and through the magic of gmake (evidenced by line 1 in the earlier output), package.mak will itself be (re-)generated from package.bld only when necessary to bootstrap the remainder of the build flow. Just as first executing a prog.cfg meta-program (written in XDCscript) will yield target-program artifacts consumed by downstream compilers and linkers, running the special package.bld script (also written in XDCscript) at the outset drives automatic generation of package.mak consumed by gmake itself.

See also

Command - xdc eXpanDed C package build command
 
xdc.bld.BuildEnvironment.targets Client documentation for xdc.bld.BuildEnvironment.targets
xdc.bld.PackageContents.addExecutable Client documentation for xdc.bld.PackageContents.addExecutable
xdc.bld.Executable.addObjects Client documentation for xdc.bld.Executable.addObjects

[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