Wolvix Forums
March 21, 2010, 11:29:59 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: The Wolvix Wiki needs your help!!
 
   Home   Help Search Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: How to build packages for Wolvix (Slackware)  (Read 2379 times)
Wolven
Administrator
Werewolf
*****
Posts: 1447



View Profile WWW
« on: August 29, 2008, 06:10:54 AM »

NOTE! THIS GUIDE IS WORK IN PROGRESS.

How to build packages for Wolvix (Slackware) Version: 0.1

Introduction:

This guide assumes you have basic knowledge about Linux, such as using the command line; that you are somewhat familiar with the Linux filesystem hierarchy; that you know what a tarball is; that you know what a dependency is; and that you know how to 'su' to root . It also assumes that you have basic knowledge about Slackware package management.

Other sources of information relevant to this topic are:
http://www.linuxpackages.net/howto.php?page=package&title=Package+Howto
http://www.linuxpackages.net/howto.php?page=perfect-package&title=Perfect+Package
http://slackwiki.org/Building_A_Package
http://slackwiki.org/Writing_A_SlackBuild_Script

I'll try to cover things in detail here, so if you're familiar with the basics of compiling from source you might want to skip parts of this guide.

If you're new to compiling and package building it might be best to read through the guide before doing any of the steps.

Naming rules for packages:

Let's start off with examine the naming of a Slackware package. This is important as there are strict rules on how to name packages. Here's a typical example: foobar-1.0.2-i486-1.tgz. The first word (foobar) before the dash ("-") is the name of the package, the numbers after the dash (1.0.2) is the version. After the version is the arch that the package was compiled for, in this case it's 'i486' which is the standard arch for Slackware, but this can also be 'i686', or even 'noarch'. After the arch comes the build number which indicates how many times the package of the same version has been compiled and released. In our example it's the first build (1).

On Wolvix packages you'll notice that the build number is accompanied with a 'wlv' tag. (foobar-1.0.2-i486-1wlv.tgz) The tag indicates who built the package. For example if your name is Joe, you might use the tag 'joe' on the package like this: foobar-1.0.2-i486-1joe.tgz, or if your nick name is Fox you might use the tag 'fox' like this: foobar-1.0.2-i486-1fox.tgz. The last part of the package (tgz) is the file extension. tgz is just a short name for tar.gz. Packages use the tgz extension to indicate that it is in fact a package and not a tar.gz archive. (More on this later.)

As you can see a Slackware package will and should look like this: name-version-arch-build.extension. Note that all the different strings are separated by a dash ("-") It is not allowed to use dashes in the version string. It is however allowed to use dashes in the name. Example: foo-bar-1.0.2-i486-1.tgz. This is allowed, but this: foobar-1.0.2-1-i486-1.tgz is not allowed. Sometimes you'll encounter source archives that use dashes and/or words like 'beta' or 'rc' in the version string. If this is the case then use an underscore ("_") instead of a dash. The use of words in the version string is allowed, example: foobar-1.0.4beta1-i486-1.tgzfoobar-1.0.2_beta1-i486-1.tgz or foobar-1.0.2_1-i486-1.tgz. All of those examples are allowed. Also note that it's customary to only use lowercase letters for the package name, but it's not a strict rule. (We'll look closer at the insides of a package later in this guide)

Compiling from source code:

Now that we know how a package should be named, let's move on to compiling source code. Compiling a program or library from source can be pretty simple if the source has few or no dependencies. It can also be frustratingly difficult to compile some source code if the application in question has many and obscure dependencies. And if the dependencies has it's own dependencies you're in for a bumpy ride... It's also worth mentioning that not all sources are the same, some sources are coded in C/C++ while others are coded in Perl or Python and the compile process differs for each language. But don't be discouraged by this, we'll start off easy.

A note for Wolvix 1.1.0:
In order to save space Wolvix 1.1.0 does not come with a "build environment" (compiler, etc) and all headers has been stripped out of the various packages. So in order to compile on Wolvix 1.1.0 you need to install a few packages first:


Code:
slapt-get --install glibc glibc-i18n kernel-headers
slapt-get --install meta-development hunter-headers

Alright. Let's get down to business. We'll start by compiling the sources for a program called Geany. The Geany sources comes in two different archive types, tar.gz and tar.bz2. it doesn't matter which you choose, the difference is that tar.bz2 archives has a higher compression rate than tar.gz. I'll go with the tar.gz archive in this example. Before we download the sources, let's create a nice set of directories to work in. In my home I'll create a work directory and inside it three sub directories: source, packages and temp. The 'source' dir will be used to hold the source archives and we'll also use it to compile in. The other two sub directories will be used a bit later in this guide.

Code:
mkdir -p work/{source,packages,temp}

Now download the source archive for Geany from Sourceforge . At the time of writing this the latest version for Geany is 0.14, so I'll download the geany-0.14.tar.gz archive to my work/source/ directory.

Launch a terminal inside the work/source/ directory and extract the source archive with the command:

Code:
tar -zxvf geany-0.14.tar.gz

Once the files are extracted you should have a geany-0.14 directory inside work/source/

Change into the geany-0.14 dir in the terminal with:

Code:
cd geany-0.14/

Once inside work/source/geany-0.14/ you can use the 'ls' command to list all the files, or use the file manager browse the directory to have a look at the content.

Inside the geany-0.14/ directory you'll see that there's a file called 'configure', this is great because this means Geany is most likely coded in C/C++ and that it follows the "standard" for sources, which makes it easier for us to compile and later on build a package for Geany. (Some C/C++ sources does not contain a 'configure' file, they only come with a pre generated 'Makefile')  One can argue that it's just as easy, or even easier to compile Perl or Python sources, this might be true, but I personally prefer to compile and build packages from C code.

As I promised we'll start off easy, so we'll just concentrate on compiling the source for now, without any tweaking, so in your terminal do the following:

Code:
./configure

After the configure step you're presented with a nice summary, like this:

Quote
Install Geany in                   : /usr/local
Using GTK version                  : 2.12.9
Build with GTK printing support    : yes
Build with plugin support          : yes
Use virtual terminal support       : yes
Use (UNIX domain) socket support   : yes

Configuration is done OK.


After the configure step is done we will start the compile process, which might take a while depending on your hardware and how much source there is to compile. To start compiling use the command:

Code:
make

Hopefully the compile process went fine. I did this on a custom Slackware 12.1 install (Which will be Wolvix 2.0.0) Once the process is done you'll see something like this as the two last lines:

Quote
make[2]: Leaving directory `/home/wolven/work/source/geany-0.14'
make[1]: Leaving directory `/home/wolven/work/source/geany-0.14'


And you'll be back in the normal prompt.

Now that the source has been compiled we can install the program to our system. This needs to be done as the root user, so 'su' to root and use this command to install the program:

Code:
make install

Once the install process is finished you'll once again see:

Quote
make[2]: Leaving directory `/home/wolven/work/source/geany-0.14'
make[1]: Leaving directory `/home/wolven/work/source/geany-0.14'


As the two last lines before you're returned to the prompt.

If all went well you should now have a Geany entry with a nice icon in the program menu under 'Development'

To remove the Geany install from your system use the command:

Code:
make uninstall

This also needs to be done as root.

OK. That was rather easy don't you think? Installing software like that works just fine, but it's not as practical as installing, upgrading or removing packages. Plus it's near impossible to distribute a compiled program like this.

Next I'll show you how to make a package from the compiled source, but first we need to examine how a Slackware package looks inside.

Anatomy of a package:

If you look inside a Slackware package you'll see the following directory structure and files:
Quote

   ./
   ./install
   ./install/doinst.sh
   ./install/slack-desc
   ./etc
   ./usr
   ./usr/bin
   ./usr/doc
   ./usr/lib
   ./usr/share
   ./var


Not all package have the ./etc or the ./var directory, but most packages will have the ./install and ./usr directories. All packages should also contain a ./install/slack-desc file and most of them will also have a ./install/doinst.sh

The slack-desc file:

First let's have a look at the slack-desc file, as this is a very important file. It contains the description for the package, if you've ever installed a Slackware package you've probably noticed the output in the terminal looking something like this when you installed it:

Quote
foobar: foobar (A superb foobar program)
foobar:
foobar: Foobar is program for bla bla bla bla bla bla
foobar: bla bla bla bla bla bla bla bla bla bla bla
foobar: bla bla bla bla bla bla bla bla bla bla bla
foobar: bla bla bla bla bla bla bla bla bla bla bla
foobar:
foobar: bla bla bla bla bla bla bla bla bla bla bla
foobar: bla bla bla bla bla bla bla bla bla bla bla
foobar:
foobar: http://foobar.example.com


Here's a nice example slack-desc taken from: http://slackwiki.org/Slack-desc

Quote
# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|' on
# the right side marks the last column you can put a character in.  You must make
# exactly 11 lines for the formatting to be correct.  It's also customary to
# leave one space after the ':'.

       |-----handy-ruler------------------------------------------------------|
appname: Summary of application name and function (one line only)
appname:      <this line is generally left blank>
appname: Description of application  -  this description should be fairly
appname: in-depth; in other words, make it clear what the package does (and
appname: maybe include relevant links and/or instructions if there's room),
appname: but don't get too verbose. 
appname: This file can have a maximum of eleven (11) lines of text preceded by
appname: the "appname: " designation. 
appname:
appname: It's a good idea to include a link to the application's homepage too.
appname:


The "appname" string must *exactly* match the application name portion of the Slackware package (for example, a package titled "gaim-1.5-i486-1.tgz" must have a slack-desc file with the <appname> string of "gaim: " rather than "Gaim: " or "GAIM: " or something else.

The "handy ruler" is meant to stop you at 79 characters, because the standard console is 80x25 and if you go beyond this the words will wrap.

You can find a nice tool for creating slack-desc files here: http://www.linuxpackages.net/slackcreator.php

The doinst.sh file:

The doinst.sh file contains commands that will run on package install, some of the commands are generated automatically when you create a package, such as scripts for re creating symbolic links. You can also place your own custom commands in the doinst.sh, but I won't cover that now. For more details about doinst.sh look here: http://slackwiki.org/Doinst.sh

Configuring the source:

You might have noticed that when we compiled and installed Geany in the example above it placed the files in the /usr/local/ directory. Example the 'geany' binary was placed in /usr/local/bin/.  The Slackware standard is to place files in /usr/somedir and not in /usr/local/somedir. For personal packages you can go with /usr/local, but if you plan to distribute the package(s) you must use the /usr directory, which is the Filesystem Hierarchy Standard.

By default most sources will use the /usr/local directory, so when we configure the sources before compiling we need to tell it that we want to use the /usr directory. This is done with the --prefix=DIR option. So let's go back to the Geany example and do a new ./configure, but this time with the --prefix=DIR option:

Code:
./configure --prefix=/usr

The above command will tell the source that we want to install the files in /usr instead of /usr/local. There are a few other options that we'll also use to make sure other files end up in the right directories, so let's do it like this: (Note! It's also customary on Slackware to place documents in /usr/doc/name-version/ instead of the default /usr/share/doc/name/ directory, but this is easier to control in a build script, so we'll get back to that later.)

Code:
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --mandir=/usr/man

In most cases these are all the configure options you'll need to use, but in some cases you'd want to control other options. What those are depends on the source, but you can get the details with the command:

Code:
./configure --help

This should display all the configure options for the source in question.

Before you continue with the new configure step uninstall Geany with the 'make uninstall' command first, if you haven't already done so:

Code:
make uninstall

Right, let's prepare Geany for package building, so configure it with the options mentioned above:

Code:
./configure --prefix=/usr --sysconfdir=/etc --localstatedir=/var --mandir=/usr/man

Now compile the source again:

Code:
make

Installing the source to temporary directory:

Since we want to build a package we will not install Geany to our root file system ("/") as we did above. Instead we will specify a temporary directory which we will install it to, so we can easily make a package for it. This is done with the 'DESTDIR=/path/to/dir' option. We'll use the 'work/temp/' directory which we created earlier for this. Note that you need to specify the full path to the directory. In my case this is '/home/wolven/work/temp' Also note that this has to be done as the root user.

Code:
make install DESTDIR=/home/wolven/work/temp

If you take a look in your work/temp/ directory now you'll see that it's now populated with a usr/ directory containing some sub directories with files in them. Here's a quick overview of the directories:

Quote
   ./usr/bin
   ./usr/include
   ./usr/lib
   ./usr/man
   ./usr/share


Creating the slack-desc:

We're soon ready to build a package for Geany, but first we need to create a slack-desc file for it, so in the work/temp/ directory create a new dir called install.

In the terminal you should now be in the work/source/geany-0.14/ directory, so let's move to the work/temp/ dir like this:

Code:
cd ../../temp

Then create the install directory:

Code:
mkdir install

You should now have an install/ and a usr/ directory inside work/temp/. Next let's create the slack-desc file. There are a number of ways to do this, but I will do it with a combination of using nano and the slack-desc tool at LinuxPackages.net.

Code:
nano install/slack-desc

My finished slack-desc for Geany looks like this:

Quote
# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description.  Line
# up the first '|' above the ':' following the base package name, and the '|' on
# the right side marks the last column you can put a character in.  You must make
# exactly 11 lines for the formatting to be correct.  It's also customary to
# leave one space after the ':'.

     |-----handy-ruler------------------------------------------------------|
geany: geany (A small and lightweight IDE)
geany:
geany: Geany is a small and lightweight integrated development environment.
geany: It was developed to provide a small and fast IDE, which has only a
geany: few dependencies from other packages.
geany:
geany: http://geany.uvena.de/
geany:
geany:
geany:
geany: Package Created By: Wolven


To make sure the description text is not too long so it will wrap, you can view the slack-desc file in the terminal for control like this:

Code:
cat install/slack-desc

Creating the package:

Now we are finally ready to build the package, (Huzza!) so let's get on with it. Make sure your in the work/temp/ directory with the terminal. And note that you need to do the following step as root:

Code:
makepkg geany-0.14-i486-1tag.tgz

Replace the 'tag' with your tag. In my case it would be 'wlv' so the command will look like this:

Code:
makepkg geany-0.14-i486-1wlv.tgz

You'll be asked the following question:

Quote
Would you like to reset all directory permissions to 755 (drwxr-xr-x) and
directory ownerships to root.root ([y]es, [n]o)?


Answer yes to this. (Note that this might break permissions on some packages, but in this case it's safe to do this.)

If the install had contained symbolic links you'd also be asked if you'd wanted to remove the links and create a doinst.sh file to re create them at install time. If that had been the case you should have answered yes.

Congratulations!! You've just created your first Slackware package. You should now copy it to the work/packages/ directory for safe keeping. After that you can install it with the 'installpkg' command (as root).

Code:
cd ../

installpkg packages/geany-0.14-i486-1tag.tgz

NOTE! If you want to compile and install a new program to work/temp/ in order to make a package for it, you need clean out the directory first. Also note that if you're going to re create the package from the install in work/temp/ you need to remove the old package from the work/temp/ directory first. If you don't do this the old package will end up inside the new package.
« Last Edit: August 31, 2008, 10:53:00 AM by Wolven » Logged

I can only show you the hammer; I can't keep you from pounding in nails with your forehead!

"Getting open source developers to agree on anything is like herding cats." --Caitlyn Martin
Wolven
Administrator
Werewolf
*****
Posts: 1447



View Profile WWW
« Reply #1 on: August 29, 2008, 06:11:59 AM »

Using build scripts:

Next we'll look at automating the package creation process by using a build script. (SlackBuild) Using build scripts is a far better way of create packages compared to doing it manually like described above, as they save both work and time, plus they are reusable if you want to update the package. It is however important to know the basics of package building before you start using build scripts so you'll understand what's going on.

There are different ways to write a build script, some can be pretty simple and straight forwards while others are more complex, but they basically all do the same thing: Extract source, configure and compile, install program in a temp directory and create a package. Creating build scripts from scratch requires a fair deal of knowledge about bash scripting, but you don't write a new script from scratch for each package you want to build, you use a template script which you edit. In many cases all you need to do is to edit the name and version in the script and off you go. Sounds easy right? Well it can be, but like with most things in life it depends on the situation. Let's have a look at a simple template:

Code:
#!/bin/sh

# Slackware build script for <appname>

# Written by (your name) (your contact information)

PRGNAM=appname # Replace with name of program
VERSION=${VERSION:-0.0.0} # Replace with version of program
ARCHIVE=tar.gz # Replace with the type of archive
ARCH=${ARCH:-i486} # Compile arch
BUILD=${BUILD:-1} # Build version
TAG=${TAG:-tag} # Replace with your tag

CWD=$(pwd)
TMP=${TMP:-/tmp/build} # The temp dir for compiling
PKG=$TMP/package-$PRGNAM # The temp dir for package building
OUTPUT=${CWD} # Package output location

# This decides what files goes in the documents directory.
# Edit this according to what's in the source tarball.
DOCS="AUTHORS ChangeLog COPYING INSTALL NEWS README TODO"

if [ "$ARCH" = "i486" ]; then
  SLKCFLAGS="-O2 -march=i486 -mtune=i686"
elif [ "$ARCH" = "i686" ]; then
  SLKCFLAGS="-O2 -march=i686 -mtune=i686"
elif [ "$ARCH" = "x86_64" ]; then
  SLKCFLAGS="-O2 -fPIC"
fi

# Exit on most errors
set -e

rm -rf $PKG
mkdir -p $TMP $PKG $OUTPUT
cd $TMP
rm -rf $PRGNAM-$VERSION

# Unpack the source tarball
tar xvf $CWD/$PRGNAM-$VERSION.$ARCHIVE

cd $PRGNAM-$VERSION
chown -R root:root .
find . \
 \( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
 -exec chmod 755 {} \; -o \
 \( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
 -exec chmod 644 {} \;

# Your application will probably need different configure flags;
# these are provided as an example only.
# Be sure to build only shared libraries unless there's some need for
# static.
CFLAGS="$SLKCFLAGS" \
CXXFLAGS="$SLKCFLAGS" \
./configure \
  --prefix=/usr \
  --sysconfdir=/etc \
  --mandir=/usr/man \
  --docdir=/usr/doc/$PRGNAM-$VERSION \
  --localstatedir=/var \
  --enable-shared=yes \
  --enable-static=no

# Compile the application and install it into the $PKG directory
make
make install DESTDIR=$PKG

# Strip binaries and libraries
( cd $PKG
  find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
  find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
)

# Compress man pages
if [ -d $PKG/usr/man ]; then
  gzip -9 $PKG/usr/man/man?/*
fi

# Compress info pages if they exist (and remove the dir file)
if [ -d $PKG/usr/info ]; then
  gzip -9 $PKG/usr/info/*.info
  rm -f $PKG/usr/info/dir
fi

# Copy program documentation into the package
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a $DOCS $PKG/usr/doc/$PRGNAM-$VERSION

# Include the SlackBuild script in the documentation directory
cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild

# Copy the slack-desc (and a custom doinst.sh if necessary) into ./install
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

# Make the package and move it to $OUTPUT
cd $PKG
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz


Now let's use this template to build a package for Geany. Copy the code for the template to a text editor and edit the relevant information. In this case all you should need to edit is PRGNAM, VERSION and TAG. Like this:
Code:
PRGNAM=geany # Replace with name of program
VERSION=${VERSION:-0.14} # Replace with version of program
ARCHIVE=tar.gz # Replace with the type of archive
ARCH=${ARCH:-i486} # Compile arch
BUILD=${BUILD:-1} # Build version
TAG=${TAG:-wlv} # Replace with your tag

Save this as geany.SlackBuild in your work/source/ directory next to the source tarball for Geany. You also need to place a copy of the slack-desc file you made for Geany in this directory, as it will be copied into the package by the script. So in your work/source/ dir you should now have three files:
Quote
geany-0.14.tar.gz
geany.SlackBuild
slack-desc


Now launch a terminal in the work/source/ dir, 'su' to root and issue the command:
Code:
sh geany.SlackBuild

If all went well you should now have a package for Geany in the work/source/ directory after the script finishes.

As you can see, using a build script is very practical and time saving compared to build packages by hand. If a new version of Geany was released now, all you had to to was download the new source, edit the version number in the script and run the script again. Unfortunately not all programs are as easy to build as Geany, some might just require a little more tweaking in the script while others might need a lot of tweaking. You should however have a basic understanding of how to build Slackware packages now and you should do some research on your own.

A good way to learn is too look at other scripts and there are quite a few website that have scripts. The most obvious palace is perhaps one of the Slackware package mirrors. Patrick Volkerding (The author of Slackware) use scripts for building all of the packages in Slackware and you'll find his scripts together with the sources. I also include the scripts I use with the Wolvix sources. If you'd like a in depth tutorial about writing scripts have a look at this guide in the SlackWiki

Other good places to find scripts are:

SlackBuilds.org
Eric Hameleers, aka: Alien BOB's website. Eric even has a SlackBuild Generator
Slacky.eu
« Last Edit: August 30, 2008, 11:06:48 AM by Wolven » Logged

I can only show you the hammer; I can't keep you from pounding in nails with your forehead!

"Getting open source developers to agree on anything is like herding cats." --Caitlyn Martin
Wolven
Administrator
Werewolf
*****
Posts: 1447



View Profile WWW
« Reply #2 on: August 29, 2008, 06:12:24 AM »

template.WolvixBuild:

Here's a template.WolvixBuild I'm currently working on. It's more complex than the template above, but it should not be too hard to understand.
Code:
#!/bin/sh
# Wolvix Build script for: <appname>
#
# Copyright 2008 Wolven (http://wolvix.org)
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS 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 AUTHOR 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.
#
# ---NOTES!----------------------------------------------------------------- #
# I do all my package building using the following directory structure:
#
# ./somedir <- Top level work directory.
# +-- source/category/appname <- Source, slack-desc and appname.WolvixBuild.
# +-- packages/category <- Finished packages and description texts.
# +-- tmp/build <- Temp compile and build directory.
#
# Wolvix package categories:
#
# desktop, development, drivers, games, graphics, kernel, kids, libraries,
# multimedia, network, office, scinetific, system, utilities, xfce, xfce-extra
# -------------------------------------------------------------------------- #

# ======================================================================================================================================= #

SRCNAM= # Set this if the source name conflicts with the Slackware package standard.
SRCVER= # Set this if the source version conflicts with the Slackware package standard.
ARCHIVE=tar.bz2 # Define what archive type the source is. (tar.bz2 | tar.gz | tgz | zip)

PRGNAM=appname # Replace with name of the program.
VERSION=0.0.0 # Replace with version of the program.
ARCH=${ARCH:-i486} # Choose compile architecture: noarch, i486, i686, x86_64
BUILD=${BUILD:-1} # Package build number.
TAG=${TAG:-wlv} # Replace 'wlv' with your tag. Usually three to four letters.
CAT=category # Replace with relevant package category.

CWD=`pwd` # Leave this like it is.
TMP=$CWD/../../../tmp/build # Temp build dir. The "traditional" option is; TMP=${TMP:-/tmp/build}
PKG=$TMP/package-$PRGNAM # Source install and package build dir. Leave this like it is.
OUTPUT=$CWD/../../../packages/$CAT # Package output dir. The "traditional" option is; OUTPUT=${OUTPUT:-/tmp}

STRIPBINARIES=true # Strip the compiled binaries? (true | false) In most cases leave this as true.
REQUIREDBUILDER=true # Use the requiredbuilder to generate slack-required? (true | false)
DESCRIPTIONTEXT=true # Generate a package.txt description file from slack-desc? (true | false)
MD5SUM=false # Generate a md5sum for the package? (true | false)
KEEPLOGS=false # Keep the generated build logs? (true | false)

PATCHNAME=file-name.patch # File name for the patch. Do NOT add the .gz extention. Use 'PATCHGZIPPED=true' instead.
PATCHGZIPPED=true # Is the patch gzipped? (true | false)
PATCHLEVEL=-p1 # Depends on the patch. (-p0 | -p1)

COMPILEOPTION=default # What type of source is it? (default | perl | python | custom)
JOBS=-j3 # Set this to match your CPU. (-j2 = single core | -j3 = dual core | -j5 = quad core )
 
# Your might need different or additional configure flags. (This is only used by the 'default' compile option.)
CONFIGURE=" \
./configure \
  --prefix=/usr \
  --sysconfdir=/etc \
  --mandir=/usr/man \
  --docdir=/usr/doc/$PRGNAM-$VERSION \
  --localstatedir=/var \
  --enable-shared=yes \
  --enable-static=no
"
# Edit this according to what docs are in the source tarball.
DOCS="AUTHORS ChangeLog COPYING INSTALL NEWS README TODO"

# Download URL for the source tarball.(Don't add the file name here, just the URL)
SOURCEURL="http://surfnet.dl.sourceforge.net/sourceforge/${PRGNAM}"

# ======================================================================================================================================= #

# Check if the custom source name and version is set.
if [ "$SRCNAM" = "" ]; then
  SRCNAM="$PRGNAM"
fi
if [ "$SRCVER" = "" ]; then
  SRCVER="$VERSION"
fi

# Exit on most errors.
set -e
trap 'echo "$0 FAILED at line $LINENO!" | tee $CDW/error-${PRGNAM}.log' ERR

# Source file availability:
SOURCE="${SRCNAM}-${SRCVER}.${ARCHIVE}"
SRCURL="${SOURCEURL}/${SRCNAM}-${SRCVER}.${ARCHIVE}"

# Check if source is available, if not try to download it.
  if ! [ -f ${CWD}/${SOURCE} ]; then
    if ! [ "${SRCURL}" = "" ]; then
      echo "Source '${SOURCE}' not available yet... will download now:"
      wget -nv -O "${CWD}/${SOURCE}" "${SRCURL}"
      if [ $? -ne 0 ]; then
        echo "Downloading '${SOURCE}' failed... aborting the build."
        mv -f "${CWD}/${SOURCE}" "${CWD}/${SOURCE}".FAIL
        exit 1
      fi
    else
      echo "File '${SOURCE}' not available... aborting the build."
      exit 1
    fi
  fi

if [ "$1" == "--download" ]; then
  echo "Download complete."
  exit 0
fi

# Create the required directories if they don't exist.
rm -rf $PKG
if [ ! -d $TMP ]; then
 mkdir -p $TMP
fi
if [ ! -d $PKG ]; then
 mkdir -p $PKG
fi
if [ ! -d $OUTPUT ]; then
 mkdir -p $OUTPUT
fi

# Change to temp directory and remove old source files.
cd $TMP
rm -rf $SRCNAM-$SRCVER

# Extract the tarball/zip archive.
echo "++"
echo "|| Extracting the source tarball(s) for $PRGNAM..."
echo "++"
  if `file $CWD/${SOURCE} | grep -q ": bzip2"`; then
    tar -xjvf $CWD/${SOURCE}
  elif `file $CWD/${SOURCE} | grep -qi ": zip"`; then
    unzip $CWD/${SOURCE}
  else
    tar -xzvf $CWD/${SOURCE}
  fi

cd $SRCNAM-$SRCVER
chown -R root:root .
chmod -R u+w,go+r-w,a-s .

# Apply patch if exists.
if [ -f $CWD/$PATCHNAME.gz ] && [ "$PATCHGZIPPED" = "true" ]; then
  zcat $CWD/$PATCHNAME.gz | patch $PATCHLEVEL --verbose || exit 1
elif  [ -f $CWD/$PATCHNAME ] && [ "$PATCHGZIPPED" != "true" ]; then
  cat $CWD/$PATCHNAME | patch $PATCHLEVEL --verbose || exit 1
fi

echo "++"
echo "|| Compiling source for $PRGNAM-$VERSION"
echo "++"

# Set the compiler arch.
if [ "$ARCH" = "i486" ]; then
  SLKCFLAGS="-O2 -march=i486 -mtune=i686"
elif [ "$ARCH" = "i686" ]; then
  SLKCFLAGS="-O2 -march=i686 -mtune=i686"
elif [ "$ARCH" = "x86_64" ]; then
  SLKCFLAGS="-O2 -fPIC"
fi

# Configure and compile the source.

# ---START--------------------------------------------------------DEFAULT--- #
if [ "$COMPILEOPTION" = "default" ];then
  CFLAGS="$SLKCFLAGS" \
  CXXFLAGS="$SLKCFLAGS" \
  $CONFIGURE 2>&1 | tee $CWD/configure-${PRGNAM}.log
  make $JOBS 2>&1 | tee $CWD/make-${PRGNAM}.log
  make install DESTDIR=$PKG 2>&1 | tee $CWD/install-${PRGNAM}.log
# ---END----------------------------------------------------------DEFAULT--- #
#                                                                            #
# ---START-----------------------------------------------------------PERL--- #
elif [ "$COMPILEOPTION" = "perl" ];then
  CFLAGS="$SLKCFLAGS" perl Makefile.PL
  make 2>&1 | tee $CWD/make-${PRGNAM}.log
  make test 2>&1 | tee $CWD/test-${PRGNAM}.log
  make install DESTDIR=$PKG 2>&1 | tee $CWD/install-${PRGNAM}.log
# Remove perllocal.pod and other special files that don't need to be installed.
( cd $PKG
  find . -name perllocal.pod -o -name ".packlist" -o -name "*.bs" | xargs rm -f
)
# ---END-------------------------------------------------------------PERL--- #
#                                                                            #
# ---START---------------------------------------------------------PYTHON--- #
elif [ "$COMPILEOPTION" = "python" ];then
  python setup.py install --root=$PKG 2>&1 | tee $CWD/install-${PRGNAM}.log
# ---END-----------------------------------------------------------PYTHON--- #
#                                                                            #
# ---START---------------------------------------------------------CUSTOM--- #
elif [ "$COMPILEOPTION" = "custom" ];then
# Replace all the lines below here.
  echo "++"
  echo "|| You've selected the 'custom' compile option, but it's not configured!"
  echo "++"
  exit 1
# Replace all the lines above here.
fi
# ---END-----------------------------------------------------------CUSTOM--- #

# ---START--------------------------------------OPTIONAL-PACKAGE-TWEAKING--- #
# Add icon.
##mkdir -p $PKG/usr/share/pixmaps
##cp $CWD/$PRGNAM.png $PKG/usr/share/pixmaps

# Make .desktop file.
##mkdir -p $PKG/usr/share/applications
##cat << EOF > $PKG/usr/share/applications/$PRGNAM.desktop
##[Desktop Entry]
##Encoding=UTF-8
##Name=
##GenericName=
##Comment=
##Exec=$PRGNAM
##Icon=/usr/share/pixmaps/$PRGNAM.png
##Type=Application
##Categories=Application;
##EOF

# Fix text entries in pre generated .desktop file.
##sed -i "s|OLD_ENTRY_GOES_HERE|NEW_ENTRY_GOES_HERE|g" $PKG/usr/share/applications/$PRGNAM.desktop
# ---END----------------------------------------OPTIONAL-PACKAGE-TWEAKING--- #

# Strip binaries and libraries. (Recommended)
if [ "$STRIPBINARIES" = "true" ]; then
  ( cd $PKG
    find . | xargs file | grep "executable" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
    find . | xargs file | grep "shared object" | grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null
  )
fi

# Compress man pages. For KDE programs, you'll need to do this for /opt/kde/share/man instead.
if [ -d $PKG/usr/man ]; then
  gzip -9 $PKG/usr/man/man?/*
fi

# Compress info pages if they exist (and remove the dir file)
if [ -d $PKG/usr/info ]; then
  gzip -9 $PKG/usr/info/*.info
  rm -f $PKG/usr/info/dir
fi

# Copy program documentation into the package. See 'DOCS=' at top.
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a $DOCS $PKG/usr/doc/$PRGNAM-$VERSION

# Include the WolvixBuild in the documentation directory.
cat $CWD/$PRGNAM.WolvixBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.WolvixBuild

# Copy the slack-desc to $PKG/install.
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc

# Copy custom doinst.sh to $PKG/install if exists.
if [ -f $CWD/doinst.sh ]; then
  cat $CWD/doinst.sh >> $PKG/install/doinst.sh
fi

# Copy custom slack-required to $PKG/install if exists.
if [ -f $CWD/slack-required ] && [ "$REQUIREDBUILDER" != "true" ]; then
  cat $CWD/slack-required > $PKG/install/slack-required
fi

# Generate description file from slack-desc and place it together with the package. (Optional)
if [ "$DESCRIPTIONTEXT" = "true" ]; then
cat $PKG/install/slack-desc | grep "^${PRGNAM}" > $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.txt
fi

# Generate slack-required file for the package and place a copy in the CWD. (Optional)
if [ -x /usr/bin/requiredbuilder ] && [ "$REQUIREDBUILDER" = "true" ]; then
  echo "++"
  echo "|| Generating slack-required..."
  echo "++"
# Exclude and/or add packages to the slack-required. Use comma (",") as separator,
##  EXCLUDE="packagename" \
##  ADD="packagename >= version-arch-tag" \
  requiredbuilder -v -y -s $CWD $PKG
fi

# Build the package
echo "++"
echo "|| Building package $PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz"
echo "++"
cd $PKG
/sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz \
2>&1 | tee $CWD/makepkg-${PRGNAM}.log

# Generate package md5sum. (Optional)
if [ "$MD5SUM" = "true" ];then
  echo "++"
  echo "|| Generating package md5sum..."
  echo "++"
  ( cd $OUTPUT
    md5sum $PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz > $PRGNAM-$VERSION-$ARCH-$BUILD$TAG.tgz.md5
  )
fi

# If $KEEPLOGS is true move the log files to $CWD/logs, if not delete them.
if [ "$KEEPLOGS" = "true" ]; then
  mkdir -p $CWD/logs && mv $CWD/*.log $CWD/logs
  echo "++"
  echo "|| Build logs stored."
  echo "++"
elif [ "$KEEPLOGS" != "true" ]; then
  rm $CWD/*.log
  echo "++"
  echo "|| Build logs deleted."
  echo "++"
fi

# Clean up the temp compile and build directory.
if [ "$1" = "--cleanup" ]; then
  rm -rf $TMP/$PRGNAM-$VERSION
  rm -rf $PKG
fi

# END OF FILE

Potential problems:

Like I've said before, some packages are easy to build others can be a pain in the a**. There are several applications I've not managed to build because of more or less obscure problems. If a build fails, it's mostly likely do to missing or out dated dependencies, but not always. Sometimes the source needs to be patched before it will compile successfully. You'll probably also encounter sources that doesn't obey the 'make install DESTDIR=DIR' option, so you need to do a "spam install" to the filesystem and have the script copy the files to the build location. Other sources might not have a 'configure' file, so you need to omit that step in the script.

There's no magic bullet to building packages, like with all things you need to practice and do research to improve your skills.
« Last Edit: September 01, 2008, 05:07:28 PM by Wolven » Logged

I can only show you the hammer; I can't keep you from pounding in nails with your forehead!

"Getting open source developers to agree on anything is like herding cats." --Caitlyn Martin
Wolven
Administrator
Werewolf
*****
Posts: 1447



View Profile WWW
« Reply #3 on: August 29, 2008, 06:44:36 AM »

THIS SPACE IS RESERVED
Logged

I can only show you the hammer; I can't keep you from pounding in nails with your forehead!

"Getting open source developers to agree on anything is like herding cats." --Caitlyn Martin
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!