11#! /usr/bin/env bash
2- # 2025021702
2+ # 2026053001
33
44# This script can run in a container (absolute paths) or in a Windows-VM.
55
66set -e -x
77
88if uname -a | grep -q " _NT" ; then
99 # We are on Windows.
10+ IS_WINDOWS=' yes'
1011 REPO_DIR=" $LFMP_DIR_REPOS "
12+ COMPILE_DIR=" $LFMP_DIR_COMPILED "
1113else
1214 # We are in a container.
15+ IS_WINDOWS=' no'
1316 REPO_DIR=" /repos"
17+ COMPILE_DIR=" /compiled"
1418fi
1519
16- if ! uname -a | grep -q " _NT " ; then
20+ if [ " $IS_WINDOWS " = ' no ' ] ; then
1721 # We are in a container.
1822 source /opt/venv/bin/activate
1923 PY_TAG=" py$( python3 -c ' import sys; print(f"{sys.version_info.major}{sys.version_info.minor}")' ) "
@@ -26,10 +30,23 @@ if ! uname -a | grep -q "_NT"; then
2630fi
2731python3 --version
2832
29- # Loop through each plugin in the list.
33+ SCRIPT_DIR=" $( dirname " $0 " ) "
34+ COMPILE_ONE=" $SCRIPT_DIR /compile-one.sh"
35+
36+ # Number of plugins to compile concurrently. Defaults to 4 (the GitHub Windows
37+ # runner has 4 vCPUs). Override with LFMP_COMPILE_JOBS.
38+ JOBS=" ${LFMP_COMPILE_JOBS:- 4} "
39+
40+ # Capture the optional user-provided plugin list once. The per-group logic
41+ # below mirrors the original behaviour: when a list is given it applies to
42+ # check-plugins only; event-plugins and notification-plugins are skipped.
43+ USER_PLUGIN_LIST=" $LFMP_COMPILE_PLUGINS "
44+
45+ # Build a flat list of "<group> <plugin>" tasks to compile.
46+ TASKS=()
3047for PLUGINS in event-plugins notification-plugins check-plugins ; do
31- if [[ ! -z " $LFMP_COMPILE_PLUGINS " && " $PLUGINS " != " check-plugins" ]]; then
32- # if check-plugin list is given, skip event-plugins and notification-plugins to save time
48+ if [[ -n " $USER_PLUGIN_LIST " && " $PLUGINS " != " check-plugins" ]]; then
49+ # if a check-plugin list is given, skip event-plugins and notification-plugins to save time
3350 echo " ✅ Skipping $REPO_DIR /monitoring-plugins/$PLUGINS ..."
3451 continue
3552 fi
@@ -39,30 +56,68 @@ for PLUGINS in event-plugins notification-plugins check-plugins ; do
3956 fi
4057 echo " ✅ Processing $PLUGINS ..."
4158
42- # If $LFMP_COMPILE_PLUGINS is empty, find all plugin directories under
43- # $REPO_DIR/monitoring-plugins/$PLUGINS/ and create a space-separated list.
44- if [[ -z " $LFMP_COMPILE_PLUGINS " ]]; then
59+ if [[ -z " $USER_PLUGIN_LIST " ]]; then
4560 echo " ✅ No plugin list provided. Discovering all plugins..."
46- # Find directories immediately under $PLUGINS/, extract their basenames, and join them with commas.
47- LFMP_COMPILE_PLUGINS=$(
61+ # List the directories immediately under $PLUGINS/ by basename.
62+ # avoid using `find` as this is sometimes problematic in Github runners
63+ GROUP_PLUGINS=$(
4864 for d in " $REPO_DIR /monitoring-plugins/$PLUGINS " /* ; do
4965 [ -d " $d " ] && basename " $d "
5066 done | sort
51- ) # avoid using `find` as this is sometimes problematic in Github runners
52- echo " ✅ Found '$LFMP_COMPILE_PLUGINS '"
67+ )
68+ echo " ✅ Found '$GROUP_PLUGINS '"
69+ else
70+ GROUP_PLUGINS=" $USER_PLUGIN_LIST "
5371 fi
5472
55- for PLUGIN in $LFMP_COMPILE_PLUGINS ; do
73+ for PLUGIN in $GROUP_PLUGINS ; do
5674 if [ " $PLUGIN " == " example" ]; then
5775 continue
5876 fi
59- if [[ -d " $REPO_DIR /monitoring-plugins/$PLUGINS /$PLUGIN " ]]; then
60- bash $( dirname " $0 " ) /compile-one.sh $PLUGINS $PLUGIN
61- else
77+ if [[ ! -d " $REPO_DIR /monitoring-plugins/$PLUGINS /$PLUGIN " ]]; then
6278 echo " ✅ Directory $REPO_DIR /$PLUGINS /$PLUGIN does not exist. Ignoring..."
79+ continue
80+ fi
81+ # On Windows only plugins carrying a `.windows` marker get compiled
82+ # (compile-one.sh enforces this too). Filter them out here so the
83+ # parallel pool below is not filled with immediate no-op invocations.
84+ if [[ " $IS_WINDOWS " = ' yes' && ! -f " $REPO_DIR /monitoring-plugins/$PLUGINS /$PLUGIN /.windows" ]]; then
85+ echo " ✅ Ignoring '$PLUGIN ' on Windows (no .windows marker)"
86+ continue
87+ fi
88+ TASKS+=(" $PLUGINS $PLUGIN " )
89+ done
90+ done
91+
92+ # Compile. The first plugin runs alone to warm up Nuitka's download/cache dir
93+ # (depends.exe, ccache, ...), so the parallel batch that follows does not race
94+ # on first-time downloads. The rest run up to $JOBS at a time. xargs returns
95+ # non-zero if any invocation fails, so `set -e` aborts the whole build.
96+ if (( ${# TASKS[@]} > 0 )) ; then
97+ echo " ✅ Compiling ${# TASKS[@]} plugin(s), up to $JOBS in parallel..."
98+ read -r WARM_GROUP WARM_PLUGIN <<< " ${TASKS[0]}"
99+ bash " $COMPILE_ONE " " $WARM_GROUP " " $WARM_PLUGIN "
100+ if (( ${# TASKS[@]} > 1 )) ; then
101+ printf ' %s\n' " ${TASKS[@]: 1} " | xargs -P " $JOBS " -L 1 bash " $COMPILE_ONE "
102+ fi
103+ fi
104+
105+ # Merge each plugin's standalone `*.dist` directory into the shared, flattened
106+ # group directory to save disk space (important on Github runners). Done here,
107+ # serially, after all parallel compiles finished, so the shared runtime files
108+ # the plugins all carry (python3xx.dll etc.) are never written concurrently.
109+ # The special `/.` suffix copies only the *contents* of each dist directory.
110+ for PLUGINS in event-plugins notification-plugins check-plugins ; do
111+ GROUP_DIR=" $COMPILE_DIR /$PLUGINS "
112+ [ -d " $GROUP_DIR " ] || continue
113+ for DIST in " $GROUP_DIR " /* .dist ; do
114+ [ -d " $DIST " ] || continue
115+ if [ -n " $( ls --almost-all " $DIST " ) " ]; then
116+ echo " ✅ cp --archive $DIST /. $GROUP_DIR /"
117+ \c p --archive " $DIST " /. " $GROUP_DIR " /
63118 fi
119+ rm -rf " $DIST "
64120 done
65- LFMP_COMPILE_PLUGINS=" "
66121done
67122
68123# On RHEL? Then also compile the Linuxfabrik Type Enforcement Policy
0 commit comments