There are four CDL-related commands which can occur at the top-level
of a CDL script: cdl_package, cdl_component, cdl_option and
cdl_interface. These correspond to the basic building blocks of the
language (CDL interfaces are described in the Section called Interfaces). All of these take the same basic form:
cdl_package <name> {
…
}
cdl_component <name> {
…
}
cdl_option <name> {
…
}
cdl_interface <name> {
…
} |
The command is followed by a name and by a body of properties, the
latter enclosed in braces. Packages and components can contain other
entities, so the cdl_package and cdl_component can also have
nested commands in their bodies. All names must be unique within a
given configuration. If say the C library package and a TCP/IP stack
both defined an option with the same name then it would not be
possible to load both of them into a single configuration. There is a
naming convention which should
make accidental name clashes very unlikely.
It is possible for two packages to use the same name if there are no
reasonable circumstances under which both packages could be loaded at
the same time. One example would be architectural HAL packages: a
given eCos configuration can be used on only one processor, so the
architectural HAL packages CYGPKG_HAL_ARM and
CYGPKG_HAL_I386 can re-use option names; in fact
in some cases they are expected to.
Each package has one top-level CDL script, which is specified in the
packages ecos.db database
entry. Typically the name of this top-level script is related to
the package, so the kernel package uses
kernel.cdl, but this is just a convention. The
first command in the top-level script should be cdl_package, and the
name used should be the same as in the ecos.db
database. There should be only one cdl_package command per package.
The various CDL entities live in a hierarchy. For example the kernel
package contains a scheduling component, a synchronization primitives
component, and a number of others. The synchronization component
contains various options such as whether or not mutex priority
inheritance is enabled. There is no upper bound on how far components
can be nested, but it is rarely necessary to go more than three or
four levels deeper than the package level. Since the naming convention
incorporates bits of the hierarchy, this has the added advantage of
keeping the names down to a more manageable size.
The hierarchy serves two purposes. It allows options to be controlled
en masse, so disabling a component automatically disables all the
options below it in the hierarchy. It also permits a much simpler
representation of the configuration in the graphical configuration
tool, facilitating navigation and modification.
By default a package is placed at the top-level of the hierarchy, but
it is possible to override this using a parent property. For example
an architectural HAL package such as CYGPKG_HAL_SH
typically re-parents itself below CYGPKG_HAL, and a
platform HAL package would then re-parent itself below the
architectural HAL. This makes it a little bit easier for users to
navigate around the hierarchy. Components, options and interfaces can
also be re-parented, but this is less common.
All components, options and interfaces that are defined directly in
the top-level script will be placed below the package in the hierarchy.
Alternatively they can be nested in the body of the cdl_package
command. The following two script fragments are equivalent:
cdl_package CYGPKG_LIBC {
…
}
cdl_component CYGPKG_LIBC_STRING {
…
}
cdl_option CYGPKG_LIBC_CTYPE_INLINES {
…
} |
and:
cdl_package CYGPKG_LIBC {
…
cdl_component CYGPKG_LIBC_STRING {
…
}
cdl_option CYGPKG_LIBC_CTYPE_INLINES {
…
}
} |
If a script defines options both inside and outside the body of the
cdl_package then the ones inside will be processed first. Language
purists may argue that it would have been better if all contained
options and components had to go into the body, but in practice it is
often convenient to be able to skip this level of nesting and the
resulting behavior is still well-defined.
Components can also contain options and other CDL entities, in fact
that is what distinguishes them from options. These can be defined in
the body of the cdl_component command:
cdl_component CYGPKG_LIBC_STDIO {
cdl_component CYGPKG_LIBC_STDIO_FLOATING_POINT {
…
}
cdl_option CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS {
…
}
} |
Nesting options inside the bodies of components like this is fine for
simple packages with only a limited number of configuration options,
but it becomes unsatisfactory as the number of options increases.
Instead it is possible to split the CDL data into multiple CDL
scripts, on a per-component basis. The script property should be
used for this. For example, in the case of the C library all
stdio-related configuration options could be put into
stdio.cdl, and the top-level CDL script
libc.cdl would contain the following:
cdl_package CYGPKG_LIBC {
…
cdl_component CYGPKG_LIBC_STDIO {
…
script stdio.cdl
}
} |
The CYGPKG_LIBC_STDIO_FLOATING_POINT component and
the CYGSEM_LIBC_STDIO_THREAD_SAFE_STREAMS option
can then be placed at the top-level of stdio.cdl.
It is possible to have some options nested in the body of a
cdl_component command and other options in a separate file accessed
by the script property. In such a case the nested options would be
processed first, and then the other script would be read in. A script
specified by a script property should only define new options,
components or interfaces: it should not contain any additional
properties for the current component.
It is possible for a component's CDL script to have a sub-component
which also has a script property, and so on. In practice excessive
nesting like this is rarely useful. It is also possible to ignore the
CDL language support for constructing hierarchies automatically and
use the parent property explicitly for every single option and
component. Again this is not generally useful.
Note: At the time of writing interfaces cannot act as containers. This may
change in a future version of the component framework. If the change
is made then interfaces would support the script property, just like
components.