scripts / make: Add Recommends support
Some checks failed
CI / Packaging - Kali Linux (pull_request) Failing after 2m59s
CI / Packaging - OpenSUSE Tumbleweed (pull_request) Successful in 4m28s
CI / Packaging test (pull_request) Failing after 0s

The spec generator only supports Requires, Conflicts and Provides from
the [pkg.requires.*], [pkg.conflicts.*] and [pkg.provides.*] sections of
make/project.conf. A package that works without but is better with another
package, like jw-amavis-run without jw-clamav-run, must hard-require it, so
the dependency is pulled in on every install and cannot be removed without
dragging the depending package along.

This commit adds Recommends support to the spec generation chain:

- CmdPkgRecommends: new pkg-recommends command that reads the
  [pkg.recommends.<flavour>] sections, same base as pkg-requires
- pkg-dist.mk: compute PKG_RECOMMENDS_RUN and pass it to pkg.sh via a new
  -E option
- pkg.sh: accept -E and forward it to the mkspec wrapper
- mkspec-wrapper.sh: accept -E and export RECOMMENDS_RUN
- create-mkspec.sh: emit a Recommends: line when RECOMMENDS_<subpkg> is set
- create-mkdebian.sh: emit a Recommends: field in the debian control file

Projects without a [pkg.recommends.*] section generate unchanged specs:
every new line is guarded by a non-empty test. zypper follows Recommends by
default, so existing OpenSUSE installations are unaffected; a recommended
package can be removed without dragging the depending package along.

Assisted-by: unsloth/Qwen3.8-27B-GGUF:Q4_K_M with pi.dev v0.85.1
Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2026-09-18 12:11:00 +02:00
commit de7984f63a
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61
7 changed files with 79 additions and 2 deletions

View file

@ -81,6 +81,7 @@ endif
PKG_REQUIRES_BUILD += $(call proj_query, pkg-requires $(PROJ_QUERY_PKG_REQUIRES_EXTRA_ARGS) build $(PROJECT))
PKG_REQUIRES_RUN += $(call proj_query, pkg-requires $(PROJ_QUERY_PKG_REQUIRES_EXTRA_ARGS) run $(PROJECT))
PKG_REQUIRES_DEVEL += $(call proj_query, pkg-requires $(PROJ_QUERY_PKG_REQUIRES_EXTRA_ARGS) devel $(PROJECT))
PKG_RECOMMENDS_RUN += $(call proj_query, pkg-recommends $(PROJ_QUERY_PKG_REQUIRES_EXTRA_ARGS) run $(PROJECT))
PKG_CONFLICTS_RUN += $(call proj_query, pkg-conflicts $(PROJ_QUERY_PKG_CONFLICTS_EXTRA_ARGS) run $(PROJECT))
PKG_CONFLICTS_DEVEL += $(call proj_query, pkg-conflicts $(PROJ_QUERY_PKG_CONFLICTS_EXTRA_ARGS) devel $(PROJECT))
PKG_PROVIDES_RUN += $(call proj_query, pkg-provides $(PROJ_QUERY_PKG_PROVIDES_EXTRA_ARGS) run $(PROJECT))
@ -101,6 +102,7 @@ include $(JWBDIR)/make/upload-rules.mk
PKG_SH = $(PKG_SH_EXE) \
-N $(PKG_PROJECT) -P $(PROJECT) \
-R "$(PKG_REQUIRES_RUN)" -D "$(PKG_REQUIRES_DEVEL)" \
-E "$(PKG_RECOMMENDS_RUN)" \
-X "$(PKG_CONFLICTS_RUN)" -Y "$(PKG_CONFLICTS_DEVEL)" \
--provides-run "$(PKG_PROVIDES_RUN)" --provides-devel "$(PKG_PROVIDES_DEVEL)" \
-m $(JWB_SCRIPT_DIR) -a $(PKG_ARCH) -p $(DIST_PCKG_DIR) -F $(PKG_FORMAT) \
@ -298,6 +300,7 @@ pkg-requires:
@echo "PKG_REQUIRES_BUILD = $(PKG_REQUIRES_BUILD)"
@echo "PKG_REQUIRES_RUN = $(PKG_REQUIRES_RUN)"
@echo "PKG_REQUIRES_DEVEL = $(PKG_REQUIRES_DEVEL)"
@echo "PKG_RECOMMENDS_RUN = $(PKG_RECOMMENDS_RUN)"
@echo "PKG_CONFLICTS_RUN = $(PKG_CONFLICTS_RUN)"
@echo "PKG_CONFLICTS_DEVEL = $(PKG_CONFLICTS_DEVEL)"
@echo "PKG_PROVIDES_RUN = $(PKG_PROVIDES_RUN)"

View file

@ -65,6 +65,7 @@ cfg_value global.subpackages | grep -q run && _cat <<- EOT
|Package: \$NAME-run
|Architecture: any
|Depends: \`format_depends "\${shlibs:Depends}, \${misc:Depends}, \$REQUIRES_RUN"\`
|[ -n "\$RECOMMENDS_RUN" ] && echo "Recommends: \`format_depends \"\$RECOMMENDS_RUN\"\`"
|# untested:
|Conflicts: \`format_depends "\$CONFLICTS_RUN"\`
|Description: `cfg_value summary`

View file

@ -112,6 +112,7 @@ for p in $subpackages; do
|echo "Summary: `cfg_value summary`"
|echo "Group: `cfg_value global.group`"
|[ "\$REQUIRES_$P" ] && echo "Requires: \$REQUIRES_$P"
|[ "\$RECOMMENDS_$P" ] && echo "Recommends: \$RECOMMENDS_$P"
|[ "\$CONFLICTS_$P" ] && echo "Conflicts: \$CONFLICTS_$P"
|[ "\$PROVIDES_$P" ] && echo "Provides: \$PROVIDES_$P"
|echo ""

View file

@ -2,7 +2,7 @@
usage()
{
echo usage: $MYNAME /path/to/mkspec.sh -h [-N name] [-T topdir] [-V version] [-S source] [-R requires] [-P project] >&2
echo usage: $MYNAME /path/to/mkspec.sh -h [-N name] [-T topdir] [-V version] [-S source] [-R requires] [-E recommends] [-P project] >&2
[ "$1" ] && exit $1
}
@ -19,7 +19,7 @@ append()
#set -x
MYNAME=`basename $0`
eval set -- `getopt -l "provides-run:" -l "provides-devel:" -o "P:T:V:S:N:hR:D:X:Y:d:" -- "$@"`
eval set -- `getopt -l "provides-run:" -l "provides-devel:" -o "P:T:V:S:N:hR:D:X:Y:E:d:" -- "$@"`
while [ "$1" != -- ]; do
echo checking "$1=$2" >&2
@ -42,6 +42,10 @@ case $1 in
append REQUIRES_RUN "$2"
shift
;;
-E)
append RECOMMENDS_RUN "$2"
shift
;;
-X)
append CONFLICTS_RUN "$2"
shift
@ -117,6 +121,7 @@ CONFLICTS="$CONFLICTS_RUN $CONFLICTS_DEVEL"
export \
REQUIRES REQUIRES_RUN REQUIRES_DEVEL \
RECOMMENDS_RUN \
CONFLICTS CONFLICTS_RUN CONFLICTS_DEVEL \
PROVIDES PROVIDES_RUN PROVIDES_DEVEL \
TOPDIR \

View file

@ -444,6 +444,7 @@ build_pkg()
local distribution=`get_os`
local rpm_requires_run="$PKG_REQUIRES_RUN"
local rpm_recommends_run="$PKG_RECOMMENDS_RUN"
local rpm_requires_devel="$PKG_REQUIRES_DEVEL"
local rpm_conflicts_run="$PKG_CONFLICTS_RUN"
local rpm_conflicts_devel="$PKG_CONFLICTS_DEVEL"
@ -503,6 +504,7 @@ build_pkg()
-S $tar_archive \
-N $PKG_PROJECT \
-R "$rpm_requires_run" \
-E "$rpm_recommends_run" \
-X "$rpm_conflicts_run" \
-D "$rpm_requires_devel" \
-Y "$rpm_conflicts_devel" \
@ -1138,6 +1140,7 @@ DIST_INST_DIR=dist/src
DIST_PCKG_DIR=dist/pckg
PKG_PROJECT="$PROJECT"
PKG_REQUIRES_RUN=""
PKG_RECOMMENDS_RUN=""
PKG_REQUIRES_DEVEL=""
PKG_ARCH=$HOSTTYPE
PKG_FORMAT=rpm
@ -1173,6 +1176,10 @@ while [ ${1:0:1} = - ]; do
eval PKG_REQUIRES_RUN=\"$2\"
shift
;;
-E)
eval PKG_RECOMMENDS_RUN=\"$2\"
shift
;;
-X)
eval PKG_CONFLICTS_RUN=\"$2\"
shift

View file

@ -0,0 +1,7 @@
from .BaseCmdPkgRelations import BaseCmdPkgRelations as Base
from .BaseCmdPkgRelations import Parent
class CmdPkgRecommends(Base): # export
def __init__(self, parent: Parent) -> None:
super().__init__(parent, 'recommends', help = 'Print recommended packages')

View file

@ -246,6 +246,7 @@ Available subcommands of projects:
pkg-conflicts Print packages conflicting with a given package
pkg-provides Print packages and capabilities provided by a given
package
pkg-recommends Print recommended packages
pkg-requires Print packages required for a given package
proj-dir Print directory of a given package
pythonpath Generate PYTHONPATH for given modules
@ -584,6 +585,58 @@ usage: jw-pkg.py projects pkg-provides [-h] [-S [SUBSECTIONS]]
Print packages and capabilities provided by a given package
positional arguments:
flavours Dependency flavours (run, build, devel, release),
separated by comma or whitespace
modules Modules (default: None)
options:
-h, --help show this help message and exit
-S, --subsections [SUBSECTIONS]
Subsections to consider, separated by comma or
whitespace (default: None)
-d, --delimiter [DELIMITER]
Output words delimiter (default: , )
-p, --no-subpackages Cut -run and -devel from package names (default:
False)
--dont-strip-revision
Always treat VERSION macro as VERSION-REVISION
(default: False)
--expand-semver-revision-range
Always treat =VERSION macro as >= VERSION-0 and <
(VERSION+1)-0 (default: False)
--syntax {semver,debian,names-only}
Output syntax (default: semver)
--recursive Find dependencies recursively (default: False)
--dont-expand-version-macros
Don't expand VERSION and REVISION macros (default:
False)
--ignore [IGNORE] Packages that should be ignored together with their
dependencies (default: )
--skip-excluded Don't consider or output modules matching the os
cascade in their [build].exclude config (default:
False)
--hide-self Don't include projects listed in <modules> in the
output (default: False)
--hide-jw-pkg Don't include packages from requires.jw in the output
(default: False)
--quote Put double quotes around each listed dependency
(default: False)
============= Running: jw-pkg.py -t ../../../.. --log-level info projects pkg-recommends --help
usage: jw-pkg.py projects pkg-recommends [-h] [-S [SUBSECTIONS]]
[-d [DELIMITER]] [-p]
[--dont-strip-revision]
[--expand-semver-revision-range]
[--syntax {semver,debian,names-only}]
[--recursive]
[--dont-expand-version-macros]
[--ignore [IGNORE]] [--skip-excluded]
[--hide-self] [--hide-jw-pkg]
[--quote]
flavours [modules ...]
Print recommended packages
positional arguments:
flavours Dependency flavours (run, build, devel, release),
separated by comma or whitespace