From RTSC-Pedia
[printable version] | offline version generated on 04-Aug-2010 21:08 UTC |
RTSC Packaging Primer/Lesson 3
Client Applications consuming deployed package content
Having deployed both acme.utils and charlie.sqrtlib, we'll turn now to a small yet typical client application that consumes the target content of these packageswhich, in the final analysis, boils down to a set of C header files and function libraries. Along the way, we'll introduce one of most important facets of RTSC from the content consumer's perspectiveprogram configurationwhich enables RTSC packages to become active participants within the familiar process of compiling/linking your program.
Much of the material presented here, though self-contained, receives more thorough treatment within the first two lessons of the RTSC Module Primer. While not a prerequisite to understanding RTSC packages, we'd still encourage you to learn about RTSC modules as well.
Contents |
Reading the program
Our client application programwhose source resides in the charlie.sqrtlib.samples packagebenchmarks an integer square-root function (isqrt) available through charlie.sqrtlib itself. To measure performance, our sample program leverages a RTSC module named Benchfound in the acme.utils packagewhich enables us to sandwich a single isqrt call between a pair of benchmark "begin/end" functions. Besides reporting the measurement in a message, our application outputs the value returned from the isqrt call using a familiar-looking printf function supported by another RTSC module named Systempart of the xdc.runtime package contained within the XDCtools product itself.
Looking now at the code, our client application actually comprises a pair of source files. The first file (prog.c) should appear rather ordinary to anyone familiar with Cthough our use of multi-segment paths within #include directives may seem unusual at first. By contrast, the second file (prog.cfg) truly represents something new and different herea RTSC meta-program that configures the corresponding target-program.
If you're not sure what role prog.cfg plays in the overall flowor for that matter, what language we're even using hereyou will by the end of this lesson. If you've already tackled the RTSC Module Primer, however, we've clearly returned to familiar territory.
|
|
The target-program. Starting with prog.c, this application follows the same pattern used in virtually every other piece of C codefirst #include some headers [1a, 2a] and then call some functions defined therein [3a, 4a]. As for the multi-segment paths leading to Bench.h and isqrt.h, you should (obviously!) recognize these as the acme.utils and charlie.sqrtlib package directorieswhich (obviously!) must contain these header files.
Drilling a little deeper, you might have also sensed some subtle differences between the contents of charlie.sqrtlib compared with the other packages used here. In the case of acme.utils and xdc.runtime, both packages happen to contain full-fledged RTSC modulescohesive collections of constants, types, and functions with a public specification and a private implementation (not unlike a class in C++ or Java). Though our focus here remains on RTSC packages, you should start to recognize and appreciate the programming style and discipline surrounding RTSC modules.
As it turns out, the charlie.sqrtlib package houses what we'll refer to as legacy contentC language headers and function libraries delivered in their original format rather than under the guise of a specified RTSC module. At the same time, just think of RTSC modules as a more disciplined development approach that ultimately yields the same sorts of artifactsheaders and libraries. Either way, RTSC packaging provide a standardized delivery vehicle and deployment mechanism that can streamline the integration of C-based target content originating from different suppliers.
The meta-program. By design, RTSC target-programsordinary C programs with a main entry-pointmetaphorically begin life as a corresponding meta-program that executes on your host computer before the final compiling/linking of your application. In our example at hand, the outcome of running the prog.cfg meta-program effectively configures the downstream prog.c target-programidentifying all RTSC modules used in the program [1b, 2b] as well as optionally assigning values to configuration parameters furnished by these modules [3b, 4b].
Here again, charlie.sqrtlib appears to break the pattern used with the other packages, in which xdc.useModule calls within the meta-program strictly mirror #include directives found in the target-program; observe the predictable correspondence between lines 1a and 1b above, an idiom applied with each RTSC module used in the application. But also recall that charlie.sqrtlib houses legacy contentC headers and libraries delivered outside the scope of any specified RTSC module; and yet, charlie.sqrtlib should merit the same level of participation in the RTSC configuration process as afforded module-rich packages such as acme.utils or xdc.runtime.
To achieve parity, charlie.sqrtlib just so happens to furnish a special meta-only module named Settings which effectively serves as a configuration agent for legacy C functions like isqrt contained within this package. Just like the acme.utils.Bench module, the charlie.sqrtlib.Settings meta-module defines configuration parameters that impact the ultimate behavior of the target-program depending upon their value at the end of the meta-program:
- alternatively assigning the module configuration parameter Bench.enable the built-in value false at line 3b of prog.cfg would effectively turn the runtime calls to the Bench_begin and Begin_end functions beginning at line 3a of prog.c into NOPs; and
- alternatively assigning the module configuration parameter Settings.optimize the enumerated value Settings.OPTIMIZE_FOR_SPACE at line 4b of prog.cfg would potentially bind the isqrt function call at line 4a of prog.c to a slower but more compact implementation.
As for the programming language used in prog.cfg, you'll (of course!) express RTSC meta-programs using the RTSC meta-languagewhich is XDCscript, a superset of industry-standard JavaScript that builds upon Mozilla's openly available Rhino implementation. We have in fact extended Rhino/JavaScript to better integrate with other elements in the overall RTSC development flowfor sure, you won't find xdc.useModule described in any JavaScript textbooks.
Recall that XDCscript is one of two special-purpose languages introduced by RTSC under the banner of eXpanDed Csuggesting that C alone is not enough. As we start exploring RTSC packages from the supplier's perspective in the next lesson, we'll introduce the other special-purpose eXpanDed C languagethe higher-level XDCspec specification language which works hand-in-hand with XDCscript to enable package producers to satisfy the diverse needs of their consumers.
Configuring RTSC programs
RTSC configuration, as we've already hinted, occurs before the final compile/link of your application: executing the prog.cfg meta-program serves as a "pre-build" step that ultimately affects the compiling and linking of the prog.c target-program. To ease integration into existing program build flowswhether driven by command-line tools or a graphical IDEwe'll rely here on another tool known as configuro to orchestrate the RTSC configuration process:
Included as part of the XDCtools product you've already installed in Lesson 0, configuro generates two output files that in turn become inputs to the compiler and linker when building your target-program:
- compiler.opt, which sets all -D and -I compiler flags needed to locate any C headers included by this program (such as acme/utils/Bench.h or charlie/sqrtlib/isqrt.h); and
- linker.cmd, which lists the appropriate C libraries containing implementations of any functions used by this program (such as Bench_begin or isqrt).
Putting some of the pieces together, the #include search-path defined through the -I flags in compiler.opt exactly reflects the current package path on a per-repository basiswhich explains how the compiler finds headers named <acme/utils/Bench.h> or <charlie/sqrtlib/isqrt.h>. Rather than collecting all .h files into a centralized include/ directory, C headers delivered within RTSC packages remain in place at the consumer's site to help ensure their integrity. We'd also claim that using package directory paths in #include directives makes code more maintainable, leaving little doubt as to the particular supplier of each file; and this approach further enables different suppliers of (uniquely-named) packages to coincidently choose the same name for a headersay, Types.h.
Besides the prog.cfg meta-program, input to configuro will typically designate a RTSC target as well as a RTSC platformpre-defined XDCscript recipes that respectively guide the compiling and linking of prog.c in our example at hand:
- a RTSC target knows how to compile C sources into an object-code library for a particular CPU instruction set and memory model using a specific vendor tool-chain; and
- a RTSC platform knows how to link and execute a C program for a particular hardware board (real or simulated) featuring a specific complement of processors, memory, and peripherals.
While clearly impacting the contents of compiler.opt and linker.cmd, the wealth of information encapsulated within a RTSC target and RTSC platform is generally available throughout the XDCscript environmentduring execution of the prog.cfg meta-program as well as from within special back-end meta-functions we'll encounter later on.
Putting a few more of the pieces together, the generated linker.cmd references function libraries using full directory paths such as «local»/myrepo/acme/utils/lib/acme.utils.a64P. As you'll learn in Lesson 7, RTSC packages play an integral role during program configuration in selecting the set of libraries used for the final link step. As the .a64P suffix may suggest, packages containing libraries compiled for different RTSC targets can query the current target's identify when making this selection. Special XDCscript meta-functions implemented by package suppliers can also reflect upon the current RTSC platform when identifying libraries; or elsein the case of charlie.sqrtlib with its Settings meta-moduleuse the current value of a client-visible configuration parameter to guide the choice.
Building and running the program
If you're "playing along" with us and actually want to build and run the program at this time, we'd recommend first copying the charlie.sqrtlib.samples package into «local»/myrepo using the repoman -c command. This way, you can freely tweak the application sources without tainting the original package contents which would still remain in «shared»/products/charlie_sqrtlib_2_71/packages.
1 2 | %> xs xdc.tools.repoman -c -v -r «local»/myrepo -p «shared»/products/cha.../packages charlie.sqrtlib.samples xdc.tools.repoman: deleting charlie.sqrtlib.samples from «local»/myrepo xdc.tools.repoman: checking if charlie.sqrtlib.samples is a bundle xdc.tools.repoman: charlie.sqrtlib.samples is not a bundle. xdc.tools.repoman: deleting contents of directory myrepo/charlie/sqrtlib/demos/package xdc.tools.repoman: copying charlie.sqrtlib.samples from «shared»/products/cha.../packages to «local»/myrepo |
The output between lines 1 and 2 occurs whenever «local»/myrepo already contains a version of the charlie.sqrtlib.samples package. To reinforce the concept of RTSC packages as individual logical entities rather than a mass of physical files, repoman will also delete packages as a unit prior to replacing them with a fresh copy. But why not simply use the native delete and copy commands of your host computer to perform these operations.... For one, because RTSC packages often house complex directory structures of their own which cannot be compromised; but even more important, because RTSC package directories may also serve as stepping-stones to other RTSC packagestry deleting a version of charlie.sqrtlib without removing the contents of charlie.sqrtlib.samples as well.
In addition to prog.c and prog.cfg, the charlie.sqrtlib.samples package contains a standard GNU makefile that enables you to build and run our sample application. Before doing so, however, you'll need to edit a pair of lines at the top of the makefile to reflect the actual directories you've chosen for «xdcroot» and «c6xtools» back in Lesson 0.
charlie/sqrtlib/samples/makefile | |
| XDCROOT = «xdcroot» C6XTOOLS = «c6xtools» ... |
Windows-hosted developers should surround «xdcroot» or «c6xtools» with double-quotes "..." if these directory paths contain any spaces in their names.
Linux-hosted developers should also edit the definition of the RMCMD symbol per instructions found in the makefile.
Using a version of gmake bundled with XDCtoolsand assuming you've added «xdcroot» to your PATHinvoking the command gmake all from the charlie/matlib/samples package directory (now) residing within the «local»/myrepo package repository should yield the following messages:
1 2 3 | %> gmake all «xdcroot»/xs xdc.tools.configuro -c «c6xtools» -t ti.targets.C64P -p ti.platforms.sim64Pxx -o cfgsite prog.cfg making package.mak (because of package.bld) ... generating interfaces for package cfgsite (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 ... «c6xtools»/bin/cl6x -q -@cfgsite/compiler.opt -c prog.c «c6xtools»/bin/lnk6x -q -z -c prog.obj cfgsite/linker.cmd -o prog.out -l «c6xtools»/lib/rts64plus.lib |
Lines 1, 2, and 3 respectively follow the flow outlined in the earlier figure, but now with all the details of invoking these tools made explicit. Looking at little closer at the options passed to configuro at line 1, suffice it to say that ti.targets.C64P designates a meta-modulethe RTSC targetwhich guides compilation of this program and that ti.platforms.sim64Pxx identifies a packagethe RTSC platformwhich directs program linking and loading.
To read more about the hundreds of RTSC packages and modules bundled with the XDCtools productand hence already found along the current package pathjust fire-up xdc.tools.cdoc.sg using the standard xs command to interactively browse client documentation originally sourced in XDCspec files contained in each package; you'll even see some documentation for third-party packages, such as acme.utils and charlie.sqrtlib. (You can also visit rtsc.eclipse.org for a snapshot of the latest XDCtools package documentation.)
To execute the program, simply invoke the gmake test command:
| %> gmake test
==> isqrt(1000)
cycle count: [63]
<== 31 |
At this point, feel free to explore the effect upon program output when you vary the value passed to the isqrt(x) function call on line 4a of prog.c; or else, when you assign Settings.OPTIMIZE_FOR_SPACE on line 4b of prog.cfg. After you make any changes, (re-)invoking the gmake test command will first perform the requisite build-stepsbut only what's needed, given the structure of our makefilebefore executing the program. To rebuild the all of the pieces from scratch, first invoke gmake clean to remove all generated files.
See also
Consuming Configurable Content | Introduction to the RTSC configuration process |
Command - xdc.tools.configuro | Target content configuration tool |
The XDCscript Language | XDCscript overview |
[printable version] | offline version generated on 04-Aug-2010 21:08 UTC |