#!/bin/sh # # Necessary preparations/configurations for the reproducible project. # # Copyright (C) 2018-2025 Mohammad Akhlaghi <mohammad@akhlaghi.org> # Copyright (C) 2021-2025 Raul Infante-Sainz <infantesainz@gmail.com> # Copyright (C) 2022-2025 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 # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This script 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 script. If not, see <http://www.gnu.org/licenses/>. # Script settings # --------------- # Stop the script if there are any errors. set -e # Project-specific settings # ------------------------- # # The variables defined here may be different between different # projects. Ideally, they should be detected automatically, but we haven't # had the chance to implement it yet (please help if you can!). Until then, # please set them based on your project (if they differ from the core # branch). need_gfortran=0 # Internal source directories # --------------------------- # # These are defined to help make this script more readable. topdir="$(pwd)" optionaldir="/optional/path" adir=reproduce/analysis/config cdir=reproduce/software/config pconf=$cdir/LOCAL.conf ptconf=$cdir/LOCAL_tmp.conf poconf=$cdir/LOCAL_old.conf depverfile=$cdir/versions.conf depshafile=$cdir/checksums.conf # Notice for top of generated files # --------------------------------- # # In case someone opens the files output from the configuration scripts in # a text editor and wants to edit them, it is important to let them know # that their changes are not going to be permenant. create_file_with_notice () { if echo "# IMPORTANT: file can be RE-WRITTEN after './project configure'" > "$1" then echo "#" >> "$1" echo "# This file was created during configuration" >> "$1" echo "# ('./project configure'). Therefore, it is not under" >> "$1" echo "# version control and any manual changes to it will be" >> "$1" echo "# over-written if the project re-configured." >> "$1" echo "#" >> "$1" else echo; echo "Can't write to $1"; echo; exit 1 fi } # Get absolute address # -------------------- # # Since the build directory will go into a symbolic link, we want it to be # an absolute address. With this function we can make sure of that. absolute_dir () { address="$1" if stat "$address" 1> /dev/null; then echo "$(cd "$(dirname "$1")" && pwd )/$(basename "$1")" else exit 1; fi } # Check file permission handling (POSIX-compatibility) # ---------------------------------------------------- # # 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 # function receives the directory as an argument and then, creates a dummy # 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 # 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 # minimal example: # # if $(check_permission $some_directory) ; then # echo "yay"; else "nay"; # fi ; check_permission () { # Make a 'junk' file, activate its executable flag and record its # permissions generally. local junkfile="$1"/check_permission_tmp_file rm -f "$junkfile" echo "Don't let my short life go to waste" > "$junkfile" chmod +x "$junkfile" local perm_before=$(ls -l "$junkfile" | awk '{print $1}') # Now, remove the executable flag and record the permissions. chmod -x "$junkfile" local perm_after=$(ls -l "$junkfile" | awk '{print $1}') # Clean up before leaving the function rm -f "$junkfile" # If the permissions are equal, the filesystem doesn't allow # permissions. if [ $perm_before = $perm_after ]; then # Setting permission FAILED return 1 else # Setting permission SUCCESSFUL return 0 fi } # Check if there is enough free space available in the build directory # -------------------------------------------------------------------- # # Use this function to check if there is enough free space in a # directory. It is meant to be passed to the 'if' statement in the # shell. So if there is enough space, it returns 0 (which translates to # TRUE), otherwise, the funcion returns 1 (which translates to FALSE). # # Expects to be called with two arguments, the first is the threshold and # the second is the desired directory. The 'df' function checks the given # path to see where it is mounted on, and how much free space there is on # that partition (in units of 1024 bytes). # # synopsis: # $ free_space_warning <acceptable_threshold> <path-to-check> # # example: # To check if there is 5MB of space available in /path/to/check # call the command with arguments as shown below: # $ free_space_warning 5000 /path/to/check/free/space free_space_warning() { fs_threshold=$1 fs_destpath="$2" return $(df -P "$fs_destpath" \ | awk 'FNR==2 {if($4>'$fs_threshold') print 1; \ else print 0; }') } # See if we are on a Linux-based system # -------------------------------------- # # Some features are tailored to GNU/Linux systems, while the BSD-based # behavior is different. Initially we only tested macOS (hence the name of # the variable), but as FreeBSD is also being inlucded in our tests. As # more systems get used, we need to tailor these kinds of things better. kernelname=$(uname -s) if [ x$kernelname = xLinux ]; then on_mac_os=no # Don't forget to add the respective C++ compiler below (leave 'cc' in # the end). c_compiler_list="gcc clang cc" elif [ x$kernelname = xDarwin ]; then host_cc=1 on_mac_os=yes # Don't forget to add the respective C++ compiler below (leave 'cc' in # the end). c_compiler_list="clang gcc cc" else on_mac_os=no cat <<EOF ______________________________________________________ !!!!!!! WARNING !!!!!!! Maneage has been tested on GNU/Linux and Darwin (macOS) systems. But, it seems that the current system is not GNU/Linux or Darwin (macOS). If you notice any problem during the configure phase, please contact us with this web-form: https://savannah.nongnu.org/support/?func=additem&group=reproduce The configuration will continue in 10 seconds... !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF sleep 10 fi # Collect CPU information # ----------------------- # # When the project is built, the type of a machine that built it also has # to to be documented. This way, if different results or behaviors are # observed in software-related or analysis-related phases of the project, # it would be easier to track down the root cause. So far this is just # later recorded as a LaTeX macro to be put in the final paper, but it # could be used in a more systematic way to optimize/revise project # workflow and build. hw_class=$(uname -m) if [ x$kernelname = xLinux ]; then byte_order=$(lscpu \ | grep 'Byte Order' \ | awk '{ \ for(i=3;i<NF;++i) \ printf "%s ", $i; \ printf "%s", $NF}') address_sizes=$(lscpu \ | grep 'Address sizes' \ | awk '{ \ for(i=3;i<NF;++i) \ printf "%s ", $i; \ printf "%s", $NF}') elif [ x$on_mac_os = xyes ]; then hw_byteorder=$(sysctl -n hw.byteorder) if [ x$hw_byteorder = x1234 ]; then byte_order="Little Endian"; elif [ x$hw_byteorder = x4321 ]; then byte_order="Big Endian"; fi # 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 byte_order="unrecognized" address_sizes="unrecognized" cat <<EOF ______________________________________________________ !!!!!!! WARNING !!!!!!! Machine byte order and address sizes could not be recognized. You can add the necessary steps in the 'reproduce/software/shell/configure.sh' script (just above this error message), or contact us with this web-form: https://savannah.nongnu.org/support/?func=additem&group=reproduce !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF sleep 5 fi # Check for Xcode in macOS systems # -------------------------------- # # When trying to build Maneage on macOS systems, there are some problems # related with the Xcode and Command Line Tools. As a consequnce, in order to # avoid these error it is highly recommended to install Xcode in the host # 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 # '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 " " echo "$xcode_version already installed in the system" echo " " else cat <<EOF ______________________________________________________ !!!!!!! WARNING !!!!!!! Maneage has been tested Darwin (macOS) systems with host Xcode installation. However, Xcode cannot be found in this system. As a consequence, the configure step may fail at some point. If this is the case, please install Xcode and try to run again the configure step. If the problem still persist after installing Xcode, please contact us with this web-form: https://savannah.nongnu.org/support/?func=additem&group=reproduce The configuration will continue in 5 seconds ... !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF sleep 5 fi fi # Check for C/C++ compilers # ------------------------- # # To build the software, we'll need some basic tools (the C/C++ compilers # in particular) to be present. has_compilers=no for c in $c_compiler_list; do # Set the respective C++ compiler. if [ x$c = xcc ]; then cplus=c++; elif [ x$c = xgcc ]; then cplus=g++; elif [ x$c = xclang ]; then cplus=clang++; else cat <<EOF ______________________________________________________ !!!!!!! BUG !!!!!!! The respective C++ compiler executable name for the C compiler '$c' hasn't been set! You can add it in the 'reproduce/software/shell/configure.sh' script (just above this error message), or contact us with this web-form: https://savannah.nongnu.org/support/?func=additem&group=reproduce !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF exit 1 fi # Check if they exist. if type $c > /dev/null 2>/dev/null; then export CC=$c; if type $cplus > /dev/null 2>/dev/null; then export CXX=$cplus has_compilers=yes break fi fi done if [ x$has_compilers = xno ]; then cat <<EOF ______________________________________________________ !!!!!!! C/C++ Compiler NOT FOUND !!!!!!! To build this project's software, the host system needs to have both C and C++ compilers. The commands that were checked are listed below: cc, c++ Generic C/C++ compiler (possibly links to below). gcc, g++ Part of GNU Compiler Collection (GCC). clang, clang++ Part of LLVM compiler infrastructure. If your compiler is not checked, please get in touch with the web-form below, so we add it. We will try our best to add it soon. Until then, please install at least one of these compilers on your system to proceed. https://savannah.nongnu.org/support/?func=additem&group=reproduce NOTE: for macOS systems, the LLVM compilers that are provided in a native Xcode install are recommended. There are known problems with GCC on macOS. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF exit 1 fi # Special directory for compiler testing # -------------------------------------- # # This directory will be deleted when the compiler testing is finished. compilertestdir=.compiler_test_dir_please_delete 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> #include <stdlib.h> int main(void){printf("...C compiler works.\n"); return EXIT_SUCCESS;} EOF if $CC $noccwarnings $testsource -o$testprog && $testprog; then rm $testsource $testprog else rm $testsource cat <<EOF ______________________________________________________ !!!!!!! C compiler doesn't work !!!!!!! Host C compiler ('$CC') can't build a simple program. A working C compiler is necessary for building the project's software. Please use the error message above to find a good solution and re-run the project configuration. If you can't find a solution, please send the error message above to the link below and we'll try to help https://savannah.nongnu.org/support/?func=additem&group=reproduce !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF exit 1 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 # 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 #include <stdio.h> #include <dlfcn.h> int main(void) { void *handle=dlopen ("/lib/CEDD_LIB.so.6", RTLD_LAZY); return 0; } EOF if $CC $testsource -o$testprog 2>/dev/null > /dev/null; then needs_ldl=no; else needs_ldl=yes; fi # See if the C compiler can build static libraries # ------------------------------------------------ # # We are manually only working with shared libraries: because some # high-level programs like Wget and cURL need dynamic linking and if we # build the libraries statically, our own builds will be ignored and these # 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 # 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. static_build=no # Print warning if the host CC is to be used. if [ x$host_cc = x1 ]; then cat <<EOF ______________________________________________________ !!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!! The GNU Compiler Collection (GCC, including compilers for C, C++, Fortran and etc) is currently not built on macOS systems for this project. To build the project's necessary software on this system, we need to use your system's C compiler. Project's configuration will continue in 5 seconds. ______________________________________________________ EOF sleep 5 fi # Necessary C library element positions # ------------------------------------- # # 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 # similarly different location. sys_cpath="" sys_library_path="" if [ x"$on_mac_os" != xyes ]; then # Get the GCC target name of the compiler, when its given, special # C libraries and headers are in a sub-directory of the host. gcctarget=$(gcc -v 2>&1 \ | tr ' ' '\n' \ | awk '/\-\-target/' \ | sed -e's/\-\-target=//') if [ x"$gcctarget" != x ]; then if [ -f /usr/lib/$gcctarget/libc.a ]; then export sys_library_path=/usr/lib/$gcctarget export sys_cpath=/usr/include/$gcctarget fi fi # For a check: #echo "sys_library_path: $sys_library_path" #echo "sys_cpath: $sys_cpath" fi # See if a link-able static C library exists # ------------------------------------------ # # 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..."; cat > $testsource <<EOF #include <stdio.h> #include <stdlib.h> #include <sys/cdefs.h> int main(void){printf("...yes\n"); return EXIT_SUCCESS;} EOF cc_call="$CC $testsource $CPPFLAGS $LDFLAGS -o$testprog -static -lc" if $cc_call && $testprog; then gccwarning=0 rm $testsource $testprog else echo; echo "Compilation command:"; echo "$cc_call" rm $testsource gccwarning=1 host_cc=1 cat <<EOF _______________________________________________________ !!!!!!!!!!!! Warning !!!!!!!!!!!! The 'sys/cdefs.h' header cannot be included, or a usable static C library ('libc.a', in any directory) cannot be used with the current settings of this system. SEE THE ERROR MESSAGE ABOVE. Because of this, we can't build GCC. You either 1) don't have them, or 2) the default system environment aren't enough to find them. 1) If you don't have them, your operating system provides them as separate packages that you must manually install. Please look into your operating system documentation or contact someone familiar with it. For example on some Redhat-based GNU/Linux distributions, the static C library package can be installed with this command: $ sudo yum install glibc-static 2) If you have 'libc.a' and 'sys/cdefs.h', but in a non-standard location (for example in '/PATH/TO/STATIC/LIBC/libc.a' and '/PATH/TO/SYS/CDEFS_H/sys/cdefs.h'), please run the commands below, then re-configure the project to fix this problem. $ export LDFLAGS="-L/PATH/TO/STATIC/LIBC \$LDFLAGS" $ export CPPFLAGS="-I/PATH/TO/SYS/CDEFS_H \$LDFLAGS" _______________________________________________________ EOF fi fi # Print a warning if GCC is not meant to be built. if [ x"$gccwarning" = x1 ]; then cat <<EOF PLEASE SEE THE WARNINGS ABOVE. Since GCC is pretty low-level, this configuration script will continue in 5 seconds and use your system's C compiler (it won't build a custom GCC). But please consider installing the necessary package(s) to complete your C compiler, then re-run './project configure'. Project's configuration will continue in 5 seconds. EOF sleep 5 fi # Fortran compiler # ---------------- # # If GCC is ultimately build within the project, the user won't need to # have a fortran compiler: we'll build it internally for high-level # programs with GCC. However, when the host C compiler is to be used, the # user needs to have a Fortran compiler available. if [ $host_cc = 1 ]; then # If a Fortran compiler is necessary, see if 'gfortran' exists and can # be used. if [ "x$need_gfortran" = "x1" ]; then # First, see if 'gfortran' exists. hasfc=0; if type gfortran > /dev/null 2>/dev/null; then hasfc=1; fi if [ $hasfc = 0 ]; then cat <<EOF ______________________________________________________ !!!!!!! Fortran Compiler NOT FOUND !!!!!!! This project requires a Fortran compiler. However, the project won't/can't build its own GCC on this system (GCC also builds the 'gfortran' Fortran compiler). Please install 'gfortran' using your operating system's package manager, then re-run this configure script to continue the configuration. Currently the only Fortran compiler we check is 'gfortran'. If you have a Fortran compiler that is not checked, please get in touch with us (with the form below) so we add it: https://savannah.nongnu.org/support/?func=additem&group=reproduce ______________________________________________________ EOF exit 1 fi # Then, see if the Fortran compiler works testsourcef=$compilertestdir/test.f echo; echo; echo "Checking host Fortran compiler..."; echo " PRINT *, \"... Fortran Compiler works.\"" > $testsourcef echo " END" >> $testsourcef if gfortran $testsourcef -o$testprog && $testprog; then rm $testsourcef $testprog else rm $testsourcef cat <<EOF ______________________________________________________ !!!!!!! Fortran compiler doesn't work !!!!!!! Host Fortran compiler ('gfortran') can't build a simple program. A working Fortran compiler is necessary for this project. Please use the error message above to find a good solution in your operating system and re-run the project configuration. If you can't find a solution, please send the error message above to the link below and we'll try to help https://savannah.nongnu.org/support/?func=additem&group=reproduce ______________________________________________________ EOF exit 1 fi fi fi # Inform the user # --------------- # # Print some basic information so the user gets a feeling of what is going # on and is prepared on what will happen next. cat <<EOF ----------------------------- Project's local configuration ----------------------------- Below, some basic local settings will be requested to start building Maneage on this system (if they haven't been specified on the command-line). This includes the top-level directories that Maneage will use on your system. Most are only optional and you can simply press ENTER, without giving any value (in this case, Maneage will download the necessary components from pre-defined webpages). It is STRONGLY recommended to read the description above each question before answering it. EOF # What to do with possibly existing configuration file # ---------------------------------------------------- # # '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). printnotice=yes rewritepconfig=yes if [ -f $pconf ]; then if [ $existing_conf = 1 ]; then printnotice=no if [ -f $pconf ]; then rewritepconfig=no; fi fi fi # Make sure the group permissions satisfy the previous configuration (if it # 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$maneage_group_name" ]; then just_a_place_holder_to_avoid_not_equal_test=1; else echo "-----------------------------" echo "!!!!!!!! ERROR !!!!!!!!" echo "-----------------------------" if [ "x$oldgroupname" = x ]; then status="NOT configured for groups" confcommand="./project configure" else status="configured for '$oldgroupname' group" confcommand="./project configure --group=$oldgroupname" fi echo "Project was previously $status!" echo "Either enable re-write of this configuration file," echo "or re-run this configuration like this:" echo echo " $confcommand"; echo exit 1 fi fi # Identify the downloader tool # ---------------------------- # # After this script finishes, we will have both Wget and cURL for # downloading any necessary dataset during the processing. However, to # complete the configuration, we may also need to download the source code # of some necessary software packages (including the downloaders). So we # 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 # '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 $wgetts -O"; elif type curl > /dev/null 2>/dev/null; then 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. downloader="$name -L -o" else cat <<EOF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Couldn't find GNU Wget, or cURL on this system. These programs are used for downloading necessary programs and data if they aren't already present (in directories that you can specify with this configure script). Therefore if the necessary files are not present, the project will crash. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! EOF downloader="no-downloader-found" fi; fi # Build directory # --------------- currentdir="$(pwd)" if [ $rewritepconfig = yes ]; then cat <<EOF =============== Build directory =============== The project's "source" (this directory) and "build" directories are treated separately. This greatly helps in managing the many intermediate files that are created during the build. The intermediate build files don't need to be archived or backed up: you can always re-build them with the contents of the source directory. The build directory also needs a fairly large amount of free space (at least several gigabytes), while the source directory (all plain text, ignoring the .git directory if you have it) will usually be a megabyte or less. The link '.build' (a symbolic link to the build directory) will be created during this configuration. It can help encourage you to set the actual build directory to a very different path to that of the source (the build directory should be considered as a large volume directory of throwaway space that can be casually deleted), while making it easy to access from here without having to remember the particular path. --- CAUTION --- Do not choose any directory under the top source directory (this directory). The build directory cannot be a subdirectory of the source. --------------- EOF bdir= junkname=pure-junk-974adfkj38 while [ x"$bdir" = x ] do # Ask the user (if not already set on the command-line). if [ x"$build_dir" = x ]; then if read -p"Please enter the top build directory: " build_dir; then just_a_place_holder_to_avoid_not_equal_test=1; else printf "ERROR: shell is in non-interactive-mode and no " printf "build directory specified. The build directory " printf "(described above) is mandatory, configuration " printf "can't continue. Please use '--build-dir' to " printf "specify a build directory non-interactively" exit 1 fi fi # If it exists, see if we can write in it. If not, try making it. if [ -d "$build_dir" ]; then if echo "test" > "$build_dir"/$junkname ; then rm -f "$build_dir"/$junkname instring="the already existing" bdir="$(absolute_dir "$build_dir")" else echo " ** Can't write in '$build_dir'"; fi else if mkdir "$build_dir" 2> /dev/null; then instring="the newly created" bdir="$(absolute_dir "$build_dir")" else echo " ** Can't create '$build_dir'"; fi fi # If it is given, make sure it isn't a subdirectory of the source # directory. if ! [ x"$bdir" = x ]; then if echo "$bdir/" \ | grep '^'"$currentdir/" 2> /dev/null > /dev/null; then # 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'. bdir= echo " ** The build-directory cannot be under the source-directory." fi fi # If things are fine so far, make sure it does not contain a space # or other meta-characters which can cause problems during software # building. if ! [ x"$bdir" = x ]; then hasmeta=0; case $bdir in *['!'\@\#\$\%\^\&\*\(\)\+\;\ ]* ) hasmeta=1 ;; esac if [ $hasmeta = 1 ]; then # If it was newly created, it will be empty, so delete it. if ! [ "$(ls -A "$bdir")" ]; then rm --dir "$bdir"; fi # Inform the user and set 'bdir' to empty again. bdir= echo " ** Build directory should not contain meta-characters" echo " ** (like SPACE, %, \$, !, ;, or parenthesis, among " echo " ** others): they can interrup the build for some software." 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 ! $(check_permission "$bdir"); then # Unable to handle permissions well bdir= echo " ** File permissions can't be modified in this directory" else # Able to handle permissions, now check for 5GB free space # in the given partition (note that the number is in units # of 1024 bytes). If this is not the case, print a warning. if $(free_space_warning 5000000 "$bdir"); then echo " !! LESS THAN 5GB FREE SPACE IN: $bdir" echo " !! We recommend choosing another partition." echo " !! Build will continue in 5 seconds..." sleep 5 fi fi fi # If the build directory was good, the loop will stop, if not, # 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 build_dir= echo " ** Please select another directory." echo "" else echo " -- Build directory set to ($instring): '$bdir'" fi done fi # Input directory # --------------- if [ x"$input_dir" = x ]; then indir="$optionaldir" else indir="$input_dir" fi noninteractive_sleep=2 if [ $rewritepconfig = yes ] && [ x"$input_dir" = x ]; then cat <<EOF ---------------------------------- (OPTIONAL) Input dataset directory ---------------------------------- This project needs the dataset(s) listed in the following file: reproduce/analysis/config/INPUTS.conf If you already have a copy of them on this system, please specify the directory hosting them on this system. If they aren't present, they will be downloaded automatically when necessary. NOTE I: This directory is optional. If not given, or if the files can't be found inside it, any necessary file will be downloaded directly in the build directory and used. NOTE II: If a directory is given, it will be used as read-only. Nothing will be written into it, so no writing permissions are necessary. TIP: If you have these files in multiple directories on your system and don't want to make duplicates, you can create symbolic links to them and put those symbolic links in the given top-level directory. EOF # Read the input directory if interactive mode is enabled. if read -p"(OPTIONAL) Input datasets directory ($indir): " inindir; then just_a_place_holder_to_avoid_not_equal_test=1; else echo "WARNING: interactive-mode seems to be disabled!" echo "If you have a local copy of the inputs, use '--input-dir'." echo "... project configuration will continue in $noninteractive_sleep sec ..." sleep $noninteractive_sleep fi # In case an input-directory is given, write it in 'indir'. if [ x$inindir != x ]; then indir="$(absolute_dir "$inindir")" echo " -- Using '$indir'" fi fi # Dependency tarball directory # ---------------------------- if [ x"$software_dir" = x ]; then ddir=$optionaldir else ddir=$software_dir fi if [ $rewritepconfig = yes ] && [ x"$software_dir" = x ]; then cat <<EOF --------------------------------------- (OPTIONAL) Software tarball directory --------------------------------------- To ensure an identical build environment, the project will use its own build of the programs it needs. Therefore the tarball of the relevant programs are necessary. If you don't specify any directory here, or it doesn't contain the tarball of a dependency, it is necessary to have an internet connection because the project will download the tarballs it needs automatically. EOF # Read the software directory if interactive mode is enabled. if read -p"(OPTIONAL) Directory of dependency tarballs ($ddir): " tmpddir; then just_a_place_holder_to_avoid_not_equal_test=1; else echo "WARNING: interactive-mode seems to be disabled!" echo "If you have a local copy of the software source, use '--software-dir'." echo "... project configuration will continue in $noninteractive_sleep sec ..." sleep $noninteractive_sleep fi # If given, write the software directory. if [ x"$tmpddir" != x ]; then ddir="$(absolute_dir "$tmpddir")" echo " -- Using '$ddir'" fi fi # Write the parameters into the local configuration file. if [ $rewritepconfig = yes ]; then # Add commented notice. create_file_with_notice $pconf # Write the values. sed -e's|@bdir[@]|'"$bdir"'|' \ -e's|@indir[@]|'"$indir"'|' \ -e's|@ddir[@]|'"$ddir"'|' \ -e's|@sys_cpath[@]|'"$sys_cpath"'|' \ -e's|@downloader[@]|'"$downloader"'|' \ -e's|@groupname[@]|'"$maneage_group_name"'|' \ $pconf.in >> $pconf else # Read the values from existing configuration file. Note that the build # directory may have space characters. Even though we currently check # against it, we hope to be able to remove this condition in the # future. inbdir=$(awk '$1=="BDIR" { for(i=3; i<NF; i++) \ printf "%s ", $i; \ printf "%s", $NF }' $pconf) # Read the software directory (same as 'inbdir' above about space). ddir=$(awk '$1=="DEPENDENCIES-DIR" { for(i=3; i<NF; i++) \ printf "%s ", $i; \ printf "%s", $NF}' $pconf) # The downloader command may contain multiple elements, so we'll just # change the (in memory) first and second tokens to empty space and # write the full line (the original file is unchanged). downloader=$(awk '$1=="DOWNLOADER" {$1=""; $2=""; print $0}' $pconf) # Make sure all necessary variables have a value err=0 verr=0 novalue="" if [ x"$inbdir" = x ]; then novalue="BDIR, "; fi 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. berr=0 ierr=0 bdir="$(absolute_dir "$inbdir")" if ! [ -d "$bdir" ]; then if ! mkdir "$bdir"; then berr=1; err=1; fi; fi if [ $err = 1 ]; then cat <<EOF ################################################################# ######## ERORR reading existing configuration file ############ ################################################################# EOF if [ $verr = 1 ]; then cat <<EOF These variables have no value: $novalue. EOF fi if [ $berr = 1 ]; then cat <<EOF Couldn't create the build directory '$bdir' (value to 'BDIR') in '$pconf'. EOF fi cat <<EOF Please run the configure script again (accepting to re-write existing configuration file) so all the values can be filled and checked. ################################################################# EOF fi fi # Delete final configuration target # --------------------------------- # # We only want to start running the project later if this script has # completed successfully. To make sure it hasn't crashed in the middle # (without the user noticing), in the end of this script we make a file and # we'll delete it here (at the start). Therefore if the script crashed in # the middle that file won't exist. sdir="$bdir"/software finaltarget="$sdir"/configuration-done.txt if ! [ -d "$sdir" ]; then mkdir "$sdir"; fi rm -f "$finaltarget" # Project's top-level built software directories # ---------------------------------------------- # # These directories are possibly needed by many steps of process, so to # avoid too many directory dependencies throughout the software and # analysis Makefiles (thus making them hard to read), we are just building # them here # Software tarballs tardir="$sdir"/tarballs if ! [ -d "$tardir" ]; then mkdir "$tardir"; fi # Installed software instdir="$sdir"/installed if ! [ -d "$instdir" ]; then mkdir "$instdir"; fi # To record software versions and citation. verdir="$instdir"/version-info if ! [ -d "$verdir" ]; then mkdir "$verdir"; fi # Program and library versions and citation. ibidir="$verdir"/proglib if ! [ -d "$ibidir" ]; then mkdir "$ibidir"; fi # Python module versions and citation. 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 # TeXLive versions. itidir="$verdir"/tex if ! [ -d "$itidir" ]; then mkdir "$itidir"; fi # 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 # Wrapper over Make as a single command so it does not default to '/bin/sh' # during installation (needed by some programs like CMake). instbindir=$instdir/bin if ! [ -d $instbindir ]; then mkdir $instbindir; fi makewshell="$instbindir/make-with-shell" echo "$instbindir/make SHELL=$instbindir/bash \$@" > $makewshell chmod +x $makewshell # Project's top-level built analysis directories # ---------------------------------------------- # Top-level built analysis directories. badir="$bdir"/analysis if ! [ -d "$badir" ]; then mkdir "$badir"; fi # Top-level LaTeX. texdir="$badir"/tex if ! [ -d "$texdir" ]; then mkdir "$texdir"; fi # LaTeX macros. mtexdir="$texdir"/macros 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$maneage_group_name" = x ]; then texbdir="$texdir"/build else user=$(whoami) texbdir="$texdir"/build-$user fi if ! [ -d "$texbdir" ]; then mkdir "$texbdir"; fi # TiKZ (for building figures within LaTeX). tikzdir="$texbdir"/tikz if ! [ -d "$tikzdir" ]; then mkdir "$tikzdir"; fi # 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, 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 # Set the symbolic links for easy access to the top project build # directories. Note that these are put in each user's source/cloned # directory, not in the build directory (which can be shared between many # users and thus may already exist). # # Note: if we don't delete them first, it can happen that an extra link # will be created in each directory that points to its parent. So to be # safe, we are deleting all the links on each re-configure of the # project. Note that at this stage, we are using the host's 'ln', not our # own, so its best not to assume anything (like 'ln -sf'). rm -f .build .local ln -s "$bdir" .build ln -s "$instdir" .local ln -s "$texdir" tex/build ln -s "$tikzdir" tex/tikz # --------- Delete for no Gnuastro --------- rm -f .gnuastro # ------------------------------------------ # 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 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)}') tbshmdir="$shmdir"/"$dirname"-$(whoami) # 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 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 # Make sure the temporary build directory is empty (un-finished # source/build files from previous builds can remain there during debugging # or software updates). rm -rf $tmpblddir/* # 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 ------------------------- Building dependencies ... ------------------------- Necessary dependency programs and libraries will be installed in $sdir/installed 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 'README-hacking.md' for more. In short, run it while the project is being configured (in another terminal, but in this same directory: '$currentdir'): $ ./project --check-config Project's configuration will continue in $tsec seconds. ------------------------- EOF sleep $tsec fi # Number of threads to build software # ----------------------------------- # # If the user hasn't manually specified the number of threads, see if we # can deduce it from the host: # - On systems with GNU Coreutils we have 'nproc'. # - On BSD-based systems (for example FreeBSD and macOS), we have a # 'hw.ncpu' in the output of 'sysctl'. # - When none of the above work, just set the number of threads to 1. if [ $jobs = 0 ]; then if type nproc > /dev/null 2> /dev/null; then numthreads=$(nproc --all); else numthreads=$(sysctl -a | awk '/^hw\.ncpu/{print $2}') if [ x"$numthreads" = x ]; then numthreads=1; fi fi else numthreads=$jobs fi # See if the linker accepts -Wl,-rpath-link # ----------------------------------------- # # '-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. # # IMPORTANT NOTE: This test has to be done **AFTER** the definition of # 'instdir', otherwise, it is going to be used as an empty string. cat > $testsource <<EOF #include <stdio.h> #include <stdlib.h> int main(void) {return EXIT_SUCCESS;} EOF if $CC $testsource -o$testprog -Wl,-rpath-link 2>/dev/null > /dev/null; then export rpath_command="-Wl,-rpath-link=$instdir/lib" else export rpath_command="" fi # Delete the compiler testing directory # ------------------------------------- # # This directory was made above to make sure the necessary compilers can be # run. rm -f $testprog $testsource rm -rf $compilertestdir # 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 # 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 if [ x"$LIBRARY_PATH" = x ]; then export LIBRARY_PATH="$sys_library_path" else export LIBRARY_PATH="$LIBRARY_PATH:$sys_library_path" fi if [ x"$CPATH" = x ]; then export CPATH="$sys_cpath" else export CPATH="$CPATH:$sys_cpath" fi fi # Libraries necessary for the system's shell # ------------------------------------------ # # In some cases (mostly the programs that Maneage doesn't yet build by # itself), the programs may call the system's shell, not Maneage's # shell. After we close-off the system environment from Maneage, this will # cause a crash! To avoid such cases, we need to find the locations of the # libraries that the shell needs and temporarily add them to the library # search path. # # About the 'grep -v "(0x[^)]*)"' term (from bug 66847, see [1]): On some # systems [2], the output of 'ldd /bin/sh' includes a line for the vDSO [3] # that is different to the formats that are assumed, prior to this commit, # by the algorithm in 'configure.sh' when evaluating the variable # 'sys_library_sh_path'. This leads to a fatal syntax error in (at least) # 'ncurses', because the option using 'sys_library_sh_path' contains an # unquoted RAM address in parentheses. Even if the address were quoted, it # would still be incorrect. This 'grep command excludes candidate host path # strings that look like RAM addresses to address the problem. # # [1] https://savannah.nongnu.org/bugs/index.php?66847 # [2] https://stackoverflow.com/questions/34428037/how-to-interpret-the-output-of-the-ldd-program # [3] man vdso if [ x"$on_mac_os" = xyes ]; then sys_library_sh_path=$(otool -L /bin/sh \ | awk '/\/lib/{print $1}' \ | sed 's#/[^/]*$##' \ | sort \ | uniq \ | awk '{if (NR==1) printf "%s", $1; \ else printf ":%s", $1}') else sys_library_sh_path=$(ldd /bin/sh \ | awk '{if($3!="") print $3}' \ | sed 's#/[^/]*$##' \ | grep -v "(0x[^)]*)" \ | sort \ | uniq \ | awk '{if (NR==1) printf "%s", $1; \ else printf ":%s", $1}') fi # Find Zenodo URL for software downloading # ---------------------------------------- # # All free-software source tarballs that are potentially used in Maneage # are also archived in Zenodo with a certain concept-DOI. A concept-DOI is # a Zenodo terminology, meaning a fixed DOI of the project (that can have # many sub-DOIs for different versions). By default, the concept-DOI points # to the most recently uploaded version. However, the concept-DOI itself is # not directly usable for downloading files. The concept-DOI will just take # us to the top webpage of the most recent version of the upload. # # The problem is that as more software are added (as new Zenodo versions), # the most recent Zenodo-URL that the concept-DOI points to, also # changes. The most reliable solution was found to be the tiny script below # 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). This is not done if the options '--debug' or `--offline` are used. zenodourl="" user_backup_urls="" zenodocheck=.build/software/zenodo-check.html if [ x$debug = x ] && [ x$offline = 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 # Add the Zenodo URL to the user's given back software URLs. Since the user # can specify 'user_backup_urls' (not yet implemented as an option in # './project'), we'll give preference to their specified servers, then add # the Zenodo URL afterwards. user_backup_urls="$user_backup_urls $zenodourl" # Build core tools for project # ---------------------------- # # Here we build the core tools that 'basic.mk' depends on: Lzip # (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" # 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 # ---------------------------------------- # # When building these software we don't have our own un-packing software, # 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 $keepgoing -f reproduce/software/make/basic.mk \ sys_library_sh_path=$sys_library_sh_path \ user_backup_urls="$user_backup_urls" \ sys_library_path=$sys_library_path \ rpath_command=$rpath_command \ static_build=$static_build \ numthreads=$numthreads \ needs_ldl=$needs_ldl \ on_mac_os=$on_mac_os \ host_cc=$host_cc \ -j$numthreads # All other software # ------------------ # # We will be making all the dependencies before running the top-level # Makefile. To make the job easier, we'll do it in a Makefile, not a # script. Bash and Make were the tools we need to run Makefiles, so we had # to build them in this script. But after this, we can rely on Makefiles. if [ $jobs = 0 ]; then numthreads=$(.local/bin/nproc --all) else numthreads=$jobs fi .local/bin/env -i HOME=$bdir \ .local/bin/make $keepgoing \ -f reproduce/software/make/high-level.mk \ sys_library_sh_path=$sys_library_sh_path \ user_backup_urls="$user_backup_urls" \ sys_library_path=$sys_library_path \ rpath_command=$rpath_command \ all_highlevel=$all_highlevel \ static_build=$static_build \ numthreads=$numthreads \ on_mac_os=$on_mac_os \ sys_cpath=$sys_cpath \ host_cc=$host_cc \ offline=$offline \ -j$numthreads # Delete the temporary Make wrapper # --------------------------------- # # See above for its description. rm $makewshell # Make sure TeX Live installed successfully # ----------------------------------------- # # TeX Live is managed over the internet, so if there isn't any, or it # suddenly gets cut, it can't be built. However, when TeX Live isn't # installed, the project can do all its processing independent of it. It # will just stop at the stage when all the processing is complete and it is # only necessary to build the PDF. So we don't want to stop the project's # configuration and building if its not present. if [ -f $itidir/texlive-ready-tlmgr ]; then texlive_result=$(cat $itidir/texlive-ready-tlmgr) else texlive_result="NOT!" fi if [ x"$texlive_result" = x"NOT!" ]; then cat <<EOF !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!! Warning !!!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! TeX Live couldn't be installed during the configuration (probably because there were downloading problems). TeX Live is only necessary in making the final PDF (which is only done after all the analysis has been complete). It 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, 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 # Citation of installed software # # After everything is installed, we'll put all the names and versions in a # human-readable paragraph and also prepare the BibTeX citation for the # software. prepare_name_version () { # 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 for f in $@; do if [ -f $f ]; then hasfiles=1; break; fi; done # If there are any files, merge all the names in a paragraph. if [ $hasfiles = 1 ]; then # Count how many names there are. This is necessary to identify the # last element. num=$(.local/bin/cat $@ \ | .local/bin/sed '/^\s*$/d' \ | .local/bin/wc -l) # Put them all in one paragraph, while sorting them, commenting any # possible underscores and removing blank lines. .local/bin/cat $@ \ | .local/bin/sort \ | .local/bin/sed -e's|_|\\_|' \ | .local/bin/awk 'NF>0 { \ c++; \ if(c==1) \ { \ if('$num'==1) printf("%s", $0); \ else printf("%s", $0); \ } \ else if(c=='$num') printf(" and %s\n", $0); \ else printf(", %s", $0) \ }' fi } # Import the context/sentences for placing between the list of software # names during their acknowledgment. . $cdir/software_acknowledge_context.sh # Report the different software in separate contexts (separating Python and # TeX packages from the C/C++ programs and libraries). proglibs=$(prepare_name_version $verdir/proglib/*) pymodules=$(prepare_name_version $verdir/python/*) texpkg=$(prepare_name_version $verdir/tex/texlive) # Acknowledge these software packages in a LaTeX paragraph. pkgver=$mtexdir/dependencies.tex # Add the text to the ${pkgver} file. .local/bin/echo "$thank_software_introduce " > $pkgver .local/bin/echo "$thank_progs_libs $proglibs. " >> $pkgver if [ x"$pymodules" != x ]; then .local/bin/echo "$thank_python $pymodules. " >> $pkgver fi .local/bin/echo "$thank_latex $texpkg. " >> $pkgver .local/bin/echo "$thank_software_conclude" >> $pkgver # Prepare the BibTeX entries for the used software (if there are any). hasentry=0 bibfiles="$ictdir/*" for f in $bibfiles; do if [ -f $f ]; then hasentry=1; break; fi; done; # Make sure we start with an empty output file. pkgbib=$mtexdir/dependencies-bib.tex echo "" > $pkgbib # Fill it in with all the BibTeX entries in this directory. We'll just # avoid writing any comments (usually copyright notices) and also put an # empty line after each file's contents to make the output more readable. if [ $hasentry = 1 ]; then for f in $bibfiles; do awk '!/^%/{print} END{print ""}' $f >> $pkgbib done fi # Report machine architecture # --------------------------- # # Report hardware hwparam="$mtexdir/hardware-parameters.tex" # Add the text to the ${hwparam} file. Since harware class might include # underscore, it must be replaced with '\_', otherwise pdftex would # complain and break the build process when doing ./project make. hw_class_fixed="$(echo $hw_class | sed -e 's/_/\\_/')" .local/bin/echo "\\newcommand{\\machinearchitecture}{$hw_class_fixed}" > $hwparam .local/bin/echo "\\newcommand{\\machinebyteorder}{$byte_order}" >> $hwparam .local/bin/echo "\\newcommand{\\machineaddresssizes}{$address_sizes}" >> $hwparam # Clean the temporary build directory # --------------------------------- # # By the time the script reaches here the temporary software build # 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'. .local/bin/rm -rf $tmpblddir/* $tmpblddir # Register successful completion # ------------------------------ echo `.local/bin/date` > $finaltarget # Final notice # ------------ # # The configuration is now complete, we can inform the user on the next # step(s) to take. if [ x$maneage_group_name = x ]; then buildcommand="./project make -j8" else buildcommand="./project make --group=$maneage_group_name -j8" fi cat <<EOF ---------------- The project and its environment are configured with no errors. To change the configuration later, you can re-run './project configure' or manually edit 'reproduce/software/config/LOCAL.conf'. Just be careful with the build-directory: its location is hard-coded in the installed software so if you change it manually, many of the project's software will crash. If you have to use another built-directory, just re-configure a clean project there. Please run the following command to start the project. (Replace '8' with the number of CPU threads on your system) $buildcommand EOF