[pacman-dev] [PATCH] Provides generation for files (a.k.a. rpm fileattrs for makepkg)
Eli Schwartz
eschwartz at archlinux.org
Sun Mar 8 21:46:55 UTC 2020
On 3/8/20 4:04 PM, Carson Black wrote:
> Whenever I'm working in a relatively fresh Arch environment, my work
> flow looks like this:
>
> - cmake .. -DFLAGS=blahblahblah
> - Wait a few seconds
> - Package providing KF5whatever not found
> - Try and deduce Arch package name from CMake package name
>
> Often, trying to figure out the relation between the build system package names
> and the Arch package names of missing dependencies ends up being the longest
> part of whatever task I was working on, which isn't very efficient.
>
> Compare this to me working in an RPM distro:
>
> - cmake .. -DFLAGS=blahblahblah
> - Wait a few seconds
> - Package providing KF5whatever not found
> - dnf install cmake(KF5whatever)
>
> The latter workflow is a lot more efficient, and is exactly what this
> commit introduces to packages generated by makepkg.
>
> Every file is iterated over at the end of the build process to generate
> additional provides without the packager needing to manually specify
> them.
>
> The code is architected in a manner designed to make it trivial to add
> new provider autogenerators.
>
> So far, there are autogenerated providers for:
> - pkgconfig(package)
> - cmake(package)
> - desktop files
> * app(desktopfilename)
> * can-open-mimetype(mimetype)>
> While these automatically generated provides can be used for packaging,
> this is intended more for interactive usage rather than an attempt to
> change how Arch packaging works.
Did you actually try this?
It's worth noting that makepkg forbids depends/provides names that
contain characters outside of the following permitted range:
[[:alnum:]+_. at -]
So if I added this to an existing PKGBUILD:
depends=("cmake(KF5Foo)")
then run
$ makepkg --printsrcinfo
==> ERROR: depends contains invalid characters: '()'
If the idea is to use these in PKGBUILDs, then we would need an update
to libmakepkg/lint_pkgbuild/pkgname.sh.in
So if this patch were to be accepted as-is, one would still NOT be able
to use the automatically generated provides for packaging.
And it feels very wrong to generate provides metadata that is forbidden
from being used.
> Signed-off-by: Carson Black <uhhadd at gmail.com>
> ---
> scripts/makepkg.sh.in | 71 ++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 70 insertions(+), 1 deletion(-)
>
> diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
> index ca3e7459..65a3648e 100644
> --- a/scripts/makepkg.sh.in
> +++ b/scripts/makepkg.sh.in
> @@ -57,6 +57,7 @@ CLEANUP=0
> DEP_BIN=0
> FORCE=0
> GENINTEG=0
> +GENPROVIDES=1
> HOLDVER=0
> IGNOREARCH=0
> INFAKEROOT=0
> @@ -520,6 +521,70 @@ find_libdepends() {
> (( ${#libdepends[@]} )) && printf '%s\n' "${libdepends[@]}"
> }
>
> +pkgconfig_prov() {
> + case $1 in
> + *.pc)
> + directory="`dirname ${1}`"
As I mentioned before, it's bad practice to use the deprecated ``
syntax, modern shellscripts should always use $()
> + export PKG_CONFIG_PATH="$DIR:$DIR/../../share/pkgconfig"
> + pkg-config --print-provides "$1" 2>/dev/null | while read name _ _; do
What is the "$DIR" variable?
Why are you exporting PKG_CONFIG_PATH instead of defining it only for
the pkg-config execution?
Why is stderr being redirected to /dev/null? pkg-config exits 1 without
output, if a nonexistent dependency is specified, so the while loop will
exit without running the "do" section even once..
pkg-config is part of archlinux's base-devel group, but pacman isn't
archlinux exclusive. If you want to add a dependency on an external
program, it should at least be documented in the beginning of makepkg.sh.in:
# makepkg uses quite a few external programs during its execution. You
# need to have at least the following installed for makepkg to function:
And it might be a good idea to add a check in libmakepkg/executable/ as
well.
> + [ -n "$name" ] || continue
When will this be empty?
> + echo "pkgconfig($name)"
> + done
> + ;;
> + esac
> +}
> +
> +cmake_prov() {
> + case $1 in
> + *.cmake)
> + base="$(basename $1)"
> + case $1 in
> + *Config.cmake)
> + echo "cmake(${base%Config.cmake})"
> + ;;
> + *-config.cmake)
> + echo "cmake(${base%-config.cmake})"
> + ;;
> + esac
> + ;;
> + esac
> +}
> +
> +desktop_prov() {
> + case "$1" in
> + *.desktop)
> + grep -q "Type=Application" "$1" || return
> + grep -q "Exec=" "$1" || return
Why do either of these conditions matter if the file provides a
mimetype? Surely that check alone is sufficient?
> + base="$(basename $1)"
> + echo "app(${base%.desktop})"
> +
> + mapfile -t -d ";" mimetypes < <(grep MimeType= $1 | cut -d '=' -f 2)
> + for mimetype in "${mimetypes[@]}"; do
> + cleaned=$(echo $mimetype | xargs)
What is "cleaned", and how is the xargs program "cleaning" it?
> +
> + [[ -z "$cleaned" ]] && continue
When will this be set but empty?
> + echo "can-open-mimetype($cleaned)"
> + done
> + ;;
> + esac
> +}
> +
> +providers=(
> + pkgconfig cmake desktop
> +)
> +
> +find_fileattrs_provides() {
> + local files
> +
> + mapfile -t files < <(find "$pkgdir" -type f)
Instead of storing it in a "files" variable first, I'd actually
recommend using a while loop...
> +
> + for file in "${files[@]}"; do
> + for function in "${providers[@]}"; do
> + "$function"_prov "$file"
> + done
> + done
> +}
>
> find_libprovides() {
> local p libprovides missing
> @@ -612,12 +677,14 @@ write_pkginfo() {
>
> mapfile -t provides < <(find_libprovides)
> mapfile -t depends < <(find_libdepends)
> + (( "$GENPROVIDES" != 0 )) && mapfile -t generated_provides < <(find_fileattrs_provides)
>
> write_kv_pair "license" "${license[@]}"
> write_kv_pair "replaces" "${replaces[@]}"
> write_kv_pair "group" "${groups[@]}"
> write_kv_pair "conflict" "${conflicts[@]}"
> write_kv_pair "provides" "${provides[@]}"
> + write_kv_pair "provides" "${generated_provides[@]}"
> write_kv_pair "backup" "${backup[@]}"
> write_kv_pair "depend" "${depends[@]}"
> write_kv_pair "optdepend" "${optdepends[@]//+([[:space:]])/ }"
> @@ -980,6 +1047,7 @@ usage() {
> printf -- "$(gettext " --nocheck Do not run the %s function in the %s")\n" "check()" "$BUILDSCRIPT"
> printf -- "$(gettext " --noprepare Do not run the %s function in the %s")\n" "prepare()" "$BUILDSCRIPT"
> printf -- "$(gettext " --nosign Do not create a signature for the package")\n"
> + printf -- "$(gettext " --noprovidesgen Do not autogenerate provides")\n"
> printf -- "$(gettext " --packagelist Only list package filepaths that would be produced")\n"
> printf -- "$(gettext " --printsrcinfo Print the generated SRCINFO and exit")\n"
> printf -- "$(gettext " --sign Sign the resulting package with %s")\n" "gpg"
> @@ -1029,7 +1097,7 @@ OPT_LONG=('allsource' 'check' 'clean' 'cleanbuild' 'config:' 'force' 'geninteg'
> 'help' 'holdver' 'ignorearch' 'install' 'key:' 'log' 'noarchive' 'nobuild'
> 'nocolor' 'nocheck' 'nodeps' 'noextract' 'noprepare' 'nosign' 'packagelist'
> 'printsrcinfo' 'repackage' 'rmdeps' 'sign' 'skipchecksums' 'skipinteg'
> - 'skippgpcheck' 'source' 'syncdeps' 'verifysource' 'version')
> + 'skippgpcheck' 'source' 'syncdeps' 'verifysource' 'version' 'noprovidesgen')
>
> # Pacman Options
> OPT_LONG+=('asdeps' 'noconfirm' 'needed' 'noprogressbar')
> @@ -1070,6 +1138,7 @@ while true; do
> --nocheck) RUN_CHECK='n' ;;
> --noprepare) RUN_PREPARE='n' ;;
> --nosign) SIGNPKG='n' ;;
> + --noprovidesgen) GENPROVIDES=0 ;;
This is unreproducible, the public metadata of the package now depends
on command-line options.
Also, no official repository packages would be built with manual
command-line options, so you'd never be able to use the results. How
does this help you if it only applies to packages you personally build?
> -o|--nobuild) BUILDPKG=0 NOBUILD=1 ;;
> -p) shift; BUILDFILE=$1 ;;
> --packagelist) BUILDPKG=0 PACKAGELIST=1 IGNOREARCH=1;;
>
--
Eli Schwartz
Bug Wrangler and Trusted User
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 1601 bytes
Desc: OpenPGP digital signature
URL: <https://lists.archlinux.org/pipermail/pacman-dev/attachments/20200308/ad67cc8f/attachment-0001.sig>
More information about the pacman-dev
mailing list