2. Project Organisation
2.1. A tour of $PREFIX
The tendra.base.mk
makefile provides several related $PREFIX_*
variables which are used to specify various locations on the filesystem for installation. Each of these corresponds to different uses:
Variable | Default | Filetypes | Description |
---|---|---|---|
PREFIX | /usr/local | – | A convenience to specify the base for everything. |
PREFIX_BIN | ${PREFIX}/bin | Executables | User-facing binaries |
PREFIX_LIB | ${PREFIX}/lib | .so, .a | User-facing libraries and their corresponding headers. These are used by users in their own code. |
PREFIX_INCLUDE | ${PREFIX}/include | .h | |
PREFIX_LIBEXEC | ${PREFIX}/libexec | Executables | Internal binaries, used by tcc. This should not be in $PATH . |
PREFIX_SHARE | ${PREFIX}/share | Plaintext | A convenience to specify the base for platform-independent resources. |
PREFIX_MAN | ${PREFIX}/man | roff | User-facing manpages, consumed by man(1). |
PREFIX_TSPEC | ${PREFIX_SHARE}/tspec | .c, .h | tspec-generated abstract API implementations. These get combined with the system headers and compiled to produce concrete API implementations, output to PREFIX_API . |
PREFIX_STARTUP | ${PREFIX_LIB}/tcc/startup | .pf, .h, environments | tcc portability tables and strictness profiles. These are platform-independent. |
PREFIX_ENV | ${PREFIX_LIB}/tcc/env | environments | tcc environments. These are platform-specific. |
PREFIX_LPI | ${PREFIX_LIB}/tcc/lpi | .tl | TDF implementations of LPI tokens (e.g. c.tl, the C language types, etc). These are platform-specific. |
PREFIX_API | ${PREFIX_LIB}/tcc/api | .tl | TDF implementations of API tokens (e.g. c89.tl, the ANSI C89 API). These are platform-specific. |
PREFIX_SYS | ${PREFIX_LIB}/tcc/sys | .a, .o, etc | System interface miscellany (e.g. crt*.o). These are platform-specific. |
PREFIX_TMP | /tmp | tcc-XXXXXX/ | Temporary workspace for tcc. |
During a build these may be overridden individually, but they default to values based on $PREFIX
, and so overriding just that suffices for most situations. The best choices for these paths depends on the filesystem layout for each particular system.
2.2. Dependencies
TenDRA is comprised of a suite of related tools, each packaged separately. The dependencies required for building these are:
Note that
here represents the system compiler, which may or may not itself be an installation of TenDRA.cc
The runtime dependencies are:
These runtime dependencies require the respective tools to be installed under $PREFIX
in order to be used. However, once installed, they know where to find their own resources, and so need not be deployed into the system's $PATH
, or set up using ldconfig(8), etc. In other words, TenDRA may be installed to some temporary $PREFIX
and run from there. The installation does not require root.
Finally, as is typical with compilers, some of the tools are written using themselves; these have generated code which occasionally needs to be rebuilt by developers. The dependencies for rebuilding are not documented here, as they are not particularly important. These dependencies are not relevant to package managers or system adminstrators building TenDRA; they are of interest to TenDRA's developers only. Typically a developer working on a particular area would regenerate just that part as required.
2.3. Bootstrap
The goal of bootstrapping is to produce the bare minimum required for the system to be able to build itself. This is neccessary because the system compiler alone is unable to build the whole of TenDRA, as many parts are written using TenDRA-specific mechanisms. For example, the API implementations which tspec produces are encoded using the #pragma
token definition syntax which is only meaningful to the tdfc2 producer.
The phases of bootstrapping TenDRA are simply:
- Use the system compiler to build just the TenDRA tools required to be able to recompile itself, and the rest of the TenDRA system. This stage may be omitted if the system compiler is itself TenDRA (when upgrading, for example).
- Use the bootstrapped minimal TenDRA compiler to build everything required for final use.
This is simpler than for many older systems, which often take into account system compilers that only implement a subset of standard C. Such a situation is unlikely to occur now, and so the bootstrap process is simplified by being able to rely on code which is written in standard C.
2.3.1. Building the bootstrap compiler
The dependencies which must be satisfied using the system compiler are as illustrated below. Note that relatively few projects are required; many tools are omitted (disp, for example) because they are not required for the next stage of rebuilding.
Bootstrapping is of course traditional for compilers; it is a natural step for any general purpose compiler to make minimal use of the system compiler, and then proceed to rebuild using itself.
The runtime dependencies for using this minimal bootstrap compiler are the same as the dependencies for those same tools in general use, as illustrated in .
2.3.2. Rebuilding using the bootstrap compiler
TODO