Creating packages for Hyperbola

Within this article we want to describe needed information on how to create a package for Hyperbola as system and assist users in a way forward to be also active developing and deploying their own software. Please have in mind not to be mistaken with our packaging guidelines, where we describe generic rules for the software included. This article here is in its focus only oriented on the technical details and the corresponding usecases.

Especially also to note that this article is meant as common guidance for users doing their own packaging the first time. When you feel confident and safe enough you can also use this to look for common notes. If you are experienced within packaging this guide is surely not your first entrypoint and is also not meant to be!

Required experiences and knowledge for this guide:

  • compiling software under GNU/Linux / UNIX
  • rudimentary knowledge about shell-scripts and handling them
  • knowledge about file-handling and folder-structures under GNU/Linux / UNIX
  • knowledge about handling configuration-files and commenting in or out their values
  • handling privileges for users and groups under GNU/Linux / UNIX
  • handling services and especially setup a webserver under GNU/Linux / UNIX (for your own repository)

If you do not have any knowledge within those named fields, this guide is not meant for you at this moment.

Hyperbola is not meant as system to be used by people beginning with Unix and Unix-like systems. Surely you can do this, but this is combined with a meant learning-curve for your own technical emancipation. Please understand that we need to define boundaries about what we are able to manage, maintain and explain. Going that deep into every detail is not possible and therefore we kindly ask for your own willingness reading into details and test commands for example on your own, where you are not sure for the moment. We would be happy if you share later on your knowledge or add more information here within the article.

The decisions behind: Are there disadvantages?

You may ask for sure: Do I really need all of this and manage packaging? The clear answer here is surely: No, you do not need to. But in fact you will also have to manage all the compiled and installed data on your own. Minimizing that effort is to create as said clear packaged software and data for you to install, remove, up- or downgrade all the time again on your own will with the clear point of knowledge what you are doing and what data is next added to your system running.

Are there disadvantages? Not really, besides you learn much more about the file-system and its structures. It just depends on your will doing so. If you have no interest? Sure, it is your choice doing so. But you can also share the scripts for others to review them, helping you with possible problems running software and in the end you can give also something back when you share your package-script and the files around for others to understand, learn, modify and share them again. Or you get hosting your own repository offering software and ports for others to download and install? As said: That is your decision, but we believe clearly within the model to share information, data and more, giving something back. We believe not within seeing free, libre software only as “gratis offered software” including full-time support at any given point. If you want that, Hyperbola is not the project and system for you and we kindly ask you to search for a different solution.

Generic overview for the usage

Packages for Hyperbola are built using the makepkg command and the information needed to do so is stored in a PKGBUILD file.

The PKGBUILD file is in fact a shellscript storing relevant variables and function-calls in a structured and standardized way. We get there back later on with a more detailed description on what is needed to create a working PKGBUILD file.

When the command makepkg is called, it searches for a corresponding file named PKGBUILD in the current directory and follows the instructions therein to acquire the required files and afterwards compile the sources and data to be packaged within a package file. The resulting package is compressed with lzip following therefore a clear naming-scheme (pkgname.pkg.tar.lz). The resulting package contains binaries and further needed data files and also installation instructions; readily installed with our package-manager.

Now what is inside that compressed tarball (file)?

  • All the files and data to install, direct in the corresponding needed structure for folders later used after the installation.
  • .PKGINFO: Contains all the metadata needed by the package-manager to deal with packages, dependencies, etc.
  • .INSTALL: An optional file used to execute commands after the install/upgrade/remove stage. Please have in mind that this file is only present if specified in the PKGBUILD before.
  • .Changelog: An optional file kept by the package maintainer documenting the changes of the package.

Preparation for your setup and environment

Before starting to develop a package you surely need also the corresponding tools installed to configure and also use your computer for building and compiling software.

Prerequisite software needed

Please first make sure that all necessary tools are installed: At best you use the package-group base-devel as it includes essentials needed for compiling from sources.

Surely one of the key tools for building packages is makepkg (provided by pacman) which does the following:

  1. Checks if package dependencies are installed.
  2. Downloads the source file(s) from the specified server(s).
  3. Unpacks the source file(s).
  4. Compiles the software and installs it under a fakeroot environment.
  5. Strips symbols from binaries and libraries.
  6. Generates the package meta-file which is included with each package.
  7. Compress the fakeroot environment into a package file.
  8. Stores the package file in the configured destination directory, which is the present working directory by default.

Build software from sources downloaded

Please remember that Hyperbola is not allowing packages being built from unstable repositories, also not general from any kind of checkout through any VCS (version control system). So we always speak about stable released tarballs. To test your preferred software to be later released as package first download a concrete source-tarball, extract it and follow the author's / maintainer's steps to install the program. Make a note of all commands and / or steps needed to compile and install it: You will be repeating those same commands in the PKGBUILD file for sure later on.

Most software authors stick to the 3-step build cycle:

./configure
make
make install

Or as alternative:

cmake .
make
make install

This is a good time to make sure the program is working correctly, for example with just a local installation done in your $HOME-folder.

Please do not use further administrative privileges to install your compiled software at this point. You will not have further control about updates otherwise. Surely you can use opendoas to get administrative privileges and install the compiled software, but as said this is outside the package-management and you will have to look on remnants later on when you want to update to a newer released version. Using the package-management has explicit advantages as you can be sure that all included data is removed and / or correct updated! Also please note that we will not support you when you deny working with packaged software. We want to encourage you using the package-manager of Hyperbola: You can install the package and share your own PKGBUILD later on with others in the community!

Creating a PKGBUILD

When you run makepkg, it will look for a PKGBUILD file in the present working directory. If a PKGBUILD file is found it will download the software's source code and compile it according to the instructions specified in the PKGBUILD file. After successful completion, the resulting binaries and data of the package, i.e. package version and dependencies, are packed in a compressed file.

You can checkout your created package with a local installation:

doas pacman -U <package file>

To begin with a new package, you should first create an empty working directory (preferably ~/pkgname), change into that directory, and create an empty file named PKGBUILD. You can also either copy the prototype PKGBUILD (to be found under: /usr/share/pacman/PKGBUILD.proto) to your working directory or copy a PKGBUILD from a similar package. The latter may be useful if you only need to change a few options or just want to upgrade / modify an existing package.

Example PKGBUILDs are located in /usr/share/pacman/. To list the files and their meanings:
  • PKGBUILD.proto for a generic meant package
  • PKGBUILD-split.proto for generating split packages depending on each other
  • PKGBUILD-vcs.proto for a package using direct VCS access

Used variables within a PKGBUILD

The following are variables that can be filled out in the PKGBUILD file.

It is common practice to define the variables in the PKGBUILD in same order as given here. However this is not mandatory as long as correct syntax is used.

pkgname

The name of the package. It should consist of alphanumeric characters and dashes ('-') and all letters should be lowercase. For the sake of consistency, pkgname should match the name of the source tarball of the software you are packaging. For instance, if the software is in foobar-2.5.tar.gz, the pkgname value should be foobar. The current working directory the PKGBUILD file is in should also match the pkgname.

pkgver

The version of the package. The value should be the same as the version released by the author of the package. It can contain letters, numbers and periods but can't contain a hyphen. If the author of the package uses a hyphen in their version numbering scheme, replace it with an underscore. For instance, if the version is 0.99-10, it should be changed to 0.99_10. If the pkgver variable is used later in the PKGBUILD then the underscore can easily be substituted for a dash on usage e.g.:

source=($pkgname-${pkgver//_/-}.tar.gz)

pkgrel

The release number of the package specific to Hyperbola. This value allows users to differentiate between consecutive builds of the same version of a package. When a new package version is first released, the release number starts at 1. As fixes and optimizations are made to the PKGBUILD file, the package will be re-released and the release number will increment by 1. When a new version of the package comes out, the release number resets to 1.

epoch

An integer value, specific to Hyperbola, representing what “lifetime” to compare version numbers against. This value allows overrides of the normal version comparison rules for packages that have inconsistent version numbering, require a downgrade, change numbering schemes, etc. By default, packages are assumed to have an epoch value of 0. Do not use this unless you know what you are doing.

pkgdesc

The description of the package. The description should be about 80 characters or less and should not include the package name in a self-referencing way.

arch

An array of architectures that the PKGBUILD file is known to build and work on. Currently, it should contain i686 and / or x86_64.

arch=('i686' 'x86_64')
An array is a data structure consisting of a collection of elements (values or variables), of same memory size, each identified by at least one array index or key. An array is stored such that the position of each element can be computed from its index tuple by a mathematical formula. The simplest type of data structure is a linear array, also called one-dimensional array. This kind of data structure is exactly what we are using in this article!

The value any can also be used for architechture-independent packages:

arch=('any')
Please remember that Hyperbola does not support any other CPU-architecture as i686 or x86_64. It will not work to use any other architecture for building!

You can access the target architecture with the variable $CARCH during the further script, and even when defining variables:

depends=(foobar)
if test "$CARCH" == x86_64; then
  depends=("${depends[@]}" glibc)
fi

url

The URL of the official site of the software being packaged.

license

The license under which the software is distributed. You can use the package licenses for reference. The alternative way is to enumerate the used licenses under the path /usr/share/licenses/common/.

Hyperbola is a free, libre operating-system. We only accept free licenses that respects the freedom of users. You can use for sure different licensing in your local packages - even non-free licensed software - but when you want to share your buildscripts the packages have to use clear free and permissive licensing otherwise we will delete the shared information immediately and cannot except them for integration. This is related to every part of a package, including the data provided!

groups

The group the package belongs in. For instance, when you install the lumina-extra package, it installs all packages that belong in the named group lumina-extra.

depends

An array of package names that must be installed before this software can be run. If a software requires a minimum version of a dependency, the >= operator should be used to point this out. For example:

depends=('foobar>=1.8.0')

You do not need to list packages that your software depends on if other packages your software depends on already have those packages listed in their dependency. For instance, gtk2 depends on glib2 and glibc. However glibc does not need to be listed as a dependency for gtk2 because it is a dependency for glib2. So look careful on the needed dependency-tree within the construction of your PKGBUILD.

makedepends

An array of package names that must be installed to build the software but unnecessary for using the software after installation. You can specify the minimum version dependency of the packages in the same format as the depends array before.

The group base-devel is assumed already installed when building with makepkg. Packages within the group base-devel should not be included in makedepends arrays.

checkdepends

An array of packages this package depends on to run its test suite but are not needed at runtime. Packages in this list follow the same format as depends. These dependencies are only considered when the check() function is present and is to be run by makepkg.

optdepends

An array of package names that are not needed for the software to function but provides additional features. A short description of what each package provides should also be noted. An optdepends may look like this:

optdepends=('cups: printing support'
'sane: scanners support'
'libgphoto2: digital cameras support'
'alsa-lib: sound support'
'giflib: GIF images support'
'libjpeg-turbo: JPEG images support'
'libpng: PNG images support')

provides

An array of package names that this package provides the features of (or a virtual package such as cron or sh). If you use this variable, you should add the version (pkgver and perhaps the pkgrel) that this package will provide if dependencies may be affected by it. For instance, if you are providing a modified qt package named qt-foobar version 3.3.8 which provides qt then the provides array should look like:

provides=('qt=3.3.8')

conflicts

An array of package names that may cause problems with this package if installed. You can also specify the version properties of the conflicting packages in the same format as the variable depends.

replaces

An array of obsolete package names that are replaced by this package, for example:

replaces=('xscreensaver')

After syncing, it will immediately replace an installed package upon encountering another package with the matching replaces in the repositories. If you are providing an alternate version of an already existing package, use the conflicts variable which is only evaluated when actually installing the conflicting package.

backup

An array of files to be backed up as file.pacsave when the package is removed. This is commonly used for packages placing configuration files in /etc. The file paths in this array should be relative paths:

etc/pacman.conf

Do not use absolute paths likewise

/etc/pacman.conf

Now for a concrete example:

backup=('etc/lighttpd/lighttpd.conf'
'etc/logrotate.d/lighttpd')

options

This array allows you to override some of the default behavior of makepkg. To set an option, include the option name in the array. To reverse the default behavior, place an ! at the front of the option. The following options may be placed in the array:

  • strip: Strip symbols from binaries/libraries
  • docs: Save doc directories specified by DOC_DIRS
  • libtool: Leave libtool (.la) files in packages
  • staticlibs: Leave static library (.a) files in packages
  • emptydirs: Leave empty directories in packages
  • zipman: Compress manual (man and info) pages in MAN_DIRS with gzip
  • purge: Remove files specified by PURGE_TARGETS
  • debug: Add debugging flags as specified in DEBUG_* variables

install

The name of the .install script to be included in the package. pacman has the ability to store and execute a package-specific script when it installs, removes or upgrades a package. The script contains the following functions which run at different times:

  • pre_install: The script is run right before files are extracted. One argument is passed: new package version.
  • post_install: The script is run right after files are extracted. One argument is passed: new package version.
  • pre_upgrade: The script is run right before files are extracted. Two arguments are passed in the following order: new package version, old package version.
  • post_upgrade: The script is run after files are extracted. Two arguments are passed in the following order: new package version, old package version.
  • pre_remove: The script is run right before files are removed. One argument is passed: old package version.
  • post_remove: The script is run right after files are removed. One argument is passed: old package version.
A prototype .install is provided at /usr/share/pacman/proto.install.

source

This is an array of files which are needed to build the package. It must contain the location of the software source, which in most cases is a full HTTP, HTTPS or FTP URL. The previously set variables pkgname and pkgver can be used effectively here:

source=("http://example.com/$pkgname-$pkgver.tar.gz") 

If you need to supply files which are not downloadable on the fly, e.g. self-made patches or other files, you simply put those into the same directory where your PKGBUILD file is in and add the filename to this array. Any paths you add here are resolved relative to the directory where the PKGBUILD is located. Before the actual build process is started, all of the files referenced in this array will be downloaded or checked for existence, and makepkg will not proceed if any are missing.

noextract

An array of files listed under the source array which should not be extracted from their archive format by makepkg.

sha512sums

An array of SHA-2 checksums with digest size 512 bits. Hyperbola is demanding per default those as all files corresponding to the source array needs to be listed also within here in the exact same order. You can generate this array quickly and easily using the following command in the directory that contains the PKGBUILD file:

makepkg -g

Defining PKGBUILD variables

The command makepkg defines three variables that you should use as part of the build and install process:

startdir: This contains the absolute path to the directory where the PKGBUILD file is located. This variable used to be used in combination with /src or /pkg postfixes, but the use of srcdir and pkgdir variables is the modern method. $startdir/src is not guaranteed to be the same as $srcdir, and likewise for $pkgdir. Use of this variable is deprecated and strongly discouraged.

srcdir: This points to the directory where makepkg extracts or copies all source files.

pkgdir: This points to the directory where makepkg bundles the installed package, which becomes the root-directory of your built package.

When you execute makepkg within a folder your PKGBUILD is within, it will automatically create the subfolders named /src and /pkg while going through the packaging-process!

Common to note is the point that it is always possible to create own variables within your PKGBUILD file, either local or global used at the whole time building and generating. Using those mechanisms is elementary needed for having a convinient execution of your package building successfully.

Hyperbola is using Debian-patchsets so you can find for example the variables _debver and _debrel without our PKGBUILD files. As presented example the package libmtp is used here (PKGBUILD):

pkgname=libmtp
pkgver=1.1.17
_debver=$pkgver
_debrel=3
pkgrel=2
pkgdesc="Library implementation of the Media Transfer Protocol"
arch=('i686' 'x86_64')
url='http://libmtp.sourceforge.net'
license=('LGPL-2.1')
depends=('libusb')
makedepends=('quilt')
source=("https://downloads.sourceforge.net/$pkgname/${pkgname}-${pkgver}.tar.gz"
        "https://deb.debian.org/debian/pool/main/libm/libmtp/libmtp_${_debver}-${_debrel}.debian.tar.xz")
sha512sums=('f2648e259529bd3dfe74a7049a79c4b0042bcaf63cc1fec8b232b66312d62e9620280e4f725312c9ef8207f1f1ceac19f460a0a8772a3cc6c7f0b00ead01add2'
            'e0f94795cc48b7f7e91147ac39baf323398a18a07a6a7aaff1ca21bf321a8b58e7dede70634ce10ef20ee5d410d0b5ac31bf44445d9aaa554dd461c040009e46')

You can see here the effective usage of the predefined and our own defined variables to create the used source array for further downloading and processing later on.

Used functions within a PKGBUILD

As already mentioned in the introduction of this article a PKGBUILD as shellscript consists of predefined variables and functions. Now we are describing the needed functions being either not mandatory but useful or absolutely needed for processing the packaging.

prepare()

The prepare() function is not mandatory and is used for preparing the uncompressed sources and files for the further processing. Common within this first function called is to add further patches, add some further needed files missing and generate the configuration.

Example finalized (PKGBUILD for libmtp):

prepare() {
  cd $pkgname-$pkgver

  if [[ ${pkgver%.*} = ${_debver%.*} ]]; then
    # Debian patches
    export QUILT_PATCHES=debian/patches
    export QUILT_REFRESH_ARGS='-p ab --no-timestamps --no-index'
    export QUILT_DIFF_ARGS='--no-timestamps'

    mv "$srcdir"/debian .

    # Doesn't apply
    rm -v debian/patches/1002-udev_rules.patch || true

    quilt push -av
  fi
}

build()

We need to implement the build() function in the PKGBUILD file. This function uses common shell commands to automatically compile software and create a directory named /pkg to install the software to. This allows makepkg to package files without having to sift through your filesystem.

The first step in the build() function is to change into the directory created by uncompressing the source tarballs named before in the source array. In most common cases the first command will look like this:

cd "$srcdir/$pkgname-$pkgver"

Here to see the clear usage of defined and common used variables. Now you need to list the same commands you used when you manually compiled the software. The build() function in essence automates everything you did by hand and compiles the software in the fakeroot build environment. If the software you are packaging uses a configure script, it is good practice to use the options needed. Example:

./configure --prefix=/usr

A lot of software installs files relative to the /usr/local directory, which should only be done if you are manually building from source. All of our packages should use the /usr directory when directly used within the system. When you create a package for your local usage you can leave the prefix-definition out as this is working with the Filesystem Hierarchy Standard.

Example finalized (PKGBUILD for libmtp):

build() {
  cd $pkgname-$pkgver
  ./configure \
    --prefix=/usr \
    --with-udev=/lib/udev
  make
}

check()

The check() function is not mandatory and is used for testing routines. Example:

make check

Users can disable it also in PKGBUILD via options variable.

package()

The final step is within the function package() to put the compiled files in a directory where makepkg can retrieve them to create a package. This by default is the /pkg directory - a simple fakeroot environment. The /pkg directory replicates the hierarchy of the root file system of the software's installation paths. If you have to manually place files under the root of your filesystem, you should install them in the /pkg directory under the same directory structure. For example, if you want to install a file to /usr/bin, it should instead be placed under $pkgdir/usr/bin. Very few install procedures require the user to copy dozens of files manually. Instead, for most software, calling make install will do so. The final line should look like the following in order to correctly install the software in the /pkg directory:

make DESTDIR="$pkgdir" install
It is sometimes the case where DESTDIR is not used in the Makefile; you may need to use prefix instead. If the package is built with autoconf / automake, use DESTDIR; this is what is documented in the manuals. If DESTDIR does not work, try building with:
make prefix="$pkgdir/usr/" install

If that does not work, you will have to look further into the install commands that are executed by “make <…> install”.

Example finalized (PKGBUILD for libmtp):

package() {
  cd $pkgname-$pkgver
  make DESTDIR="$pkgdir" install
  install -Dm644 COPYING -t "${pkgdir}/usr/share/licenses/$pkgname"
}

Split functions within a PKGBUILD

Before we close now this paragraph the so-called split packages should be mentioned as there are some special notations needed. Following up another example based on the package spacefm (PKGBUILD):

  • There is the new variable pkgbase needed besides now pkgname being defined as an array including all resulting sub-ordered packages.
  • Within the functions prepare() and build() source-folders are duplicated and building separate so the results can be used later on.
  • There are exactly fitting functions for package() named after the entries within the array pkgname before. Please have in mind that this is elementary needed as makepkg awaits clear defined output for every definition.

You can also see that it is possible to enhance variables or overwrite them later on direct in the functions, so the resulting packages follow an own individual definition for their metadata:

package_spacefm() {
  pkgdesc+=" (GTK+ 3 version)"
  depends=('gtk' 'startup-notification' 'ffmpegthumbnailer')
  optdepends=('util-linux: disk eject support'
              'lsof: device processes'
              'pmount: mount as non-root user')

  cd gtk3
  make DESTDIR="${pkgdir}" install
  rm -f "$pkgdir"/usr/bin/spacefm-installer
  install -Dm644 COPYING -t "${pkgdir}/usr/share/licenses/$pkgname"
}

package_spacefm-gtk2() {
  pkgdesc+=" (GTK+ 2 version)"
  depends=('gtk2' 'desktop-file-utils' 'startup-notification' 'ffmpegthumbnailer')
  optdepends=('lsof: device processes'
              'pmount: mount as non-root user')

  cd gtk2
  make DESTDIR="${pkgdir}" install
  install -Dm644 COPYING -t "${pkgdir}/usr/share/licenses/$pkgname"
}

Those split definitions are only possible and needed when the software itself supports different definitions at time building and you have the intention to offer also those as dedicated package.

Setup for a clean build-environment

Until now we have described makepkg being executed local for building your packages. Sure this would be enough for yourself on your current installed system, but when you want to handover the script and files to others you should recognize this as not sufficient. Remember here that your system is absolutely your own and therefore unique with its configuration and installed data. So if you handover your scripts for packaging you need to make absolutely sure that this is going to work flawless for everyone else.

You will need to test your packaging within a clean chroot environment. For this Hyperbola is offering the package libretools to grant needed tools and commands doing so. With libretools you can:

  • Create named chroot-environments for building
  • Reset those created environments at any given time
  • Approve package-scripts and create also free, libre source-tarballs
chroot is an operation on Unix and Unix-like operating systems that changes the apparent root directory for the current running process and its children.

So the generic goal here is to recreate a clean installation with the handover for full control towards you as acting person for packages at any given time. Especially because of a standard definition for the hierarchy of files and folders we can make sure that a chroot-operation is possible in that way. Redefining this is a violation of the standards and not allowed in the way Hyperbola wants to grant usage.

Now we describe the needed steps to create a working local chroot-environment. At first you should make yourself sure for what kind of environment you want to build and therefore also with what source-base on Hyperbola. We are offering stable and testing for that purpose. Your libretools installed will always orient on your local defined mirrorlist, to be found under /etc/pacman.d/mirrorlist. If you want to build with the testing branch you need to activate those mirrors and deactivate stable. If you want to build with stable branch you need to activate those mirrors and keep testing deactivated.

Now for the installation after you have made sure about your target environment:

doas pacman -S libretools

Creating the initial chroot-enviroment after libretools was installed:

doas librechroot clean-repo

Creating your local chroot-copy within you will later create the packages:

(32bit)

doas librechroot -C /etc/pacman.conf -M /usr/share/pacman/defaults/makepkg.conf.i686 -n i686 make

(64bit)

doas librechroot -C /etc/pacman.conf -M /usr/share/pacman/defaults/makepkg.conf.x86_64 -n x86_64 make
Please remember again the connection between your local installed system and libretools. When you have an installation for 64bit you need first to modify your pacman configuration under /etc/pacman.conf to reflect a possible 32bit-architecture. Change the following entry from:
Architecture = auto

To this value:

Architecture = i686

You can change this back after the creation of your chroot-environment.

We have now possible environments named x86_64 and i686. At this point it is needed to mention that you can clearly choose also different names for your environments when creating them. Those are only first recommendations resulting from the experiences made.

Please note that you can only use 32bit and 64bit on a system supporting 64bit. Systems only supporting 32bit can also only support 32bit as possible chroot.

You can update and synchronize your chroot-enviroments with the following commands:

doas librechroot -n i686 update
doas librechroot -n i686 sync

We recommend doing this regular especially when you are using testing as your base.

Now having one or more environments you can again start with creating your package but from now on with the command following that syntax, as example within our created chroot-environment named i686:

doas libremakepkg -n i686

Creating your own repository

You can create your complete own repository for local or remote usage. The difference in between is for sure that local usage means only yourself as user for packages while remote usage includes everyone else. So let's assume that you have created now two packages:

ls
armagetronad  jumpnbump

In every folder listed is a compiled package ready for its further usage. For armagetronad this may be:

armagetronad-0.2.9.1.0-1-i686.pkg.tar.lz

Let's copy all package-files to a newly created folder where our database will reside:

cp ./*.pkg.tar.lz /var/local/mypkgs

We enter now the folder for our new repository:

cd /var/local/mypkgs

And afterwards create our package-database:

repo-add mypkgs.db.tar.lz *.pkg.tar.lz

Example for resulting output:

# repo-add mypkgs.db.tar.lz *.pkg.tar.lz
==> adding package 'armagetronad-0.2.9.1.0-1-i686.pkg.tar.lz'
  -> Computing checksums...
  -> Creating 'desc' db entry...
  -> Creating 'files' db entry...
==> adding package 'jumpnbump-1.61-2-i686.pkg.tar.lz'
  -> Computing checksums...
  -> Creating 'desc' db entry...
  -> Creating 'files' db entry...
==> Creating updated database file 'mypkgs.db.tar.lz'

Now you can add your own repository to your pacman.conf under /etc/pacman.conf:

[mypkgs]
Server = file:///var/local/mypkgs

Or you can share this via HTTPS / HTTP:

[mypkgs]
Server = https://<your-ip-address>/mypkgs