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:]+_.@-]
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 <[email protected]>
> ---
> 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
signature.asc
Description: OpenPGP digital signature
