We are pleased to present one of our new creations: pkgbuild, a tool written in standard C++, using libCURL, ZLib, BZip2 and libLZMA (part of XZ).
It is a modern Slackware packages builder, network-transparent, multi-architecture, designed to greatly simplify the creation of a package, automatically executing the required post processing.
What does it do?
- Recognize and build packages for the following architectures: i386, i486, i586, i686, x86_64, IA64, IA32e, s390, s390x, sparc and sparc64.
- Has the ability to build Slackware packages with the following formats: TGZ, TBZ, TLZ and TXZ.
- Has the ability to create files needed for slapt-get support.
- Has the ability to manage configuration files, with or without "noreplace" attribute, and to retain the original permissions, using standard Slackware tools.
- Has the ability to create correct packages even running as user, because the compressed tarballs (tar-1.13 compatible) are generated by its internally engine.
- Has the ability to install/upgrade the generated packages using standard Slackware tools (only running as root, of course)
- Has the ability to download (and verify the checksum) of the required files, using any protocol supported by libCURL (HTTP, HTTPS, FTP, FTPS, file, etc.)
- Has the ability to create (and use) source packages, as TXZ archives.
- Has the ability to allows very easy creation of split/multiple packages.
Now the bad news:
pkgbuild uses scripts similar to the RPM spec's, but not identical. These build scripts use the extension ".pkgspec".
To use pkgbuild, you will need to learn the syntax of it's scripts.
An example script is below:
Code:
# PkgBuild Spec for <mysql> package(s)
Name: mysql
Version: 5.1.46
Release: 1
# Sources
Source: %{__name}-%{__version}.tar.bz2
Source0: rc.mysqld
%package
Group: CORE_APPS
Requires: gcc >= 4.4.3-%{__arch}-2
Requires: glibc-solibs >= 2.11.1-%{__arch}-2
Requires: ncurses >= 5.7-%{__arch}-1
Requires: openssl >= 0.9.8n-%{__arch}-1 | openssl-solibs >= 0.9.8n-%{__arch}-1
Requires: perl >= 5.10.1-%{__arch}-1
Requires: zlib >= 1.2.3-%{__arch}-2
%package embedded
Group: LIBS
Requires: gcc >= 4.4.3-%{__arch}-2
Requires: glibc-solibs >= 2.11.1-%{__arch}-2
Requires: zlib >= 1.2.3-%{__arch}-2
%description
# The "handy ruler" below makes it easier to edit a package description. The second
# '#' on the right side marks the last column you can put a character in. It's also
# customary to make exactly 11 lines for the formatting to be correct.
#-----handy-ruler-----------------------------------------------------#
mysql (SQL-based relational database server)
MySQL is a fast, multi-threaded, multi-user, and robust SQL
(Structured Query Language) database server. It comes with a nice API
which makes it easy to integrate into other applications.
The home page for MySQL is http://www.mysql.com/
%description embedded
# The "handy ruler" below makes it easier to edit a package description. The second
# '#' on the right side marks the last column you can put a character in. It's also
# customary to make exactly 11 lines for the formatting to be correct.
#-----handy-ruler-----------------------------------------------------#
mysql-embedded (Embedded SQL-based relational database server)
MySQL is a fast, multi-threaded, multi-user, and robust SQL
(Structured Query Language) database server.
This package contains the embedded version of MySQL server, which makes
it easy to integrate into other applications.
The home page for MySQL is http://www.mysql.com/
%begin
%setup
%{__chbuilddir}
CFLAGS="${CFLAGS:-%__optflags}" ; export CFLAGS ; \
CXXFLAGS="${CXXFLAGS:-%__optflags -felide-constructors -fno-exceptions -fno-rtti}" ; export CXXFLAGS ; \
CXX="gcc" ; export CXX ; \
./configure \
--prefix=%{_prefix} \
--libdir=%{_libdir} \
--with-mysqld-user=mysql \
--with-unix-socket-path=%{_localstatedir}/run/mysql/mysql.sock \
--localstatedir=%{_localstatedir}/lib/mysql \
--mandir=%{_mandir} \
--infodir=%{_infodir} \
--enable-assembler \
--without-debug \
--enable-thread-safe-client \
--with-extra-charsets=complex \
--with-ssl=/usr \
--enable-largefile \
--with-innodb \
--with-readline \
%{__configure_flags}
%begin build
%{__make} %{_smp_mflags}
%begin install
%{__make} install DESTDIR=$__installdir
# install additional headers needed for building external engine plugins
for i in sql include regex; do
for j in $i/*.h; do
%{__install} -m 644 $j $__installdir%{_includedir}/mysql/
done
done
%{__mkdir_p} $__installdir%{_includedir}/mysql/atomic
for i in include/atomic/*.h; do
%{__install} -m 644 $i $__installdir%{_includedir}/mysql/atomic/
done
# The ./configure option to omit this has gone away, so we'll omit it the old-fashioned way.
# It's all in the source tarball if you need it.
%{__rm} -rf $__installdir%{_prefix}/sql-bench
# Install support files
%{__mkdir_p} $__installdir%{_sysconfdir}
%{__cp} -af support-files/my-{huge,large,medium,small}.cnf $__installdir%{_sysconfdir}
# Install docs
mkdir -p $__installdir%{_docdir}/Docs
( cd Docs
# Seems most of the Docs/* are gone, but we'll leave the cp stuff in case it returns.
# %{__cp} -af INSTALL-BINARY *.html *.txt Flags \
%{__cp} -af INSTALL-BINARY \
$__installdir%{_docdir}/Docs
)
## Too large to justify since the .html version is right there:
#%{__rm} -f $__installdir%{_docdir}/Docs/manual.txt
# This is the directory where databases are stored
%{__mkdir_p} $__installdir%{_localstatedir}/lib/mysql
# This is where the socket is stored
%{__mkdir_p} $__installdir%{_localstatedir}/run/mysql
# Do not include the test suite:
%{__rm} -rf $__installdir%{_prefix}/mysql-test
# Add init script:
%{__mkdir_p} $__installdir%{_sysconfdir}/rc.d
# This is intentionally chmod 644.
%{__cat} %SOURCE0 > $__installdir%{_sysconfdir}/rc.d/rc.mysqld
# Add some handy library symlinks:
if [ -r $__installdir%{_libdir}/mysql/libmysqlclient.so.16 ]; then
( cd $__installdir%{_libdir}
%{__rm} -f libmysqlclient.so libmysqlclient.so.16
%{__ln} -sf mysql/libmysqlclient.so .
%{__ln} -sf mysql/libmysqlclient.so.16 .
)
else
exit 1
fi
if [ -r $__installdir%{_libdir}/mysql/libmysqlclient_r.so.16 ]; then
( cd $__installdir%{_libdir}
%{__rm} -f libmysqlclient_r.so libmysqlclient_r.so.16
%{__ln} -sf mysql/libmysqlclient_r.so .
%{__ln} -sf mysql/libmysqlclient_r.so.16 .
)
else
exit 1
fi
# Final cleanup
#%{__rm} -f $__installdir%{_libdir}/*.so.?
%{__rm} -f $__installdir%{_infodir}/dir
######################################################################
# Build and install the MySQL Embedded Server
%{__make} distclean
CFLAGS="${CFLAGS:-%__optflags}" ; export CFLAGS ; \
CXXFLAGS="${CXXFLAGS:-%__optflags -felide-constructors -fno-exceptions -fno-rtti}" ; export CXXFLAGS ; \
CXX="gcc" ; export CXX ; \
./configure \
--prefix=%{_prefix} \
--libdir=%{_libdir} \
--datadir=%{_datadir} \
--sysconfdir=%{_sysconfdir}/mysql \
--libexecdir=%{_libexecdir} \
--localstatedir=%{_localstatedir}/lib/mysql \
--without-docs \
--without-man \
--without-server \
--with-embedded-server \
--without-innodb \
--without-berkeley-db \
--without-row-based-replication \
--without-readline \
--disable-shared \
--with-charset=utf8 \
--without-debug \
--with-pthread \
--without-ssl \
--without-query-cache \
--without-geometry \
--with-pic
%{__make} %{_smp_mflags}
%{__cp} -a libmysqld/libmysqld.a $__installdir%{_libdir}/mysql/
%files
%defattr(-,root,root,-)
%doc COPYING ChangeLog EXCEPTIONS-CLIENT INSTALL-SOURCE README
%config %{_sysconfdir}/rc.d/rc.mysqld
%dir %attr(0750,mysql,mysql) %{_localstatedir}/lib/mysql
%dir %attr(0755,mysql,mysql) %{_localstatedir}/run/mysql
%{_sysconfdir}/my-*.cnf
%{_bindir}/*
%{_docdir}/Docs/*
%{_includedir}/mysql/atomic/*.h
%{_includedir}/mysql/*.h
%{_infodir}/mysql.info*
%{_libdir}/libmysqlclient.so*
%{_libdir}/libmysqlclient_r.so*
%{_libdir}/mysql/libdbug.a
%{_libdir}/mysql/libheap.a
%{_libdir}/mysql/libmyisam*.a
%{_libdir}/mysql/libmysqlclient*.a
%{_libdir}/mysql/libmysqlclient*.la
%{_libdir}/mysql/libmysqlclient*.so*
%{_libdir}/mysql/libmystrings.a
%{_libdir}/mysql/libmysys.a
%{_libdir}/mysql/libvio.a
%{_libdir}/mysql/plugin/*.a
%{_libdir}/mysql/plugin/*.la
%{_libdir}/mysql/plugin/*.so*
%{_libexecdir}/*
%{_mandir}/man1/*.1*
%{_mandir}/man8/*.8*
%{_datadir}/aclocal/mysql.m4
%{_datadir}/mysql/*
%files embedded
%defattr(-,root,root,-)
%{_libdir}/mysql/libmysqld.a
%changelog
* Friday 07 May 2010 Darth Vader <darkstarlinux@gmail.com> -
- Initial build.
Another example:
Code:
# PkgBuild Spec for <sudo> package(s)
Name: sudo
Version: 1.7.2p6
Release: 1
Group: CORE_APPS
# Sources
Source: %{__name}-%{__version}.tar.gz
%package
Requires: glibc-solibs >= 2.11.1-%{__arch}-2
%description
# The "handy ruler" below makes it easier to edit a package description. The second
# '#' on the right side marks the last column you can put a character in. It's also
# customary to make exactly 11 lines for the formatting to be correct.
#-----handy-ruler-----------------------------------------------------#
sudo (give limited root privileges to certain users)
'sudo' is a command that allows users to execute some commands as
root. The /etc/sudoers file (edited with 'visudo') specifies which
users have access to sudo and which commands they can run. 'sudo'
logs all its activities to /var/log/ so the system administrator
can keep an eye on things.
%begin
%setup
%configure \
--with-getpass \
--with-C2 \
--with-env-editor \
--disable-pam-session \
--with-pam=no
%begin build
%{__make} %{_smp_mflags}
%begin install
%{__make} install DESTDIR=$__installdir
( cd $__installdir%{_bindir} ; %{__ln} -sf sudo sudoedit )
%{__rm} -f $__installdir%{_mandir}/man8/sudoedit.8
( cd $__installdir%{_mandir}/man8 ; %{__ln} -sf sudo.8 sudoedit.8 )
# Create the timestamp directory
%{__mkdir_p} $__installdir%{_localstatedir}/run/sudo
%files
%defattr(-,root,root,-)
%doc ChangeLog HISTORY INSTALL LICENSE PORTING README README.LDAP TROUBLESHOOTING UPGRADE WHATSNEW
%config(noreplace) %{_sysconfdir}/sudoers
%attr(4711,root,root) %{_bindir}/sudo
%{_bindir}/sudoedit
%attr(0755,root,root) %{_sbindir}/visudo
%{_libexecdir}/sudo_noexec.so
%{_mandir}/man5/sudoers.5*
%{_mandir}/man8/sudo.8*
%{_mandir}/man8/sudoedit.8*
%{_mandir}/man8/visudo.8*
%dir %attr(0700,root,root) %{_localstatedir}/run/sudo
%changelog
* Friday 07 May 2010 Darth Vader <darkstarlinux@gmail.com> -
- Initial build.
And here is another example:
Code:
# PkgBuild Spec for <most> package(s)
Name: most
Version: 5.0.0a
Release: 1
Group: CORE_APPS
# Sources
Source: %{__name}-%{__version}.tar.bz2
%package
Requires: glibc-solibs >= 2.11.1-%{__arch}-2
Requires: slang >= 2.2.2-%{__arch}-1
%description
# The "handy ruler" below makes it easier to edit a package description. The second
# '#' on the right side marks the last column you can put a character in. It's also
# customary to make exactly 11 lines for the formatting to be correct.
#-----handy-ruler-----------------------------------------------------#
most (another pager, like 'more' and 'less')
most is a paging program that displays, one windowful at a time, the
contents of a file on a terminal. Unlike other well-known paging
programs, most supports multiple windows and can scroll left and
right. Why settle for less?
'most' was written by John E. Davis.
%begin
%setup
%configure --datarootdir=%{_prefix}
%begin build
%{__make} %{_smp_mflags}
%begin install
%{__make} install DESTDIR=$__installdir
%{__rm} -rf $__installdir%{_docrootdir}/%{__name}
%files
%defattr(-,root,root,-)
%doc README changes.txt lesskeys.rc most-fun.txt most.doc most.rc
%{_bindir}/most
%{_mandir}/man1/most.1*
%changelog
* Friday 07 May 2010 Darth Vader <darkstarlinux@gmail.com> -
- Initial build.
The major advantage is that using this scripting language and its macros, you can easily achieve different architecture packages. For example, Slackware and Slackware64 and even an Sparc port could use a unified source tree.
Of course, you wonder why we have created us this tool, if we plan to further improve this pkgbuild, and why we want to offer it to Slackware users.
We'll be honest. pkgbuild is a companion tool of DPM, which is a complete packages management solution derived from
lpmtool and that we intend to use it in future. There is also a tool called dpmbuild, which uses a similar scripting language, but which generates DPM packages.
In fact, pkgbuild is a simplified version of dpmbuild, being limited by the Slackware package format. I.e. for scripts, DPM packages supports pre/post installation scripts, pre/post upgrade scripts, triggers, etc..
Well, we use this pkgbuild to learn the use of its scripting language, and to ease our transition to the DPM packages.
Of course, we understand that not everyone will be willing to use our DPM's (i.e. we are sure about PV response to ideas like this: NO!), but also pkgbuild is a stand-alone tool for creating Slackware packages.
Therefore,
we offer this tool to Slackware community and will continue to improve it as a way to promote the learning of this scripting language. Even after our complete transition to DPM packages, we continue to keep in sync pkgbuild and it's companion, dpmbuild.
Eventually, even if we abandon pkgbuild once, it is an open source application anyway, you have access to it's sources at current state and others can continue its development.
However, the pkgbuild SVN repository is here:
svn://svn.darkstarlinux.ro/svnroot/projects/trunk/playground/pkgbuild
If you want to test and/or to use pkgbuild, you can find latest version here:
http://ftp.darkstarlinux.ro/software/pkgbuild/
The current version is 1.0.27.
pkgbuild configuration requires a special method, so in the tarball you will find a script called "pkgbuild.build" which will compile pkgbuild, then pkgbuild will self-compile and the resulted Slackware package will be installed in the system.
Warning: don't build directly the pkgbuild with the triplet configure/make/make install without studying the "pkgbuild.build" script and passing the correct parameters.
Unfortunately, at this time, pkgbuild not have its own documentation, so we suggest now, you read the documentation of dpmbuild, which can be found here:
http://ftp.darkstarlinux.ro/software...tml/build.html
There are following differences between dpmbuild and pkgbuild:
pkgbuild accept the header "Summary" or "Changelog" section, but ignores it.
Sadly, the documentation is not exactly up-to date, both pkgbuild and dpmbuild use a different version for descriptions than the one described in the documentation, as seen in these example scripts (using the "Description" sections).
pkgbuild uses the headers "Requires", "Conflicts" and "Suggests" if exists, with the syntax of slapt-get and their content will reach the files that you suspect them. This is specifically slapt-get files. Not add these headers and the files will not appear.
pkgbuild uses the headers "Groups" if exists, and write it's content in the file install/slack-groups. This is an specifically DARKSTAR file. Not add these headers and the file will not appear.
Compared with dpmbuild, pkgbuild accept only two script sections: "%pre" and "%post". Their content will written on install/doinst.sh, in order that you suspect: "%pre" content on top, "%post" content on bottom.
Also the single accepted script "interpreter" is (of course): "/bin/sh" or smart process the command /sbin/ldconfig, aka %{__ldconfig}.
To control the tarballs compression format, use the header:
Code:
UseCompression: GZip
Accepted values: None (generate uncompressed tarballs), GZip, BZip2, LZMA and XZ (or Default)
To control the symlinks management, use the header:
Accepted values: None (the symlinks is leaved in place), Append or Prepend (or Default). In these cases, pkgbuild "move the symlinks" on install/doinst.sh.
pkgbuild generates source packages as XZ compressed tarballs, with the name format:
<name>-<version>-<release>.src.txz
Therefore, pkgbuild can use these source packages to build packages, using the parameter
-r.
I.e. to rebuild the source mysql-5.1.46-1.src.txz with the architecture i586 and to install/upgrade all resulted packages, you can use:
Code:
pkgbuild -a i586 -ri mysql-5.1.46-1.src.txz
Also... The equivalent of $BUILD is the header "Release". If you want to use always an $TAG equivalent (i.e "SBo"), build and install pkgbuild with the command:
Code:
pkgbuild.build --with-buildtag="SBo"
or locally use the header:
In these cases, the "release" value will become <release><buildtag> (i.e. "3SBo").
A few words about the files attribute %config and %config(noreplace).
Suppose you want to configure two files:
Code:
%config(noreplace) %{_sysconfig}/rc.d/rc.init1.conf
%config %{_sysconfig}/rc.d/rc.init1
After compiling the package, we look in tarball and we see that these files have the extension ".pkgnew"
Code:
/etc/rc.d/rc.init1.conf.pkgnew
/etc/rc.d/rc.init1.pkgnew
After you install this package, we have the following situation in system:
Code:
/etc/rc.d/rc.init1.conf
/etc/rc.d/rc.init1.conf.pkgnew.20100525-210904
/etc/rc.d/rc.init1
/etc/rc.d/rc.init1.pkgsave.20100525-210904
What happened?
pkgbuild added in to install/doinstall.sh special instructions, and when you installed the package, our
standard installpkg executed:
File
/etc/rc.d/rc.inet1.conf differ by /
etc/rc.d/rc.inet1.conf.pkgnew therefore
/etc/rc.d/rc.inet1.conf.pkgnew was saved as
/etc/rc.d/rc.inet1.conf.pkgnew.$DATE
File
/etc/rc.d/rc.inet1 differ by
/etc/rc.d/rc.inet1.pkgnew therefore
/etc/rc.d/rc.inet1 was saved as
/etc/rc.d/rc.inet1.pkgsave.$DATE and
/etc/rc.d/rc.inet1.pkgnew replaced the original file.
In both cases, the original file permissions are copied to the new files.
Therefore, the %config(noreplace) attribute is useful for configuration files, and %config attribute for files that need backup. I.e. the boot scripts.
A Slackware standard behavior will be offered by %config(noreplace).
-------------
That's it. Not everything is just perfectly, but is usable. You have to remember that pkgbuild is considered experimentally until a serious testing. Don't use it in production machines!
I wait your opinion, questions, your suggestions for improvements, and why not? your bug-reports or even your contributions.