For many configurability requirements, options provide sufficient
expressive power. However there are times when a higher level of
abstraction is appropriate. As an example, suppose that some package
relies on the presence of code that implements the standard kernel
scheduling interface. However the requirement is no more stringent
than this, so the constraint can be satisfied by the mlqueue
scheduler, the bitmap scheduler, or any additional schedulers that may
get implemented in future. A first attempt at expressing the
dependency might be:
requires CYGSEM_KERNEL_SCHED_MLQUEUE || CYGSEM_KERNEL_SCHED_BITMAP |
This constraint will work with the current release, but it is limited.
Suppose there is a new release of the kernel which adds another
scheduler such as a deadline scheduler, or suppose that there is a new
third party package which adds such a scheduler. The package
containing the limited constraint would now have to be updated and
another release made, with possible knock-on effects.
CDL interfaces provide an abstraction mechanism: constraints can be
expressed in terms of an abstract concept, for example
“scheduler”, rather than specific implementations such as
CYGSEM_KERNEL_SCHED_MLQUEUE and
CYGSEM_KERNEL_SCHED_BITMAP. Basically an interface
is a calculated configuration option:
cdl_interface CYGINT_KERNEL_SCHEDULER {
display "Number of schedulers in this configuration"
…
} |
The individual schedulers can then implement this interface:
cdl_option CYGSEM_KERNEL_SCHED_MLQUEUE {
display "Multi-level queue scheduler"
default_value 1
implements CYGINT_KERNEL_SCHEDULER
…
}
cdl_option CYGSEM_KERNEL_SCHED_BITMAP {
display "Bitmap scheduler"
default_value 0
implements CYGINT_KERNEL_SCHEDULER
…
} |
Future schedulers can also implement this interface. The value of an
interface, for the purposes of expression evaluation, is the number of
active and enabled options which implement this interface. Packages
which rely on the presence of a scheduler can impose constraints such
as:
requires CYGINT_KERNEL_SCHEDULER |
If none of the schedulers are enabled, or if the kernel package is not
loaded, then CYGINT_KERNEL_SCHEDULER will evaluate
to 0. If at least one scheduler is active and
enabled then the constraint will be satisfied.
Because interfaces have a calculated value determined by the
implementors, the default_value and calculated properties are not
applicable and should not appear in the body of a cdl_interface
command. Interfaces have the data flavor by
default, but the bool and
booldata flavors may be specified instead. A
bool interface is disabled if there are no active
and enabled implementors, otherwise it is enabled. A
booldata interface is disabled if there are no
active and enabled implementors, otherwise it is enabled and has a
value corresponding to the number of these implementors. Other
properties such as requires and compile can be used as normal.
Some component writers will not want to use interfaces in this way.
The reasoning is that their code will only have been tested with the
existing schedulers, so the requires constraint needs to be
expressed in terms of those schedulers; it is possible that the
component will still work with a new scheduler, but there are no
guarantees. Other component writers may take a more optimistic view
and assume that their code will work with any scheduler until proven
otherwise. It is up to individual component writers to decide which
approach is most appropriate in any given case.
One common use for interfaces is to describe the hardware
functionality provided by a given target. For example the CDL
scripts for a TCP/IP package might want to know whether or not the
target hardware has an ethernet interface. Generally it is not
necessary for the TCP/IP stack to know exactly which ethernet hardware
is present, since there should be a device driver which implements the
appropriate functionality. In CDL terms the device drivers should
implement an interface CYGHWR_NET_DRIVERS, and the
CDL scripts for the TCP/IP stack can use this in appropriate
expressions.
Note: Using the term interface for this concept is
sometimes confusing, since the term has various other meanings as
well. In practice, it is often correct. If there is a configuration
option that implements a given CDL interface, then usually this
option will enable some code that provides a particular interface at
the C or C++ level. For example an ethernet device driver implements
the CDL interface CYGHWR_NET_DRIVERS, and also
implements a set of C functions that can be used by the TCP/IP stack.
Similarly CYGSEM_KERNEL_SCHED_MLQUEUE implements
the CDL interface CYGINT_KERNEL_SCHEDULER and
also provides the appropriate scheduling functions.