[CLUE-Cert] build engine for automating building of LFS

Dennis J Perkins djperkins at americanisp.net
Sun Apr 27 22:04:53 MDT 2003


I played around a bit more on how to make a build engine to automate 
building LFS.  I concentrated on resolving dependencies to build the 
packages in the correct order.  This is very preliminary!

The real trick will be making sure the toolchain is built cleanly.  
Comments?

I'm still sticking with shell scripts, but awk might be very useful in 
handling the meta-information files.  I think we could teach people a 
lot about shell scripts doing this.  And I haven't even gotten to dialog 
or cdialog yet.



                Package Format

A package contains two files, a meta-information file (packagename.desc) 
and a shell script (packagename.conf).

meta-information file for bash
------------------------------
PACKAGE bash
VERSION 2.051
NEEDS    ncurses
END

NEEDS is optional.  Multiple dependencies can be listed after NEEDS or 
multiple NEEDS lines can be used.

Additional tags could include URL, DESC, etc.


The shell script is used to provide additional information to the build 
engine for configuring and building a package.  This includes 
configuration and make options, and hooks for providing custom code at 
certain points of the build process.


package shell script for bash
-----------------------------

# bash

confoptions="--enable-static-link --with-curses"


I played with bash's eval function and found that code can be linked to 
the hooks in the build function in the following manner:

link_gcc() { ln -s gcc $LFS/static/bin/cc }

postmake=link_gcc



                Build Engine Layout


The build engine reads lfs.files to determine which packages to compile 
and install.  It also reads the meta-information file for each package 
listed in lfs.files to resolve any dependencies.  The package order in 
lfs.files is not important because the build engine will create the 
proper package order.  It will also try to include any packages 
specified by NEEDS, even if that package is not included in lfs.files.


pkgs/packagename.desc    metainformation about package
pkgs/packagename.conf    bash shell script to build package.  This file can
            contain variables, parameters, and functions.



lfs.files --- list of packages to build
---------------------------------------
bash
binutils
bzip2
diffutils
fileutils
findutils
gawk
sh-utils
gcc
grep
ncurses
gzip
make
patch
sed
texinfo
textutils
util-linux



                Sample Code

#!/bin/bash
#
# Program name: build
#

declare -a build_order

# build has not been tested!!!

build() { # $1=package

    for patch in $patches
    do
        patch $patchoptions ${patchdir}/$patch
    done

    if [ $builddir = "y" ]; then
        bdir=${srcdir}-build
        test -d $bdir && rm -rf $bdir
        mkdir ../$bdir
        cd ../$bdir
    else
        cd $srcdir
    fi

    eval $preconfigure

    if [ -z $bdir ]; then
        ./configure --prefix=$prefix $confoptions
    else
        ../${srcdir}/configure --prefix=$prefix $confoptions
    fi

    eval $premake

    make $makeflags $makeoptions

    if [ $do_checks = "y" ]; then
        make check
    fi

    eval $postmake

    make install $makeinstallflags
}


# check_dep and build_deptree seem to be working properly.

check_dep() { # $1=package

    local found
    local i
    local needs
    local pkg

    # Return error if package not found.
    if [ ! -f pkgs/${1}.desc ]; then
        errmsg="Cannot find ${1}.conf"
        return 1
    fi

    # Read list of dependencies from conf file.
    while read keyword param
    do
        case $keyword in
            NEEDS)
                needs="$needs $param"
                ;;
        esac
    done < pkgs/${1}.desc

    # No dependencies found.
    if [ -z "$needs" ]; then
        return 0
    fi

    for pkg in $needs
    do
        found="n"
        if [ ${#build_order[@]} -gt 0 ]; then
            for i in $( seq 0 $((${#build_order[@]} - 1 )) )
            do
                # Needed package is already in build_order.
                if [ ${build_order[i]} = $pkg ]; then
                    found="y"
                    break
                fi
            done
        fi

        if [ $found = "n" ]; then
            if check_dep $pkg
            then
                i=${#build_order[@]}
                build_order[$i]=$pkg
                i=$((i + 1))
            else
                errmsg="$1 needs $pkg."
                return 1
            fi
        fi
    done
    return 0
}


build_deptree() {

    local i

    while read line
    do
        # Skip if package is commented out.
            if echo $line | grep '^#' 2>&1 > /dev/null
        then
            continue
        fi

        if check_dep $line
        then
            build_order[$i]=$line
            i=$((i + 1))
        else
            echo $errmsg
            exit 1
        fi

    done < lfs.files

    # For loop is used to verify that build order is correct.
    # Remove when done testing.
    for i in $( seq 0 $((${#build_order[@]} - 1 )) )
    do
        echo ${i}: ${build_order[i]}
    done
}






More information about the clue-cert mailing list