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. 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}`" + export PKG_CONFIG_PATH="$DIR:$DIR/../../share/pkgconfig" + pkg-config --print-provides "$1" 2>/dev/null | while read name _ _; do + [ -n "$name" ] || continue + 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 + 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) + + [[ -z "$cleaned" ]] && continue + + echo "can-open-mimetype($cleaned)" + done + ;; + esac +} + +providers=( + pkgconfig cmake desktop +) + +find_fileattrs_provides() { + local files + + mapfile -t files < <(find "$pkgdir" -type f) + + 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 ;; -o|--nobuild) BUILDPKG=0 NOBUILD=1 ;; -p) shift; BUILDFILE=$1 ;; --packagelist) BUILDPKG=0 PACKAGELIST=1 IGNOREARCH=1;; -- 2.25.1