build: introduce GLUON_FEATURES

To reduce the number of packages that need to be listed in
GLUON_SITE_PACKAGES, this adds a new variable GLUON_FEATURES. Sets of
packages are enabled automatically based on the combination of listed
feature flags.

Site-specified package feeds can provide their own feature flag
definitions.
This commit is contained in:
Matthias Schiffer 2017-07-09 01:09:15 +02:00
parent e2b508ee2a
commit 6ca841bad5
No known key found for this signature in database
GPG Key ID: 16EF3F64CB201D9C
7 changed files with 215 additions and 28 deletions

View File

@ -77,13 +77,19 @@ list-targets: FORCE
GLUON_DEFAULT_PACKAGES := -odhcpd -ppp -ppp-mod-pppoe -wpad-mini gluon-core ip6tables hostapd-mini
GLUON_FEATURE_PACKAGES := $(shell scripts/features.sh '$(GLUON_FEATURES)')
ifneq ($(.SHELLSTATUS),0)
$(error Error while evaluating GLUON_FEATURES)
endif
GLUON_PACKAGES :=
define merge_packages
$(foreach pkg,$(1),
GLUON_PACKAGES := $$(strip $$(filter-out -$$(patsubst -%,%,$(pkg)) $$(patsubst -%,%,$(pkg)),$$(GLUON_PACKAGES)) $(pkg))
)
endef
$(eval $(call merge_packages,$(GLUON_DEFAULT_PACKAGES) $(GLUON_SITE_PACKAGES)))
$(eval $(call merge_packages,$(GLUON_DEFAULT_PACKAGES) $(GLUON_FEATURE_PACKAGES) $(GLUON_SITE_PACKAGES)))
GLUON_PACKAGES_YES := $(filter-out -%,$(GLUON_PACKAGES))
GLUON_PACKAGES_NO := $(patsubst -%,%,$(filter -%,$(GLUON_PACKAGES)))

View File

@ -0,0 +1,45 @@
Feature flags
=============
Feature flags provide a convenient way to define package selections without
making it necessary to list each package explicitly.
The main feature flag definition file is ``package/features``, but each package
feed can provide addition defintions in a file called ``features`` at the root
of the feed repository.
Each flag *$flag* without any explicit definition will simply include the package
with the name *gluon-$flag* by default. The feature definition file can modify
the package selection in two ways:
* The *nodefault* function suppresses default of including the *gluon-$flag*
package
* The *packages* function adds a list of packages (or removes, when package
names are prepended with minus signs) when a given logical expression
is satisfied
Example::
nodefault 'web-wizard'
packages 'web-wizard' \
'gluon-config-mode-hostname' \
'gluon-config-mode-geo-location' \
'gluon-config-mode-contact-info'
packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \
'gluon-config-mode-mesh-vpn'
This will
* Disable the inclusion of a (non-existent) package called *gluon-web-wizard*
* Enable three config mode packages when the *web-wizard* feature is enabled
* Enable *gluon-config-mode-mesh-vpn* when both *web-wizard* and one
of *mesh-vpn-fastd* and *mesh-vpn-tunneldigger* is enabled
Supported syntax elements of logical expressions are:
* \& (and)
* \| (or)
* \! (not)
* parentheses

View File

@ -33,6 +33,7 @@ Several Freifunk communities in Germany use Gluon as the foundation of their Fre
:maxdepth: 2
dev/basics
dev/feature-flags
dev/hardware
dev/upgrade
dev/wan

View File

@ -1,29 +1,29 @@
## gluon site.mk makefile example
## GLUON_SITE_PACKAGES
# specify Gluon/LEDE packages to include here
# Specify Gluon features/packages to enable;
# Gluon will automatically enable a set of packages
# depending on the combination of features listed
GLUON_SITE_PACKAGES := \
gluon-alfred \
gluon-respondd \
gluon-autoupdater \
gluon-config-mode-autoupdater \
gluon-config-mode-contact-info \
gluon-config-mode-geo-location \
gluon-config-mode-hostname \
gluon-config-mode-mesh-vpn \
gluon-ebtables-filter-multicast \
gluon-ebtables-filter-ra-dhcp \
gluon-web-admin \
gluon-web-autoupdater \
gluon-web-network \
gluon-web-wifi-config \
gluon-mesh-batman-adv-15 \
gluon-mesh-vpn-fastd \
gluon-radvd \
gluon-status-page \
haveged \
iwinfo
GLUON_FEATURES :=
autoupdater \
ebtables-filter-multicast \
ebtables-filter-ra-dhcp \
mesh-batman-adv-15 \
mesh-vpn-fastd \
radvd \
respondd \
status-page \
web-advanced \
web-wizard
## GLUON_SITE_PACKAGES
# Specify additional Gluon/LEDE packages to include here;
# A minus sign may be prepended to remove a packages from the
# selection that would be enabled by default or due to the
# chosen feature flags
GLUON_SITE_PACKAGES := haveged iwinfo
## DEFAULT_GLUON_RELEASE
# version string to use for images

View File

@ -382,15 +382,20 @@ legacy \: package
wifi_names = {'wifi_freifunk', 'wifi_freifunk5', 'wifi_mesh', 'wifi_mesh5'},
}
Packages
--------
Build configuration
-------------------
The ``site.mk`` is a Makefile which should define constants
The ``site.mk`` is a Makefile which defines various values
involved in the build process of Gluon.
GLUON_FEATURES
Defines a list of features to include. The feature list is used to generate
the default package set.
GLUON_SITE_PACKAGES
Defines a list of packages which should be installed additionally
to the ``gluon-core`` package.
Defines a list of packages which should be installed in addition to the
default package set. It is also possible to remove packages from the
default set by prepending a minus sign to the package name.
GLUON_RELEASE
The current release version Gluon should use.
@ -407,6 +412,34 @@ GLUON_LANGS
List of languages (as two-letter-codes) to be included in the web interface. Should always contain
``en``.
Features
^^^^^^^^
Most feature flags enable only a single package that is derived from the flag
name; for example, the flag *mesh-batman-adv-15* will include the package
*gluon-mesh-batman-adv-15*.
The following flags will add multiple packages:
* *web-wizard*
- *gluon-config-mode-hostname*
- *gluon-config-mode-geo-location*
- *gluon-config-mode-contact-info*
- *gluon-config-mode-autoupdater* (if the *autoupdater* feature is enabled)
- *gluon-config-mode-mesh-vpn* (if the *mesh-vpn-fastd* or *mesh-vpn-tunneldigger* feature is enabled)
* *web-advanced*
- *gluon-web-admin*
- *gluon-web-network*
- *gluon-web-wifi-config*
- *gluon-web-autoupdater* (if the *autoupdater* feature is enabled)
- *gluon-web-mesh-vpn-fastd* (if the *mesh-vpn-fastd* feature is enabled)
Site-provided package feeds can define additional feature flags.
.. _site-config-mode-texts:
Config mode texts

26
package/features Normal file
View File

@ -0,0 +1,26 @@
nodefault 'web-wizard'
packages 'web-wizard' \
'gluon-config-mode-hostname' \
'gluon-config-mode-geo-location' \
'gluon-config-mode-contact-info'
packages 'web-wizard & autoupdater' \
'gluon-config-mode-autoupdater'
packages 'web-wizard & (mesh-vpn-fastd | mesh-vpn-tunneldigger)' \
'gluon-config-mode-mesh-vpn'
nodefault 'web-advanced'
packages 'web-advanced' \
'gluon-web-admin' \
'gluon-web-network' \
'gluon-web-wifi-config'
packages 'web-advanced & autoupdater' \
'gluon-web-autoupdater'
packages 'web-advanced & mesh-vpn-fastd' \
'gluon-web-mesh-vpn-fastd'

76
scripts/features.sh Executable file
View File

@ -0,0 +1,76 @@
#!/bin/bash --norc
set -e
shopt -s nullglob
nodefault() {
# We define a function instead of a variable, as variables could
# be predefined in the environment (in theory)
eval "gluon_feature_nodefault_$1() {
:
}"
}
packages() {
:
}
for f in package/features packages/*/features; do
. "$f"
done
# Shell variables can't contain minus signs, so we escape them
# using underscores (and also escape underscores to avoid mapping
# multiple inputs to the same output)
sanitize() {
local v="$1"
v="${v//_/_1}"
v="${v//-/_2}"
echo -n "$v"
}
vars=
for feature in $1; do
if [ "$(type -t gluon_feature_nodefault_${feature})" != 'function' ]; then
echo "gluon-${feature}"
fi
vars="$vars $(sanitize "$feature")=1"
done
nodefault() {
:
}
packages() {
local cond="$(sanitize "$1")"
shift
# We only allow variable names, parentheses and the operators: & | !
if [ "$(expr match "$cond" '.*[^A-Za-z0-9_()&|! ].*')" -gt 0 ]; then
exit 1
fi
# Let will return false when the result of the passed expression is 0,
# so we always add 1. This way false is only returned for syntax errors.
local ret="$(env -i $vars bash --norc -ec "let _result_='1+($cond)'; echo -n \"\$_result_\"" 2>/dev/null)"
case "$ret" in
2)
for pkg in "$@"; do
echo "$pkg"
done
;;
1)
;;
*)
exit 1
esac
}
for f in package/features packages/*/features; do
. "$f"
done