aboutsummaryrefslogtreecommitdiff
path: root/project
diff options
context:
space:
mode:
Diffstat (limited to 'project')
-rwxr-xr-xproject339
1 files changed, 236 insertions, 103 deletions
diff --git a/project b/project
index d087286..f2986fb 100755
--- a/project
+++ b/project
@@ -3,8 +3,8 @@
# High-level script to manage the project.
# Run './project --help' for a description of how to use it.
#
-# Copyright (C) 2019-2022 Mohammad Akhlaghi <mohammad@akhlaghi.org>
-# Copyright (C) 2021-2022 Raul Infante-Sainz <infantesainz@gmail.com>
+# Copyright (C) 2019-2025 Mohammad Akhlaghi <mohammad@akhlaghi.org>
+# Copyright (C) 2021-2025 Raul Infante-Sainz <infantesainz@gmail.com>
#
# 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
@@ -33,13 +33,18 @@ set -e
jobs=0 # 0 is for the default for the 'configure.sh' script.
group=
debug=
+quiet=0
+timing=0
host_cc=0
+offline=
operation=
build_dir=
input_dir=
+keep_going=
check_config=
make_targets=
software_dir=
+pauseformsg=1
clean_texdir=0
prepare_redo=0
highlightnew=0
@@ -87,7 +92,7 @@ RECOMMENDATION: If this is the first time you are configuring this
template, please don't use the options and let the script explain each
parameter in full detail by simply running './project configure'.
-Project 'make' special features.
+Project 'make' special tagets
./project make Build the project on one thread
./project make -jN Built the project in parallel on N threads.
./project make clean Clean all files generated by 'make' (not software).
@@ -104,29 +109,34 @@ Project 'make' special features.
With the options below you can modify the default behavior.
Configure options:
+ --all-highlevel Build all high-level software (for development).
-b, --build-dir=STR Top directory to build the project in.
- -e, --existing-conf Use (possibly existing) local configuration.
- --host-cc Use host system's C compiler, don't build GCC.
- -i, --input-dir=STR Directory containing input datasets (optional).
- -s, --software-dir=STR Directory containing necessary software tarballs.
--check-config During configuration, show what is being built.
--clean-texdir Remove possibly existing build-time subdirectories
under the project's 'tex/' directory (can happen
when source is from arXiv for example).
- --all-highlevel Build all high-level software (for development).
+ -e, --existing-conf Use (possibly existing) local configuration.
+ -i, --input-dir=STR Directory containing input datasets (optional).
+ --host-cc Use host system's C compiler, don't build GCC.
+ --quiet Do not print basic info messages (with '-e').
+ --no-pause Do not sleep/pause after basic info messages.
+ -s, --software-dir=STR Directory containing necessary software tarballs.
Configure and Make options:
-d, --debug[=FLAGS] In configure: use -j1, no -k, and no Zenodo check.
In make: 'FLAGS' will be directly passed to 'make'.
+ -k, --keep-going Keep going when some targets can't be made.
-g, --group=STR Build and run with write permissions for a group.
-j, --jobs=INT Number of threads to build/run the software.
-?, --help Print this help list.
Make (analysis) options:
-p, --prepare-redo Re-do preparation (only done automatically once).
+ -t, --timing Starting and ending times written in 'timing.txt'.
Make (final PDF) options:
--refresh-bib Force refresh the bibliography.
+ --highlight-all Activate '--highlight-new' & '--highlight-notes'.
--highlight-new Highlight '\new' parts of text as green.
--highlight-notes Show '\tonote' regions as red text in PDF.
@@ -174,59 +184,71 @@ do
shell) func_operation_set $1; shift;;
# Configure options:
- -b|--build-dir) build_dir="$2"; check_v "$1" "$build_dir"; shift;shift;;
- -b=*|--build-dir=*) build_dir="${1#*=}"; check_v "$1" "$build_dir"; shift;;
- -b*) build_dir=$(echo "$1" | sed -e's/-b//'); check_v "$1" "$build_dir"; shift;;
- -e|--existing-conf) existing_conf=1; shift;;
+ -e|--existing-conf) existing_conf=1; shift;;
-e*|--existing-conf=*) on_off_option_error --existing-conf -e;;
- --host-cc) host_cc=1; shift;;
+ --host-cc) host_cc=1; shift;;
--host-cc=*) on_off_option_error --host-cc;;
- -i|--input-dir) input_dir="$2"; check_v "$1" "$input_dir"; shift;shift;;
- -i=*|--input-dir=*) input_dir="${1#*=}"; check_v "$1" "$input_dir"; shift;;
- -i*) input_dir=$(echo "$1" | sed -e's/-i//'); check_v "$1" "$input_dir"; shift;;
- -s|--software-dir) software_dir="$2"; check_v "$1" "$software_dir"; shift;shift;;
- -s=*|--software-dir=*) software_dir="${1#*=}"; check_v "$1" "$software_dir"; shift;;
- -s*) software_dir=$(echo "$1" | sed -e's/-s//'); check_v "$1" "$software_dir"; shift;;
- --check-config) check_config=1; shift;;
+ --offline) offline=1; shift;;
+ --offline=*) on_off_option_error --offline;;
+ -i|--input-dir) input_dir="$2"; check_v "$1" "$input_dir"; shift;shift;;
+ -i=*|--input-dir=*) input_dir="${1#*=}"; check_v "$1" "$input_dir"; shift;;
+ -i*) input_dir=$(echo "$1" | sed -e's/-i//'); check_v "$1" "$input_dir"; shift;;
+ -s|--software-dir) software_dir="$2"; check_v "$1" "$software_dir"; shift;shift;;
+ -s=*|--software-dir=*) software_dir="${1#*=}"; check_v "$1" "$software_dir"; shift;;
+ -s*) software_dir=$(echo "$1" | sed -e's/-s//'); check_v "$1" "$software_dir"; shift;;
+ --check-config) check_config=1; shift;;
--check-config=*) on_off_option_error --check-config;;
- --clean-texdir) clean_texdir=1; shift;;
+ --clean-texdir) clean_texdir=1; shift;;
--clean-texdir=*) on_off_option_error --clean-texdir;;
- --all-highlevel) all_highlevel=1; shift;;
+ --all-highlevel) all_highlevel=1; shift;;
--all-highlevel=*) on_off_option_error --all-highlevel;;
+ --no-pause) pauseformsg=0; shift;;
+ --no-pause=*) on_off_option_error --no-pause;;
+ --quiet) quiet=1; shift;;
+ --quiet=*) on_off_option_error --quiet;;
# Configure and Make options:
- -g|--group) group="$2"; check_v group "$group"; shift;shift;;
- -g=*|--group=*) group="${1#*=}"; check_v group "$group"; shift;;
- -g*) group=$(echo "$1" | sed -e's/-g//'); check_v group "$group"; shift;;
- -j|--jobs) jobs="$2"; check_v jobs "$jobs"; shift;shift;;
- -j=*|--jobs=*) jobs="${1#*=}"; check_v jobs "$jobs"; shift;;
- -j*) jobs=$(echo "$1" | sed -e's/-j//'); check_v jobs "$jobs"; shift;;
- -'?'|--help) print_help; exit 0;;
- -'?'*|--help=*) on_off_option_error --help -?;;
-
- # Make options
- # ------------
- #
- # Note that Make's 'debug' can take values, but when called without any
- # value, it is like giving it a value of 'a'):
- --refresh-bib) [ -f tex/src/references.tex ] && touch tex/src/references.tex; shift;;
- --highlight-new) highlightnew=1; shift;;
- --highlight-new=*) on_off_option_error --highlight-new;;
- --highlight-notes) highlightnotes=1; shift;;
- --highlight-notes=*) on_off_option_error --highlight-notes;;
- -d|--debug) if [ x$operation = x ]; then
- echo "Please set the operation before calling '--debug'"; exit 1
- elif [ x$operation = xconfigure ]; then debug=a; shift;
- elif [ x$operation = xmake ]; then
- if [ x"$2" = x ]; then echo "In make-mode, '--debug' needs a value"; exit 1
- else debug="$2"; check_v debug "$debug"; shift;shift; fi
- else
- echo "Operation '$operation' not recognized, please use 'configure' or 'make'"
- fi;;
- -d=*|--debug=*) debug="${1#*=}"; check_v debug "$debug"; shift;;
- -d*) debug=$(echo "$1" | sed -e's/-d//'); check_v debug "$debug"; shift;;
- -p|--prepare-redo) prepare_redo=1; shift;;
- -p=*|--prepare-redo=*) on_off_option_error --prepare-redo; shift;;
+ -b|--build-dir) build_dir="$2"; check_v "$1" "$build_dir";shift;shift;;
+ -b=*|--build-dir=*) build_dir="${1#*=}"; check_v "$1" "$build_dir";shift;;
+ -b*) build_dir=$(echo "$1" | sed -e's/-b//'); check_v "$1" "$build_dir";shift;;
+ -g|--group) group="$2"; check_v group "$group"; shift;shift;;
+ -g=*|--group=*) group="${1#*=}"; check_v group "$group"; shift;;
+ -g*) group=$(echo "$1" | sed -e's/-g//'); check_v group "$group"; shift;;
+ -j|--jobs) jobs="$2"; check_v jobs "$jobs"; shift;shift;;
+ -j=*|--jobs=*) jobs="${1#*=}"; check_v jobs "$jobs"; shift;;
+ -j*) jobs=$(echo "$1" | sed -e's/-j//'); check_v jobs "$jobs"; shift;;
+ -k|--keep-going) keep_going="--keep-going"; shift;;
+ -k=*|--keep-going=*) on_off_option_error --keep-going -k;;
+ -k*) on_off_option_error --keep-going -k;;
+ -'?'|--help) print_help; exit 0;;
+ -'?'*|--help=*) on_off_option_error --help -?;;
+
+ # Make options (analysis):
+ -p|--prepare-redo) prepare_redo=1; shift;;
+ -p=*|--prepare-redo=*) on_off_option_error --prepare-redo; shift;;
+ -t|--timing) timing=1; shift;;
+ -t=*|--timing=*) on_off_option_error --timing; shift;;
+
+ # Make options (final PDF):
+ --refresh-bib) [ -f tex/src/references.tex ] && touch tex/src/references.tex; shift;;
+ --highlight-all) highlightnew=1; highlightnotes=1; shift;;
+ --highlight-all=*) on_off_option_error --highlight-new;;
+ --highlight-new) highlightnew=1; shift;;
+ --highlight-new=*) on_off_option_error --highlight-new;;
+ --highlight-notes) highlightnotes=1; shift;;
+ --highlight-notes=*) on_off_option_error --highlight-notes;;
+ -d|--debug) if [ x$operation = x ]; then
+ echo "Please set the operation before calling '--debug'"; exit 1
+ elif [ x$operation = xconfigure ]; then debug=a; shift;
+ elif [ x$operation = xmake ]; then
+ if [ x"$2" = x ]; then
+ echo "In make-mode, '--debug' needs a value; see GNU Make manual"; exit 1
+ else debug="$2"; check_v debug "$debug"; shift;shift; fi
+ else
+ echo "Operation '$operation' not recognized, please use 'configure' or 'make'"
+ fi;;
+ -d=*|--debug=*) debug="${1#*=}"; check_v debug "$debug"; shift;;
+ -d*) debug=$(echo "$1" | sed -e's/-d//'); check_v debug "$debug"; shift;;
# Unrecognized option:
-*) echo "$scriptname: unknown option '$1'"; exit 1;;
@@ -280,8 +302,8 @@ EOF
ls $coloropt .build/software/build-tmp || junk=1;
fi
- # Make the temporary directory, delete its contents, then put new
- # links of all built software.
+ # Make the temporary directory, delete its contents, then put
+ # new links of all built software.
if ! [ -d $checkdir ]; then mkdir $checkdir; fi
rm -f $checkdir/*
@@ -302,10 +324,11 @@ EOF
if [ $printresults = 1 ]; then
echo "--- Last 5 packages that were built:"
- # Then sort all the links based on the most recent dates of the
- # files they link to (with '-L').
+ # Then sort all the links based on the most recent dates of
+ # the files they link to (with '-L').
ls -Llt $checkdir \
- | awk '/^-/ && c++<5 {printf "[at %s] %s\n", $(NF-1), $NF}'
+ | awk '/^-/ && c++<5 {printf "[at %s] %s\n", \
+ $(NF-1), $NF}'
fi
else
cat <<EOF
@@ -329,14 +352,15 @@ fi
-# Basic group settings
-# --------------------
+# Group check
+# -----------
if ! [ x$group = x ]; then
# Check if group is usable.
if ! sg "$group" "echo Group \'$group\' exists"; then
- echo "$scriptname: '$group' is not a usable group name on this system.";
- echo "(TIP: you can use the 'groups' command to see your groups)"
+ printf "$scriptname: '$group' is not a usable group name on "
+ printf "this system. TIP: you can use the 'groups' command "
+ printf "to see your groups)\n"
exit 1
fi
@@ -348,9 +372,45 @@ fi
-# Error when configuration isn't run
-configuration_necessary() {
- cat <<EOF
+# Build directory symbolic links
+# ------------------------------
+#
+# The source directory will contain two symbolic links that point to the
+# build directory:
+
+# - .build: the top build directory.
+#
+# - .local: the second to the top software installed directory. They are
+# used during the configuration phase to simplify commands and are also
+# very useful during the development of a maneage'd project (to easily
+# get to the build directory or execut Maneage'd software).
+#
+# This needs to be done on every run because:
+# - './project configure' can be run with a new build directory, and
+# keeping the old '.build' conflicts with the new build directory
+# that the user gave.
+# - './project make' or './project shell' (within a newly cloned source
+# directory from inside a container): the links do not exist but have
+# to be set to the container's build directory.
+# - This is not an expensive operation.
+if ! [ x"$build_dir" = x ]; then
+ rm -f .build .local
+ ln -s $build_dir .build
+ ln -s $build_dir/software/installed .local
+fi
+
+
+
+
+
+# Function to validate configuration
+# ----------------------------------
+#
+# Check if the configuration is missing/incomplete
+configuration_check() {
+ confdone=software/config/hardware-parameters.tex
+ if ! [ -f .build/$confdone ]; then
+ cat <<EOF
The project is either (1) not configured on this system, or (2) the
configuration wasn't successful.
@@ -370,15 +430,70 @@ If there was a problem, please let us know by filling this online form:
http://savannah.nongnu.org/support/?func=additem&group=reproduce
EOF
- exit 1
+ exit 1
+ fi
}
-# Run operations in controlled environment
-# ----------------------------------------
+# Function for TeX Preparations
+# -----------------------------
+#
+# Make sure that the necessary analysis directories directory exist in the
+# build directory. These will be necessary in various phases of hte
+# analysis and having them inside the lower-level Make steps will require
+# setting them as prerequisites for many basic jobs (thus making the
+# Makefiles harder to read and add potentials for bugs: forgetting to add
+# them for example). Also, we don't want the configure phase to make any
+# edits in the analysis directory, so they are not built there.
+tex_preparations () {
+
+ # Extract the location of the build directory.
+ bdir=$(.local/bin/realpath .build)
+
+ # We are using our custom-built 'mkdir' which is guaranteed to have the
+ # '-p' option (that will also build intermediate directories) and won't
+ # complain if the directory already exists.
+ badir=$bdir/analysis
+ texdir=$badir/tex
+ btexdir=$texdir/build
+ tikzdir=$btexdir/tikz
+ mtexdir=$texdir/macros
+ .local/bin/mkdir -p $mtexdir $btexdir $tikzdir
+
+ # If 'tex/build' and 'tex/tikz' are symbolic links then 'rm -f'
+ # will delete them and we can continue. However, when the project
+ # is being built from the tarball (from arXiv for example), these
+ # two are not symbolic links but actual directories with the
+ # necessary built-components to build the PDF in them. In this
+ # case, because 'tex/build' is a directory, 'rm -f' will fail, so
+ # we'll just rename the two directories (as backup) and let the
+ # project build the proper symbolic links afterwards.
+ if rm -f tex/build; then
+ rm -f tex/tikz
+ else
+ mv tex/tikz tex/tikz-from-tarball
+ mv tex/build tex/build-from-tarball
+ fi
+
+ # Build the symbolic links.
+ if ! [ -L tex/tikz ]; then ln -s "$tikzdir" tex/tikz; fi
+ if ! [ -L tex/build ]; then ln -s "$texdir" tex/build; fi
+}
+
+
+
+
+
+# Function to run in controlled environment
+# -----------------------------------------
+#
+# Controlling the environment is necessary for running the analysis. Like
+# the other funcitons here, this is defined to simplify the high-level code
+# within the 'make)' switch statement.
+perms="u+r,u+w,g+r,g+w,o-r,o-w,o-x"
controlled_env() {
# Get the full address of the build directory:
@@ -390,6 +505,7 @@ controlled_env() {
envmake="$envmake highlightnew=$highlightnew"
envmake="$envmake highlightnotes=$highlightnotes .local/bin/make"
envmake="$envmake --no-builtin-rules --no-builtin-variables -f $1"
+ envmake="$envmake $keep_going"
if ! [ x"$debug" = x ]; then envmake="$envmake --debug=$debug"; fi
# Set the number of jobs. Note that for the 'configure.sh' script the
@@ -412,7 +528,6 @@ controlled_env() {
# Do requested operation
# ----------------------
-perms="u+r,u+w,g+r,g+w,o-r,o-w,o-x"
configscript=./reproduce/software/shell/configure.sh
case $operation in
@@ -433,8 +548,11 @@ case $operation in
# to make sure they have them, we are activating the executable
# flags by default here every time './project configure' is run. If
# any other file in your project needs such flags, add them here.
- chmod +x reproduce/software/shell/* reproduce/software/config/*.sh \
- reproduce/analysis/bash/*
+ if ! [ -x reproduce/software/shell/configure.sh ]; then
+ chmod +x reproduce/analysis/bash/* \
+ reproduce/software/shell/* \
+ reproduce/software/config/*.sh
+ fi
# If the user requested, clean the TeX directory from the extra
# (to-be-built) directories that may already be there (and will not
@@ -446,10 +564,13 @@ case $operation in
# Variables to pass to the configuration script.
export jobs=$jobs
export debug=$debug
+ export quiet=$quiet
export host_cc=$host_cc
+ export offline=$offline
export build_dir=$build_dir
export input_dir=$input_dir
export scriptname=$scriptname
+ export pauseformsg=$pauseformsg
export maneage_group_name=$group
export software_dir=$software_dir
export existing_conf=$existing_conf
@@ -469,7 +590,8 @@ case $operation in
# creates problems when another group member wants to update
# the software for example. We thus need to manually add the
# group writing flag to all installed software files.
- echo "Enabling group writing permission on all installed software..."
+ printf "Enabling group writing permission on all installed "
+ printf "software...\n"
.local/bin/chmod -R g+w .local/;
fi
;;
@@ -481,63 +603,74 @@ case $operation in
# Batch execution of the project.
make)
- # Make sure the configure script has been completed properly
- # ('configuration-done.txt' exists).
- if ! [ -f .build/software/configuration-done.txt ]; then
- configuration_necessary
- fi
+ # Make sure the configure script is complete and necessary LaTeX
+ # directories are in place.
+ configuration_check
+ tex_preparations
+
+ # Register the start of this run if requested (we are appending the
+ # new information so previous information is preserved until the
+ # user intentionally deletes/cleans it).
+ if [ $timing = 1 ]; then echo "start: $(date)" >> timing.txt; fi
# Run data preparation phase (optionally build Makefiles with
# special values for optimizing the main 'top-make.mk'). But note
# that data preparation is only done automatically the first time
- # the project is built (when '.build/software/preparation-done.mk'
+ # the project is built (when '.build/analysis/preparation-done.mk'
# doesn't yet exist). After that, if the user wants to re-do the
# preparation they have to use the '--prepare-redo' option.
- if ! [ -f .build/software/preparation-done.mk ] \
+ if ! [ -f .build/analysis/preparation-done.mk ] \
|| [ x"$prepare_redo" = x1 ]; then
controlled_env reproduce/analysis/make/top-prepare.mk
fi
- # Run the actual project.
+ # Call top-make (highest level analysis Makefile).
controlled_env reproduce/analysis/make/top-make.mk
+
+ # Register the time of the project's ending.
+ if [ $timing = 1 ]; then echo "end: $(date)" >> timing.txt; fi
;;
+
+
+
+ # Interactive shell of Maneage.
shell)
- # Make sure the configure script has been completed properly
- # ('configuration-done.txt' exists).
- if ! [ -f .build/software/configuration-done.txt ]; then
- configuration_necessary
- fi
+ # Make sure the configure script has been completed properly.
+ configuration_check
# Run the project's own shell without inheriting any environment
# from the host. The 'TERM' environment variable is necessary for
# tools like some text editors.
- bdir=`.local/bin/realpath .build`
+ bdir=$(.local/bin/realpath .build)
instdir="$bdir"/software/installed
bindir="$bdir"/software/installed/bin
rcfile=$(pwd)/reproduce/software/shell/bashrc.sh
.local/bin/env -i \
- HOME="$bdir" \
- TERM="$TERM" \
- PATH="$bindir" \
- CCACHE_DISABLE=1 \
- PROJECT_STATUS=shell \
- SHELL="$bindir"/bash \
- COLORTERM="$COLORTERM" \
- PROJECT_RCFILE="$rcfile" \
- LDFLAGS=-L"$instdir"/lib \
- CPPFLAGS=-I"$instdir"/include \
- LD_LIBRARY_PATH="$instdir"/lib \
- OMPI_MCA_plm_rsh_agent=/bin/false \
- PYTHONPATH="$instdir"/lib/python/site-packages \
- PYTHONPATH3="$instdir"/lib/python/site-packages \
- PS1="[\[\033[01;35m\]maneage@\h \W\[\033[32m\]\[\033[00m\]]$ " \
- "$bindir"/bash --noprofile --rcfile "$rcfile"
+ HOME="$bdir" \
+ TERM="$TERM" \
+ PATH="$bindir" \
+ CCACHE_DISABLE=1 \
+ PROJECT_STATUS=shell \
+ SHELL="$bindir"/bash \
+ COLORTERM="$COLORTERM" \
+ PROJECT_RCFILE="$rcfile" \
+ LDFLAGS=-L"$instdir"/lib \
+ CPPFLAGS=-I"$instdir"/include \
+ LD_LIBRARY_PATH="$instdir"/lib \
+ OMPI_MCA_plm_rsh_agent=/bin/false \
+ PYTHONPATH="$instdir"/lib/python/site-packages \
+ PYTHONPATH3="$instdir"/lib/python/site-packages \
+ PS1="[\[\033[01;35m\]maneage@\h \W\[\033[32m\]\[\033[00m\]]$ " \
+ "$bindir"/bash --noprofile --rcfile "$rcfile"
;;
+
+
+
# Operation not specified.
*)
cat <<EOF