Libraries from Archive Libraries

Under some circumstances it is necessary to build a target from targets across multiple subdirectories. Consider the following (abbreviated) example from libgit2.

$ tree libgit2
libgit2
|-- deps
|   |-- http-parser
|   `-- zlib
|-- include
|   `-- git2
|-- src
|   |-- transports
|   |-- unix
|   `-- win32
|-- tests
`-- tests-clar
	|-- attr
	|-- buf
	|-- object
	|   |-- commit
	|   |-- raw
	|   `-- tree
	|-- odb
	`-- status

The final target is either an archive library (libgit2.a) or a shared library (libgit2.so) It is composed of groups of objects from deps/http-parser, src, src/transports and possibly deps/zlib and src/unix or src/win32.

It would be possible to build the library at the top level from objects in lower levels, for example:

Lib git2 deps/http-parser/*.c src/*.c src/unix/*.c

However this forces all of the build rules (CFlags, IncludePaths, etc.) to be specified at the top level. It is better if the components can be built individually and then combined to form the final library. tmake supports this by allowing library objects to be combined into other archive and shared libaries. This is done as follows.

=== deps/http-parser/build.spec ====================
Lib --publish http-parser *.c
====================================================

=== src/build.spec =================================
Lib --publish src *.c transports/*.c unix/*.c
====================================================

=== build.spec =====================================
Lib git2 <lib>http-parser <lib>src
====================================================

The special objects selector, <lib>name, is used to select all the objects from the corresponding published library.

(Note that this is related to the mechanism which allows published libraries to be found by other components with UseLibs)

When the inputs to the git2 library are collected, the selector such as <lib>src is replaced with the objects that are listed as inputs to the src library. In addition, a dependency on the 'src' library is added to the 'git2' library to ensure that the objects are available when required.

This approach has the advantage that the aggregate library can be created in any directory, not just a parent of each of the component libraries.

The same mechanism can be used for creating a shared libraries from other libraries, and both shared and archive libraries can be used as the component libraries.

Note 1: The selector selects the objects from the component library, not the library itself.

Note 2: The component library must be published in order to be available.

Note 3: When creating an aggregate shared library, the appropriate compile flags (e.g. $(SH_CFLAGS) must be added to objects in the component libraries. tmake is not able to automatically determine if this restriction has been followed.

The results of the search are