#!/bin/sh # # Author: Pekka Riikonen # # Copyright (C) 2005 Pekka Riikonen # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote # products derived from this software without specific prior written # permission. # # 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. # ############################################################################### # XXXXXXXXXXXXXXX # # TODO # # --makedist # "pre-dist-hooks" # "post-dist-hooks" # "include" # "exclude" # "option" # default conffile in -i # default distro in -i # # NOTE: inherit inherits only distdefs, undefs, hooks, options, includes # and excludes. It must not inherit others. # # XXXXXXXXXXXXXXX # Scripts have the following variables in their disposal # # distribution distribution name # dist_version distribution version # package the package name of the distribution # Allowed structure for distdefs in non-source files #ifdef SILC_DIST_DEFINE #endif SILC_DIST_DEFINE #ifndef SILC_DIST_DEFINE #endif SILC_DIST_DEFINE #ifdef SILC_DIST_DEFINE #else !SILC_DIST_DEFINE #endif SILC_DIST_DEFINE #ifndef SILC_DIST_DEFINE #else SILC_DIST_DEFINE #endif SILC_DIST_DEFINE # Allowed structure for distdefs in source files #ifdef SILC_DIST_DEFINE #endif /* SILC_DIST_DEFINE */ #ifndef SILC_DIST_DEFINE #endif /* SILC_DIST_DEFINE */ #ifdef SILC_DIST_DEFINE #else /* !SILC_DIST_DEFINE */ #endif /* SILC_DIST_DEFINE */ #ifndef SILC_DIST_DEFINE #else /* SILC_DIST_DEFINE */ #endif /* SILC_DIST_DEFINE */ ############################################################################### # Global variables # Distribution subdirectory distdir="distdir" # This current distribution distribution=default dist_version=0.0 package= # All inherited distributions in this distribution inherits= # All distribution defines for this distribution distdefs= # All distribution undefines for this distribution undistdefs= # All distribution options options= # All includes includes= # All excludes excludes= # All pre, post pre-dist and post-dist hooks pre_hooks= post_hooks= pre_dist_hooks= post_dist_hooks= # Distribution license and license header license= licenseh= # Whether to output ad_debug information debug=false ver="1.0" makedist=false ############################################################################### # Configuration file if test -f "$distdir/autodist.conf"; then . $distdir/autodist.conf fi DP=$DISTPREFIX ############################################################################### # Functions # # Print out debug information if debugging is enabled. To enable debugging # set the global variable "debug" to true value. # # Arguments: ad_debug # ad_debug() { if test x$debug = xtrue; then echo autodist: $1 fi } # # Prints out error message and exits the script. # # Arguments: ad_fatal # ad_fatal() { echo autodist: error: $1 exit 1 } # # Initializes the Autodist environment, creates default distribution # directory, and default distribution. # # Arguments: ad_initialize # ad_initialize() { ad_debug "-->$FUNCNAME()" # Create default distdir if test '!' -f $distdir; then mkdir -p $distdir fi # Create default distribution # XXX ad_debug "<--$FUNCNAME()" } # # Creates the distdefs header file including defined distdefs # # Arguments: ad_create_distdefs_h # ad_create_distdefs_h() { ad_debug "-->$FUNCNAME()" fname=$DISTDEFS rm -f $fname echo "/*" > $fname echo " Automatically generated by Autodist $ver. Do not edit." >> $fname echo >> $fname echo " Generated: `date` by `whoami`" >> $fname echo " Distribution: $distribution" >> $fname echo " License: $license" >> $fname echo "*/" >> $fname echo >> $fname echo "#ifndef _"$DP"_DISTDEFS_H" >> $fname echo "#define _"$DP"_DISTDEFS_H" >> $fname echo >> $fname for i in $distdefs do echo "#define $i 1" >>$fname done echo >> $fname echo "#endif /* _"$DP"_DISTDEFS_H */" >> $fname ad_debug "<--$FUNCNAME()" } # # Creates the main configure script for the distribution. This runs # the aclocal, autoheader and autoconf tools. # # Arguments: ad_make_configure # ad_make_configure() { ad_debug "-->$FUNCNAME()" local run_autoconf=false rm -f configure if test "$ACLOCAL"; then ad_debug "Running aclocal" $ACLOCAL 1>/dev/null 2>/dev/null if test $? != 0; then ad_fatal "aclocal failed" fi fi if test "$AUTOCONF"; then ad_debug "Running autoconf" $AUTOCONF if test $? != 0; then ad_fatal "autoconf failed" fi run_autoconf=true fi if test "$AUTOHEADER"; then ad_debug "Running autoheader" $AUTOHEADER if test $? != 0; then ad_fatal "autoheader failed" fi fi if test "$LIBTOOLIZE"; then ad_debug "Running libtoolize" $LIBTOOLIZE if test $? != 0; then ad_fatal "libtoolize failed" fi fi if test x$run_autoconf = xtrue; then if test '!' -f configure; then ad_fatal "creating configure script failed" fi fi ad_debug "<--$FUNCNAME()" } # # Creates the configure.ac script from the configure.ad fragments in # the source tree. Takes the source configure file as argument which # is used to create the actual configure.ac. # # Arguments: ad_make_configure_ac # ad_make_configure_ac() { ad_debug "-->$FUNCNAME(): $1" if test '!' -f $1; then ad_fatal "The configure file '$1' does not exist" fi rm -f configure.ac configure.ad.cfs cfs=`find . -name configure\*\.ad` for i in $cfs do if test "x$i" = "x$1"; then continue fi ad_debug "including $i" cat $i >> configure.ad.cfs done # Header for configure.ac fname="configure.tmp.ac" echo "# Automatically generated by Autodist $ver. Do not edit." > $fname echo "# To make changes edit the $i file in the source tree." >> $fname echo >> $fname echo "# Source: $i" >> $fname echo "# Generated: `date` by `whoami`" >> $fname echo "# Distribution: $distribution" >> $fname echo "# License: $license" >> $fname echo >> $fname ad_debug "creating configure.ac" if test -f configure.ad.cfs; then sed '/AD_INCLUDE_CONFIGURE/ r configure.ad.cfs' $1 > $fname.tmp sed -e "/AD_INCLUDE_CONFIGURE/s///" $fname.tmp >> $fname rm -f configure.ad.cfs $fname.tmp else cat $1 >> $fname fi # Process AD_INIT sed -e "/AD_INIT/s//AC_INIT($distribution, $dist_version, [], $package)/" $fname > $fname.tmp # Process for distribution ad_process_file $fname.tmp configure.ac rm -f $fname $fname.tmp ad_debug "<--$FUNCNAME(): $1" } # # Creates the Makefile.in files by running the automake tool. # # Arguments: ad_make_makefile_ins # ad_make_makefile_ins() { ad_debug "-->$FUNCNAME()" if test "$AUTOMAKE"; then ad_debug "Running automake" $AUTOMAKE if test $? != 0; then ad_fatal "automake failed" fi fi ad_debug "<--$FUNCNAME()" } # # Creates the Makefile.am files from the Makefile.ad files in the # source tree. This runs the distribution specific processing for the # Makefile.ad files. # # Arguments: ad_make_makefile_ams # ad_make_makefile_ams() { ad_debug "-->$FUNCNAME()" files=`find . -name Makefile\.ad` for i in $files do fname=`echo $i | sed s/\.ad//` # Header for the Makefile.am echo "# Automatically generated by Autodist $ver from Makefile.ad. Do not edit." > $fname.am echo "# To make changes edit the $i file in the source tree." >> $fname.am echo >> $fname.am echo "# Source: $i" >> $fname.am echo "# Generated: `date` by `whoami`" >> $fname.am echo "# Distribution: $distribution" >> $fname.am echo "# License: $license" >> $fname.am echo >> $fname.am # Run the distribution processing for this Makefile.ad ad_debug "Processing $i to be $fname.am" ad_process_file $i $fname.am done ad_debug "<--$FUNCNAME()" } # # Processes all files with .ad suffix, with exception of configure*.ad # and Makefile.ad files, for distribution from the source tree. # # Arguments: ad_process_ads # ad_process_ads() { ad_debug "-->$FUNCNAME()" files=`find . -name \*\.ad \! -name configure\*\.ad \! -name Makefile\.ad` for i in $files do fname=`echo $i | sed s/\.ad//` # Header echo "# Automatically generated by Autodist $ver. Do not edit." > $fname echo "# To make changes edit the $i file in the source tree." >> $fname echo >> $fname echo "# Source: $i" >> $fname echo "# Generated: `date` by `whoami`" >> $fname echo "# Distribution: $distribution" >> $fname echo "# License: $license" >> $fname echo >> $fname # Run the distribution processing for this file ad_debug "Processing $i to be $fname" ad_process_file $i $fname done ad_debug "<--$FUNCNAME()" } # # Processes the entire source tree for distribution. This inspects files # in the source tree, with exception of any file with .ad suffix, and # performs distribution processing for the file. The original file is # replaced with the processed file. This function is used when creating # the distribution for packaging. # # Arguments: ad_process_source_tree # ad_process_source_tree() { ad_debug "-->$FUNCNAME(): $1" ad_debug "<--$FUNCNAME(): $1" } # # Creates distribution of the source tree. All files in the distribution # will be processed and the distribution will be packaged. # ad_makedist() { ad_debug "-->$FUNCNAME()" ad_debug "<--$FUNCNAME()" } # # Parses the distribution. Gets all distribution defines from the # distribution. This also expands all inherited distributions recursively # to get all inherited distribution defines. From inherited distributions # their name and package name is not inherited. # # Arguments: parse_distribution # ad_parse_distribution() { ad_debug "-->$FUNCNAME(): $1" if test '!' -f $distdir/$1; then ad_fatal "Distribution '$1' is not declared" fi # Get inherited local inhs=`cat $distdir/$1 | grep -v "#" \ | grep "inherit " | cut -d' ' -f2 | sort | uniq` # Get distdefs local defs=`cat $distdir/$1 | grep -v "#" \ | grep "define " | cut -d' ' -f2 | sort | uniq` if test "$inhs" = "" && test "$defs" = ""; then ad_fatal "Distribution '$1' does not define anything" fi # Get undefined distdefs local undefs=`cat $distdir/$1 | grep -v "#" \ | grep "undef " | cut -d' ' -f2` # Get options local opts=`cat $distdir/$1 | grep -v "#" \ | grep "option " | cut -d' ' -f2` # Get includes local incs=`cat $distdir/$1 | grep -v "#" \ | grep "include " | cut -d' ' -f2` # Get excludes local excs=`cat $distdir/$1 | grep -v "#" \ | grep "exclude " | cut -d' ' -f2` ad_debug "inherits=$inhs" ad_debug "distdefs=$defs" ad_debug "includes=$incs" ad_debug "excludes=$excs" ad_debug "undistdefs=$undefs" ad_debug "options=$opts" # Expand distdefs from inherited distributions for i in $inhs do if test x$1 = x$i; then ad_fatal "Infinite recursion detected. Fix the '$distdir/$1' \ distribution to not have 'inherit $i' declared." fi if test '!' -f $distdir/$i; then ad_fatal "Distribution '$i' is not declared (inherited from '$1')" fi ad_parse_distribution $i true done # Get license license=`cat $distdir/$1 | grep -v "#" \ | grep "license " | cut -d' ' -f2` licenseh=`cat $distdir/$1 | grep -v "#" \ | grep "license-header " | cut -d' ' -f2` ad_debug "license=$license" ad_debug "licenseh=$licenseh" if test x$2 = xfalse; then # Get distribution name local dname=`cat $distdir/$1 | grep -v "#" | grep "name "` if test "$dname"; then distribution=$dname fi # Get distribution package name (optional) local dpname=`cat $distdir/$1 | grep -v "#" \ | grep "package " | cut -d' ' -f2` if test "$dpname"; then package=$dpname else package=$distribution fi ad_debug "distribution=$distribution" ad_debug "package=$package" fi # Get hooks (optional) local prh=`cat $distdir/$1 | grep -v "#" \ | grep "pre-hook " | cut -d' ' -f2` local poh=`cat $distdir/$1 | grep -v "#" \ | grep "post-hook " | cut -d' ' -f2` local prdh=`cat $distdir/$1 | grep -v "#" \ | grep "pre-dist-hook " | cut -d' ' -f2` local podh=`cat $distdir/$1 | grep -v "#" \ | grep "post-dist-hook " | cut -d' ' -f2` # Return to caller inherits="$inherits $inhs" distdefs="$distdefs $defs" includes="$includes $incs" excludes="$excludes $incs" undistdefs="$undistdefs $undefs" options="$options $opts" pre_hooks="$pre_hooks $prh" post_hooks="$post_hooks $poh" pre_dist_hooks="$pre_dist_hooks $prdh" post_dist_hooks="$post_dist_hooks $podh" ad_debug "<--$FUNCNAME(): $1" } # # Processes parsed distdefs. Removes duplicates, and undefined distdefs # from the distdefs. # # Arguments: ad_process_distdefs # ad_process_distdefs() { ad_debug "-->$FUNCNAME()" # Remove all undefined distribution defines for i in $undistdefs do ad_debug "undefining $i distdef" distdefs=`echo $distdefs | sed s/$i//` done rm -f autodist.tmp.defs autodist.pre.hooks autodist.post.hooks rm -f autodist.pre.dist.hooks autodist.post.dist.hooks # Remove duplicate distdefs for i in $distdefs do echo $i >>autodist.tmp.defs done distdefs=`cat autodist.tmp.defs | sort | uniq` distdefs=`echo $distdefs` rm -f autodist.tmp.defs ad_debug "distdefs=$distdefs" # Remove duplicate pre-hooks for i in $pre_hooks do echo ". $i" >>autodist.tmp.defs done if test -f autodist.tmp.defs; then cat autodist.tmp.defs | sort | uniq > autodist.pre.hooks rm -f autodist.tmp.defs fi # Remove duplicate post-hooks for i in $post_hooks do echo ". $i" >>autodist.tmp.defs done if test -f autodist.tmp.defs; then cat autodist.tmp.defs | sort | uniq > autodist.post.hooks rm -f autodist.tmp.defs fi # Remove duplicate pre-dist-hooks for i in $pre_dist_hooks do echo ". $i" >>autodist.tmp.defs done if test -f autodist.tmp.defs; then cat autodist.tmp.defs | sort | uniq > autodist.pre.dist.hooks rm -f autodist.tmp.defs fi # Remove duplicate post-dist-hooks for i in $post_dist_hooks do echo ". $i" >>autodist.tmp.defs done if test -f autodist.tmp.defs; then cat autodist.tmp.defs | sort | uniq > autodist.post.dist.hooks rm -f autodist.tmp.defs fi ad_debug "<--$FUNCNAME()" } # # Process a file given as argument for the distribution. # # Arguments: process_file # ad_process_file() { local found=false ad_debug "-->$FUNCNAME(): $1 $2" # Process only regular files if test '!' -f $1; then ad_debug "<--$FUNCNAME(): $1 $2" return fi ad_debug "Getting #ifdef's and #ifndef's" # Get defined distribution defines local defs=`awk "/#ifdef "$DP"_DIST_|#else "$DP"_DIST_/ { print; }" \ $1 |cut -d'*' -f2 |cut -d' ' -f2 | sort | uniq` # Get explicitly not-defined distribution defines local ndefs=`awk "/#ifndef "$DP"_DIST_|#else !"$DP"_DIST_/ { print; }" \ $1 |cut -d'*' -f2 |cut -d' ' -f2 | cut -d'!' -f2 | sort | uniq` ad_debug "defs=$defs" ad_debug "ndefs=$ndefs" # Create the script to include and exclude stuff in the file according # to the distribution defines local f=autodist.tmp.script rm -f $f # ifdefs ad_debug "processing ifdefs" for d in $defs do found=false for i in $distdefs do if test x$d = x$i; then found=true break fi done # If distribution define was not found exclude those lines from the file. # This also handles the #ifdef's #else (ie. #ifndef) branch. if test x$found = xfalse; then ad_debug "ifdef $d will be excluded (it is NOT defined)" echo "/^#ifdef $d/,/^#else !$d|^#endif $d/ { next; }" >> $f else echo "/^#else !$d/,/^#endif $d/ { next; }" >> $f fi done # ifndefs ad_debug "processing ifndefs" for d in $ndefs do found=false for i in $distdefs do if test x$d = x$i; then found=true break fi done # If distribution define was found exclude those lines from the file. # This also handles the #ifndef's #else (ie. #ifdef) branch. if test x$found = xtrue; then ad_debug "ifndef $d will be excluded (it IS defined)" echo "/^#ifndef $d/,/^#else $d|^#endif $d/ { next; }" >> $f else echo "/^#else $d/,/^#endif $d/ { next; }" >> $f fi done # Now process the file with the script if test -f $f; then # Those distdef lines that remain in the file are removed to make # the appearance prettier echo "/^#ifdef "$DP"_DIST_|^#endif "$DP"_DIST_|^#else "$DP"_DIST_|^#else !"$DP"_DIST_|^#ifndef "$DP"_DIST_/ { next; }" >> $f echo "{ print; }" >> $f # Execute the script awk -f $f $1 >> $2 fi rm -f $f ad_debug "<--$FUNCNAME(): $1 $2" } # # Process a source file given as argument for the distribution. # # Arguments: process_source_file # ad_process_source_file() { local found=false ad_debug "-->$FUNCNAME(): $1 $2" # Process only regular files if test '!' -f $1; then ad_debug "<--$FUNCNAME(): $1 $2" return fi ad_debug "Getting #ifdef's and #ifndef's" # Get defined distribution defines local defs=`awk '/#ifdef SILC_DIST_|#else \/\* SILC_DIST_/ { print; }' \ $1 |cut -d'*' -f2 |cut -d' ' -f2 | sort | uniq` # Get explicitly not-defined distribution defines local ndefs=`awk '/#ifndef SILC_DIST_|#else \/\* \!SILC_DIST_/ { print; }' \ $1 |cut -d'*' -f2 |cut -d' ' -f2 | cut -d'!' -f2 | sort | uniq` ad_debug "defs=$defs" ad_debug "ndefs=$ndefs" # Create the script to include and exclude stuff in the file according # to the distribution defines local f=autodist.tmp.script rm -f $f # ifdefs ad_debug "processing ifdefs" for d in $defs do found=false for i in $distdefs do if test x$d = x$i; then found=true break fi done # If distribution define was not found exclude those lines from the file. # This also handles the #ifdef's #else (ie. #ifndef) branch. if test x$found = xfalse; then ad_debug "ifdef $d will be excluded (it is NOT defined)" echo "/^#ifdef $d/,/^#else \/\* \!$d|^#endif \/\* $d/ { next; }" >> $f else echo "/^#else \/\* \!$d/,/^#endif \/\* $d/ { next; }" >> $f fi done # ifndefs ad_debug "processing ifndefs" for d in $ndefs do found=false for i in $distdefs do if test x$d = x$i; then found=true break fi done # If distribution define was found exclude those lines from the file. # This also handles the #ifndef's #else (ie. #ifdef) branch. if test x$found = xtrue; then ad_debug "ifndef $d will be excluded (it IS defined)" echo "/^#ifndef $d/,/^#else \/\* $d|^#endif \/\* $d/ { next; }" >> $f else echo "/^#else \/\* $d/,/^#endif \/\* $d/ { next; }" >> $f fi done # Now process the file with the script if test -f $f; then # Those distdef lines that remain in the file are removed to make # the appearance prettier echo "/^#ifdef SILC_DIST_|^#endif \/\* SILC_DIST_|^#else \/\* SILC_DIST_|^#else \/\* \!SILC_DIST_|^#ifndef SILC_DIST_/ { next; }" >> $f echo "{ print; }" >> $f # Execute the script awk -f $f $1 >> $2 fi rm -f $f ad_debug "<--$FUNCNAME(): $1 $2" } ############################################################################### # Autodist code usage="Usage: autodist [options] [distribution] [version]" help="\ Autodist prepares source tree for configuration, compilation and distribution. Prepares the source tree from the \`autodist.ad' configuration file. Generates Automake.am files from Automake.ad files, configure.ac file from configure.ad file(s), generates the configure script by running Autoconf tool, and generates Makefile.in files by running Automake tool. Operation modes: -h, --help print this help, then exit -V, --version print version number, then exit -v, --verbose verbosely report processing -d, --distdir search distributions from -s, --distdefs [] print distribution defines of , then exit -m, --makedist create and package distribution -i, --init initialize Autodist environment, create default distribution directory and distribution, then exit" # # Process command line arguments # while test $# -gt 0; do case "${1}" in -d |--distdir) shift; test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } distdir="${1}"; shift;; --list) exit 0;; -s | --distdefs) shift; if test $# -eq 0; then ad_parse_distribution $distribution false echo "Distribution: ${distribution}" 1>&2; else ad_parse_distribution $1 false echo "Distribution: ${1}" 1>&2; fi ad_process_distdefs echo "Distdefs:" 1>&2; echo "${distdefs}"; exit 0;; -i | --init) ad_initialize; exit 0;; -m | --makedist) makdist=true shift;; -v | --verbose) debug=true shift;; -h | --help | --h*) echo "${usage}" 1>&2; echo 1>&2; echo "${help}" 1>&2; echo 1>&2; exit 0;; -V | --version) echo "autodist (SILC Autodist) $ver" 1>&2; echo "Written by Pekka Riikonen" 1>&2; echo 1>&2; echo "Copyright (C) 2004 - 2005 SILC Project" 1>&2; echo "\ This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. " 1>&2; exit 0;; --) shift; break;; -*) echo "${usage}" 1>&2; exit 1;; *) break;; esac done # # Parse the requested distribution # if test $# != 0; then distribution="${1}"; shift fi ad_parse_distribution $distribution false ad_process_distdefs if test $# != 0; then dist_version="${1}"; fi ad_debug "Preparing source tree for configuration and compilation..." ad_debug "Preparing $distribution distribution version $dist_version" # # Create the distribution defines header file # if test "$DISTDEFS"; then ad_create_distdefs_h else ad_fatal "DISTDEFS not defined in $distdir/autodist.conf" fi # # Run pre-hooks # if test -f autodist.pre.hooks; then . autodist.pre.hooks rm -f autodist.pre.hooks fi # # Generate the Makefile.am files from Makefile.ad files # ad_make_makefile_ams # # Generate the configure.ac from configure.ad file(s) # ad_make_configure_ac ./configure.ad # # Generate configure script # ad_make_configure # # Generate Makefile.in files # ad_make_makefile_ins # # Process all files with .ad suffix for distribution processing # ad_process_ads # # Run post-hooks # if test -f autodist.post.hooks; then . autodist.post.hooks rm -f autodist.post.hooks fi # # Generate distribution, if requested # if test x$makedist = xtrue; then ad_debug "Creating distribution" exit 0 fi ad_debug "Done, now run ./configure and make." exit 0