29.3. Adding Platform Types and Platforms

When abuild starts up, it reads its internal information about
supported platforms and platform types. It then reads additional
information from plugins, which it combines with its built-in
information. This section contains information about the
specific formats of the directives used to add platform types and
platforms to abuild.

Platform type information is read from a plain text file that
contains platform type declarations. Information about platforms
is obtained by running a program, usually written in Perl. The
reason for putting platform type information in a file and
platform information in a program is that the list of platform
types should be static for a given build tree, while the list of
available platforms is a function of what the build host can
provide. Abuild automatically skips build items that belong to
a valid platform type that happens to have no platforms in it,
but if it encounters a build item with invalid platform types, it
considers that an error.

29.3.1. Adding Platform Types

Of the target types that abuild supports, the only one for
which additional platform types and platforms may be specified
is the object-code target type. Platform
types are declared in a file called
platform-types. Abuild looks for this
file first in its own private directory and
then at the root of each declared plugin. The
platform-types file contains a single
platform type declaration on each line. Comment lines starting
with the # character and blank lines are
ignored. Each line may have the following syntax:

You may optionally specify another previously-declared
object-code platform type as the new platform type's parent. If
a platform type is declared without a parent platform type, it
has indep as its implicit parent. (Note that
indep may not be declared explicitly as a parent;
only other object-code platform types may be
declared are parents.) Declaring a parent platform type means
that any platform in the new platform type may link against any
platform in the parent platform type. It is up to the creator
of the platform types to ensure that this is actually the case.

One example use of parent platform types would be to implement a
base platform type for a particular environment and then to
create derived platform types that refine some aspect of the
base platform type. For example, this could be used to overlay
additional include directories or libraries on top of support
for an embedded operating system to support selective hardware.
It would also be possible to create platform types that refine
the native platform type for specific
circumstances. Most uses of parent platform types could be
achieved in some other way, such as through use of conditionals
in Abuild.interface or
Abuild.mk files or through use of
pass-through build items with multiple dependencies, but when
used properly, parent platform types can reduce the number of
times common code has to be recompiled for different platform
types.

The ability to specify parent platform types was introduced in
abuild 1.1.4 and is closely related to platform type
compatibility as discussed in Section 24.2, “Dependencies and Platform Compatibility”. It's
possible that a future version of abuild may further
generalize the ability to create compatibility relationships
among platform types.

29.3.2. Adding Platforms

Since platforms are, by their nature, dynamic, abuild runs a
program that outputs platform declarations rather than reading
them from a file. This makes it possible for the existence of a
platform to be conditional upon the existence of a specific
tool, the value of an environment variable, or other factors.
To get the list of platforms, abuild runs a program called
list_platforms. Abuild invokes
list_platforms with the following arguments:

list_platforms [ --windows ] --native-data oscputoolset

The --windows option is only present when
abuild is running on a Windows system. The three options to
--native-data provide information about the
default native platform. Most compiler plugins will not need to
use this information since there is special way to add a native
platform, as discussed below.

To discover new platforms, abuild first runs the
list_platforms program in its own
private directory, and then it runs any
list_platforms programs it finds at the root
directories of any plugins. On a Windows system, abuild
explicitly invokes the list_platforms program
as perl list_platforms
options. For this reason,
to support portability to a Windows system,
list_platforms programs must be written in
perl. If necessary, a future version of abuild may provide a
mechanism to make writing list_platforms
programs in other languages. Note that abuild passes the
--windows flag to
list_platforms when running on Windows. This
not only saves the list_platforms program
from detecting Windows on its own but is actually necessary
since list_platforms couldn't tell on its own
whether it is being run to support a native Windows build of
abuild or whether it is being run to support a Cygwin build of
abuild.
[56]

Each line of output of list_platforms
declares either a new platform or a new native compiler, which
implies a new platform. A given platform may be declared
exactly one time across abuild's internally defined platforms
and plugins. When a platform type contains multiple platforms,
unless overridden, abuild always chooses to build on the last
platform declared that belongs to a given platform type. Since
plugins are evaluated in the order in which they are declared,
that means that platforms declared in later plugins can override
earlier ones as well as abuild's internal platform list with
respect to determining which platforms will be built by default.
[57]
When specifying a new platform or local compiler, the
list_platforms program may include the option
-lowpri to indicate that this is a low priority
platform or native compiler. This will cause the new platform
to be added with lower priority than previously declared
compilers including the built-in ones. Such compilers will only
be chosen if explicitly selected. The user can further refine
the choice of which platforms are built, including selecting low
priority compilers and platforms, by using platform selectors
(see Section 24.1, “Platform Selection”).

Each line of output of list_platforms must
take one of the following forms:

By convention, each native compiler should support a platform
with no options, a platform with the debug option,
and a platform with the release option. The
default should be to select the platform with no options, which
means the list_platforms program should
output platforms with no options last. The platform with no
options should provide both debugging and optimization flags.
The debug platform should omit all optimization
flags, and the release platform should omit all
debugging flags. For normal, everyday development, it generally
makes sense to have both debugging and optimization turned on.
The reason to have debugging turned on is that it makes it
possible to do light debugging in a debugger even with optimized
code. The reason to have optimization turned on is so that any
problems introduced by the optimizer and additional static
analysis that the compiler may do when optimizing will be
enabled during normal development. Since optimized code is
harder to debug in a symbolic debugger, the debug
version of a platform omits all optimization. Since it is often
desirable to ship code without debugging information in it, the
release version of a platform omits all debug
information.

These options only define the default behavior. It is still
possible to override debugging and optimization information on a
per-file basis or globally for a build item in
Abuild.mk (see Section 18.2.1, “C and C++: ccxx Rules”).
Note that on some platforms (such as Windows with Visual C++),
mixing debugging and non-debugging code may not be reliable. On
most UNIX platforms, it works fine to mix debugging and
non-debugging code.

When declaring a platform, all platform types that contain the
platform must have already been declared.

Note that object code platform names take the form
os.cpu.toolset.compiler[.option].
When declaring a platform with the native-compiler
directive, abuild automatically constructs a platform name by
using the native values for os, cpu,
and toolset. This saves every
list_platforms program from having to
determine this information.

[56]
Note that Cygwin is not Windows. Cygwin is really more like a
UNIX environment. Although abuild uses Cygwin to provide
make and other UNIX-like tools, the
Windows abuild executable is a native Windows application.
If you were to compile a Cygwin version of abuild, it would
not consider itself to be running in Windows and would not
invoke list_platforms with the
--windows option. That said, there are a few
pieces of code in the periphery of abuild that assume that,
if we're in a Cygwin environment, it is to support Windows.
These are all commented as such. Those parts of the code
would need to change if someone were to attempt to package
abuild for Cygwin.

[57]
Note, however, that the --list-platforms
option shows highest priority platforms first, which
effectively means that it shows the user platforms in the
opposite of their declaration order.