activeIf property
Work in progress.
Purpose
Provide additional control over the active state of an xCDL object.
Inactive objects are ignored by the configuration system and are greyed out when shown in the configuration hierarchy.
Syntax
{
"cdlOptions | cdlComponents": [
{
"name": "...",
...
"activeIf": [ "<expression>",... ],
...
}
]
}
The value of the activeIf property is an array of strings that contain boolean
expressions, typically used to verify hardware properties. If all these
expressions evaluate to true, the object is considered active.
Default value
If missing, no additional constraints are considered, the object is active.
Description
Configuration options or other objects may be either active or inactive.
Typically, this is controlled by the object's location in the overall hierarchy.
Consider the option utils-lists/trace, which exists below the component
utils-lists. If the whole component is disabled, then all options it contains
are inactive: there is no point in enabling trace for the utils-lists if the
utils-lists are not used; any requires constraints associated with trace are
irrelevant; any sourceFile property or other build-related property is
ignored and no source files are added to the build.
In some cases, the hierarchy does not provide sufficient control over whether or
not a particular object should be active. For example, the math library could
have support for floating point exceptions, which is only worthwhile if the
hardware implements appropriate functionality, as specified by the architectural
HAL. The relevant math library configuration options should remain below the
libm package in the overall hierarchy but should be inactive unless there is
appropriate hardware support. In cases like this, an activeIf property is
appropriate.
Another common use of activeIf properties is to avoid excessive nesting in the
configuration hierarchy. If some option B is only relevant if option A is
enabled, it is possible to turn A into a component that contains B. However,
adding another level to the hierarchy for a component that will contain just one
entry may be considered excessive. In such cases, it is possible for B to have
an activeIf dependency on A.
activeIf defines an array of boolean goal expressions, all of which must be
satisfied for the object to be active. For details of goal expression syntax,
see the section called Goal expressions in the
xCDL language page.
In most cases, the goal expressions will
be very simple, often involving just one other object, but more complicated
expressions can be used when appropriate.
The activeIf and requires properties have certain similarities, but they
serve a different purpose. Suppose there are two options A and B, and option B
relies on functionality provided by A. This could be expressed as either B
activeIf A or as B requires A. The points to note are:
- If B activeIf A is used and A is disabled or inactive, then configuration (graphical) tools will generally prevent any attempt at modifying B. For example the text for B could be greyed out, and the associated check button (if B is a boolean option) would be disabled. If the user needs the functionality provided by option B then it is necessary to go to option A first and enable it.
- If B requires A is used and A is disabled or inactive, configuration (graphical) tools will still allow B to be manipulated and enabled. This would result in a new conflict which may get resolved automatically or may require user intervention.
- If there are hardware dependencies, an
activeIfcondition is usually the preferred approach. There is no point in allowing the user to manipulate a configuration option if the corresponding functionality cannot possibly work on the currently selected hardware. The same argument applies to coarse-grained dependencies; for example if an option depends on the presence of a TCP/IP stack, then anactiveIfisEnabled('net')condition is appropriate. It may be possible to satisfy the condition, but it requires the fairly drastic step of loading another package. Furthermore, if the user wanted a TCP/IP stack in the configuration, it would probably have been loaded already. - If option B exists to provide additional debugging information about the
functionality provided by A, then an
activeIfconstraint is appropriate. There is no point in letting users enable extra debugging facilities for a feature that is not actually present. - The configuration system's inference engine will cope equally well with
activeIfandrequiresproperties. Suppose there is a conflict because some third option depends on B. If B activeIf A then the inference engine will attempt to make A active and enabled, and then to enable B if necessary. If B requires A then the inference engine will attempt to enable B and resolve the resulting conflict by causing A to be both active and enabled. Although the inference occurs in a different order, in most cases the effect will be the same.
Examples
TODO: update
Do not provide extra semaphore debugging if there are no semaphores:
{
"cdlOptions": [
{
"name": "kernel.instrument.binsem",
...
"activeIf": [ "isEnabled('kernel.synch')" ],
"customDefine": "OS_PACKAGE_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY"
...
}
]
}
Avoid another level in the configuration hierarchy:
{
"cdlOptions": [
{
"name": "kernel.synch.mutex.priorityInheritance.simple.relay",
...
"activeIf": [ "isEnabled('kernel.synch.mutex.priorityInheritance.simple')" ],
"customDefine": "OS_PACKAGE_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE_SIMPLE_RELAY",
...
}
]
}
Functionality that is only relevant if another package is loaded:
{
"cdlOptions": [
{
"name": "start.uitron-compatibility",
...
"activeIf": [ "isLoaded('uitron')" ],
"customDefine": "OS_PACKAGE_START_UITRON_COMPATIBILITY",
...
}
]
}
Check that the hardware or HAL provide the appropriate functionality:
{
"cdlOptions": [
{
"name": "hal.debug.gdb.break-support.debug-break-support",
...
"activeIf": [ "isEnabled('hal.debug.gdb.stubs-break')" ],
"customDefine": "OS_DEBUG_HAL_DEBUG_GDB_BREAK_SUPPORT",
...
}
]
}
See also
requiresproperty
eCos reference
active-ifproperty