Integrating Existing Content/Example 1

From RTSC-Pedia

Jump to: navigation, search
revision tip
—— LANDSCAPE orientation
[printable version]  offline version generated on 21-Oct-2014 15:10 UTC

Integrating Existing Content/Example 1

Minimal wrapping of a pre-built library as a RTSC package

Contents

Wrapping Existing Content

In this example, we illustrate how to take an existing pre-built library with associated C headers and "wrap" it into a RTSC package in such a way that it can be delivered, installed, and used in a

  • RTSC environment as though it were an ordinary package, or
  • minimal C development environment without any RTSC tools.

For the purpose of this example, we assume there is a pre-built library named dsplib.lib and a "top-level" header file named dsplib.h that must be delivered with this library that declares the functions provided by it.

Creating the Wrapper Package

All packages must have a unique name so as to avoid collisions with packages created by others and to allow the content of the package to be referenced by applications that require its content. In this example, we'll call the package "ti.dsplib".

In order to create a package there are at least two files that must be created in the package's base directory:

  1. package.xdc - specifies the name and version of the package
  2. package.bld - specifies what should be delivered in the released form of the package

In this example, we place all libraries in a ./lib sub-directory and all headers in the package's base directory. The package.bld file specifies that all files in these directories should be added to the package and that the format of the package archive should be a zip file.

ti/dsplib/package.xdc
 
 
 
//! Simple wrapper of dsplib and its headers
package ti.dsplib [1, 0, 0] {
}
ti/dsplib/package.bld
 
 
 
 
// release package as a .zip file
Pkg.attrs.archiver = "zip";
// include everything under ./, including ./lib
Pkg.exportAll = true;

If we simply wanted to use the this package in a minimal C environment - one in which the only tools available include the compiler, linker, and a POSIX make build tool - we would be done. The user would simply need to know that they should add the library (or libraries) in the ./lib sub-directory to their linker's command line and add the package's base directory to their compiler's command line. In order to use this package in a RTSC environment, however, we need to add one more file: package.xs. This normally optional file contains XDCscript functions that override the default behavior of RTSC for this package. In our case, we only need to override the getLibs() function so that it returns the name of the library required to link with applications using the functions provided by dsplib.lib.

ti/dsplib/package.xs
 
 
 
function getLibs(prog) {
    return ("./lib/dsplib.lib");
}

That's it! Simply create the directory ti/dsplib, copy these files into it, copy all pre-built libraries into the ./lib sub-directory and any headers into ./ (the package's base). Note that there is no reason why the libraries have to be in a ./lib sub-directory or that the headers must be in ./; they could be placed anywhere in or under ti/dsplib. However, since the placement of the headers can affect the client application's source code, you should be careful about where they are located.

To build the deployable .zip archive, simply cd to the package's base directory and type "xdc release".

 
 
 
 
 
 
 
 
 
% cd ti/dsplib
% xdc release
making package.mak (because of package.bld) ...
generating interfaces for package ti.dsplib ...
all files complete.
generating schema include file list ...
generating external package references package/package.ext.xml ...
generating package references graph package/package.rel.dot ...
making release file ti_dsplib.zip ...

The generated ti_dsplib.zip archive contains all files necessary to use dsplib.lib in either a RTSC environment or a minimal C environment.

Using ti.dsplib from GNU make

Since RTSC packages are simply directories containing a few extra files, using the ti.dsplib in an environment that only has a C compiler, linker, and GNU make is no different than using any zip file containing libraries and headers that you need for your application. In particular, you simply unzip the ti.dsplib archive into any directory, say /usr/local/packages, and modify your makefiles to add

  • the path to the set of libraries that you link with, and
  • the path to the set of directories your compiler will search for headers

makefile
 
 
 
 
 
 
 
 
 
 
 
CC      := gcc
PKGROOT := /user/local/packages
 
INCS := -I$(PKGROOT)
LIBS := $(PKGROOT)/ti/dsplib/lib/dsplib.lib
 
%.o : %.c 
        $(CC) $(CCOPTS) $(INCS) -c $<
 
app.exe: $(LIBS)
        $(CC) -o $@ app.o $(LIBS) -lstdc++
app.c
 
 
 
 
 
#include <ti/dsplib/dsplib.h>
 
int main(void) {
    :
}

Suppose an application doesn't directly reference the functions provided by dsplib.lib but, rather, references functions defined in a different library, say h264.lib, that references the functions in dsplib.lib. In this case, you must use the libraries and headers for the h264.lib library and place dsplib.lib after h264.lib on the link command line. If the h264.lib library is similarly wrapped, the makefile and application sources would change as shown below.

makefile (fragment)
 
 
 
 
 
 
 
CC      := gcc
PKGROOT := /user/local/packages
 
INCS := -I$(PKGROOT)
LIBS := $(PKGROOT)/acme/video/lib/h264.lib \
        $(PKGROOT)/ti/dsplib/lib/dsplib.lib
   :
app.c
 
 
 
 
 
#include <acme/video/h264.h>
 
int main(void) {
    :
}

Of course, the provider of the h264.lib library must tell you about its dependence on dsplib.lib so that you can create an appropriate linker command line.

Using ti.dsplib as a Package

Every application has an associated configuration script. This configuration script names the packages and modules directly referenced by the application. In this case, the application directly references the dsplib.lib functions and ti.dsplib doesn't contain any modules, so the configuration script simply loads the ti.dsplib package as a whole.

Configuration scripts generate several files that make it easy to integrate packaged content into your build environment. This integration occurs just once: adding, removing, or updating a package in the the set of packages used requires no changes to the build integration. See Consuming Configurable Content/makefiles to see how this is done in a GNU make environment. Assuming the configuration tool is integrated into your build system, you can use the wrapped dsplib.lib by simply adding one line to your configuration script and rebuilding.

local/app/main.cfg
 
xdc.loadPackage('ti.dsplib');
app.c
 
 
 
 
 
#include <ti/dsplib/dsplib.h>
 
int main(void) {
    :
}

Suppose the application only indirectly references the dsplib.lib functions as a consequence of a reference to the package acme.video which, in turn, has a direct reference to the functions in dsplib.lib. In this case, the application configuration script would only need to reference acme.video (or a module within this package).

local/app/main.cfg
 
xdc.loadPackage('acme.video');
app.c
 
 
 
 
 
#include <acme/video/h264.h>
 
int main(void) {
    :
}

So, how does the RTSC configuration tool figure out that the application needs to link with dsplib.lib? The acme.video must specify that it directly references the libraries "provided" by ti.dsplib. There are several ways to do this, but the easiest is for the acme.video package to simply add a requires statement to its package.xdc file. You must rebuild acme.video for the requires statement to take effect.

acme/video/package.xdc
 
 
 
requires ti.dsplib;
package acme.video [1, 0, 0] {
}

By adding the specification of the dependency on ti.dsplib to the acme.video package, the user of this package need not be aware of its internal dependencies which may change over time.

Variations

In the example above, we copied all the content that we wanted to wrap into a package. But what if we simply referenced content that has already been separately installed by the user? This has the advantage that the content can be independently updated without having to create a new version of the wrapper package.

The getLibs() function may also return an absolute path to an existing library. We can use this ability, combined with the ability to execute arbitrary XDCscript code, to simply locate an appropriate dsplib.lib file that was installed separately from this wrapper package. Suppose, for example, that dsplib.lib was previously installed on your workstation and, as part of this installation, some environment variable was set that identifies the installation directory, say DSPLIB_ROOT.

In this case, we could wrap dsplib.lib as a package without having to copy the library and its headers into the ti.dsplib package itself. We simply need to implement a different getLibs() function; one that uses the environment to locate the appropriate library.

ti/dsplib/package.xs
 
 
 
 
function getLibs(prog) {
    var root = java.lang.System.getenv("DSPLIB_ROOT");
    return (root + "/lib/dsplib.lib");
}

For more information about what's possible within XDCscript functions, see The XDCscript Language. In short, there is nothing you can't do.

See also

The XDCscript Language XDCscript overview
Command - xdc eXpanDed C package build command
xdc.IPackage.getLibs Client documentation for xdc.IPackage.getLibs
RTSC Packaging Primer/Lesson 4 Elementary Packages — producing charlie.sqrtlib.samples
 
Consuming Configurable Content/makefiles RTSC configuration with makefiles

[printable version]  offline version generated on 21-Oct-2014 15:10 UTC
Copyright © 2008 The Eclipse Foundation. All Rights Reserved
Personal tools
package reference