Raw File
pm2-build-packages
#! /bin/bash

# Padico -- a High Performance Parallel and Distributed Computing Environment
# Copyright (c) 2002-2004 INRIA and the University of Rennes 1
# Copyright (c) 2011-2022 INRIA
# Alexandre DENIS <Alexandre.Denis@inria.fr>
# Christian PEREZ <Christian.Perez@inria.fr>

# The software has been registered at the Agency for the Protection of
# Programs (APP) under the number IDDN.FR.001.260013.000.S.P.2002.000.10000.

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

usage() {
cat 1>&2 <<EOF

usage: $0 [<options>...] <conf_file>

 <conf_file>         configuration file describing packages to install
                     (- for stdin)
 Available <options> are:
  -h, --help         show this help message
  --prefix=<prefix>  destination where to install packages
                     may be omitted if config file contains prefix=<prefix>
  --log=<log>        log all messages to file <log>
  --nogen            do not run ./autogen.sh in packages
  --noconf           do not run ./configure in packages (implies --nogen)
  --purge            purge build directory before building
  --final            delete build directory after building
  --clean            clean packages before building
  <var>=<value>      set shell variable <var> with value <value>
  -- <options>       all <options> will be given directly to configure of all packages

 Syntax for <conf_file>
  . empty lines and lines begining with # are ignored
  . each line has the form:
<var>=<value>
    set shell variable <var>
pkg <package> [<options>...]
    build package <package> with configure options <options>
    shell expansion is performed on <package> to allow the use of variables
    <package> may be:
      - a source absolute directory
      - a name without leading / interpreted as a directory in the same tree as this script
      - an archive file, unpacked before beeing built
cmd <cmd>
    run arbitrary shell commands
var <var>
    request variable <var> to be set

  . see examples for more information on syntax

 Build tree:
  . installation of packages is done in <prefix>
  . packages are configured and built in <prefix>/build/<package>/
  . source tarbals are extracted to <prefix>/src/<package>/
  . <prefix>/lib/pkgconfig/ is automatically added to PKG_CONFIG_PATH in the
    configure environment if not already present

EOF
}

flavor=
self="$0"
case "${self}" in
    */*)
	;;
    *)
	self=$( which $0 )
	;;
esac

self_dir_rel=$( dirname ${self} )
self_path=$( cd ${self_dir_rel}  ; pwd )
root_dir=${self_path}/..
self_fullcmd="$0 $*"

while [ "x$1" != "x" ]; do
    case "$1" in
	-h|--help)
	    usage
	    exit 0
	    ;;
	--prefix=*)
	    prefix="$( echo $1 | sed -e 's,^--prefix=,,')"
	    ;;
	--nogen)
	    build_option_nogen=yes
	    ;;
	--noconf)
	    build_option_noconf=yes
	    build_option_nogen=yes
	    ;;
	--purge)
	    build_option_purge=yes
	    ;;
	--final)
	    build_option_final=yes
	    ;;
        --clean)
	    build_option_clean=yes
	    ;;
	--log=*)
	    logfile="$( echo $1 | sed -e 's,^--log=,,')"
	    fifo=/tmp/pm2-log-$$.tmp
	    trap "rm -f ${fifo}" EXIT
	    mkfifo ${fifo}
	    tee <${fifo} ${logfile} &
	    echo "# ## log generated by command line:" > ${fifo}
	    echo "# ${self_fullcmd}"                   > ${fifo}
	    echo "# run from PWD=${PWD}"               > ${fifo}
	    exec 1>&-
	    exec 1>${fifo} 2>${fifo}
	    ;;
	-)
	    flavor="-"
	    ;;
	--)
	    global_options="${global_options} $*"
	    shift
	    cmdline_options="$*"
	    break
	    ;;
	-*)
	    echo "# ** unkown option '$1'." 1>&2
	    usage
	    exit 1
	    ;;
	*=*)
	    eval "$1"
	    ;;
	*)
	    flavor="$1"
	    ;;
    esac
    # save options for sub-packages
    case "$1" in
	-*)
	    global_options="${global_options} $1"
	    ;;
	*=*)
	    global_options="${global_options} $1"
	    ;;
	*)
	    ;;
    esac
    shift
done

if [ "x${flavor}" != "x-" ]; then
    if [ "x${flavor}" = "x" ]; then
	echo "# ** no config file given." 1>&2
	usage
	exit 1
    fi
    if [ ! -r "${flavor}" ]; then
	echo "# ** config file '${flavor}' not found." 1>&2
	usage
	exit 1
    fi
fi

MAKE=make

# ## extract_package_*: extracts packages from various sources, returns srcdir

# find srcdir from unpacked archive
extract_package_unpacked_archive() {
    basedir="$1"
    for d in ${basedir}/*; do
	if [ -d ${d} ]; then
	    srcdir=${d}
	    break
	fi
    done
    if [ ! -r ${srcdir} ]; then
	echo "# ** no directory found in archive ${package}" 1>&2
	exit 1
    fi
    echo "${srcdir}"
}

# make the given path absolute
extract_package_make_abs() {
    case "$1" in
	/*)
	    echo "$1" ;;
	*)
	    echo "${PWD}/$1" ;;
    esac
}

# package is a .tar.gz
extract_package_targz() {
    package="`extract_package_make_abs $1`"
    n=$( basename ${package} .tar.gz )
    mkdir -p ${prefix}/src/${n}
    echo "# unpacking package: ${package}" 1>&2
    ( cd ${prefix}/src/${n} ; tar xzf ${package} )
    extract_package_unpacked_archive "${prefix}/src/${n}"
}
# package is a .tar.bz2
extract_package_tarbz2() {
    package="`extract_package_make_abs $1`"
    n=$( basename ${package} .tar.bz2 )
    mkdir -p ${prefix}/src/${n}
    echo "# unpacking package: ${package}" 1>&2
    ( cd ${prefix}/src/${n} ; tar xjf ${package} )
    extract_package_unpacked_archive "${prefix}/src/${n}"
}
# package is a .atr.xz
extract_package_tarxz() {
    package="`extract_package_make_abs $1`"
    n=$( basename ${package} .tar.xz )
    mkdir -p ${prefix}/src/${n}
    echo "# unpacking package: ${package}" 1>&2
    ( cd ${prefix}/src/${n} ; tar xJf ${package} )
    extract_package_unpacked_archive "${prefix}/src/${n}"
}

# frontend to extract packages
extract_package() {
    package="$1"
    if [ -d "${root_dir}/${package}" ]; then
	# package is a pm2 module name
	echo "# package ${package} recognized as ${root_dir}/${package}/" 1>&2
	echo "${root_dir}/${package}"
    elif [ -d "${package}" ]; then
	# package is a directory
	echo "# package ${package} recognized as directory" 1>&2
	echo "${package}"
    elif [ -r ${package} ]; then
	# other cases, need to extract archives to get srcdir
	case "${package}" in
	    *.tar.gz)
		extract_package_targz "${package}"
		;;
	    *.tar.bz2)
		extract_package_tarbz2 "${package}"
		;;
	    *.tar.xz)
		extract_package_tarxz "${package}"
		;;
	    *)
		echo "# ** cannot detect kind for package ${package}" 1>&2
		exit 1
		;;
	esac
	echo "# package ${package} recognized as archive" 1>&2
    else
	exit 1
    fi
}

build_package() {
    package="$1"
    cd ${root_dir}
    # find package srcdir, unpack if needed
    package_srcdir="`extract_package ${package}`"
    echo "# package srcdir: ${package_srcdir}" 1>&2
    if [ ! -r "${package_srcdir}" ]; then
	echo "# ** cannot read package ${package_srcdir}" 1>&2
	exit 1
    fi
    package_name="`basename ${package_srcdir}`"
    # build directory
    if [ "x${build_option_purge}" != "x" ]; then
	echo "# purge directory ${prefix}/build/${package_name}" 1>&2
	rm -rf ${prefix}/build/${package_name}
	echo
    fi
    mkdir -p ${prefix}/build/${package_name}
    shift
    # autogen
    if [ "x${build_option_nogen}" = "x" ]; then
	if [ -x ${package_srcdir}/autogen.sh ]; then
	    echo "# autogen: ${package_name}" 1>&2
	    cd ${package_srcdir}
	    ./autogen.sh
	    rc=$?
	elif [ -x ${package_srcdir}/bootstrap ]; then
	    echo "# bootstrap: ${package_name}" 1>&2
	    cd ${package_srcdir}
	    ./bootstrap
	    rc=$?
	fi
	if [ $rc != 0 ]; then exit 1; fi
    else
	echo "# autogen disabled for package: ${package_name}" 1>&2
    fi
    # configure
    cd ${prefix}/build/${package_name}
    if [ "x${build_option_noconf}" = "x" ]; then
	if [ -x ${package_srcdir}/configure ]; then
            # autoconf
	    echo "# configure: ${package_name} with options: --prefix=${prefix} ${common_options} ${cmdline_options} $*" 1>&2
	    ${package_srcdir}/configure --prefix=${prefix} ${common_options} ${cmdline_options} $*
	    rc=$?
	    if [ $rc != 0 ]; then exit 1; fi
	    echo
	elif [ -r ${package_srcdir}/CMakeLists.txt ]; then
	    # cmake
	    cmake -DCMAKE_INSTALL_PREFIX:PATH=${prefix} $* ${package_srcdir}
	else
	    # no configure- copy sources
	    cp -r ${package_srcdir}/* ${prefix}/build/${package_name}/
	fi
    else
	echo "# configure disabled for package: ${package_name}" 1>&2
    fi
    # make clean
    if [ "x${build_option_clean}" != "x" ]; then
	echo "# make clean: ${package_name}" 1>&2
	${MAKE} clean
	# do not catch return code; ignore silently "make clean" errors
    fi
    # make
    echo "# make: ${package_name}" 1>&2
    ${MAKE}
    rc=$?
    if [ $rc != 0 ]; then exit 1; fi
    echo
    # make install
    echo "# make install: ${package_name}" 1>&2
    ${MAKE} install
    rc=$?
    if [ $rc != 0 ]; then exit 1; fi
    echo
    # clean-up
    if [ "x${build_option_final}" != "x" ]; then
	echo "# delete directory ${prefix}/build/${package_name} after building" 1>&2
	rm -rf ${prefix}/build/${package_name}
	echo
    fi
    echo "# ## done: ${package_name}" 1>&2
    echo
    echo
    cd ${root_dir}
}

echo
echo "# ## build packages using config file: ${flavor}" 1>&2
echo

if [ "x${flavor}" = "x-" ]; then
    exec 3<&0
else
    exec 3< ${flavor}
fi

cd ${root_dir}

v=
while true; do
  read -u 3 v content
  rc=$?
  if [ ${rc} != 0 ]; then break; fi
  case "${v}" in
      "")
	  ;;
      '#'*)
	  ;;
      var)
	  varname=$( echo "${content}" | cut -f 1 -d ' ' )
	  echo "# checking variable ${varname}" 1>&2
	  if [ "x${!varname}" = "x" ]; then
	      echo "# ** variable '${varname}' needed by config file is not set." 1>&2
	      exit 1
	  else
	      echo "# ok: ${varname}=${!varname}" 1>&2
	  fi
	  ;;
      cmd)
	  echo "# running cmd: ${content}" 1>&2
	  eval "${content}"
	  rc=$?
	  if [ $rc != 0 ]; then exit 1; fi
	  ;;
      export)
	  echo "# set environment variable: ${content}" 1>&2
	  eval "export ${content}"
	  ;;
      *=*)
          echo "# set local variable: ${v} ${content}" 1>&2
	  eval "${v} ${content}"
	  ;;
      pkg)
	  package_verbatim=$( echo "${content}" | cut -f 1 -d ' ' )
	  package=$( eval echo ${package_verbatim} )
	  options=$( eval echo "${content}" | cut -s -f 2- -d ' ' )
	  if [ "x${prefix}" = "x" ]; then
	      echo "# ** 'prefix' not set." 1>&2
	      exit 1
	  fi
	  case "${PKG_CONFIG_PATH}" in
	      *${prefix}/lib/pkgconfig*) ;;
	      *)  echo "# add ${prefix}/lib/pkgconfig in PKG_CONFIG_PATH" 1>&2
		  export PKG_CONFIG_PATH=${prefix}/lib/pkgconfig:${PKG_CONFIG_PATH}
		  ;;
	  esac
	  case "${LD_LIBRARY_PATH}" in
	      *${prefix}/lib*) ;;
	      *)  echo "# add ${prefix}/lib in LD_LIBRARY_PATH" 1>&2
		  export LD_LIBRARY_PATH=${prefix}/lib:${LD_LIBRARY_PATH}
		  ;;
	  esac
	  case "${PATH}" in
	      *${prefix}/bin*) ;;
	      *)  echo "# add ${prefix}/bin in PATH" 1>&2
		  export PATH=${prefix}/bin:${PATH}
		  ;;
	  esac
	  echo
	  echo
	  echo "# ## building package: ${package}"
	  echo "#    with options: ${options} ${cmdline_options}"
	  echo
	  build_package ${package} ${options}
	  ;;
      sub)
	  package=${content}
	  echo "# build sub-package: ${package}" 1>&2
	  pushd ${self_path}
	  ${self} ${global_options} ${package}
	  rc=$?
	  echo "# done: ${package}; rc = ${rc}" 1>&2
	  if [ $rc != 0 ]; then exit 1; fi
	  popd
	  ;;
  esac
done
exec 3<&-

baseflavor=$(basename ${flavor})

echo "# Generating module... ${prefix}/share/modules/pm2/$(basename ${flavor} .conf)"
mkdir -p ${prefix}/share/modules/pm2
sed -e "s,@prefix@,${prefix},g" < ${self_path}/module.in > ${prefix}/share/modules/pm2/$(basename ${flavor} .conf)
echo "# Generating shell config files... ${prefix}/share/${baseflavor}.sh)"

echo "setenv PATH ${prefix}/bin:\${PATH}"                                 >  ${prefix}/share/${baseflavor}.csh
echo "setenv LD_LIBRARY_PATH ${prefix}/lib:\${LD_LIBRARY_PATH}"           >> ${prefix}/share/${baseflavor}.csh
echo "setenv PKG_CONFIG_PATH ${prefix}/lib/pkgconfig:\${PKG_CONFIG_PATH}" >> ${prefix}/share/${baseflavor}.csh

echo "export PATH=${prefix}/bin:\${PATH}"                                 >  ${prefix}/share/${baseflavor}.sh
echo "export LD_LIBRARY_PATH=${prefix}/lib:\${LD_LIBRARY_PATH}"           >> ${prefix}/share/${baseflavor}.sh
echo "export PKG_CONFIG_PATH=${prefix}/lib/pkgconfig:\${PKG_CONFIG_PATH}" >> ${prefix}/share/${baseflavor}.sh

echo
echo "# You can now customize your environment with:"
echo
case "$SHELL" in
    *csh)
	echo "source ${prefix}/share/${baseflavor}.csh"
	;;
    *)
	echo ". ${prefix}/share/${baseflavor}.sh"
	;;
esac
echo

back to top