diff options
Diffstat (limited to 'reproduce/software/shell/configure.sh')
-rwxr-xr-x | reproduce/software/shell/configure.sh | 315 |
1 files changed, 230 insertions, 85 deletions
diff --git a/reproduce/software/shell/configure.sh b/reproduce/software/shell/configure.sh index 812f3d3..4f71bee 100755 --- a/reproduce/software/shell/configure.sh +++ b/reproduce/software/shell/configure.sh @@ -2,7 +2,9 @@ # # Necessary preparations/configurations for the reproducible project. # -# Copyright (C) 2018-2021 Mohammad Akhlaghi <mohammad@akhlaghi.org> +# Copyright (C) 2018-2023 Mohammad Akhlaghi <mohammad@akhlaghi.org> +# Copyright (C) 2021-2023 Raul Infante-Sainz <infantesainz@gmail.com> +# Copyright (C) 2022-2023 Pedram Ashofteh Ardakani <pedramardakani@pm.me> # # This script is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -111,7 +113,7 @@ absolute_dir () # Check file permission handling (POSIX-compatibility) # ---------------------------------------------------- # -# Check if a `given' directory handles permissions as expected. +# Check if a 'given' directory handles permissions as expected. # # This is to prevent a known bug in the NTFS filesystem that prevents # proper installation of Perl, and probably some other packages. This @@ -119,15 +121,15 @@ absolute_dir () # file, and examines whether the given directory handles the file # permissions as expected. # -# Returns `0' if everything is fine, and `255' otherwise. Choosing `0' is -# to mimic the `$ echo $?' behavior, while choosing `255' is to prevent +# Returns '0' if everything is fine, and '255' otherwise. Choosing '0' is +# to mimic the '$ echo $?' behavior, while choosing '255' is to prevent # misunderstanding 0 and 1 as true and false. # # ===== CAUTION! ===== # # -# Since there is a `set -e' before running this function, the whole script -# stops and exits IF the `check_permission' (or any other function) returns -# anything OTHER than `0'! So, only use this function as a test. Here's a +# Since there is a 'set -e' before running this function, the whole script +# stops and exits IF the 'check_permission' (or any other function) returns +# anything OTHER than '0'! So, only use this function as a test. Here's a # minimal example: # # if $(check_permission $some_directory) ; then @@ -135,7 +137,7 @@ absolute_dir () # fi ; check_permission () { - # Make a `junk' file, activate its executable flag and record its + # Make a 'junk' file, activate its executable flag and record its # permissions generally. local junkfile="$1"/check_permission_tmp_file rm -f "$junkfile" @@ -157,7 +159,7 @@ check_permission () return 1 else # Setting permission SUCCESSFUL - return 0 + return 0 fi } @@ -189,7 +191,7 @@ free_space_warning() { fs_threshold=$1 fs_destpath="$2" - return $(df "$fs_destpath" \ + return $(df -P "$fs_destpath" \ | awk 'FNR==2 {if($4>'$fs_threshold') print 1; \ else print 0; }') } @@ -272,8 +274,17 @@ elif [ x$on_mac_os = xyes ]; then if [ x$hw_byteorder = x1234 ]; then byte_order="Little Endian"; elif [ x$hw_byteorder = x4321 ]; then byte_order="Big Endian"; fi - address_size_physical=$(sysctl -n machdep.cpu.address_bits.physical) - address_size_virtual=$(sysctl -n machdep.cpu.address_bits.virtual) + # On macOS, the way of obtaining the number of cores is different + # between Intel or Apple M1 CPUs. Here we disinguish between Apple M1 + # or others. + maccputype=$(sysctl -n machdep.cpu.brand_string) + if [ x"$maccputype" = x"Apple M1" ]; then + address_size_physical=$(sysctl -n machdep.cpu.thread_count) + address_size_virtual=$(sysctl -n machdep.cpu.logical_per_package) + else + address_size_physical=$(sysctl -n machdep.cpu.address_bits.physical) + address_size_virtual=$(sysctl -n machdep.cpu.address_bits.virtual) + fi address_sizes="$address_size_physical bits physical, " address_sizes+="$address_size_virtual bits virtual" else @@ -308,7 +319,9 @@ fi # system. Here, it is checked that this is the case, and if not, warn the user # about not having Xcode already installed. if [ x$on_mac_os = xyes ]; then - xcode=$(which xcodebuild) + + # 'which' isn't in POSIX, so we are using 'command -v' instead. + xcode=$(command -v xcodebuild) if [ x$xcode != x ]; then xcode_version=$(xcodebuild -version | grep Xcode) echo " " @@ -423,8 +436,19 @@ if ! [ -d $compilertestdir ]; then mkdir $compilertestdir; fi # Check C compiler # ---------------- +# +# Here we check if the C compiler works properly. About the "no warning" +# variable ('nowarnings'): +# +# -Wno-nullability-completeness: on macOS Big Sur 11.2.3 and Xcode 12.4, +# hundreds of 'nullability-completeness' warnings are printed which can +# be very annoying and even hide important errors or warnings. It is +# also harmless for our test here, so it is generally added. testprog=$compilertestdir/test testsource=$compilertestdir/test.c +if [ x$on_mac_os = xyes ]; then + noccwarnings="-Wno-nullability-completeness" +fi echo; echo; echo "Checking host C compiler ('$CC')..."; cat > $testsource <<EOF #include <stdio.h> @@ -432,7 +456,7 @@ cat > $testsource <<EOF int main(void){printf("...C compiler works.\n"); return EXIT_SUCCESS;} EOF -if $CC $testsource -o$testprog && $testprog; then +if $CC $noccwarnings $testsource -o$testprog && $testprog; then rm $testsource $testprog else rm $testsource @@ -465,8 +489,8 @@ fi # See if we need the dynamic-linker (-ldl) # ---------------------------------------- # -# Some programs (like Wget) need dynamic loading (using `libdl'). On -# GNU/Linux systems, we'll need the `-ldl' flag to link such programs. But +# Some programs (like Wget) need dynamic loading (using 'libdl'). On +# GNU/Linux systems, we'll need the '-ldl' flag to link such programs. But # Mac OS doesn't need any explicit linking. So we'll check here to see if # it is present (thus necessary) or not. cat > $testsource <<EOF @@ -498,7 +522,7 @@ fi # programs will go and find their necessary libraries on the host system. # # Another good advantage of shared libraries is that we can actually use -# the shared library tool of the system (`ldd' with GNU C Library) and see +# the shared library tool of the system ('ldd' with GNU C Library) and see # exactly where each linked library comes from. But in static building, # unless you follow the build closely, its not easy to see if the source of # the library came from the system or our build. @@ -535,7 +559,7 @@ fi # # On some systems (in particular Debian-based OSs), the static C library # and necessary headers in a non-standard place, and we can't build GCC. So -# we need to find them first. The `sys/cdefs.h' header is also in a +# we need to find them first. The 'sys/cdefs.h' header is also in a # similarly different location. sys_cpath="" sys_library_path="" @@ -566,7 +590,7 @@ fi # See if a link-able static C library exists # ------------------------------------------ # -# A static C library and the `sys/cdefs.h' header are necessary for +# A static C library and the 'sys/cdefs.h' header are necessary for # building GCC. if [ x"$host_cc" = x0 ]; then echo; echo; echo "Checking if static C library is available..."; @@ -742,9 +766,9 @@ EOF # What to do with possibly existing configuration file # ---------------------------------------------------- # -# `LOCAL.conf' is the top-most local configuration for the project. If it +# 'LOCAL.conf' is the top-most local configuration for the project. If it # already exists when this script is run, we'll make a copy of it as backup -# (for example the user might have ran `./project configure' by mistake). +# (for example the user might have ran './project configure' by mistake). printnotice=yes rewritepconfig=yes if [ -f $pconf ]; then @@ -761,7 +785,7 @@ fi # exists and we don't want to re-write it). if [ $rewritepconfig = no ]; then oldgroupname=$(awk '/GROUP-NAME/ {print $3; exit 0}' $pconf) - if [ "x$oldgroupname" = "x$reproducible_paper_group_name" ]; then + if [ "x$oldgroupname" = "x$maneage_group_name" ]; then just_a_place_holder_to_avoid_not_equal_test=1; else echo "-----------------------------" @@ -797,16 +821,31 @@ fi # need to check the host's available tool for downloading at this step. if [ $rewritepconfig = yes ]; then if type wget > /dev/null 2>/dev/null; then - name=$(which wget) + + # 'which' isn't in POSIX, so we are using 'command -v' instead. + name=$(command -v wget) + + # See if the host wget has the '--no-use-server-timestamps' option + # (for example wget 1.12 doesn't have it). If not, we'll have to + # remove it. This won't affect the analysis of Maneage in anyway, + # its just to avoid re-downloading if the server timestamps are + # bad; at the worst case, it will just cause a re-download of an + # input software source code (for data inputs, we will use our own + # wget that has this option). + tsname="no-use-server-timestamps" + tscheck=$(wget --help | grep $tsname || true) + if [ x"$tscheck" = x ]; then wgetts="" + else wgetts="--$tsname"; + fi # By default Wget keeps the remote file's timestamp, so we'll have # to disable it manually. - downloader="$name --no-use-server-timestamps -O"; + downloader="$name $wgetts -O"; elif type curl > /dev/null 2>/dev/null; then - name=$(which curl) + name=$(command -v curl) # - cURL doesn't keep the remote file's timestamp by default. - # - With the `-L' option, we tell cURL to follow redirects. + # - With the '-L' option, we tell cURL to follow redirects. downloader="$name -L -o" else cat <<EOF @@ -903,7 +942,7 @@ EOF # If it was newly created, it will be empty, so delete it. if ! [ "$(ls -A $bdir)" ]; then rm --dir "$bdir"; fi - # Inform the user that this is not acceptable and reset `bdir'. + # Inform the user that this is not acceptable and reset 'bdir'. bdir= echo " ** The build-directory cannot be under the source-directory." fi @@ -928,10 +967,10 @@ EOF fi fi - # If everything is still fine so far, see if we're able to - # manipulate file permissions in the directory's filesystem and if - # so, see if there is atleast 5GB free space. - if ! [ x"$bdir" = x ]; then + # If everything is still fine so far, see if we're able to + # manipulate file permissions in the directory's filesystem and if + # so, see if there is atleast 5GB free space. + if ! [ x"$bdir" = x ]; then if ! $(check_permission "$bdir"); then # Unable to handle permissions well bdir= @@ -950,7 +989,7 @@ EOF fi # If the build directory was good, the loop will stop, if not, - # reset `build_dir' to blank, so it continues asking for another + # reset 'build_dir' to blank, so it continues asking for another # directory and let the user know that they must select a new # directory. if [ x"$bdir" = x ]; then @@ -1079,7 +1118,7 @@ if [ $rewritepconfig = yes ]; then -e's|@ddir[@]|'"$ddir"'|' \ -e's|@sys_cpath[@]|'"$sys_cpath"'|' \ -e's|@downloader[@]|'"$downloader"'|' \ - -e's|@groupname[@]|'"$reproducible_paper_group_name"'|' \ + -e's|@groupname[@]|'"$maneage_group_name"'|' \ $pconf.in >> $pconf else # Read the values from existing configuration file. Note that the build @@ -1108,7 +1147,7 @@ else if [ x"$downloader" = x ]; then novalue="$novalue"DOWNLOADER; fi if [ x"$novalue" != x ]; then verr=1; err=1; fi - # Make sure `bdir' is an absolute path and it exists. + # Make sure 'bdir' is an absolute path and it exists. berr=0 ierr=0 bdir="$(absolute_dir "$inbdir")" @@ -1192,6 +1231,10 @@ if ! [ -d "$ibidir" ]; then mkdir "$ibidir"; fi ipydir="$verdir"/python if ! [ -d "$ipydir" ]; then mkdir "$ipydir"; fi +# R module versions and citation. +ircrandir="$verdir"/r-cran +if ! [ -d "$ircrandir" ]; then mkdir "$ircrandir"; fi + # Used software BibTeX entries. ictdir="$verdir"/cite if ! [ -d "$ictdir" ]; then mkdir "$ictdir"; fi @@ -1200,21 +1243,14 @@ if ! [ -d "$ictdir" ]; then mkdir "$ictdir"; fi itidir="$verdir"/tex if ! [ -d "$itidir" ]; then mkdir "$itidir"; fi -# Temporary software un-packing/build directory: if the host has the -# standard `/dev/shm' mounting-point, we'll do it in shared memory (on the -# RAM), to avoid harming/over-using the HDDs/SSDs. The RAM of most systems -# today (>8GB) is large enough for the parallel building of the software. -# -# For the name of the directory under `/dev/shm' (for this project), we'll -# use the names of the two parent directories to the current/running -# directory, separated by a `-' instead of `/'. We'll then appended that -# with the user's name (in case multiple users may be working on similar -# project names). Maybe later, we can use something like `mktemp' to add -# random characters to this name and make it unique to every run (even for -# a single user). -tmpblddir="$sdir"/build-tmp -rm -rf "$tmpblddir"/* "$tmpblddir" # If its a link, we need to empty its - # contents first, then itself. +# Some software install their libraries in '$(idir)/lib64'. But all other +# libraries are in '$(idir)/lib'. Since Maneage's build is only for a +# single architecture, we can set the '$(idir)/lib64' as a symbolic link to +# '$(idir)/lib' so all the libraries are always available in the same +# place. +instlibdir="$instdir"/lib +if ! [ -d "$instlibdir" ]; then mkdir "$instlibdir"; fi +ln -fs "$instlibdir" "$instdir"/lib64 @@ -1238,7 +1274,7 @@ if ! [ -d "$mtexdir" ]; then mkdir "$mtexdir"; fi # TeX build directory. If built in a group scenario, the TeX build # directory must be separate for each member (so they can work on their # relevant parts of the paper without conflicting with each other). -if [ "x$reproducible_paper_group_name" = x ]; then +if [ "x$maneage_group_name" = x ]; then texbdir="$texdir"/build else user=$(whoami) @@ -1287,29 +1323,106 @@ rm -f .gnuastro -# Set the top-level shared memory location. + + +# Software building directory (possibly in RAM) +# --------------------------------------------- +# +# Building the software for the project will need the creation of many +# small temporary files that will ultimately be deleted. To avoid harming +# HDDs/SSDs and improve speed, it is therefore better to build them in the +# RAM when possible. The RAM of most systems today (>8GB) is large enough +# for the parallel building of the software. + +# Set the top-level shared memory location. Currently there is only one +# standard location (for GNU/Linux OSs), so doing this check here and the +# main job below may seem redundant. However, it is written separately from +# the main code below because later, we expect to add more possible +# mounting locations (for other OSs). if [ -d /dev/shm ]; then shmdir=/dev/shm else shmdir="" fi -# If a shared memory mounted directory exists and there is enough space -# there (in RAM), build a temporary directory for this project. -needed_space=2000000 +# If a shared memory mounted directory exists and has the necessary +# conditions, set that directory to build software. if [ x"$shmdir" != x ]; then + + # Make sure it has enough space. + needed_space=2000000 available_space=$(df "$shmdir" | awk 'NR==2{print $4}') if [ $available_space -gt $needed_space ]; then + + # Set the Maneage-specific directory within the shared + # memory. We'll use the names of the two parent directories to the + # current/running directory, separated by a '-' instead of + # '/'. We'll then appended that with the user's name (in case + # multiple users may be working on similar project names). + # + # Maybe later, we can use something like 'mktemp' to add random + # characters to this name and make it unique to every run (even for + # a single user). dirname=$(pwd | sed -e's/\// /g' \ - | awk '{l=NF-1; printf("%s-%s",$l, $NF)}') + | awk '{l=NF-1; printf("%s-%s", $l, $NF)}') tbshmdir="$shmdir"/"$dirname"-$(whoami) - if ! [ -d "$tbshmdir" ]; then mkdir "$tbshmdir"; fi + + # Try to make the directory if it does not yet exist. A failed + # directory creation will be tested for a few lines later, when + # testing for the existence and executability of a test file. + if ! [ -d "$tbshmdir" ]; then (mkdir "$tbshmdir" || true); fi + + # Some systems may protect '/dev/shm' against the right to execute + # programs by ordinary users. We thus need to check that the device + # allows execution within this directory by this user. + shmexecfile="$tbshmdir"/shm-execution-check.sh + rm -f $shmexecfile # We also don't want any existing flags. + + # Create the file to be executed, but do not fail fatally if it + # cannot be created. We will check a few lines later if the file + # really exists. + (cat > "$shmexecfile" <<EOF || true) +#!/bin/sh +echo "This file successfully executed." +EOF + + # If the file was successfully created, then make the file + # executable and see if it runs. If not, set 'tbshmdir' to an empty + # string so it is not used in later steps. In any case, delete the + # temporary file afterwards. + # + # We aren't adding '&> /dev/null' after the execution command + # because it can produce false failures randomly on some systems. + if [ -e "$shmexecfile" ]; then + + # Add the executable flag. + chmod +x "$shmexecfile" + + # The following line tries to execute the file. + if "$shmexecfile"; then + # Successful execution. The colon is a "no-op" (no + # operation) shell command. + : + else + tbshmdir="" + fi + rm "$shmexecfile" + else + tbshmdir="" + fi fi else tbshmdir="" fi -# If a shared memory directory was created set `build-tmp' to be a -# symbolic link to it. Otherwise, just build the temporary build -# directory under the project build directory. + + + + +# If a shared memory directory was created, set the software building +# directory to be a symbolic link to it. Otherwise, just build the +# temporary build directory under the project's build directory. +tmpblddir="$sdir"/build-tmp +rm -rf "$tmpblddir"/* "$tmpblddir" # If it is a link, we need to empty + # its contents first, then itself. if [ x"$tbshmdir" = x ]; then mkdir "$tmpblddir"; else ln -s "$tbshmdir" "$tmpblddir"; fi @@ -1320,6 +1433,9 @@ fi # Inform the user that the build process is starting # ------------------------------------------------- +# +# Everything is ready, let the user know that the building is going to +# start. if [ $printnotice = yes ]; then tsec=10 cat <<EOF @@ -1328,12 +1444,13 @@ if [ $printnotice = yes ]; then Building dependencies ... ------------------------- -Necessary dependency programs and libraries will be built in +Necessary dependency programs and libraries will be installed in $sdir/installed -NOTE: the built software will NOT BE INSTALLED on your system (no root -access is required). They are only for local usage by this project. +NOTE: the built software will NOT BE INSTALLED in standard places of your +OS (so no root access is required). They are only for local usage by this +project. **TIP**: you can see which software are being installed at every moment with the following command. See "Inspecting status" section of @@ -1382,7 +1499,7 @@ fi # See if the linker accepts -Wl,-rpath-link # ----------------------------------------- # -# `-rpath-link' is used to write the information of the linked shared +# '-rpath-link' is used to write the information of the linked shared # library into the shared object (library or program). But some versions of # LLVM's linker don't accept it an can cause problems. # @@ -1415,13 +1532,13 @@ rm -rf $compilertestdir -# Paths needed by the host compiler (only for `basic.mk') +# Paths needed by the host compiler (only for 'basic.mk') # ------------------------------------------------------- # # At the end of the basic build, we need to build GCC. But GCC will build # in multiple phases, making its own simple compiler in order to build # itself completely. The intermediate/simple compiler doesn't recognize -# some system specific locations like `/usr/lib/ARCHITECTURE' that some +# some system specific locations like '/usr/lib/ARCHITECTURE' that some # operating systems use. We thus need to tell the intermediate compiler # where its necessary libraries and headers are. if [ x"$sys_library_path" != x ]; then @@ -1458,18 +1575,19 @@ fi # which will download the DOI-resolved webpage, and extract the Zenodo-URL # of the most recent version from there (using the 'coreutils' tarball as # an example, the directory part of the URL for all the other software are -# the same). +# the same). This is not done if the option '--debug' is used. +zenodourl="" user_backup_urls="" zenodocheck=.build/software/zenodo-check.html -if $downloader $zenodocheck https://doi.org/10.5281/zenodo.3883409; then - zenodourl=$(sed -n -e'/coreutils/p' $zenodocheck \ - | sed -n -e'/http/p' \ - | tr ' ' '\n' \ - | grep http \ - | sed -e 's/href="//' -e 's|/coreutils| |' \ - | awk 'NR==1{print $1}') -else - zenodourl="" +if [ x$debug = x ]; then + if $downloader $zenodocheck https://doi.org/10.5281/zenodo.3883409; then + zenodourl=$(sed -n -e'/coreutils/p' $zenodocheck \ + | sed -n -e'/http/p' \ + | tr ' ' '\n' \ + | grep http \ + | sed -e 's/href="//' -e 's|/coreutils| |' \ + | awk 'NR==1{print $1}') + fi fi rm -f $zenodocheck @@ -1490,6 +1608,7 @@ user_backup_urls="$user_backup_urls $zenodourl" # (compression program), GNU Make (that 'basic.mk' is written in), Dash # (minimal Bash-like shell) and Flock (to lock files and enable serial # download). +export on_mac_os ./reproduce/software/shell/pre-make-build.sh \ "$bdir" "$ddir" "$downloader" "$user_backup_urls" @@ -1497,6 +1616,28 @@ user_backup_urls="$user_backup_urls $zenodourl" +# Corrections for debugging mode +# ------------------------------ +# +# If the user wants to debug the software configuration, they are usually +# focused on the building of the single problematic software. Therefore, +# the default multi-threaded execution of Make with the '--keep-going' +# option are very annoying and can even hide important warnings. Recall +# that with '--keep-going', Make will continue building other targets, even +# if one target fails. When the user runs './project configure --debug', +# the 'debug' variable will not be empty and this mode will be activated. +if [ x$debug = x ]; then + keepgoing="--keep-going" +else + jobs=1 + numthreads=1 + keepgoing="" +fi + + + + + # Build other basic tools our own GNU Make # ---------------------------------------- # @@ -1504,7 +1645,7 @@ user_backup_urls="$user_backup_urls $zenodourl" # Bash, Make, or AWK. In this step, we'll install such low-level basic # tools, but we have to be very portable (and use minimal features in all). echo; echo "Building necessary software (if necessary)..." -.local/bin/make -k -f reproduce/software/make/basic.mk \ +.local/bin/make $keepgoing -f reproduce/software/make/basic.mk \ user_backup_urls="$user_backup_urls" \ sys_library_path=$sys_library_path \ rpath_command=$rpath_command \ @@ -1532,7 +1673,7 @@ else numthreads=$jobs fi .local/bin/env -i HOME=$bdir \ - .local/bin/make -k -f reproduce/software/make/high-level.mk \ + .local/bin/make $keepgoing -f reproduce/software/make/high-level.mk \ user_backup_urls="$user_backup_urls" \ sys_library_path=$sys_library_path \ rpath_command=$rpath_command \ @@ -1577,17 +1718,21 @@ is not used at all during the analysis. Therefore, if you don't need the final PDF, and just want to do the analysis, you can safely ignore this warning and continue. -If you later have internet access and would like to add TeX live to your -project, please delete the respective files, then re-run configure as shown -below. +If you later have internet access and would like to add TeX Live to your +project, then please delete the following two files: rm .local/version-info/tex/texlive-ready-tlmgr + rm .build/software/tarballs/install-tl-unx.tar.gz + +and re-run configure: + ./project configure -e !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF + sleep 10 # increase the chance that an interactive user reads this message fi @@ -1601,7 +1746,7 @@ fi # software. prepare_name_version () { - # First see if the (possible) `*' in the input arguments corresponds to + # First see if the (possible) '*' in the input arguments corresponds to # anything. Note that some of the given directories may be empty (no # software installed). hasfiles=0 @@ -1702,9 +1847,9 @@ hw_class_fixed="$(echo $hw_class | sed -e 's/_/\\_/')" # --------------------------------- # # By the time the script reaches here the temporary software build -# directory should be empty, so just delete it. Note `tmpblddir' may be a +# directory should be empty, so just delete it. Note 'tmpblddir' may be a # symbolic link to shared memory. So, to work in any scenario, first delete -# the contents of the directory (if it has any), then delete `tmpblddir'. +# the contents of the directory (if it has any), then delete 'tmpblddir'. .local/bin/rm -rf $tmpblddir/* $tmpblddir @@ -1725,10 +1870,10 @@ echo `.local/bin/date` > $finaltarget # # The configuration is now complete, we can inform the user on the next # step(s) to take. -if [ x$reproducible_paper_group_name = x ]; then +if [ x$maneage_group_name = x ]; then buildcommand="./project make -j8" else - buildcommand="./project make --group=$reproducible_paper_group_name -j8" + buildcommand="./project make --group=$maneage_group_name -j8" fi cat <<EOF |