Skip to content

New pacman features

Eugene Zamlinsky edited this page Dec 21, 2018 · 9 revisions

Welcome, ArchLinux hackers!

I would like to introduce you some new features, that may appear in the makepkg script soon. Or may not...

Few words about myself. I'm great fan of ArchLinux distro, and have long term Linux administrating and programming experience (more than 10 years). I manage Linux-based servers and my home ArchStation (workstation).

The persons who are develop this distro. I should say: you are doing fantastic job. It is the best distro, I ever saw. I like the KISS principle you follow. And please, let me make ArchLinux even better, than it is now.

I used Gentoo few years ago, and like its package tuning functions. Not sure, that USE flags are the best practice to turn on/off package dependencies. But it allows you to keep distro clean from non required components. I thought: "Why Arch has no something like this?" Let's do it! And I really did.

So, now I'm ready to show you, what makepkg can do for you.

First step. Installation.

I did testing package https://aur.archlinux.org/packages/pacman-ezamlinsky-git/, you may wish to install on your testing ArchLinux computer (VirtualBox or home computer). This package will replace local pacman installation with a new one.

Do not worry. It is standard pacman, I took from official pacman git https://projects.archlinux.org/pacman.git. The difference between official package and this one is, that makepkg script and some man pages were changed.

Second step. New options.

New makepkg has 2 additional options: -t|(--tune) and -u|(--update).

Tune option allows you interactively tune package dependencies, before compilation and following installation. Update option does package upgrade up to new version, but keeps all previously set dependencies. It is very important when you update customized package, and wish to not configure it again and again, each time a new version is released.

Here is an example of --tune option in work.
[jack@JackDesktop curl]$ makepkg --tune
==> Configuring package: curl-ebuild 7.63.0-1
-> Mandatory packages: glibc
-> Enabled packages: ca-certificates krb5 libidn2 libnghttp2 libpsl libssh2 openssl zlib
-> Disabled packages: axtls brotli c-ares gnutls libldap libmetalink librtmp.so libssh mbedtls nettle nspr nss polarssl wolfssl
Would you like to edit package dependencies?

If you say Y(yes), then you will see configuration Wizard. It will guide you through package selection dialog. Use hint message on top of this dialog, to find how to enable or disable packages.

Below you may see how I modified curl package in way I like.
INFO: Type [E] to enable package, [D] to disable, [N] or [S] to skip.
Optional package 'axtls' is disabled. Change? s
Optional package 'brotli' is disabled. Change? s
Optional package 'c-ares' is disabled. Change? s
Optional package 'ca-certificates' is enabled. Change? s
Optional package 'gnutls' is disabled. Change? e
Optional package 'krb5' is enabled. Change? s
Optional package 'libidn2' is enabled. Change? s
Optional package 'libldap' is disabled. Change? e
Optional package 'libmetalink' is disabled. Change? s
Optional package 'libnghttp2' is enabled. Change? d
Optional package 'libpsl' is enabled. Change? s
Optional package 'librtmp.so' is disabled. Change? s
Optional package 'libssh' is disabled. Change? s
Optional package 'libssh2' is enabled. Change? s
Optional package 'mbedtls' is disabled. Change? s
Optional package 'nettle' is disabled. Change? s
Optional package 'nspr' is disabled. Change? s
Optional package 'nss' is disabled. Change? s
Optional package 'openssl' is enabled. Change? s
Optional package 'polarssl' is disabled. Change? s
Optional package 'wolfssl' is disabled. Change? s
Optional package 'zlib' is enabled. Change? s
Mandatory packages: glibc
Enabled packages: ca-certificates gnutls krb5 libidn2 libldap libpsl libssh2 openssl zlib
Disabled packages: axtls brotli c-ares libmetalink libnghttp2 librtmp.so libssh mbedtls nettle nspr nss polarssl wolfssl

Note, that makepkg shows you small summary at the bottom of dialog. You may revise what packages you have enabled or disabled. And then you will see standard compilation process that you did many times.

Third step. Dependency tracking.

Normally, makepkg does not automatically track package dependencies. I don't mean files tracking, but package dependency tracking. Actually, you were obliged to use special tool, like https://wiki.archlinux.org/index.php/Namcap, to collect all software dependencies (shared libraries, scripts, images and other files).

You were responsible to invoke this tool each time, to check what shared libraries are used, by newly created package. If some of them are missed, then you will get non working program, or even a server that will not to start. And you will not have any idea why.

I found elegant way to solve this problem. Or just make it a little bit smaller. This way is called automatically dependency tracking.

When software is built, then makepkg runs "objdump -p" command for each binary file, and get the list of shared objects are used. Then it does some Bash script magic: Shared object name -> Local file -> File owner (package). All virtual dependencies like this Provides : libcurl.so=4-64 are resolved to real package names.

ArchLinux has a lot of this virtual packages. And all of them will be tracked to real package names.

FFmpeg sample:
Provides : libavcodec.so=58-64 libavdevice.so=58-64
libavfilter.so=7-64 libavformat.so=58-64
libavresample.so=4-64 libavutil.so=56-64
libpostproc.so=55-64 libswresample.so=3-64
libswscale.so=5-64

So, when compilation is accomplished, then makepkg will show you short summary:
==> Generating runtime dependencies...
-> Manually set dependencies: ca-certificates glibc krb5 libidn2 libnghttp2 libpsl libssh2 openssl zlib
-> Automatically found dependencies: (here you will see all of automatically found dependencies)

And then it will include full list of packages, this package depend of, into final tar.xz archive. After that you may be sure, that no shared library was missed. And pacman will successfully install all necessary libraries, and resolve package dependencies.

Forth step. Makepkg syntax extension.

This section will be very interesting for package maintainers mainly.

Typically, open source programs have two types of dependencies: hard and soft.

  • Hard dependency means that program hardly depends of the library. It can not be compiled if a library doesn't present into the system.

  • Soft dependency means that a library is optional, and final program can work with/without it. This will cut functionality, but not critical. Soft dependencies may be treated as optional packages. They are not hardly required. And you may wish to turn off some of them.

Here is an example, how they defined into a new PKGPUILD file.
depends=(
#Mandatory
'glibc'
#Optional
'-axtls' '-brotli' '-c-ares' '+ca-certificates' '-gnutls' '+krb5' '+libidn2'
'-libldap' '-libmetalink' '+libnghttp2' '+libpsl' '-librtmp.so' '-libssh'
'+libssh2' '-mbedtls' '-nettle' '-nspr' '-nss' '+openssl' '-polarssl'
'-wolfssl' '+zlib'
)

Prefix '+' means, that a package maintainer recommends you to have this package enabled. '-' have it disabled. You can easily change this, when invoke "makepkg --tune". Please, do not change PKGBUILD file, but use customization Wizard.

If you do not need package tuning, then skip the Wizard, and all '+' marked packages will be linked with a program and '-' marked will not.

Autoconf configuration script, meson, cmake and others have options setting mechanism, that control compilation behavior and program features, to be enabled/disabled.

These options should be inserted into "config_opts" array:
config_opts=(
'--prefix=/usr'
'--bindir=/usr/bin'
'--sbindir=/usr/bin'
'--libdir=/usr/lib'
'--libexecdir=/usr/lib'
'--sysconfdir=/etc'
'--localstatedir=/var'
'--enable-shared'
'--disable-static'
'--enable-optimize'
'--disable-debug'
'--disable-manual'
'--enable-ipv6'
'--enable-pthreads'
)

All of them will be forwarder as is to configuration script.

If you use some optional packages, then you may need to send additional options to configuration script. Array "custom_opts" is the place where you may do this.

It is sample code from "cURL" PKGBUILD.
# FORMAT: 'package_name ? enabled_features : disabled_features' is similar
# to bash shell operator 'let expr ? val1 : val2' and supports &, |, ^, !
# operations with package names to make complex package rules.
# Use space, tab or new line to distinguish multiple options.
# Use keyword 'null' for empty set.
custom_opts=(
'axtls ? --with-axtls : --without-axtls'
'brotli ? --with-brotli : --without-brotli'
'c-ares ? --enable-ares : --disable-ares'
'ca-certificates : --with-ca-bundle=/etc/ssl/certs/ca-certificates.crt: --without-ca-bundle'
'gnutls & nettle ? --enable-tls-srp --with-gnutls : --disable-tls-srp --without-gnutls'
'krb5 ? --with-gssapi : --without-gssapi'
'libidn2 ? --with-libidn2 : --without-libidn2'
'libldap ? --enable-ldap --enable-ldaps --with-ldap-lib --with-lber-lib : --disable-ldap --disable-ldaps --without-ldap-lib --without-lber-lib'
'libmetalink ? --with-libmetalink : --without-libmetalink'
'libnghttp2 ? --with-nghttp2 : --without-nghttp2'
'libpsl ? --with-libpsl : --without-libpsl'
'librtmp.so ? --enable-rtsp --with-librtmp : --disable-rtsp --without-librtmp'
'libssh ? --with-libssh : --without-libssh'
'libssh2 ? --with-libssh2 : --without-libssh2'
'mbedtls ? --with-mbedtls : --without-mbedtls'
'nss & nspr ? --with-nss : --without-nss'
'openssl ? --with-ssl --enable-openssl-auto-load-config : --without-ssl --disable-openssl-auto-load-config'
'polarssl ? --with-polarssl : --without-polarssl'
'wolfssl ? --with-wolfssl --with-cyassl : --without-wolfssl --without-cyassl'
'zlib ? --with-zlib :--without-zlib'
)

Be aware, that each line is a rule for Bash "let expr". So, you may form relatively complex conditional expression, that comes true if a user choose or masked the package. This is really good place to realize your maintainers ambitions.

Do not forget, that PKGBUILD is a typical Bash script. You may use all of the power of shell scripting language.

Fifth step. Backward compatibility.

New makepkg is backward support with old PKGBUILD scripts. It may be used with all legacy AUR packages. All package names are not prefixed with "+" or "-" are treated as mandatory, and will be compiled anyway.

If you would like to test new makepkg functions, then go to AUR repository https://aur.archlinux.org/packages/?O=0&SeB=s&K=Jack_Black&outdated=&SB=n&SO=a&PP=250&do_Search=Go. I have already ported some PKGBUILD scripts from my ArchStation, for your testing and expert revise. I have more than 300 packages in a new format, and will try to post them as soon as possible.

Do not forget to comment, and send me all bugs you may find. Have a nice hacking.

P.S: If you are one of pacman developer, I will appreciate if you include these new features into next official pacman release. I already did lot of testing and cleaned source code from bugs I found.