# Building Triceps

## Downloading Triceps

The official Triceps site is located at SourceForge.

is the high-level page.

is the SourceForge project page.

The official releases of Triceps can be downloaded from SourceForge.

The release policy of Triceps is aimed towards the easy development. As the new features are added (or sometimes removed), they are checked into the SVN repository and documented in the blog form at . Periodically the documentation updates are collected from the blog into this manual, and the official releases are produced.

If you want to try out the most bleeding-edge features that have been described on the blog but not officially released yet, you can get the most recent code directly from the SVN repository. The SVN code can be checked out with

    svn co https://triceps.svn.sourceforge.net/svnroot/triceps/trunk

You don't need any login for check-out. You can keep it current with latest changes by periodically running

    svn update

. After you've checked out the trunk, you can build it as usual.
download

## The reference environment

The tested reference build environment is where I do the Triceps development, and currently it is Linux Fedora 11. The build should work automatically on the other Linux systems as well but has not been tested much in practice.

The build should work on the other Unix environments too but would require some manual configuration for the available libraries, and has not been tested either.

Currently you must use the GNU Linux toolchain: GNU make, GNU C++ compiler (version 4.4.1 has been tested), glibc, valgrind. You can build without valgrind by running only the non-valgrind tests.

The tested Perl version is 5.10.0, and should work on any later version as well. With the earlier versions your luck may vary. The Makefile.PL has been configured to require at least 5.8.0 but you may edit it and try building on the older versions.

I am interested in hearing the reports about builds in various environments.

The normal build expectation is for the 64-bit machines. The 32-bit machines should work (and the code even includes the special cases for them) but have been untested at the moment. Some of the tests might fail of the 32-bit and/or big-endian machines due to the different computation of the hash values, and thus producing a different row order in the result.

build environment

## The basic build

If everything works, the basic build is simple, go to the Triceps directory and run:

    make all
    make test

That would build and test both the &Cpp; and Perl portions of Triceps. The &Cpp; libraries will be created under

    cpp/build

. The Perl libraries will be created under

    perl/Triceps/blib

.

The tests are normally run with valgrind for the &Cpp; part, without valgrind for the Perl part. The reason is that Perl produces lots of false positives, and the suppressions depend on particular Perl versions and are not exactly reliable.

If your system differs substantially, you may need to adjust the configurable settings manually, since there is no

    ./configure

script in the Triceps build yet. More information about them is in the &xrsp;.

In some circumstances the Per unit test print the error messages as a normal part of running the test. Such messages are prepended with a message that they are expected, for example:

    Expect message(s) like: Error in PerlSortedIndex(bad) comparator: test a death in PerlSortedIndex comparator
    Error in PerlSortedIndex(bad) comparator: test a death in PerlSortedIndex comparator
    Error in PerlSortedIndex(bad) comparator: test a death in PerlSortedIndex comparator

These messages come from the tests of the &Cpp; code catching of the fatal errors in the Perl code. In the future all such catching will be converted to the stack unwind and confession back to the surrounding Perl code. However for now there still are the old-style handlers that simply print the error message.

The other interesting

    make

targets are:

    clean

  Remove all the built files.

    clobber

  Remove the object files, forcing the libraries to be rebuilt next time.

    vtest

  Run the unit tests with valgrind, checking for leaks and memory corruption.

    qtest

  Run the unit tests quickly, without valgrind.

    release

  Export from SVN a clean copy of the code and create a release package. The package name will be triceps-version.tgz, where the version is taken from the SVN directory name, from where the current directory is checked out. This includes the build of the documentation.

build

## Building the documentation

If you have downloaded the release package of Triceps, the documentation is already included it in the built form. The PDF and HTML versions are available in

    doc/pdf

and

    doc/html

. It is also available online from .

The documentation is formatted in DocBook, that produces the PDF and HTML outputs. If you check out the source from SVN and want to build the documentation, you need to download the DocBook tools needed to build it. I hate the dependency situations, when to build something you need to locate, build and download dozens of other packages firsti, and then the versions turn out to be updated, and don't want to work together, and all kinds of hell break loose. To make things easier, I've collected the set of packages that I've used for the build and that are known to work. They've collected in . The DocBook packages come originally from , plus a few extra packages that by now I forgot where I've got from. An excellent book on the DocBook tools and their configuration is . And if you're interested, the text formatting in Docbook is described in .

DocBook is great in the way it takes cary of great many things automatically but configuring it is plainly a bitch. Fortunately, it's all already taken care of. I've reused the infrastructure I've built for my book for Triceps. Though some elements got dropped and some added.

Downloading and extraction of the DocBook tools gets taken care of by running

    make -C doc/dbtools

These tools are written in Java, and the packages are already the compiled binaries, so they don't need to be built. As long as you have the Java runtime environment, they just run. However like many Java packages, they are sloppy and often don't return the correct return codes on errors. So the results of the build have to be checked visually afterwards.

The build also uses Ghostscript for converting the figues from the EPS format. The luck with Ghostscript versions also varies. The version 8.70 works for me. I've seen some versions crash on this conversion. Fortunately, it was crashing after the conversion actually succeeded, so a workaround was to ignore the exit code from Ghostscript.

After the tools have been extracted, the build is done by

    make -C doc/src

The temporary files are cleaned with

    make -C doc/src cleanwork

The results will be in

    doc/pdf

and

    doc/html

.

If like me you plan to use the DocBook tools repeatedly to build the docs for different versions of Triceps, you can download and extract them once in some other directory and then set the exported variable

    TRICEPS_TOOLS_BASE

to point to it.
build documentation
DocBook

## Running the examples and simple programs

Overall, the examples live together with unit tests. The primary target language for Triceps is Perl, so the examples from the manual are the Perl examples located in

    perl/Triceps/t

. The files with names starting with

    x

contain the examples as such, like

    xWindow.t

. Usually there are multiple related examples in the same file.

The examples as shown in the manual usually read the inputs from stdin and print their results on stdout. The actual examples in

    perl/Triceps/t

are not quite exactly the same because they are plugged into the unit test infrastructure. The difference is limited to the input/output functions: rather than reading and writing on the stdin and stdout, they take the inputs from variables, put the results into variables, and have the results checked for correctness. This way the examples stay working and do not experience the bit rot when something changes.

Speaking of the examples outputs, the common convention in this manual is to show the lines entered from stdin as bold and the lines printed on stdout as regular font. This way they can be easily told apart, and the effects can be connected to their causes. Like this:

> OP_INSERT,1,AAA,10,10 Contents: id="1" symbol="AAA" price="10" size="10" lbAverage OP_INSERT symbol="AAA" id="1" price="10" > OP_INSERT,3,AAA,20,20 Contents: id="1" symbol="AAA" price="10" size="10" id="3" symbol="AAA" price="20" size="20" lbAverage OP_INSERT symbol="AAA" id="3" price="15"

The other unit tests in the

    .t

files are interesting too, since they contain absolutely all the possible usages of everything, and can be used as a reference. However they tend to be much more messy and hard to read, exactly because they contain in them lots of tiny snippets that do everything.

The easiest way to start trying out your own small programs is to place them into the same directory

    perl/Triceps/t

and run them from there. Just name them with the suffix

    .pl

, so that they would not be picked up by the Perl unit test infrastructre (or if you do want to run them as a part of unit tests, use the suffix

    .t

).

To make your programs find the Triceps modules, start them with

    use ExtUtils::testlib;
    use Triceps;
    use Carp;

The module

    ExtUtils::testlib

takes care of setting the include paths to find Triceps. You can run them from the parent directory, like:

    perl t/xWindow.t

The parent directory is the only choice, since

    ExtUtils::testlib

can not set up the include paths properly from the other directories.
examples

## Installation of the Perl library

If you have the root permissions on the machine and want to install Triceps in the central location, just run

    make -C perl/Triceps install

If you don't, there are multiple options. One is to create your private Perl hierarchy in the home directory. If you decide to put it into

    $HOME/inst

, the installation there becomes

    mkdir -p $HOME/inst
    cp -Rf perl/Triceps/blib/* $HOME/inst/

You can then set the environment variable

    export PERL5LIB=$HOME/inst/lib:$HOME/inst/arch

to have your private hierarchy prepended to the Perl's standard library path. You can then insert

    use Triceps;

and the Triceps module will be found. If you want to have the man pages from that directory working too, set

    export MANPATH=$HOME/inst:$MANPATH

Not that Triceps has any usable man pages at the moment.

However if you're building a package that uses Triceps and will be shipped to the customer and/or deployed to a production machine, placing the libraries into the home directory is still not the best idea. Not only you don't want to pollute the random home directories, you also want to make sure that your libraries get picked up, and not the ones that might happen to be installed on the machine from some other sources (because they may be of different versions, or completely different libraries that accidentaly have the same name).

The best idea then is to copy Triceps and all the other libraries into your distribution package, and have the binaries (including the scripts) find them by a relative path.

Suppose you build the package prototype in the

    $PKGDIR

, with the binaries and scripts located in the subdirectory

    bin

, and the Triceps library located in the subdirectory

    blib

. When you build your package, you install the Triceps library in that prototype by

    cp -Rf perl/Triceps/blib $PKGDIR/

Then this package gets archived, sent to the destination machine and unarchived. Whatever the package type,

    tar

,

    cpio

or

    rpm

, doesn't matter. The relative paths under it stay the same. For example, if it gets installed under

    /opt/my_package

, the directory hierarchy would look like this:

    /opt/my_package
         +- bin
         |  +- my_program.pl
         +- blib
            +- ... Triceps stuff ...

The script

    my_program.pl

can then use the following code at the top to load the Triceps package:

    #!/usr/bin/perl

    use File::Basename;

    # This is the magic sequence that adds the relative include paths.
    BEGIN {
    	my $mypath = dirname($0);
    	unshift @INC, "${mypath}/../blib/lib", "${mypath}/../blib/arch";
    }

    use Triceps;

It finds its own path from

    $0

, by taking its directory name. Then it adds the relative directories for the Perl modules and XS shared libraries to the include path. And finally loads Triceps using the modified include path. Of course, more paths for more packages can be added as well. The script can also use that own directory (if saved into a global instead of

    my

variable) to run the other programs later, find the configuration files and so on.
installation

## Installation of the &Cpp; library

There are no special install scripts for the &Cpp; libraries and includes. To build your &Cpp; code with Triceps, simply specify the location of Triceps sources and built libraries with options

    -I

and

    -L

. For example, if you have built Triceps in

    $HOME/srcs/triceps-1.0.0

, you can add the following to your Makefile:

    TRICEPSBASE=$(HOME)/srcs/triceps-1.0.0
    CFLAGS += -I$(TRICEPSBASE)/cpp -DTRICEPS_NSPR4
    LDFLAGS += -L$(TRICEPSBASE)/cpp/build -ltriceps -lnspr4 -pthread

The Triceps include files expect that the Triceps &Cpp; subdirectory is directly in the include path as shown.

The exact set of

    -D

flags and extra

    -l

libraries may vary with the Triceps configuration. To get the exact ones used in the configuration, run the special configuration

    make

targets:

    make --quiet -f cpp/Makefile.inc getconf
    make --quiet -f cpp/Makefile.inc getxlib

The additions to

    CFLAGS

are returned by

    getconf

. The additional external libraries for

    LDFLAGS

are returned by

    getxlib

. It's important to use the same settings in the build of Triceps itself and of the user programs. The differing settings may cause the program to crash.

If you build your code with the dynamic library, the best packaging practice is to copy the

    libtriceps.so

to the same directory where your binary is located and specify its location with the build flags (for GCC, the flags of other compilers may vary):

    LDFLAGS += "-Wl,-rpath='$$ORIGIN/.'"

Or any relative path would do. For example, if your binary package contains the binaries in the subdirectory

    bin

and the libraries in the subdirectory

    lib

, the setting for the path of the libraries relative to the binaries will be:

    LDFLAGS += "-Wl,-rpath='$$ORIGIN/../lib'"

But locating the binaries and the shared libraries won't work if Triceps and your program get ever ported to Windows. Windows searches for the DLLs only in the same directory.

Or it might be easier to build your code with the static library: just instead of

    -ltriceps

, link explicitly with

    $(TRICEPSBASE)/cpp/build/libtriceps.a

and the libraries it requires:

    LDFLAGS += $(TRICEPSBASE)/cpp/build/libtriceps.a -lpthread -lnspr4

installation

## Disambiguation of the &Cpp; library

A problem with the shared libraries is that you never know, which exact library will end up linked at run time. The system library path takes priority over the one specified in

    -rpath

. So if somene has installed a Triceps shared library system-wide, it would be found and used instead of your one. And it might be of a completely different version. Or some other package might have messed with

    LD_LIBRARY_PATH

in the user's

    .profile

, and inserted its path with its own version of Triceps.

Messing with

    LD_LIBRARY_PATH

is bad. The good solution is to give your libraries some unique name, so that it would not get confused. Instead of

    libtriceps.so

, name it something like

    libtriceps_my_corp_my_project_v_123.so

.

Triceps can build the libraries with such names directly. To change the name, edit

    cpp/Makefile.inc

and change

    LIBRARY := triceps

to

    LIBRARY := triceps_my_corp_my_project_v_123

and it will produce the custom-named library. The Perl part of the build detects this name change automatically and still works (though for the Perl build it doesn't change much, the static &Cpp; Triceps library gets linked into the XS-produced shared library).

There is also a special

    make

target to get back the base name of the Triceps library:

    make --quiet -f cpp/Makefile.inc getlib

The other potential naming conflict could happen with both shared and dynamic libraries. It appears when you want to link two different versions of the library into the same binary. This is needed rarely, but still needed. If nothing special is done, the symbol names in two libraries clash and nothing works. Triceps provides a way around it by having an opportunity to rename the &Cpp; namespaces, instead of the default namespace

    Triceps

. It can be done again by editing

    cpp/Makefile.inc

and modifying the setting

    TRICEPS_CONF

:

    TRICEPS_CONF += -DTRICEPS_NS=TricepsMyVersion

Suppose that you have two Triceps versions that you want both to use in the same binary. Suppose that you are building them in

    $(HOME)/srcs/triceps-1.0.0

and

    $(HOME)/srcs/triceps-2.0.0

.

Then you edit

    $(HOME)/srcs/triceps-1.0.0/cpp/Makefile.inc

and put in there

    TRICEPS_CONF += -DTRICEPS_NS=Triceps1

And in

    $(HOME)/srcs/triceps-2.0.0/cpp/Makefile.inc

put

    TRICEPS_CONF += -DTRICEPS_NS=Triceps2

If you use the shared libraries, you need to disambiguate their names too, as described above, but for the static libraries you don't have to.

Almost there, but you need to have your code use the different namespaces for different versions too. The good practice is to include in your files

    #include

and then use everywhere the Triceps namespace

    TRICEPS_NS

instead of

    Triceps

. Then as long as one source file deals with only one version of Triceps, it can be easily manipulated to which version to use by providing that version in the include path. And you get your program to work with two versions of Triceps by linking the object files produces from these source files together into one binary. Then you just build some of your files with

    -I$(HOME)/srcs/triceps-1.0.0/cpp

and some with

    -I$(HOME)/srcs/triceps-2.0.0/cpp

and avoid any conflicts or code changes.

At the link time, you will need to link with the libraries from both versions.

## Build configuration settings

Since Triceps has no autoconfiguration yet, it may need to be configured manually for the target operating system. The same method is used for the build options.

The configuration options are set in the file

    cpp/Makefile.inc

. The extra defines are added in

    TRICEPS_CONF

, the extra library dependencies in

    TRICEPS_XLIB

.

So far the only such configurable library dependency is the NSPR4 library. It's used for its implementation of the atomic integers and pointers. Without it the code still works but uses a less efficient implementation of an integer or pointer protected by a mutex. It is enabled by

    TRICEPS_CONF += -DTRICEPS_NSPR4
    TRICEPS_XLIB += -lnspr4

The other build options require only the

    -D

settings.

    TRICEPS_CONF += -DTRICEPS_NS=TricepsMyVersion

Changes the namespace of Triceps.

    TRICEPS_CONF += -DTRICEPS_BACKTRACE=false

Disables the use of the glibc stack backtrace library (it's a standard part of glibc nowadays but if you use a non-GNU libc, you might have to disable it). This library is used to make the messages on fatal errors more readable, and let you find the location of the error easier.