x72.html
Building Packages with OpenPKG
OpenPKG uses a version of RPM modified to work entirely within a package's directory structure. There are some changes in the way RPMs are built, some the result of encouraging non-root users to build the RPMs, others in the way the RPM sources, builds, and packages are handled in the file system.
Changes in RPM
There have been several changes to the ``rpm'' program:
-
Build by non-root users.
-
More rational directory structure.
-
Cleaner formatting of specfiles.
-
Utility macros for common functions such as file editing and building a list of files installed.
-
Encourages building packages with user specified options.
-
An add-on perl script that rebuilds multiple packages based on dependencies and user defined options.
Packages are built by non-root users, limiting the amount of damage done by bad specfiles.
More rational directory structure -- instead of the SOURCES, SPECS, BUILD, RPMS, and SRPMS directories found under the standard RPM directory, OpenPKG's RPMs are all built under the %{l_prefix}/RPM/{PKG,SRC,TMP} directories. The RPM database is under the %{l_prefix}/RPM/DB directory instead of someplace under /var/lib.
Each package's sources, patches and spec files are in one directory, %{l_prefix}/RPM/SRC/%{name} instead of being split between the SOURCES and SPECS directories as done with standard RPM. I find this much easier to use than having spec files and sources in different directories.
The BUILD directory is replaced by the %{l_prefix}/RPM/TMP directory, and by convention the BUILD_ROOT directory is the same as the build directory with a ``-root'' suffix. This convention makes it easy to look at the installed files using $PWD-root when in the build directory.
A second advantage to using the %{l_prefix}/RPM/TMP directory is that this can be easily symlinked to a directory on a UFS file system when running on Apple's OS\ X OS where the default file system is case insensitive.
The specfile handling has been cleaned up so that macros such as %setup and %patch may be indented from the left margin. This permits indentation of all the major specfile sections for easier reading.
The specfiles can contain options which control the build process making it far easier to build complex programs such as ``apache''.
One of the most important features of the OpenPKG system is the ``openpkg'' script that is used to build and maintain OpenPKG instances. This works in conjunction with the user's ~/.openpkg/build file which contains the location of the SRPMS, and various build options to generate scripts to rebuild and install all packages necessary to one or more packages.
``openpkg build -Ua > /tmp/build.all'' creates a script that will rebuild all packages that are installed on the system, and out of date compared to the archive.
``openpkg build apache > /tmp/build.apache'' creates a script that will build apache and any other packages that apache needs based on the options selected in the ~/.openpkg/build file.
# OpenPKG default parameters for ``openpkg build'' # | -r /e/openpkg/SRC # | -f /e/openpkg/SRC/00INDEX.rdf.bz2 # -f ftp://ftp.celestial.com/mirrors/ftp.openpkg.org/current/00INDEX.rdf # -f ftp://ftp.celestial.com/mirrors/ftp.openpkg.org/release/1.2/00INDEX.rdf #-r ftp://ftp.celestial.com/private/ftp.openpkg.org/current/SRC #-f ftp://ftp.celestial.com/private/ftp.openpkg.org/current/SRC/00INDEX.rdf.bz2 -r ftp://ftp.celestial.com/private/ftp.openpkg.org/release/1.3/SRC -f ftp://ftp.celestial.com/private/ftp.openpkg.org/release/1.3/SRC/00INDEX.rdf.bz2 #-f ftp://ftp.celestial.com/private/ftp.openpkg.org/release/1.3/SRC/00INDEX.rdf -P sudo # -N sudo # the newest version breaks postfix # -E openldap # We're modifying these ourselves # -E postfix # -E myodbc # -E unixodbc -E smail -D smail::with_sendmail=no -D samba::with_docs -D coreutils::with_legacy -D with_cvs_badroot -D gdbm::with_ndbm -D perl::with_shared # openssh options # -D openssh::with_pam -D openssh::with_pcre -D openssh::with_tcp_wrappers -D openssh::with_x11 # This is for vim at least. -D with_x11 -D vim::with_x11=no # Apache -D apache::with_mod_auth_mysql -D apache::with_mod_php_gettext -D with_mod_access_referer=no -D with_mod_auth_ldap -D with_mod_auth_pam=no -D with_mod_dav=no -D apache::with_mod_php_pgsql=yes -D with_mod_fastcgi=no -D with_mod_gzip -D with_mod_layout=no -D with_mod_macro=no -D with_mod_perl -D with_mod_php -D with_mod_php3=no -D with_mod_php3_ftp=no -D with_mod_php3_gd=no -D with_mod_php3_jpeg=no -D with_mod_php3_mysql=no -D with_mod_php3_openssl=no -D with_mod_php3_zlib=no -D with_mod_php_bc -D with_mod_php_bzip2 -D with_mod_php_calendar -D with_mod_php_curl -D with_mod_php_db -D with_mod_php_debug -D with_mod_php_freetype -D with_mod_php_ftp -D with_mod_php_gd=no -D with_mod_php_imap -D with_mod_php_java=no -D with_mod_php_mhash -D with_mod_php_mm -D with_mod_php_mysql -D with_mod_php_oci8=no -D with_mod_php_openldap -D with_mod_php_openssl -D with_mod_php_pcre -D with_mod_php_pdflib -D with_mod_php_transsid -D with_mod_php_xml -D with_mod_php_zlib -D with_mod_relocate=no -D with_mod_roaming=no -D with_mod_ssl -D with_mod_throttle=no # perl dbi -D perl-dbi::with_dbd_mysql -D perl-dbi::with_dbd_pg -D perl-dbi::with_dbd_odbc # perl-xml -D with_libxml -D with_libxslt # glib -D with_threads # postfix -D postfix::with_tls -D postfix::with_ldap -D postfix::with_whoson # postgres -D postgresql::with_cxx=yes -D postgresql::with_perl=yes -D postgresql::with_odbc=yes -D postgresql::with_compat=no |
Building RPMS
RPM works on the principle of building software packages from pristine sources, applying patches as necessary, compiling, and building binary and source RPM files under the control of a single specification file. The spec file controls package building, creation of binary files for installation and source, and anything necessary when the package is installed, updated, or removed. Here is an example of the gcc.spec file used for the OpenPKG build of gcc. It is fairly complex, and has good examples of many of the features of rpm.
## ## gcc.spec -- OpenPKG RPM Specification ## Copyright (c) 2000-2003 The OpenPKG Project <http://www.openpkg.org/> ## Copyright (c) 2000-2003 Ralf S. Engelschall <rse@engelschall.com> ## Copyright (c) 2000-2003 Cable & Wireless <http://www.cw.com/> ## ## Permission to use, copy, modify, and distribute this software for ## any purpose with or without fee is hereby granted, provided that ## the above copyright notice and this permission notice appear in all ## copies. ## ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED ## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF ## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. ## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF ## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ## SUCH DAMAGE. ## # package version %define V_full 3.3 %define V_comp %nil %define V_bounds 1.01 %define V_spp 3 # package information Name: gcc Summary: GNU Compiler Collection URL: http://gcc.gnu.org/ Vendor: Free Software Foundation Packager: The OpenPKG Project Distribution: OpenPKG [CORE] Group: Language License: GPL Version: %{V_full} Release: 1.3.0 # package options %option with_cxx yes %option with_optimize yes %option with_binutils yes %option with_threads yes %option with_bounds no %option with_spp no %option with_gcc no # options sanity check %if "%{with_bounds}" == "yes" && "%{with_spp}" == "yes" RPM ERROR: options with_bounds and with_ssp conflict %endif # list of sources Source0: ftp://gcc.gnu.org/pub/gcc/releases/gcc-%{version}/gcc-%{version}.tar.bz2 Patch0: gcc.patch Patch1: http://web.inter.nl.net/hcc/Haj.Ten.Brugge/bounds-checking-gcc-%{version}-%{V_bounds}.patch.bz2 Patch2: http://www.trl.ibm.com/projects/security/ssp/gcc3_3/protector-%{version}-%{V_spp}.tar.gz # build information Prefix: %{l_prefix} BuildRoot: %{l_buildroot} BuildPreReq: OpenPKG, openpkg >= 1.3.0, make PreReq: OpenPKG, openpkg >= 1.3.0 %if "%{with_binutils}" == "yes" BuildPreReq: binutils >= 2.13 PreReq: binutils >= 2.13 %endif AutoReq: no AutoReqProv: no %if "%{with_gcc}" == "yes" Provides: gcc = %{version}-%{release} %endif %description The GNU Compiler Collection (GCC) provides a standard conforming and highly portable ISO C and ISO C++ compiler. %prep %setup -q -n gcc-%{version} %patch0 -p0 %if "%{with_bounds}" == "yes" %patch1 -p1 %endif %if "%{with_spp}" == "yes" ( cd gcc %{l_gzip} -d -c %{PATCH protector-%{version}-%{V_spp}.tar.gz} | %{l_tar} xf - %{l_patch} -p1 <protector.dif ) || exit $? %endif %{l_shtool} subst -v -s \ -e "s;PREFIX_INCLUDE_DIR;PREFIX_INCLUDE_DIR_DISABLED;g" \ gcc/configure %build # create build sub-directory mkdir obj cd obj # determine ld(1) and as(1) usage l_with_gnu_ld_as="" %if "%{with_binutils}" == "yes" l_with_gnu_ld_as="${l_with_gnu_ld_as} --with-gnu-ld --with-ld=%{l_prefix}/bin/ld" l_with_gnu_ld_as="${l_with_gnu_ld_as} --with-gnu-as --with-as=%{l_prefix}/bin/as" %else case "%{l_target}" in *-linux* | *-freebsd* ) l_with_gnu_ld_as="${l_with_gnu_ld_as} --with-gnu-as --with-gnu-ld" ;; esac %endif # determine threads usage %if "%{with_threads}" == "yes" l_enable_threads="posix" %else l_enable_threads="single" %endif # determine language usage l_enable_languages="c" %if "%{with_cxx}" == "yes" l_enable_languages="${l_enable_languages},c++" %endif # configure the package CC="%{l_cc}" \ CFLAGS="%{l_cflags}" \ ../configure \ --prefix=%{l_prefix} \ --exec-prefix=%{l_prefix} \ --includedir=%{l_prefix}/include/gcc%{V_comp} \ --with-gxx-include-dir=%{l_prefix}/include/g++%{V_comp} \ --with-local-prefix=%{l_prefix}/lib/gcc%{V_comp}-lib \ --enable-languages="${l_enable_languages}" \ --enable-threads="${l_enable_threads}" \ --disable-maintainer-mode \ --disable-shared \ --disable-nls \ ${l_with_gnu_ld_as} # explicitly redirect remaining gcc-lib directories %{l_shtool} subst -v -s \ -e "s;/gcc-lib/;/gcc%{V_comp}-lib/;" \ `find . -name Makefile -type f -print` # determine build flags l_cflags="" l_boot_cflags="" l_libcflags="-g" l_libcxxflags="-g" %if "%{with_binutils}" == "yes" # at least GNU as from GNU binutils supports -pipe always l_boot_cflags="$l_boot_cflags -pipe" l_libcxxflags="$l_libcxxflags -pipe" %endif %if "%{with_optimize}" == "yes" # conservatively optimize the generated program code # (also _tune_ for particular CPUs, but _without_ requiring these CPUs!) l_cflags="$l_cflags -O" l_boot_cflags="$l_boot_cflags -O2 -fomit-frame-pointer -funroll-loops" case "%{l_target}" in *x86-* ) l_boot_cflags="$l_boot_cflags -mcpu=pentium3" ;; *sparc64-* ) l_boot_cflags="$l_boot_cflags -mtune=v9" ;; esac l_libcxxflags="$l_libcxxflags -O2 -fno-implicit-templates" %else # else do no optimizations at all to reduce problems to minimum in advance l_boot_cflags="$l_boot_cflags -O0" l_libcxxflags="$l_libcxxflags -O0" %endif # build the package %{l_make} %{l_mflags} \ MAKE="%{l_make} %{l_mflags}" \ BOOT_CFLAGS="${l_boot_cflags}" \ CFLAGS="${l_cflags}" \ LIBCFLAGS="${l_libcflags}" \ LIBCXXFLAGS="${l_libcxxflags}" \ bootstrap-lean %install rm -rf $RPM_BUILD_ROOT # fetch GNU platform triple triple=`./config.guess` triple=`./config.sub ${triple}` # perform the standard installation procedure ( cd obj %{l_make} %{l_mflags} install DESTDIR=$RPM_BUILD_ROOT ) || exit $? # cleanup installation tree mv $RPM_BUILD_ROOT%{l_prefix}/lib/lib*.a \ $RPM_BUILD_ROOT%{l_prefix}/lib/gcc%{V_comp}-lib/${triple}/%{V_full}/ for multilib in `$RPM_BUILD_ROOT%{l_prefix}/bin/gcc --print-multi-lib`; do subdir=`echo "$multilib" | sed -e 's/;.*$//'` [ ".$subdir" = .. ] && continue mv $RPM_BUILD_ROOT%{l_prefix}/lib/$subdir/lib*.a \ $RPM_BUILD_ROOT%{l_prefix}/lib/gcc%{V_comp}-lib/${triple}/%{V_full}/$subdir/ rm -rf $RPM_BUILD_ROOT%{l_prefix}/lib/$subdir done mv $RPM_BUILD_ROOT%{l_prefix}/${triple}/include/* \ $RPM_BUILD_ROOT%{l_prefix}/lib/gcc%{V_comp}-lib/${triple}/%{V_full}/include/ \ >/dev/null 2>&1 || true # strip installation tree rm -rf $RPM_BUILD_ROOT%{l_prefix}/${triple} rm -rf $RPM_BUILD_ROOT%{l_prefix}/man/man7 >/dev/null 2>&1 || true rm -f $RPM_BUILD_ROOT%{l_prefix}/lib/*.la >/dev/null 2>&1 || true rm -f $RPM_BUILD_ROOT%{l_prefix}/bin/*-gcc* >/dev/null 2>&1 || true %if "%{with_cxx}" == "yes" rm -f $RPM_BUILD_ROOT%{l_prefix}/bin/*-c++ >/dev/null 2>&1 || true rm -f $RPM_BUILD_ROOT%{l_prefix}/bin/*-g++ >/dev/null 2>&1 || true %endif strip $RPM_BUILD_ROOT%{l_prefix}/bin/* >/dev/null 2>&1 || true for prog in cc1 cc1plus collect2 cpp; do strip $RPM_BUILD_ROOT%{l_prefix}/lib/gcc%{V_comp}-lib/${triple}/%{V_full}/${prog} \ >/dev/null 2>&1 || true done # bump up installation tree ln $RPM_BUILD_ROOT%{l_prefix}/bin/gcc \ $RPM_BUILD_ROOT%{l_prefix}/bin/cc ln $RPM_BUILD_ROOT%{l_prefix}/man/man1/gcc.1 \ $RPM_BUILD_ROOT%{l_prefix}/man/man1/cc.1 %if "%{with_cxx}" == "yes" ln $RPM_BUILD_ROOT%{l_prefix}/man/man1/g++.1 \ $RPM_BUILD_ROOT%{l_prefix}/man/man1/c++.1 %endif # resolve filename conflicts %if "%{with_gcc}" != "yes" && "%{V_comp}" != "" ( cd $RPM_BUILD_ROOT%{l_prefix}/bin for file in *; do mv ${file} ${file}%{V_comp} done ) || exit $? ( cd $RPM_BUILD_ROOT%{l_prefix}/info for file in *; do mv ${file} `echo ${file} | sed -e 's;^\([^.]*\)\(\..*\)$;\1%{V_comp}\2;'` done ) || exit $? ( cd $RPM_BUILD_ROOT%{l_prefix}/man/man1 for file in *; do mv ${file} `echo ${file} | sed -e 's;^\([^.]*\)\(\..*\)$;\1%{V_comp}\2;'` done ) || exit $? %endif # determine installation file list %{l_rpmtool} files -v -ofiles -r$RPM_BUILD_ROOT %{l_files_std} %files -f files %clean rm -rf $RPM_BUILD_ROOT |