#!/bin/sh # # newapkbuild - generate a new APKBUILD # Copyright (c) 2009 Natanael Copa # # Distributed under GPL-2.0-only # program_version=@VERSION@ sharedir=${ABUILD_SHAREDIR:-@sharedir@} if ! [ -f "$sharedir/functions.sh" ]; then echo "$sharedir/functions.sh: not found" >&2 exit 1 fi . "$sharedir/functions.sh" is_url() { case "$1" in http://*|https://*|ftp://*) return 0;; esac return 1 } is_github_url() { case $1 in https://github.com/*/*/archive/*.tar.gz) return 0;; esac return 1 } prepare_rust() { cat >>APKBUILD<<__EOF__ cargo fetch --locked __EOF__ } # Build sections build_make() { cat >>APKBUILD<<__EOF__ make __EOF__ } build_autotools() { cat >>APKBUILD<<__EOF__ ./configure \\ --build=\$CBUILD \\ --host=\$CHOST \\ --prefix=/usr \\ --sysconfdir=/etc \\ --mandir=/usr/share/man \\ --localstatedir=/var make __EOF__ } build_cmake() { # References: # http://www.cmake.org/Wiki/CMake_Useful_Variables # http://www.vtk.org/Wiki/CMake_Cross_Compiling # This is incomplete: CMAKE_{HOST_,}SYSTEM_PROCESSOR needs to be set, # and likewise CMAKE_FIND_ROOT_PATH and a few other details. cat >>APKBUILD<<__EOF__ if [ "\$CBUILD" != "\$CHOST" ]; then CMAKE_CROSSOPTS="-DCMAKE_SYSTEM_NAME=Linux -DCMAKE_HOST_SYSTEM_NAME=Linux" fi cmake -B build \\ -DCMAKE_INSTALL_PREFIX=/usr \\ -DCMAKE_INSTALL_LIBDIR=lib \\ -DBUILD_SHARED_LIBS=True \\ -DCMAKE_BUILD_TYPE=None \\ \$CMAKE_CROSSOPTS . cmake --build build __EOF__ } build_meson() { # References: # http://mesonbuild.com/Reference-manual.html # http://mesonbuild.com/Cross-compilation.html cat >>APKBUILD<<__EOF__ abuild-meson \\ . output meson compile -C output __EOF__ } build_perl() { cat >>APKBUILD<<__EOF__ PERL_MM_USE_DEFAULT=1 perl Makefile.PL INSTALLDIRS=vendor make __EOF__ } build_python() { cat >>APKBUILD<<__EOF__ python3 setup.py build __EOF__ } build_rust() { cat >>APKBUILD<<__EOF__ cargo build --frozen --release __EOF__ } build_empty() { cat >>APKBUILD<<__EOF__ # Replace with proper build command(s) : __EOF__ } # Check sections check_make() { cat >>APKBUILD<<__EOF__ make check __EOF__ } check_cmake() { cat >>APKBUILD<<__EOF__ cd build CTEST_OUTPUT_ON_FAILURE=TRUE ctest __EOF__ } check_python() { cat >>APKBUILD<<__EOF__ pytest __EOF__ } check_empty() { cat >>APKBUILD<<__EOF__ # Replace with proper check command(s) : __EOF__ } check_meson() { cat >>APKBUILD<<__EOF__ meson test --no-rebuild --print-errorlogs -C output __EOF__ } check_rust() { cat >>APKBUILD<<__EOF__ cargo test --frozen __EOF__ } # Package sections package_make() { cat >>APKBUILD<<__EOF__ make DESTDIR="\$pkgdir" install __EOF__ } package_cmake() { cat >>APKBUILD<<__EOF__ DESTDIR="\$pkgdir" cmake --install build __EOF__ } package_autotools() { package_make } package_meson() { cat >>APKBUILD<<__EOF__ DESTDIR="\$pkgdir" meson install --no-rebuild -C output __EOF__ } package_perl() { cat >>APKBUILD<<__EOF__ make DESTDIR="\$pkgdir" install find "\$pkgdir" \\( -name perllocal.pod -o -name .packlist \\) -delete __EOF__ } package_python() { cat >>APKBUILD<<__EOF__ python3 setup.py install --prefix=/usr --root="\$pkgdir" __EOF__ } package_empty() { cat >>APKBUILD<<__EOF__ # Replace with proper package command(s) : __EOF__ } package_rust() { cat >>APKBUILD<<__EOF__ # Replace with proper package command(s) : __EOF__ } # Create new aport from templates newaport() { local newname="${1##*/}" local pn=${newname%[-_][0-9]*} local pv local source= is_url "$1" && source="$1" if is_github_url $source; then if [ -z "$pkgname" ]; then pkgname=${source%/archive/*} pkgname=${pkgname##*/} fi pv=${newname%.t*} #strip .tar.gz .tgz .tar.bz2 etc pv=${pv#*[a-z]} source="${source%.t*}/$pkgname-$pv.tar.gz" elif [ "$pn" != "$newname" ]; then pv=${newname#$pn[-_]} pv=${pv%.t*} #strip .tar.gz .tgz .tar.bz2 etc fi if [ -z "$pkgname" ]; then pkgname=$pn fi if [ -e "$pkgname"/APKBUILD ] && [ -z "$force" ]; then error "$pkgname/APKBUILD already exists" return 1 fi mkdir -p "$pkgname" cd "$pkgname" if [ -z "$source" ] && [ -n "$sourceforge" ]; then source="https://downloads.sourceforge.net/$pn/$pn-$pv.tar.gz" fi if [ -z "$depends" ] && [ "$buildtype" = "python" ]; then depends="python3" fi if [ -z "$depends" ] && [ "$buildtype" = "perl" ]; then depends="perl" fi if [ -z "$checkdepends" ] && [ "$buildtype" = "python" ]; then checkdepends="py3-pytest" fi case "$buildtype" in python) makedepends="py3-setuptools";; cmake) makedepends="cmake";; meson) makedepends="meson";; rust) makedepends="cargo";; *) makedepends="\$depends_dev";; esac # Replace pkgver in $source if [ -n "$source" ]; then source=$(echo "$source" | sed "s/$pv/\$pkgver/g") fi # Copy init.d scripts if requested if [ -n "$cpinitd" ]; then cp "$sharedir"/sample.initd $pkgname.initd cp "$sharedir"/sample.confd $pkgname.confd cp "$sharedir"/sample.pre-install $pkgname.pre-install cp "$sharedir"/sample.post-install $pkgname.post-install install="\$pkgname.pre-install \$pkgname.post-install" source="$source $pkgname.initd $pkgname.confd " fi # Generate header with standard variables cat >APKBUILD<<__EOF__ # Contributor:${PACKAGER:+" "}${PACKAGER} # Maintainer:${MAINTAINER:+" "}${MAINTAINER} pkgname=$pkgname pkgver=$pv pkgrel=0 pkgdesc="$pkgdesc" url="$url" arch="all" license="$license" depends="$depends" depends_dev="" makedepends="$makedepends" checkdepends="$checkdepends" install="$install" subpackages="\$pkgname-dev \$pkgname-doc" source="$source" __EOF__ abuild -f fetch checksum unpack # Figure out the builddir for i in src/*; do if [ -d "$i" ]; then sdir=$i builddir=$(echo ${i#*/} | sed "s/$pv/\$pkgver/g") fi done printf 'builddir="$srcdir/%s"\n\n' "$builddir" >> APKBUILD # Subpackage -dev is usually required only for C/C++. Since depends_dev # confuses a lot people, remove it if there's no .h or .hpp file. find "$sdir" -name "*.h" -o -name "*.hpp" -maxdepth 3 2>/dev/null \ | head -n 1 | grep -q ".*" \ || sed -i -e '/^depends_dev=.*/d' -e 's/\$depends_dev\s*//' APKBUILD # Try to autodetect the buildtype if [ -z "$buildtype" ]; then if [ -x "$sdir"/configure ]; then buildtype="autotools" elif [ -r "$sdir"/Makefile.PL ] || [ "${pn#perl-}" != "$pn" ]; then buildtype="perl" elif [ -r "$sdir"/waf ]; then buildtype="waf" elif [ -r "$sdir"/meson.build ]; then buildtype="meson" elif [ -d "$sdir"/cmake ] || [ -r "$sdir/CMakeLists.txt" ]; then buildtype="cmake" elif [ -r "$sdir"/Makefile ]; then buildtype="make" elif [ -r "$sdir"/setup.py ] || [ "${pn#py[0-9]-}" != "$pn" ]; then buildtype="python" elif [ -r "$sdir"/Cargo.toml ]; then buildtype="rust" fi fi case "$buildtype" in rust) cat >>APKBUILD<<__EOF__ prepare() { default_prepare __EOF__ prepare_rust cat >>APKBUILD<<__EOF__ } __EOF__ ;; esac # Create build() function cat >>APKBUILD<<__EOF__ build() { __EOF__ case "$buildtype" in make) build_make;; cmake) build_cmake;; meson) build_meson;; autotools) build_autotools;; perl) build_perl;; python) build_python;; rust) build_rust;; *) build_empty;; esac cat >>APKBUILD<<__EOF__ } __EOF__ # Create check() function cat >>APKBUILD<<__EOF__ check() { __EOF__ case "$buildtype" in make|autotools|perl) check_make;; cmake) check_cmake;; meson) check_meson;; python) check_python;; rust) check_rust;; *) check_empty;; esac cat >>APKBUILD<<__EOF__ } __EOF__ # Create package() function cat >>APKBUILD<<__EOF__ package() { __EOF__ case "$buildtype" in make) package_make;; cmake) package_cmake;; autotools) package_autotools;; meson) package_meson;; perl) package_perl;; python) package_python;; rust) package_rust;; *) package_empty;; esac if [ -n "$cpinitd" ]; then cat >>APKBUILD<<__EOF__ install -m755 -D "\$srcdir"/\$pkgname.initd \\ "\$pkgdir"/etc/init.d/\$pkgname install -m644 -D "\$srcdir"/\$pkgname.confd \\ "\$pkgdir"/etc/conf.d/\$pkgname __EOF__ fi cat >>APKBUILD<<__EOF__ } __EOF__ # regenerate checksum so they end last in APKBUILD abuild -f checksum } usage() { cat >&2 <<-__EOF__ $program $program_version - generate a new APKBUILD Usage: $program [-n PKGNAME] [-d PKGDESC] [-l LICENSE] [-u URL] [-a | -C | -m | -p | -y | -r] [-s] [-c] [-f] [-h] PKGNAME[-PKGVER] | SRCURL Options: -n Set package name to PKGNAME (only use with SRCURL) -d Set package description to PKGDESC -l Set package license to LICENSE, use identifiers from: -u Set package URL -a Create autotools package (use ./configure ...) -C Create CMake package (Assume cmake/ is there) -m Create meson package (Assume meson.build is there) -p Create perl package (Assume Makefile.PL is there) -y Create python package (Assume setup.py is there) -r Create rust package (Assume Cargo.toml is there) -s Use sourceforge source URL -c Copy a sample init.d, conf.d, and install script -f Force even if directory already exists -h Show this help __EOF__ } set_buildtype() { if [ -n "$buildtype" ]; then error "More than one buildtype flag specified ($buildtype and $1)" exit 1 fi buildtype="$1" } check_arguments() { if [ $# -eq 0 ]; then error "Missing required argument: PKGNAME[-PKGVER] | SRCURL" exit 1 fi if [ $# -gt 1 ]; then shift error "Unrecognized arguments: $*" exit 1 fi if [ -n "$1" ] && ! is_url "$1" && [ -n "$pkgname" ]; then error "-n is only allowed when using SRCURL as last argument" exit 1 fi if is_url "$1" && [ -n "$sourceforge" ]; then error "-s is only allowed when using PKGNAME as last argument" exit 1 fi } while getopts "acCmd:fhl:n:pyu:sr" opt; do case $opt in 'a') set_buildtype "autotools";; 'c') cpinitd=1;; 'C') set_buildtype "cmake";; 'm') set_buildtype "meson";; 'd') pkgdesc="$OPTARG";; 'f') force=1;; 'h') usage; exit;; 'l') license="$OPTARG";; 'n') pkgname="$OPTARG";; 'p') set_buildtype "perl";; 'y') set_buildtype "python";; 'r') set_buildtype "rust";; 'u') url="$OPTARG";; 's') sourceforge=1;; esac done shift $(( $OPTIND - 1 )) check_arguments "$@" newaport $1