#!/bin/bash # Slackware build script for SML/NJ # Copyright 2014 R. S. Ananda Murthy, Mysore, India # Copyright 2026 Kyle Guinn # All rights reserved. # # Redistribution and use of this script, with or without modification, is # permitted provided that the following conditions are met: # # 1. Redistributions of this script must retain the above copyright # notice, this list of conditions and the following disclaimer. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED # WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO # EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; # OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, # WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. cd $(dirname $0) ; CWD=$(pwd) PRGNAM=smlnj VERSION=${VERSION:-110.99.9} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} PKGTYPE=${PKGTYPE:-tgz} if [ -z "$ARCH" ]; then case "$(uname -m)" in i?86) ARCH=i586 ;; arm*) ARCH=arm ;; *) ARCH=$(uname -m) ;; esac fi if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then echo "$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE" exit 0 fi TMP=${TMP:-/tmp/SBo} PKG=$TMP/package-$PRGNAM OUTPUT=${OUTPUT:-/tmp} set -e rm -rf $PKG mkdir -p $TMP $PKG $OUTPUT cd $TMP rm -rf $PRGNAM-$VERSION mkdir -p $PRGNAM-$VERSION cd $PRGNAM-$VERSION cp $CWD/*.tgz . # Replace the above cp line with this to auto-download; # the remaining source files will be fetched on demand: #wget "http://smlnj.cs.uchicago.edu/dist/working/${VERSION}/config.tgz" tar xvf config.tgz # Disambiguator for path variables used in SML/NJ's build system: # # $ROOT and $INSTALLDIR are the roots of the source and build trees, # respectively. $ROOT should be an absolute path; its value comes from # $PWD or $(pwd) which means install.sh should be run from the $ROOT # directory. $INSTALLDIR defaults to $ROOT if we don't specify it, but if # we do, the directory must already exist. # # $INSTALLDIR is also intended to be the final installation location. The # $INSTALLDIR path gets "frozen into the generated heap image" and into # several scripts. Furthermore, some scripts used during recompile # currently don't support $INSTALLDIR != $ROOT (makeml and installml both # assume $INSTALLDIR is $twoup) so trying to change it is futile. # # There is no $DESTDIR equivalent to install to a temporary location. # Instead it is expected that the build tree will be copied elsewhere. The # environment variable $SMLNJ_HOME is intended to override the paths that # are frozen into the scripts and heap. Those same scripts are used during # the build, and any pre-existing $SMLNJ_HOME will interfere with them. # # $CM_PATHCONFIG and $CM_LOCAL_PATHCONFIG are the locations of pathconfig # files, used by SML/NJ to find its libraries. The default $CM_PATHCONFIG # is $SMLNJ_HOME/lib/pathconfig when $SMLNJ_HOME is set in the environment, # or /usr/lib/smlnj-pathconfig otherwise. (The latter location is "rarely # used" and we will replace it below.) Similarly, $CM_LOCAL_PATHCONFIG is # $HOME/.smlnj-pathconfig when $HOME is set in the environment, or is # unused otherwise. This logic is in base/cm/util/stdcfg.sml. # # Un-export all of these variables to avoid surprises. # Some will be used as documented here, just not exported. export -n ROOT INSTALLDIR SMLNJ_HOME CM_PATHCONFIG CM_LOCAL_PATHCONFIG # Not using $LIBDIRSUFFIX, SML/NJ has its own mechanism to select 32-bit # vs. 64-bit. $INSTALLDIR can contain files for multiple architectures. # # ABI compatibility of user-generated heaps created with one version vs. # runtime and libraries of a different version is unknown, so assume they # may be incompatible and place everything in a version-specific directory. ROOT=$TMP/$PRGNAM-$VERSION INSTALLDIR=/usr/lib/$PRGNAM-$VERSION # Configure it to extract all known sources so we can patch them. # Extraction occurs during bootstrap; some patching must wait until then. sed -i -e 's|#.*\(request src-smlnj\)|\1|' config/targets # If any variable mentioned in `sml -E` is exported at heap creation time, # its value will clobber SML/NJ's defaults. (This is the mechanism for # values getting "frozen into the heap".) The heap is generated thrice: # 1. config/install.sh at bootstrap (search for @SMLboot) # 2. base/system/makeml at recompile (search for @SMLboot) # 3. config/install.sh at recompile (search for @CMredump) # # This is particularly important for $CM_PATHCONFIG as all three locations # set it to $INSTALLDIR/lib/pathconfig (in our temporary build directory), # losing the default behavior described above. Driver scripts add it back # (poorly) by setting $CM_PATHCONFIG to $SMLNJ_HOME/lib/pathconfig, but # this workaround requires $SMLNJ_HOME to be set when running the scripts. # When $SMLNJ_HOME is not set, then there is a dependency on the temporary # build directory and things will break once that directory is removed. # # Most of the patching below is to: # 1. Avoid having the temporary build directory hard-coded into the heap. # 2. Restore the default $CM_PATHCONFIG lookup behavior. # 3. Allow running driver scripts without the need to set $SMLNJ_HOME; # those scripts should know where SML/NJ is installed. # # In config/install.sh, delay the $CM_PATHCONFIG export until building # libraries, where the path change is actually needed. Fixes the 1st and # 3rd heap generation steps. sed -i \ -e 's|\(export CM_PATHCONFIG\)|#\1|' \ -e 's|\(\s*\)\(.*installer.cm.*\)|\1export CM_PATHCONFIG\n\1\2|' \ config/install.sh # If you were to "freeze in" a new default (for any variable), do it at the # 3rd heap generation step like this: #sed -i "s|\(\s*\)\(.*@CMredump.*\)|\1CM_PATHCONFIG=$INSTALLDIR/lib/pathconfig \2|" config/install.sh # Begin bootstrap: Build/install driver scripts/runtime/heap/libraries. # Heap and some libraries are from prebuilt boot.$ARCH-$OPSYS.tgz. config/install.sh # Bootstrap complete, now let it recompile the prebuilt parts. # Fix the 2nd heap generation step now that sources are extracted. sed -i 's|\(export CM_PATHCONFIG\)|#\1|' base/system/makeml # Replace /usr/lib/smlnj-pathconfig in the default $CM_PATHCONFIG lookup # with $INSTALLDIR/lib/pathconfig. Once installed, SML/NJ will find its # pathconfig file without needing $SMLNJ_HOME or $CM_PATHCONFIG to be set. sed -i "s/usr.*lib.*smlnj-pathconfig/$(echo $INSTALLDIR/lib/pathconfig | cut -d/ -f2- | sed 's|/|", "|g')/" base/cm/util/stdcfg.sml # Enable all available targets. Do this after bootstrap to avoid # unnecessarily rebuilding anything not needed for bootstrap. sed -i \ -e 's|#.*\(request asdl\)|\1|' \ -e 's|#.*\(request pgraph-util\)|\1|' \ -e 's|#.*\(request eXene\)|\1|' \ -e 's|#.*\(request mlrisc-tools\)|\1|' \ -e 's|#.*\(request nowhere\)|\1|' \ -e 's|#.*\(request heap2asm\)|\1|' \ config/targets # Begin recompile: See https://github.com/smlnj/legacy/raw/main/README.md # $SMLNJ_HOME must additionally be set during cmb-make since the build # tree (here $ROOT) isn't yet installed to its final location, and its # $CM_PATHCONFIG is no longer clobbered to $INSTALLDIR/lib/pathconfig. # This is the proper use of $SMLNJ_HOME. cd base/system SMLNJ_HOME=$ROOT PATH=$ROOT/bin:$PATH ./cmb-make $ROOT/bin/sml ./makeml #./testml # Interactive, not a test suite. ./installml -clean cd ../.. config/install.sh # Recompile complete. # Fix the remaining paths frozen into the driver scripts. # Avoid setting $CM_PATHCONFIG in the driver scripts (no longer necessary). find bin -maxdepth 1 -type f -exec sed -i "s|$ROOT|$INSTALLDIR|" {} + find bin -maxdepth 1 -type f -exec sed -i '/CM_PATHCONFIG/{N;N;N;d}' {} + chown -R root:root bin lib doc chmod -R u+w,go-w,a+rX-st bin lib doc mkdir -p $PKG$INSTALLDIR cp -a bin lib $PKG$INSTALLDIR find $PKG -exec file {} + | grep -e "executable" -e "shared object" | grep ELF \ | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true # Create a $PRGNAM -> $PRGNAM-$VERSION symlink. If multiple versions are # installed simultaneously, users can add a particular version's directory # to their $PATH, or they can let the symlink choose a default version. # The /etc/profile.d scripts created below will handle the common case. INSTALLDIR=$(dirname $INSTALLDIR)/$PRGNAM ln -s $PRGNAM-$VERSION $PKG$INSTALLDIR mkdir -p $PKG/etc/profile.d cat > $PKG/etc/profile.d/$PRGNAM.sh.new <<-EOF #!/bin/sh if [ -d ${INSTALLDIR}/bin ]; then PATH="\${PATH}:${INSTALLDIR}/bin" export PATH fi EOF chmod +x $PKG/etc/profile.d/$PRGNAM.sh.new cat > $PKG/etc/profile.d/$PRGNAM.csh.new <<-EOF #!/bin/csh if ( -d ${INSTALLDIR}/bin ) then setenv PATH \${PATH}:${INSTALLDIR}/bin endif EOF chmod +x $PKG/etc/profile.d/$PRGNAM.csh.new mkdir -p $PKG/usr cp -a doc/man $PKG/usr find $PKG/usr/man -type f -exec gzip -9 {} + mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION cp -a doc/html doc/pdf $PKG/usr/doc/$PRGNAM-$VERSION cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild mkdir -p $PKG/install cat $CWD/slack-desc > $PKG/install/slack-desc cat $CWD/doinst.sh > $PKG/install/doinst.sh cd $PKG /sbin/makepkg -l y -c n $OUTPUT/$PRGNAM-$VERSION-$ARCH-$BUILD$TAG.$PKGTYPE