diff options
author | Mohammad Akhlaghi <mohammad@akhlaghi.org> | 2019-04-15 01:47:58 +0100 |
---|---|---|
committer | Mohammad Akhlaghi <mohammad@akhlaghi.org> | 2019-04-15 02:24:09 +0100 |
commit | 313b936b502d22b6a2ff43f560dee0bb51fd01d0 (patch) | |
tree | 70f884b91b393be4d3c6b7cfaeaf3412900bd16f /reproduce/software/make/high-level.mk | |
parent | 4722ea598edd6b630227404c48c1c09ac527e9b8 (diff) |
New architecture to separate software-building and analysis steps
Until now, the software building and analysis steps of the pipeline were
intertwined. However, these steps (of how to build a software, and how to
use it) are logically completely independent.
Therefore with this commit, the pipeline now has a new architecture
(particularly in the `reproduce' directory) to emphasize this distinction:
The `reproduce' directory now has the two `software' and `analysis'
subdirectories and the respective parts of the previous architecture have
been broken up between these two based on their function. There is also no
more `src' directory. The `config' directory for software and analysis is
now mixed with the language-specific directories.
Also, some of the software versions were also updated after some checks
with their webpages.
This new architecture will allow much more focused work on each part of the
pipeline (to install the software and to run them for an analysis).
Diffstat (limited to 'reproduce/software/make/high-level.mk')
-rw-r--r-- | reproduce/software/make/high-level.mk | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/reproduce/software/make/high-level.mk b/reproduce/software/make/high-level.mk new file mode 100644 index 0000000..f7b1f4f --- /dev/null +++ b/reproduce/software/make/high-level.mk @@ -0,0 +1,720 @@ +# Build the project's dependencies (programs and libraries). +# +# ------------------------------------------------------------------------ +# !!!!! IMPORTANT NOTES !!!!! +# +# This Makefile will be run by the initial `./configure' script. It is not +# included into the reproduction pipe after that. +# +# ------------------------------------------------------------------------ +# +# Copyright (C) 2018-2019 Mohammad Akhlaghi <mohammad@akhlaghi.org> +# +# This Makefile 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 Makefile 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. +# +# A copy of the GNU General Public License is available at +# <http://www.gnu.org/licenses/>. + + + +# Top level environment +include reproduce/software/make/build-rules.mk +include reproduce/software/config/installation/LOCAL.mk +include reproduce/software/config/installation/texlive.mk +include reproduce/software/config/installation/versions.mk + +lockdir = $(BDIR)/locks +tdir = $(BDIR)/software/tarballs +ddir = $(BDIR)/software/build-tmp +idir = $(BDIR)/software/installed +ibdir = $(BDIR)/software/installed/bin +ildir = $(BDIR)/software/installed/lib +dtexdir = $(shell pwd)/reproduce/software/bibtex +ibidir = $(BDIR)/software/installed/version-info/bin +ilidir = $(BDIR)/software/installed/version-info/lib +itidir = $(BDIR)/software/installed/version-info/tex +ictdir = $(BDIR)/software/installed/version-info/cite +ipydir = $(BDIR)/software/installed/version-info/python + +# Define the top-level programs to build (installed in `.local/bin'). +# +# About ATLAS: currently the template does not depend on ATLAS but many +# high level software depend on it. The current rule for ATLAS is tested +# successfully on Mac (only static) and GNU/Linux (shared and static). But, +# since it takes a few hours to build, it is not currently a target. +top-level-libraries = # atlas +top-level-python = astroquery matplotlib +top-level-programs = gnuastro metastore +all: $(foreach p, $(top-level-libraries), $(ilidir)/$(p)) \ + $(foreach p, $(top-level-programs), $(ibidir)/$(p)) \ + $(foreach p, $(top-level-python), $(ipydir)/$(p)) \ + $(itidir)/texlive + +# Other basic environment settings: We are only including the host +# operating system's PATH environment variable (after our own!) for the +# compiler and linker. For the library binaries and headers, we are only +# using our internally built libraries. +# +# To investigate: +# +# 1) Set SHELL to `$(ibdir)/env - NAME=VALUE $(ibdir)/bash' and set all +# the parameters defined bellow as `NAME=VALUE' statements before +# calling Bash. This will enable us to completely ignore the user's +# native environment. +# +# 2) Add `--noprofile --norc' to `.SHELLFLAGS' so doesn't load the +# user's environment. +.ONESHELL: +.SHELLFLAGS := --noprofile --norc -ec +export CCACHE_DISABLE := 1 +export PATH := $(ibdir) +export SHELL := $(ibdir)/bash +export CPPFLAGS := -I$(idir)/include +export PKG_CONFIG_PATH := $(ildir)/pkgconfig +export PKG_CONFIG_LIBDIR := $(ildir)/pkgconfig +export LD_RUN_PATH := $(ildir):$(il64dir) +export LD_LIBRARY_PATH := $(ildir):$(il64dir) +export LDFLAGS := $(rpath_command) -L$(ildir) + + +# We want the download to happen on a single thread. So we need to define a +# lock, and call a special script we have written for this job. These are +# placed here because we want them both in the `high-level.mk' and +# `python.mk'. +$(lockdir): | $(BDIR); mkdir $@ +downloader="wget --no-use-server-timestamps -O"; +downloadwrapper = ./reproduce/analysis/bash/download-multi-try + + + + + +# Python packages +include reproduce/software/make/python.mk + + + + + +# Tarballs +# -------- +# +# All the necessary tarballs are defined and prepared with this rule. +# +# Note that we want the tarballs to follow the convention of NAME-VERSION +# before the `tar.XX' prefix. For those programs that don't follow this +# convention, but include the name/version in their tarball names with +# another format, we'll do the modification before the download so the +# downloaded file has our desired format. +tarballs = $(foreach t, cfitsio-$(cfitsio-version).tar.gz \ + atlas-$(atlas-version).tar.bz2 \ + cmake-$(cmake-version).tar.gz \ + curl-$(curl-version).tar.gz \ + freetype-$(freetype-version).tar.gz \ + fftw-$(fftw-version).tar.gz \ + ghostscript-$(ghostscript-version).tar.gz \ + git-$(git-version).tar.xz \ + gnuastro-$(gnuastro-version).tar.lz \ + gsl-$(gsl-version).tar.gz \ + hdf5-$(hdf5-version).tar.gz \ + install-tl-unx.tar.gz \ + jpegsrc.$(libjpeg-version).tar.gz \ + lapack-$(lapack-version).tar.gz \ + libbsd-$(libbsd-version).tar.xz \ + libpng-$(libpng-version).tar.xz \ + libgit2-$(libgit2-version).tar.gz \ + metastore-$(metastore-version).tar.gz \ + openmpi-$(openmpi-version).tar.gz \ + openblas-$(openblas-version).tar.gz \ + tiff-$(libtiff-version).tar.gz \ + wcslib-$(wcslib-version).tar.bz2 \ + , $(tdir)/$(t) ) +$(tarballs): $(tdir)/%: | $(lockdir) + if [ -f $(DEPENDENCIES-DIR)/$* ]; then + cp $(DEPENDENCIES-DIR)/$* $@ + else + # Remove all numbers, `-' and `.' from the tarball name so we can + # search more easily only with the program name. + n=$$(echo $* | sed -e's/[0-9\-]/ /g' -e's/\./ /g' \ + | awk '{print $$1}' ) + + # Set the top download link of the requested tarball. + mergenames=1 + if [ $$n = cfitsio ]; then + mergenames=0 + v=$$(echo $(cfitsio-version) | sed -e's/\.//' \ + | awk '{l=length($$1); \ + printf (l==4 ? "%d\n" \ + : (l==3 ? "%d0\n" \ + : (l==2 ? "%d00\n" \ + : "%d000\n") ), $$1)}') + w=https://heasarc.gsfc.nasa.gov/FTP/software/fitsio/c/cfitsio$$v.tar.gz + elif [ $$n = atlas ]; then + mergenames=0 + w=https://sourceforge.net/projects/math-atlas/files/Stable/$(atlas-version)/atlas$(atlas-version).tar.bz2/download + elif [ $$n = cmake ]; then + mergenames=0 + majv=$$(echo $(cmake-version) \ + | sed -e's/\./ /' \ + | awk '{printf("%d.%d", $$1, $$2)}') + w=https://cmake.org/files/v$$majv/cmake-$(cmake-version).tar.gz + elif [ $$n = curl ]; then w=https://curl.haxx.se/download + elif [ $$n = fftw ]; then w=ftp://ftp.fftw.org/pub/fftw + elif [ $$n = freetype ]; then w=https://download.savannah.gnu.org/releases/freetype + elif [ $$n = hdf ]; then + mergenames=0 + majorver=$$(echo $(hdf5-version) | sed -e 's/\./ /g' | awk '{printf("%d.%d", $$1, $$2)}') + w=https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-$$majorver/hdf5-$(hdf5-version)/src/$* + elif [ $$n = ghostscript ]; then w=https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs926 + elif [ $$n = git ]; then w=http://mirrors.edge.kernel.org/pub/software/scm/git + elif [ $$n = gnuastro ]; then w=http://ftp.gnu.org/gnu/gnuastro + elif [ $$n = gsl ]; then w=http://ftp.gnu.org/gnu/gsl + elif [ $$n = install ]; then w=http://mirror.ctan.org/systems/texlive/tlnet + elif [ $$n = jpegsrc ]; then w=http://ijg.org/files + elif [ $$n = lapack ]; then w=http://www.netlib.org/lapack + elif [ $$n = libbsd ]; then w=http://libbsd.freedesktop.org/releases + elif [ $$n = libpng ]; then w=https://download.sourceforge.net/libpng + elif [ $$n = libgit ]; then + mergenames=0 + w=https://github.com/libgit2/libgit2/archive/v$(libgit2-version).tar.gz + elif [ $$n = metastore ]; then w=http://akhlaghi.org/src + elif [ $$n = openblas ]; then + mergenames=0 + w=https://github.com/xianyi/OpenBLAS/archive/v$(openblas-version).tar.gz + elif [ $$n = openmpi ]; then + mergenames=0 + majorver=$$(echo $(openmpi-version) | sed -e 's/\./ /g' | awk '{printf("%d.%d", $$1, $$2)}') + w=https://download.open-mpi.org/release/open-mpi/v$$majorver/$* + elif [ $$n = tiff ]; then w=https://download.osgeo.org/libtiff + elif [ $$n = wcslib ]; then w=ftp://ftp.atnf.csiro.au/pub/software/wcslib + else + echo; echo; echo; + echo "'$$n' not recognized as a dependency name to download." + echo; echo; echo; + exit 1 + fi + + # Download the requested tarball. Note that some packages may not + # follow our naming convention (where the package name is merged + # with its version number). In such cases, `w' will be the full + # address, not just the top directory address. But since we are + # storing all the tarballs in one directory, we want it to have + # the same naming convention, so we'll download it to a temporary + # name, then rename that. + if [ $$mergenames = 1 ]; then tarballurl=$$w/"$*" + else tarballurl=$$w + fi + + # Download using the script specially defined for this job. + touch $(lockdir)/download + downloader="wget --no-use-server-timestamps -O" + $(downloadwrapper) "$$downloader" $(lockdir)/download \ + $$tarballurl $@ + fi + + + + + +# Libraries +# --------- +# +# We would prefer to build static libraries, but some compilers like LLVM +# don't have static capabilities, so they'll only build dynamic/shared +# libraries. Therefore, we can't use the easy `.a' suffix for static +# libraries as targets and there are different conventions for shared +# library names. +# +# For the actual build, the same compiler that built the library will build +# the programs, so exact knowledge of the suffix is ultimately irrelevant +# for us here. So, we'll make an `$(ildir)/built' directory and make a +# simple plain text file in it with the basic library name (an no prefix) +# and create/write into it when the library is successfully built. +$(ilidir)/cfitsio: $(tdir)/cfitsio-$(cfitsio-version).tar.gz \ + $(ibidir)/curl + + # CFITSIO hard-codes the absolute address of cURL's `curl-config' + # program (which gives the necessary header and linking + # information) into the configure script. So we'll have to modify + # it manually before doing the standard build. + topdir=$(pwd); cd $(ddir); tar xf $< + customtar=cfitsio-$(cfitsio-version)-custom.tar.gz + sed cfitsio/configure \ + -e's|/usr/bin/curl-config|$(ibdir)/curl-config|g' \ + > cfitsio/configure_tmp + mv cfitsio/configure_tmp cfitsio/configure + chmod +x cfitsio/configure + tar cf $$customtar cfitsio + cd $$topdir + + # Continue the standard build on the customized tarball. + $(call gbuild, $$customtar, cfitsio, static, \ + --enable-sse2 --enable-reentrant) \ + && rm $$customtar \ + && echo "CFITSIO $(cfitsio-version)" > $@ + +$(ilidir)/gsl: $(tdir)/gsl-$(gsl-version).tar.gz + $(call gbuild, $<, gsl-$(gsl-version), static) \ + && echo "GNU Scientific Library $(gsl-version)" > $@ + +$(ilidir)/fftw: $(tdir)/fftw-$(fftw-version).tar.gz + $(call gbuild, $<, fftw-$(fftw-version), static, \ + --enable-shared) \ + && cp $(dtexdir)/fftw.tex $(ictdir)/ \ + && echo "FFTW $(fftw-version) \citep{fftw}" > $@ + +# Freetype is necessary to install matplotlib +$(ilidir)/freetype: $(tdir)/freetype-$(freetype-version).tar.gz \ + $(ilidir)/libpng + $(call gbuild, $<, freetype-$(freetype-version), static) \ + && echo "FreeType $(freetype-version)" > $@ + +$(ilidir)/hdf5: $(tdir)/hdf5-$(hdf5-version).tar.gz \ + $(ilidir)/openmpi + export CC=mpicc; \ + export FC=mpif90; \ + $(call gbuild, $<, hdf5-$(hdf5-version), static, \ + --enable-parallel \ + --enable-fortran, V=1) \ + && echo "HDF5 library $(hdf5-version)" > $@ + +$(ilidir)/libbsd: $(tdir)/libbsd-$(libbsd-version).tar.xz + $(call gbuild, $<, libbsd-$(libbsd-version), static,,V=1) \ + && echo "Libbsd $(libbsd-version)" > $@ + +$(ilidir)/libjpeg: $(tdir)/jpegsrc.$(libjpeg-version).tar.gz + $(call gbuild, $<, jpeg-9b, static) \ + && echo "Libjpeg $(libjpeg-version)" > $@ + +$(ilidir)/libpng: $(tdir)/libpng-$(libpng-version).tar.xz + $(call gbuild, $<, libpng-$(libpng-version), static) \ + && echo "Libpng $(libpng-version)" > $@ + +$(ilidir)/libtiff: $(tdir)/tiff-$(libtiff-version).tar.gz \ + $(ilidir)/libjpeg + $(call gbuild, $<, tiff-$(libtiff-version), static, \ + --disable-webp --disable-zstd) \ + && echo "Libtiff $(libtiff-version)" > $@ + +$(ilidir)/openmpi: $(tdir)/openmpi-$(openmpi-version).tar.gz + $(call gbuild, $<, openmpi-$(openmpi-version), static, , V=1) \ + && echo "OpenMPI $(openmpi-version)" > $@ + +$(ilidir)/atlas: $(tdir)/atlas-$(atlas-version).tar.bz2 \ + $(tdir)/lapack-$(lapack-version).tar.gz + + # Get the operating system specific features (how to get + # CPU frequency and the library suffixes). To make the steps + # more readable, the different library version suffixes are + # named with a single character: `s' for no version in the + # name, `m' for the major version suffix, and `f' for the + # full version suffix. + # GCC in Mac OS doesn't work. To work around this issue, on Mac + # systems we force ATLAS to use `clang' instead of `gcc'. + if [ x$(on_mac_os) = xyes ]; then + s=dylib + m=3.dylib + f=3.6.1.dylib + core=$$(sysctl hw.cpufrequency | awk '{print $$2/1000000}') + clangflag="--force-clang=$(ibdir)/clang" + else + s=so + m=so.3 + f=so.3.6.1 + clangflag= + core=$$(cat /proc/cpuinfo | grep "cpu MHz" \ + | head -n 1 \ + | sed "s/.*: \([0-9.]*\).*/\1/") + fi + + # See if the shared libraries should be build for a single CPU + # thread or multiple threads. + N=$$(nproc) + srcdir=$$(pwd)/reproduce/src/make + if [ $$N = 1 ]; then + sharedmk=$$srcdir/dependencies-atlas-single.mk + else + sharedmk=$$srcdir/dependencies-atlas-multiple.mk + fi + + # The linking step here doesn't recognize the `-Wl' in the + # `rpath_command'. + export LDFLAGS=-L$(ildir) + cd $(ddir) \ + && tar xf $< \ + && cd ATLAS \ + && rm -rf build \ + && mkdir build \ + && cd build \ + && ../configure -b 64 -D c -DPentiumCPS=$$core \ + --with-netlib-lapack-tarfile=$(word 2, $^) \ + --cripple-atlas-performance \ + -Fa alg -fPIC --shared $$clangflag \ + --prefix=$(idir) \ + && make \ + && if [ "x$(on_mac_os)" != xyes ]; then \ + cd lib && make -f $$sharedmk && cd .. \ + && for l in lib/*.$$s*; do \ + patchelf --set-rpath $(ildir) $$l; done \ + && cp -d lib/*.$$s* $(ildir) \ + && ln -fs $(ildir)/libblas.$$s $(ildir)/libblas.$$m \ + && ln -fs $(ildir)/libf77blas.$$s $(ildir)/libf77blas.$$m \ + && ln -fs $(ildir)/liblapack.$$f $(ildir)/liblapack.$$s \ + && ln -fs $(ildir)/liblapack.$$f $(ildir)/liblapack.$$m; \ + fi \ + && make install + + # We need to check the existance of `libptlapack.a', but we can't + # do this in the `&&' steps above (it will conflict). So we'll do + # the check after seeing if `libtatlas.so' is installed, then we'll + # finalize the build (delete the untarred directory). + if [ "x$(on_mac_os)" != xyes ]; then \ + [ -e lib/libptlapack.a ] && cp lib/libptlapack.a $(ildir); \ + cd $(ddir); \ + rm -rf ATLAS; \ + fi + + # We'll check the full installation with the static library (not + # currently building shared library on Mac. + if [ -f $(ildir)/libatlas.a ]; then \ + echo "ATLAS $(atlas-version)" > $@; \ + fi + +$(ilidir)/openblas: $(tdir)/openblas-$(openblas-version).tar.gz + if [ x$(on_mac_os) = xyes ]; then \ + export CC=clang; \ + fi; \ + cd $(ddir) \ + && tar xf $< \ + && cd OpenBLAS-$(openblas-version) \ + && make \ + && make PREFIX=$(idir) install \ + && cd .. \ + && rm -rf OpenBLAS-$(openblas-version) \ + && echo "OpenBLAS $(openblas-version)" > $@ + + + + +# Libraries with special attention on Mac OS +# ------------------------------------------ +# +# Libgit2 and WCSLIB don't set their installation path, or don't do it +# properly, in their finally installed shared libraries. But since we are +# linking everything (including OpenSSL and its dependencies) dynamically, +# we need to also make a shared libraries and can't use static +# libraries. So for Mac OS systems we have to correct their addresses +# manually. +# +# For example, Libgit2 page recommends doing a static build, especially for +# Mac systems (with `-DBUILD_SHARED_LIBS=OFF'): "It’s highly recommended +# that you build libgit2 as a static library for Xcode projects. This +# simplifies distribution significantly, as the resolution of dynamic +# libraries at runtime can be extremely problematic.". This is a major +# problem we have been having so far with Mac systems: +# https://libgit2.org/docs/guides/build-and-link +$(ilidir)/libgit2: $(tdir)/libgit2-$(libgit2-version).tar.gz \ + $(ibidir)/cmake \ + $(ibidir)/curl + # Build and install the library. + $(call cbuild, $<, libgit2-$(libgit2-version), static, \ + -DUSE_SSH=OFF -DBUILD_CLAR=OFF \ + -DTHREADSAFE=ON ) + + # Correct the shared library absolute address if necessary. + if [ x$(on_mac_os) = xyes ]; then + install_name_tool -id $(ildir)/libgit2.26.dylib \ + $(ildir)/libgit2.26.dylib + fi + + # Write the target file. + echo "Libgit2 $(libgit2-version)" > $@ + +$(ilidir)/wcslib: $(tdir)/wcslib-$(wcslib-version).tar.bz2 \ + $(ilidir)/cfitsio + # Build and install the library. + $(call gbuild, $<, wcslib-$(wcslib-version), , \ + LIBS="-pthread -lcurl -lm" \ + --with-cfitsiolib=$(ildir) \ + --with-cfitsioinc=$(idir)/include \ + --without-pgplot --disable-fortran) + + # Correct the shared library absolute address if necessary. + if [ x$(on_mac_os) = xyes ]; then + install_name_tool -id $(ildir)/libwcs.6.2.dylib \ + $(ildir)/libwcs.6.2.dylib; + fi + + # Write the target file. + echo "WCSLIB $(wcslib-version)" > $@ + + + + + +# Programs +# -------- +# +# CMake can be built with its custom `./bootstrap' script. +$(ibidir)/cmake: $(tdir)/cmake-$(cmake-version).tar.gz \ + $(ibidir)/curl + # After searching in `bootstrap', I couldn't find `LIBS', only + # `LDFLAGS'. So the extra libraries are being added to `LDFLAGS', + # not `LIBS'. + # + # On Mac systems, the build complains about `clang' specific + # features, so we can't use our own GCC build here. + if [ x$(on_mac_os) = xyes ]; then \ + export CC=clang; \ + export CXX=clang++; \ + fi; \ + cd $(ddir) \ + && rm -rf cmake-$(cmake-version) \ + && tar xf $< \ + && cd cmake-$(cmake-version) \ + && ./bootstrap --prefix=$(idir) --system-curl --system-zlib \ + --system-bzip2 --system-liblzma --no-qt-gui \ + && make LIBS="$$LIBS -lssl -lcrypto -lz" VERBOSE=1 \ + && make install \ + && cd .. \ + && rm -rf cmake-$(cmake-version) \ + && echo "CMake $(cmake-version)" > $@ + +# cURL (and its library, which is needed by several programs here) can +# optionally link with many different network-related libraries on the host +# system that we are not yet building in the template. Many of these are +# not relevant to most science projects, so we are explicitly using +# `--without-XXX' or `--disable-XXX' so cURL doesn't link with them. Note +# that if it does link with them, the configuration will crash when the +# library is updated/changed by the host, and the whole purpose of this +# project is avoid dependency on the host as much as possible. +$(ibidir)/curl: $(tdir)/curl-$(curl-version).tar.gz + $(call gbuild, $<, curl-$(curl-version), , \ + LIBS="-pthread" \ + --with-zlib=$(ildir) \ + --with-ssl=$(idir) \ + --without-mesalink \ + --with-ca-fallback \ + --without-librtmp \ + --without-libidn2 \ + --without-wolfssl \ + --without-brotli \ + --without-gnutls \ + --without-cyassl \ + --without-libpsl \ + --without-axtls \ + --disable-ldaps \ + --disable-ldap \ + --without-nss, V=1) \ + && echo "cURL $(curl-version)" > $@ + +$(ibidir)/ghostscript: $(tdir)/ghostscript-$(ghostscript-version).tar.gz + $(call gbuild, $<, ghostscript-$(ghostscript-version)) \ + && echo "GPL Ghostscript $(ghostscript-version)" > $@ + +$(ibidir)/git: $(tdir)/git-$(git-version).tar.xz \ + $(ibidir)/curl + $(call gbuild, $<, git-$(git-version), static, \ + --without-tcltk --with-shell=$(ibdir)/bash, \ + V=1) \ + && echo "Git $(git-version)" > $@ + +# Metastore is used (through a Git hook) to restore the source modification +# dates of files after a Git checkout. Another Git hook saves all file +# metadata just before a commit (to allow restoration after a +# checkout). Since this project is managed in Makefiles, file modification +# dates are critical to not having to redo the whole analysis after +# checking out between branches. +# +# Note that we aren't using the standard version of Metastore, but a fork +# of it that is maintained in this repository: +# https://gitlab.com/makhlaghi/metastore-fork +# +# Libbsd is not necessary on macOS systems, because macOS is already a +# BSD-based distribution. But on GNU/Linux systems, it is necessary. +ifeq ($(on_mac_os),yes) +needlibbsd = +else +needlibbsd = $(ilidir)/libbsd +endif +$(ibidir)/metastore: $(tdir)/metastore-$(metastore-version).tar.gz \ + $(needlibbsd) \ + $(ibidir)/git + + # The build command below will change the current directory of this + # build, so we'll fix its value here. + current_dir=$$(pwd) + + # Metastore doesn't have any `./configure' script. So we'll just + # call `pwd' as a place-holder for the `./configure' command. + # + # File attributes are also not available on some systems, since the + # main purpose here is modification dates (and not attributes), + # we'll also set the `NO_XATTR' flag. + $(call gbuild, $<, metastore-$(metastore-version), static,, \ + NO_XATTR=1 V=1,,pwd,PREFIX=$(idir)) + + # Write the relevant hooks into this system's Git hooks, so Git + # calls metastore properly on every commit and every checkout. + # + # Note that the -O and -G options used here are currently only in a + # fork of `metastore' currently hosted at: + # https://github.com/mohammad-akhlaghi/metastore + user=$$(whoami) + group=$$(groups | awk '{print $$1}') + cd $$current_dir + if [ -f $(ibdir)/metastore ]; then + for f in pre-commit post-checkout; do + sed -e's|@USER[@]|'$$user'|g' \ + -e's|@GROUP[@]|'$$group'|g' \ + -e's|@BINDIR[@]|$(ibdir)|g' \ + -e's|@TOP_PROJECT_DIR[@]|'$$current_dir'|g' \ + reproduce/software/bash/git-$$f > .git/hooks/$$f + chmod +x .git/hooks/$$f + echo "Metastore (forked) $(metastore-version)" > $@ + done + else + echo; echo; echo; + echo "*****************" + echo "metastore couldn't be installed!" + echo + echo "Its used for preserving timestamps on Git commits." + echo "Its useful for development, not simple running of the project." + echo "So we won't stop the configuration because it wasn't built." + echo "*****************" + fi + +# The order of dependencies is based on how long they take to build (how +# large they are): Libgit2 depends on CMake which takes a VERY long time to +# build. Also, Ghostscript and GSL are relatively large packages. So when +# building in parallel, its better to have these packages start building +# early. +$(ibidir)/gnuastro: $(tdir)/gnuastro-$(gnuastro-version).tar.lz \ + $(ilidir)/gsl \ + $(ilidir)/wcslib \ + $(ilidir)/libjpeg \ + $(ilidir)/libtiff \ + $(ilidir)/libgit2 \ + $(ibidir)/ghostscript +ifeq ($(static_build),yes) + staticopts="--enable-static=yes --enable-shared=no"; +endif + $(call gbuild, $<, gnuastro-$(gnuastro-version), static, \ + $$staticopts, -j$(numthreads), \ + make check -j$(numthreads)) \ + && cp $(dtexdir)/gnuastro.tex $(ictdir)/ \ + && echo "GNU Astronomy Utilities $(gnuastro-version) \citep{gnuastro}" > $@ + + + + + + + + + + + + + + + + + + + + +# Since we want to avoid complicating the PATH, we are putting a symbolic +# link of all the TeX Live executables in $(ibdir). But symbolic links are +# hard to track for Make (as a target). Also, TeX in general is optional +# for the project (the processing is the main target, not the generation of +# the final PDF). So we'll make a simple ASCII file called +# `texlive-ready-tlmgr' and use its contents to mark if we can use it or +# not. +$(itidir)/texlive-ready-tlmgr: $(tdir)/install-tl-unx.tar.gz \ + reproduce/software/config/installation/texlive.conf + + # Unpack, enter the directory, and install based on the given + # configuration (prerequisite of this rule). + @topdir=$$(pwd) + cd $(ddir) + rm -rf install-tl-* + tar xf $(tdir)/install-tl-unx.tar.gz + cd install-tl-* + sed -e's|@installdir[@]|$(idir)|g' \ + $$topdir/reproduce/software/config/installation/texlive.conf \ + > texlive.conf + + # TeX Live's installation may fail due to any reason. But TeX Live + # is optional (only necessary for building the final PDF). So we + # don't want the configure script to fail if it can't run. + if ./install-tl --profile=texlive.conf; then + + # Put a symbolic link of the TeX Live executables in `ibdir'. The + # main problem is that the year and build system (for example + # `x86_64-linux') are also in the directory names, making it hard + # to be generic. We are using wildcards here, but only in this + # Makefile, not in any other. + ln -fs $(idir)/texlive/20*/bin/*/* $(ibdir)/ + + # Register that the build was successful. + echo "TeX Live is ready." > $@ + else + echo "NOT!" > $@ + fi + + # Clean up + cd .. + rm -rf install-tl-* + + + + + +# To keep things modular and simple, we'll break up the installation of TeX +# Live itself (only very basic TeX and LaTeX) and the installation of its +# necessary packages into two packages. +$(itidir)/texlive: reproduce/software/config/installation/texlive.mk \ + $(itidir)/texlive-ready-tlmgr + + # To work with TeX live installation, we'll need the internet. + @res=$$(cat $(itidir)/texlive-ready-tlmgr) + if [ x"$$res" = x"NOT!" ]; then + echo "" > $@ + else + # Install all the extra necessary packages. If LaTeX complains + # about not finding a command/file/what-ever/XXXXXX, simply run + # the following command to find which package its in, then add it + # to the `texlive-packages' variable of the first prerequisite. + # + # ./.local/bin/tlmgr info XXXXXX + # + # We are putting a notice, because if there is no internet, + # `tlmgr' just hangs waiting. + tlmgr install $(texlive-packages) + + # Make a symbolic link of all the TeX Live executables in the bin + # directory so we don't have to modify `PATH'. + ln -fs $(idir)/texlive/20*/bin/*/* $(ibdir)/ + + # Get all the necessary versions. + texlive=$$(pdflatex --version | awk 'NR==1' | sed 's/.*(\(.*\))/\1/' \ + | awk '{print $$NF}'); + + # Package names and versions. + tlmgr info $(texlive-packages) --only-installed | awk \ + '$$1=="package:" {version=0; \ + if($$NF=="tex-gyre") name="texgyre"; \ + else name=$$NF} \ + $$1=="cat-version:" {version=$$NF} \ + $$1=="cat-date:" {if(version==0) version=$$2; \ + printf("%s %s\n", name, version)}' >> $@ + fi |