Compare commits

..

1 Commits

Author SHA1 Message Date
Allan McRae
e47cf49055 makepkg: implement alternative package splitting approach
The original package splitting approach in makepkg was aligned to the KDE
packaging approach (at the time) where each component had its own
"make install-foo" target.  In practice, distributions want to split a wider
variety of packages that do not fit this mould, and various hacks have arisen.

Implement a secondary approach to package splitting.  A PKGBUILD can provide
a 'stash()' function that is run between building and packaging.  This
function will typically do the full install of the built software into the
$stashdir directory.  I.e. run a command similar to
"make DESTDIR=$stashdir install".  Each 'package_foo()' function can then
include a list of files that are transferred from the stash into the package,
in addition to any other packaging commands.

For example:
filelist=('usr/bin/pacman'
          'usr/lib/*')

The filelist accepts glob patterns as understood by bash with extglob
enabled - including '*', '?' and '[]'.  Files can be excluded from the
filelist by prefixing with the '!' character.

Files are removed from the stash as they are included in packages.  This
allows makepkg to warn about any files that are not packaged.  To include
files in multiple packages, an additional copy should be made in the stash
function.

Signed-off-by: Allan McRae <allan@archlinux.org>
2025-11-08 11:30:36 +10:00

View File

@@ -78,6 +78,7 @@ SKIPPGPCHECK=0
SIGNPKG=''
SPLITPKG=0
SOURCEONLY=0
STASHFUNC=0
VERIFYSOURCE=0
MAKEPKG_LINT_PKGBUILD=${MAKEPKG_LINT_PKGBUILD:-1}
@@ -154,6 +155,9 @@ clean_up() {
if (( CHECKFUNC )); then
rm -f "${pkgbase}-${fullver}-${CARCH}-check.log"*
fi
if (( STASHFUNC )); then
rm -f "${pkgbase}-${fullver}-${CARCH}-stash.log"*
fi
if (( PKGFUNC )); then
rm -f "${pkgbase}-${fullver}-${CARCH}-package.log"*
elif (( SPLITPKG )); then
@@ -465,6 +469,10 @@ run_check() {
run_function_safe "check"
}
run_stash() {
run_function_safe "stash"
}
run_package() {
run_function_safe "package${1:+_$1}"
}
@@ -849,9 +857,93 @@ restore_package_variables() {
done
}
package_stashed_files() {
local package=$1
local filelist
get_pkgbuild_attribute "$package" 'filelist' 1 filelist
if (( ${#filelist[@]} == 0 )); then
return 0;
fi
cd $stashdir
mapfile -t stashfiles < <(find "$stashdir")
stashfiles=(${stashfiles[@]#$stashdir/})
# match inclusions
declare -a match
for f in "${filelist[@]}"; do
if [[ ! $f =~ ^!.* ]]; then
local i=0
for m in ${stashfiles[@]}; do
if [[ "$m" == $f ]]; then
match+=("$m")
unset stashfiles[$i]
fi
((i++))
done
stashfiles=(${stashfiles[@]})
fi
done
# unmatch exclusions
for f in "${filelist[@]}"; do
if [[ $f =~ ^!.* ]]; then
local i=0
for m in ${match[@]}; do
if [[ "$m" == ${f:1} ]]; then
unset match[i]
fi
((i++))
done
match=(${match[@]})
fi
done
# gather a list of directories to be created in package
declare -a dirlist
for f in ${match[@]}; do
while [[ $f =~ / ]]; do
f=${f%/*}
dirlist+=($f)
done
done
mapfile -t dirlist < <(printf "%s\n" ${dirlist[@]} | LC_ALL=C sort -u)
# exclude directories from the filelist
mapfile -t filelist < <(
for f in ${match[@]}; do
[[ ! -d $f ]] && echo $f
done
)
# ensure directories are explicitly included so permissions are maintained
local tmptar=$(mktemp $pkgname.tar.XXXXXXXX)
for d in ${dirlist[@]}; do
bsdtar --append -f $tmptar --exclude "$d\/*" $d/
done
bsdtar -xf $tmptar -C $pkgdir
rm $tmptar
# move files into package
for f in ${filelist[@]}; do
mv "$stashdir"/$f "$pkgdir"/$f
done
}
run_single_packaging() {
local pkgdir="$pkgdirbase/$pkgname"
mkdir "$pkgdir"
if (( STASHFUNC )); then
package_stashed_files $1
fi
if [[ -n $1 ]] || (( PKGFUNC )); then
run_package $1
fi
@@ -862,6 +954,10 @@ run_single_packaging() {
run_split_packaging() {
local pkgname_backup=("${pkgname[@]}")
if (( STASHFUNC )); then
stashdir=$(mktemp -d $pkgdirbase/stash_XXXXXX)
run_stash
fi
# We might run this function when we only have package_pkgname
# and we don't want that marked as a split package
(( ${#pkgname[@]} > 1 )) && pkgtype=split
@@ -1176,7 +1272,6 @@ if [[ $BUILDDIR -ef "$startdir" ]]; then
else
srcdir="$BUILDDIR/$pkgbase/src"
pkgdirbase="$BUILDDIR/$pkgbase/pkg"
fi
# set pkgdir to something "sensible" for (not recommended) use during build()
@@ -1221,6 +1316,9 @@ if have_function check; then
CHECKFUNC=1
fi
fi
if have_function stash; then
STASHFUNC=1
fi
if have_function package; then
PKGFUNC=1
fi
@@ -1258,6 +1356,14 @@ if (( INFAKEROOT )); then
create_debug_package
if (( STASHFUNC )); then
leftovers=($(find $stashdir ! -type d))
if (( ${#leftovers[@]} > 0 )); then
warning "$(gettext "Files in the stash area remain unpackaged")"
printf "%s\n" "${leftovers[@]#$stashdir/}"
fi
fi
msg "$(gettext "Leaving %s environment.")" "fakeroot"
exit $E_OK
fi