Each package, component, option, and interface has a body of
properties, which provide the component framework with information
about how to handle each option. For example there is a property for a
descriptive text message which can be displayed to a user who is
trying to figure out just what effect manipulating the option would
have on the target application. There is another property for the
default value, for example whether a particular option should be
enabled or disabled by default.
All of the properties are optional, it is legal to define a
configuration option which has an empty body. However some properties
are more optional than others: users will not appreciate having to
manipulate an option if they are not given any sort of description or
documentation. Other properties are intended only for very specific
purposes, for example make_object and include_files, and are used
only rarely.
Because different properties serve very different purposes, their
syntax is not as uniform as the top-level commands. Some properties
take no arguments at all. Other properties take a single argument such
as a description string, or a list of arguments such as a compile
property which specifies the file or files that should be compiled if
a given option is active and enabled. The define_proc property takes
as argument a snippet of Tcl code. The active_if, calculated,
default_value, legal_values and requires properties take various
expressions. Additional properties may be defined in future which take
new kinds of arguments.
All property parsing code supports options for every property,
although at present the majority of properties do not yet take any
options. Any initial arguments that begin with a hyphen character
- will be interpreted as an option, for example:
cdl_package CYGPKG_HAL_ARM {
…
make -priority 1 {
…
}
} |
If the option involves additional data, as for the
-priority example above, then this can be written
as either -priority=1 or as
-priority 1. On occasion the option parsing
code can get in the way, for example:
cdl_option CYGNUM_LIBC_TIME_DST_DEFAULT_STATE {
…
legal_values -1 to 1
default_value -1
} |
Neither the legal_values nor the default_value property will
accept -1 as a valid option, so this will result in
syntax errors when the CDL script is read in by the component
framework. To avoid problems, the option parsing code will recognize
the string -- and will not attempt to interpret any
subsequent arguments. Hence this option should be written as:
cdl_option CYGNUM_LIBC_TIME_DST_DEFAULT_STATE {
…
legal_values -- -1 to 1
default_value -- -1
} |
The property parsing code involves a recursive invocation of the Tcl
interpreter that is used to parse the top-level commands. This means
that some characters in the body of an option will be treated
specially. The # character can be used for
comments. The backslash character \, the
dollar character $, square brackets
[ and ], braces
{ and }, and the quote character
" may all receive special treatment. Most of the
time this is not a problem because these characters are not useful for
most properties. On occasion having a Tcl interpreter around
performing the parser can be very powerful. For more details of
how the presence of a Tcl interpreter can affect CDL scripts,
see the Section called An Introduction to Tcl.
Many of the properties can be used in any of cdl_package,
cdl_component, cdl_option or cdl_interface. Other properties are
more specific. The script property is only relevant to components.
The define_header, hardware, include_dir, include_files, and
library properties apply to a package as a whole, so can only occur
in the body of a cdl_package command. The calculated,
default_value, legal_values and flavor properties are not
relevant to packages, as will be explained later. The calculated and
default_value properties are also not relevant to interfaces.
This section lists the various properties, grouped by purpose. Each
property also has a full reference page in Chapter 5.
Properties related to values and expressions are described in more
detail in the Section called Values and Expressions. Properties related to
header file generation and to the build process are described in
Chapter 4.
Users can only be expected to manipulate configuration options
sensibly if they are given sufficient information about these options.
There are three properties which serve to explain an option in plain
text: the display property gives
a textual alias for an option, which is usually more comprehensible
than something like CYGPKG_LIBC_TIME_ZONES`; the
description property gives a
longer description, typically a paragraph or so; the doc property specifies the location of
additional on-line documentation related to a configuration option. In
the context of a graphical tool the display string will be the
primary way for users to identify configuration options; the
description paragraph will be visible whenever the option is
selected; the on-line documentation will only be accessed when the
user explicitly requests it.
cdl_package CYGPKG_UITRON {
display "uITRON compatibility layer"
doc ref/ecos-ref.a.html
description "
eCos supports a uITRON Compatibility Layer, providing
full Level S (Standard) compliance with Version 3.02 of
the uITRON Standard, plus many Level E (Extended) features.
uITRON is the premier Japanese embedded RTOS standard."
…
} |
All three properties take a single argument. For display and
description this argument is just a string. For doc it should be a
pointer to a suitable HTML file, optionally including an anchor within
that page. If the directory layout
conventions are observed then the component framework will look
for the HTML file in the package's doc sub-directory, otherwise the doc
filename will be treated as relative to the package's top-level directory.
There are two properties related to the hierarchical organization of
components and options: parent and
script.
The parent property can be used to move a CDL entity somewhere
else in the hierarchy. The most common use is for packages, to avoid
having all the packages appear at the top-level of the configuration
hierarchy. For example an architectural HAL package such as
CYGPKG_HAL_SH is placed below the common HAL
package CYGPKG_HAL using a parent property.
cdl_package CYGPKG_HAL_SH {
display "SH architecture"
parent CYGPKG_HAL
…
} |
The parent property can also be used in the body of a
cdl_component, cdl_option or cdl_interface, but this is less
common. However care has to be taken since excessive re-parenting can
be confusing. Care also has to be taken when reparenting below some
other package that may not actually be loaded in a given
configuration, since the resulting behavior is undefined.
As a special case, if the parent is the empty string then the
CDL entity is placed at the root of the hierarchy. This is useful
for global preferences, default compiler flags, and other settings
that may affect every package.
The script property can only be used in the body of a
cdl_component command. The property takes a single filename as
argument, and this should be another CDL script containing
additional options, sub-components and interfaces that should go below
the current component in the hierarchy. If the directory layout conventions are
observed then the component framework will look for the specified file
relative to the cdl
subdirectory of the package, otherwise the filename will be treated as
relative to the package's top-level directory.
cdl_component CYGPKG_LIBC_STDIO {
display "Standard input/output functions"
flavor bool
requires CYGPKG_IO
requires CYGPKG_IO_SERIAL_HALDIAG
default_value 1
description "
This enables support for standard I/O functions from <stdio.h>."
script stdio.cdl
} |
There are seven properties which are related to option values and
state: flavor,
calculated,
default_value,
legal_values,
active_if,
implements, and
requires. More detailed
information can be found in the Section called Values and Expressions.
In the context of configurability, the concept of an option's value is
somewhat non-trivial. First an option may or may not be loaded: it is
possible to build a configuration which has the math library but not
the kernel; however the math library's CDL scripts still reference
kernel options, for example
CYGSEM_LIBM_THREAD_SAFE_COMPAT_MODE has a
requires constraint on
CYGVAR_KERNEL_THREADS_DATA. Even if an option is
loaded it may or may not be active, depending on what is happening
higher up in the hierarchy: if the C library's
CYGPKG_LIBC_STDIO component is disabled then some
other options such as CYGNUM_LIBC_STDIO_BUFSIZE
become irrelevant. In addition each option has both a boolean
enabled/disabled flag and a data part. For many options only the
boolean flag is of interest, while for others only the data part is of
interest. The flavor property can be used to control this:
- flavor none
This flavor indicates that neither the boolean nor the data parts are
user-modifiable: the option is always enabled and the data is always
set to 1. The most common use for this is to have a
component that just acts as a placeholder in the hierarchy, allowing
various options to be grouped below it.
- flavor bool
Only the boolean part of the option is user-modifiable. The data part
is fixed at 1.
- flavor data
Only the data part of the option is user-modifiable. The boolean part
is fixed at enabled.
- flavor booldata
Both the boolean and the data part of the option are user-modifiable.
For more details of CDL flavors and how a flavor affects expression
evaluation, and other consequences, see the Section called Values and Expressions. The flavor property cannot be used for a
package because packages always have the booldata
flavor. Options and components have the bool flavor
by default, since most configuration choices are simple yes-or-no
choices. Interfaces have the data flavor by default.
The calculated property can be used for options which should not be
user-modifiable, but which instead are fixed by the target hardware or
determined from the current values of other options. In general
calculated options should be avoided, since they can be confusing to
users who need to figure out whether or not a particular option can
actually be changed. There are a number of valid uses for calculated
options, and quite a few invalid ones as well. The reference packages should be consulted
for further details. The property takes an ordinary CDL expression as
argument, for example:
# A constant on some target hardware, perhaps user-modifiable on other
# targets.
cdl_option CYGNUM_HAL_RTC_PERIOD {
display "Real-time clock period"
flavor data
calculated 12500
} |
The calculated property cannot be used for packages or interfaces.
The value of a package always corresponds to the version of that
package which is loaded, and this is under user control. Interfaces
are implicitly calculated, based on the number of active and enabled
implementors.
The default_value property is similar to calculated, but only
specifies a default value which users can modify. Again this property
is not relevant to packages or interfaces. A typical example would be:
cdl_option CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT {
display "Include GDB multi-threading debug support"
requires CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
default_value CYGDBG_KERNEL_DEBUG_GDB_THREAD_SUPPORT
…
} |
The legal_values property imposes a constraint on the possible
values of the data part of an option. Hence it is only applicable to
options with the data or
booldata flavors. It cannot be used for a package
since the only valid value for a package is its version number. The
arguments to the legal_values property should constitute a CDL list expression.
cdl_option CYGNUM_LIBC_TIME_STD_DEFAULT_OFFSET {
display "Default Standard Time offset"
flavor data
legal_values -- -90000 to 90000
default_value -- 0
…
} |
The active_if property does not relate directly to an option's
value, but rather to its active state. Usually this is controlled via
the configuration hierarchy: if the
CYGPKG_LIBC_STDIO component is disabled then all
options below it are inactive and do not have any consequences.
In some cases the hierarchy does not provide sufficient control, for
example an option should only be active if two disjoint sets of
conditions are satisfied: the hierarchy could be used for one of these
conditions, and an additional active_if property could be used for
the other one. The arguments to active_if should constitute a
CDL goal expression.
# Do not provide extra semaphore debugging if there are no semaphores
cdl_option CYGDBG_KERNEL_INSTRUMENT_BINSEM {
active_if CYGPKG_KERNEL_SYNCH
…
} |
The implements property is related to the concept of CDL interfaces. If an option is
active and enabled and it implements a particular interface then it
contributes 1 to that interface's value.
cdl_package CYGPKG_NET_EDB7XXX_ETH_DRIVERS {
display "Cirrus Logic ethernet driver"
implements CYGHWR_NET_DRIVERS
implements CYGHWR_NET_DRIVER_ETH0
…
} |
The requires property is used to impose constraints on the user's
choices. For example it is unreasonable to expect the C library to
provide thread-safe implementations of certain functions if the
underlying kernel support has been disabled, or even if the kernel is
not being used at all.
cdl_option CYGSEM_LIBC_PER_THREAD_ERRNO {
display "Per-thread errno"
doc ref/ecos-ref.15.html
requires CYGVAR_KERNEL_THREADS_DATA
default_value 1
…
} |
The arguments to the requires property should be a CDL goal expression.
When creating or updating a build tree the component framework will
also generate configuration header files, one per package. By default
it will generate a #define for each option,
component or interface that is active and enabled. For options with
the data or booldata flavors the
#define will use the option's data part, otherwise
it will use the constant 1. Typical output would
include:
#define CYGFUN_LIBC_TIME_POSIX 1
#define CYGNUM_LIBC_TIME_DST_DEFAULT_STATE -1 |
There are six properties which can be used to control the header file
generation process:
define_header,
no_define,
define_format,
define,
if_define, and
define_proc.
By default the component framework will generate a configuration
header file for each package based on the package's name: everything
up to and including the first underscore is discarded, the rest of the
name is lower-cased, and a .h suffix is appended.
For example the configuration header file for the kernel package
CYGPKG_KERNEL is pkgconf/kernel.h. The define_header
property can be used to specify an alternative filename. This applies
to all the components and options within a package, so it can only be
used in the body of a cdl_package command. For example the following
specifies that the configuration header file for the SPARClite HAL
package is pkgconf/hal_sparclite.h.
cdl_package CYGPKG_HAL_SPARCLITE {
display "SPARClite architecture"
parent CYGPKG_HAL
hardware
define_header hal_sparclite.h
…
} |
Note: At present the main use for the define_header property is related
to hardware packages, see the reference
pages for more details.
The no_define property is used to suppress the generation of the
default #define. This can be useful if an option's
consequences are all related to the build process or to constraints,
and the option is never actually checked in any source code. It can
also be useful in conjunction with the define, if_define or
define_proc properties. The no_define property does not take any
arguments.
cdl_component CYG_HAL_STARTUP {
display "Startup type"
flavor data
legal_values { "RAM" "ROM" }
default_value {"RAM"}
no_define
define -file system.h CYG_HAL_STARTUP
…
} |
This example also illustrates the define property, which can be used
to generate a #define in addition to the default
one. It takes a single argument, the name of the symbol to be defined.
It also takes options to control the configuration header file in
which the symbol should be defined and the format to be used.
The define_format property can be used to control how the value part
of the default #define gets formatted. For example
a format string of "0x%04x" could be used to
generate a four-digit hexadecimal number.
The if_define property is intended for use primarily to control
assertions, tracing, and similar functionality. It supports a specific
implementation model for these, allowing control at the grain of
packages or even individual source files. The reference pages provide additional
information.
The define_proc property provides an escape mechanism for those
cases where something special has to happen at configuration header
file generation time. It takes a single argument, a fragment of Tcl
code, which gets executed when the header file is generated. This code
can output arbitrary data to the header file, or perform any other
actions that might be appropriate.
There are six properties which affect the build process:
compile,
make,
make_object,
library,
include_dir, and
include_files.
The last three apply to a package as a whole, and can only occur in
the body of a cdl_package command.
Most of the source files that go into a package should simply be
compiled with the appropriate compiler, selected by the target
architecture, and with the appropriate flags, with an additional set
defined by the target hardware and possible modifications on a
per-package basis. The resulting object files will go into the library
libtarget.a, which can then be linked against
application code. The compile property is used to list these source
files:
cdl_package CYGPKG_ERROR {
display "Common error code support"
compile strerror.cxx
include_dir cyg/error
…
} |
The arguments to the compile property should be one or more source
files. Typically most of the sources will be needed for the package as
a whole, and hence they will be listed in one or more compile
properties in the body of the cdl_package. Some sources may be
specific to particular configuration options, in other words there is
no point in compiling them unless that option is enabled, in which
case the sources should be listed in a compile property in the
corresponding cdl_option, cdl_component or cdl_interface body.
Some packages may have more complicated build requirements, for
example they may involve a special target such as a linker script
which should not end up in the usual library, or they may involve
special build steps for generating an object file. The make and
make_object properties provide support for such requirements, for
example:
cdl_package CYGPKG_HAL_MN10300_AM33 {
display "MN10300 AM33 variant"
…
make {
<PREFIX>/lib/target.ld: <PACKAGE>/src/mn10300_am33.ld
$(CC) -E -P -Wp,-MD,target.tmp -DEXTRAS=1 -xc $(INCLUDE_PATH) \
$(CFLAGS) -o $@ $<
@echo $@ ": \\" > $(notdir $@).deps
@tail +2 target.tmp >> $(notdir $@).deps
@echo >> $(notdir $@).deps
@rm target.tmp
}
} |
For full details of custom build steps and the build process
generally, see Chapter 4.
By default all object files go into the library
libtarget.a. It is possible to override this at
the package level using the library property, but this should be
avoided since it complicates application development: instead of just
linking with a single library for all eCos-related packages, it
suddenly becomes necessary to link with several libraries.
The include_dir and include_files properties relate to a package's
exported header files. By default a package's header files will be
exported to the install/include
directory. This is the desired behavior for some packages like the C
library, since headers like stdio.h should exist at that level.
However if all header files were to end up in that directory then
there would be a significant risk of a name clash. Instead it is
better for packages to specify some sub-directory for their exported
header files, for example:
cdl_package CYGPKG_INFRA {
display "Infrastructure"
include_dir cyg/infra
…
} |
The various header files exported by the infrastructure, for example
cyg_ass.h and cyg_trac.h will now end up in the
install/include/cyg/infra
sub-directory, where a name clash is very unlikely.
For packages which follow the directory layout conventions the
component framework will assume that the package's
include sub-directory contains
all exported header files. If this is not the case, for example
because the package is sufficiently simple that the layout convention
is inappropriate, then the exported header files can be listed
explicitly in an include_files property.
The hardware property is
only relevant to packages. Some packages such as device drivers and
HAL packages are hardware-specific, and generally it makes no sense to
add such packages to a configuration unless the corresponding hardware
is present on your target system. Typically hardware package selection
happens automatically when you select your target. The hardware
property should be used to identify a hardware-specific package, and
does not take any arguments.
cdl_package CYGPKG_HAL_MIPS {
display "MIPS architecture"
parent CYGPKG_HAL
hardware
include_dir cyg/hal
define_header hal_mips.h
…
} |
At present the hardware property is largely ignored by the component
framework. This may change in future releases.