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 <uhhadd@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