1#!/bin/sh
2#
3# Copyright (C) 2019-2023 Free Software Foundation, Inc.
4#
5# Copying and distribution of this file, with or without modification,
6# are permitted in any medium without royalty provided the copyright
7# notice and this notice are preserved.  This file is offered as-is,
8# without any warranty.
9#
10# Written by Assaf Gordon and Bernhard Voelker.
11
12
13# To build all versions since 5.0 (if possible):
14# git tag \
15#   | grep '^v[5678]' \
16#   | sed 's/^v//' \
17#   | sort -V \
18#   | while read f; do \
19#       ./build-older-versions.sh $f 2>&1 \
20#          | tee build/build.$f.log ; \
21#     done
22
23PREFIX="${PREFIX:=$HOME/old-coreutils}"
24
25base=$(basename "$0")
26
27die()
28{
29  echo "$base: error: $*" >&2
30  exit 1
31}
32
33warn()
34{
35  echo "$base: warning: $*" >&2
36}
37
38get_patch_file()
39{
40  case "$1" in
41    5.0)  echo coreutils-5.0-on-glibc-2.28.diff ;;
42    5.97|6.[345679]) echo coreutils-5.97-on-glibc-2.28.diff ;;
43    6.10) echo coreutils-6.10-on-glibc-2.28.diff ;;
44    6.11) echo coreutils-6.11-on-glibc-2.28.diff ;;
45    6.12) echo coreutils-6.12-on-glibc-2.28.diff ;;
46    7.[23456]|8.[123]) echo coreutils-7.2-on-glibc-2.28.diff ;;
47    8.[456789]|8.1[012]) echo coreutils-8.4-on-glibc-2.28.diff ;;
48    8.1[3456]) echo coreutils-8.13-on-glibc-2.28.diff ;;
49    8.17) echo coreutils-8.17-on-glibc-2.28.diff ;;
50    8.1[89]|8.2[0123]) echo coreutils-8.18-on-glibc-2.28.diff ;;
51    8.2[456789]) echo coreutils-8.24-on-glibc-2.28.diff ;;
52    8.[3456789]*) warn "patch not needed for version '$1'" ;;
53    5.[12]*|5.9*)  die "version '$1' does not have a patch (yet) " \
54                       "use versions 5.0 or 5.97" ;;
55    7.1)  die "version '$1' does not have a patch (yet)" \
56                       "use versions 6.12 or 7.2" ;;
57    5*|6*|7*|8*) die "non-existing version" ;;
58    *) die "unknown version" ;;
59  esac
60}
61
62get_url()
63{
64  _base_url="https://ftp.gnu.org/gnu/coreutils/coreutils-$1.tar"
65  case "$1" in
66    5.*|6.*|7.*) echo "$_base_url.gz" ;;
67    8.*)         echo "$_base_url.xz" ;;
68    *) die "unknown version" ;;
69  esac
70}
71
72##
73## Setup
74##
75test -n "$1" \
76  || die "missing coreutils version to build (e.g. '6.12')"
77
78cd $(dirname "$0")
79
80patch_file=$(get_patch_file "$1") \
81  || die "cannot build version '$1'"
82
83# Test for the patch file if the above returned one.
84if test "$patch_file"; then
85  test -e "$patch_file" \
86    || die "internal error: patch file '$patch_file' does not exist"
87fi
88
89url=$(get_url "$1")
90tarball=$(basename "$url")
91
92mkdir -p "build" \
93  && cd "build" \
94  || die "creating version build dir 'build' failed"
95
96##
97## Download tarball (if needed)
98##
99if ! test -e "$tarball" ; then
100   wget -O "$tarball.t" "$url" \
101        && mv "$tarball.t" "$tarball" \
102        || die "failed to download '$url'"
103fi
104
105##
106## Extract tarball (if needed)
107##
108srcdir=${tarball%.tar.*}
109if ! test -d "$srcdir" ; then
110    tar -xvf "$tarball" || die "failed to extract '$tarball'"
111fi
112
113##
114## Patch (if needed)
115##
116cd "$srcdir" \
117  || die "changing directory to '$srcdir' failed"
118
119# Patch will fail if it was already applied (using "--forward" turns
120# that into a no-op). So don't check for failure.
121# Is there a way to differentiate between 'already applied' and
122# 'failed to apply' ?
123test "$patch_file" \
124  && patch --ignore-whitespace --batch --forward -p1 < "../../$patch_file"
125
126##
127## Configure
128##
129version="${srcdir#coreutils}" # note:  this keeps the '-' in '$version'
130vprefix="$PREFIX/coreutils$version"
131if ! test -e "Makefile" ; then
132  ./configure \
133    --program-suffix="$version" \
134    --prefix="$vprefix" \
135    || die "failed to run configure in 'build/$srcdir/'"
136fi
137
138##
139## Build
140##
141make -j4 \
142  || die "build failed in 'build/$srcdir'"
143
144##
145## Install
146##
147make install \
148  || die "make-install failed in 'build/$srcdir' (to '$vprefix')"
149
150
151# Create convenience links for the executables and manpages in common directory.
152(
153  mkdir -p "$PREFIX/bin" "$PREFIX/man/man1" \
154    || die "creating common bin or man directory failed"
155  cd $vprefix/bin \
156    || die "changing directory to just-installed 'bin' directory failed"
157  for f in *; do
158    ln -snvf "../coreutils$version/bin/$f" "$PREFIX/bin/$f" \
159      || die "creating symlink of executable '$f' failed"
160  done
161
162  share=  # older versions do not have 'share'.
163  cd "$vprefix/share/man/man1" 2>/dev/null \
164    && share='/share' \
165    || cd "$vprefix/man/man1" \
166    || die "changing directory to just-installed 'man/man1' directory failed"
167  for f in *; do
168    ln -snfv "../../coreutils$version$share/man/man1/$f" "$PREFIX/man/man1/$f" \
169      || die "creating symlink of man page '$f' failed"
170  done
171) || exit 1
172
173# Build and install PDF (if possible).
174if make SUBDIRS=. pdf; then
175  make SUBDIRS=. install-pdf \
176    || die "make-install-pdf failed in 'build/$srcdir' (to '$vprefix')"
177else
178  echo "$0: no PDF available"
179fi
180
181# Print summary
182cat<<EOF
183
184
185=================================================================
186
187GNU Coreutils$version successfully installed.
188
189Source code in $PWD/build/$srcdir
190Installed in $vprefix
191
192symlinks for all programs (all versions) in $PREFIX/bin
193manual pages for all programs in $PREFIX/share/man/man1
194
195Run the following command to add all programs to your \$PATH:
196
197    export PATH=\$PATH:\$HOME/old-coreutils/bin
198    export MANPATH=\$MANPATH:\$HOME/old-coreutils/man
199
200EOF
201