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