#!/bin/bash
shopt -s extglob
set +o posix
ulimit -s unlimited
ulimit -n 4096

# mozilla-firefox.SlackBuild
# by Stuart Winter
# Based on Unbranded 'Firefox' build script from Slackware 13.
# 03-April-2009
#
# Copyright 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2018, 2019, 2020, 2021  Patrick J. Volkerding, Sebeka, Minnesota, USA
# 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.

# Record toolchain & other info for the build log:
slackbuildinfo

# Paths to skeleton port's source & real Slackware source tree:
slackset_var_cwds

# If there is a private Google API key available at compile time, use
# it to enable support for Google Safe Browsing. For Slackware builds,
# we use a private key issued for the Slackware project. If you are
# rebuilding and need this support, or you are producing your own
# distribution, you may obtain your own Google API key at no charge by
# following these instructions:
# https://bugzilla.mozilla.org/show_bug.cgi?id=1377987#c0
if [ -f "$PORTCWD/.GoogleSafeBrowsingAPI_Key" ]; then
   GOOGLE_API_KEY="--with-google-safebrowsing-api-keyfile=$PORTCWD/.GoogleSafeBrowsingAPI_Key"
fi

# Major version number - needed for /usr/lib/firefox dir:
MAJORVER=$VERSION
MOZVERS=${MOZVERS:-release}
RELEASEVER=$(echo $VERSION | cut -f 1 -d r | cut -f 1 -d b | cut -f 1 -d e)

# Specify this variable for a localized build.
# For example, to build a version of Firefox with Italian support, run
# the build script like this:
#
# MOZLOCALIZE=it ./arm/build
#
MOZLOCALIZE=${MOZLOCALIZE:-}

# Without LANG=C, building the Python environment may fail with:
# "UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 36: ordinal not in range(128)"
LANG=C

# Add a shell script to start the firefox binary with MOZ_ALLOW_DOWNGRADE=1
# to avoid backing up (and disabling) the user profile if a browser downgrade
# is detected. We made it fine for years without this feature, and all the
# feedback we've seen suggests that it is causing more problems than it
# solves. For example, this feature causes a profile reset trying to switch
# between a 32-bit and 64-bit browser on installations that share a common
# /home directory. If you want to build with the stock default behavior, set
# this to something other than "YES":
MOZ_ALLOW_DOWNGRADE=${MOZ_ALLOW_DOWNGRADE:-YES}

# Temporary build locations:
export TMPBUILD=$TMP/build-$PKGNAM
export PKG=$TMP/package-$PKGNAM
mkpkgdirs # Delete & re-create temporary directories then cd into $TMPBUILD

# Much builds with distcc but it fails eventually, so we'll retry without it.
# There's some code to rm /tmp/DISTCC if the variable ! null, but any errors
# won't be trapped, so /tmp/DISTCC will no longer invoke distcc.
# I need to fix this bug using trap to a cleanup function.
function disable_distcc() {
  if [ -d /tmp/DISTCC ]; then
      DISTCCDISABLED=yes
      export PATH=$( echo $PATH | sed -e 's?/tmp/DISTCC:??g' )
      unset NUMJOBS
      # And since some paths get harded coded from configuration time, point them back
      # to local:
      pushd /tmp/DISTCC
      find . -name '*g++' | while read line ; do ln -vfs /usr/bin/g++ ${line} ; done
      find . -name '*c++' | while read line ; do ln -vfs /usr/bin/g++ ${line} ; done
      find . -name '*cc' | while read line ; do ln -vfs /usr/bin/gcc ${line} ; done
      find . -name '*gcc' | while read line ; do ln -vfs /usr/bin/gcc ${line} ; done
      popd
      echo "*** WARNING: distcc is now disabled"
  fi
}
function distcc_cleanup() {
# Remove distcc if we had to disable it:
  if [ ! -z "$DISTCCDISABLED" ]; then
     rm -rfv /tmp/DISTCC
  fi
}

export NUMJOBS="-j$(( $(nproc) -1 ))"

# PGO is disabled by default:
PGO=${PGO:-no}

# If not specified, figure out if this is a beta or a release
MOZVERS=${MOZVERS:-release}
if echo $VERSION | grep -q b ; then MOZVERS=beta ; fi

#######################################################################
# Handle build-time dependencies
#######################################################################
# Slackware64 is doing this in another script, but we'll bring it in here.
## Build or unpack build-time dependencies:
##. ./build-deps.sh

#
# Note this is going into (on the Slackware ARM build machines at least) /root/tmp so it'll
# be outside of the Mozilla temp build dir.
mkdir -vpm755 $TMP/mozilla-firefox-build-deps/usr/bin
export PATH=$TMP/mozilla-firefox-build-deps/usr/bin:$HOME/.cargo/bin:$PATH

# Do we need to install "cbindgen" ?
echo "** Output from cargo install --list **"
cargo install --list | grep -i cbindgen
cargo install --list | grep -qi cbindgen
if [ $? -eq 1 ]; then
   echo "Building cbindgen"
   ( unset VERSION
     cd $CWD/build-deps/cbindgen
     ./cbindgen.build )
 else
   echo "*** cbindgen is already installed - not building"
fi
# Build node.js.
# We'll modify the upstream Slackware build script to save maintaining our own:
# grr.  This is now entirely stupid because it's a small script.  I'll put this into its own package
# in /extra after this.
# This installs into a temporary dir, so we need to rebuild it every time.
# Use the Slackware ARM temporary location:
if [ ! -x $TMP/mozilla-firefox-build-deps/usr/bin/node ]; then
   cp -fa $CWD/build-deps/nodejs/ $TMPBUILD/
   sed -i 's?/tmp?'"$TMP"'?g'  $TMPBUILD/nodejs/nodejs.build
   # Install not to $PKG (then delete later), but into a temp folder outside of
   # Firefox, so we can use it for subsequent builds of FF.
   sed -i 's?$PKG?'"$TMP"/mozilla-firefox-build-deps/'?g' $TMPBUILD/nodejs/nodejs.build
   sed -i 's?=$TMP/mozilla-firefox-build-deps/usr?=/usr?g' $TMPBUILD/nodejs/nodejs.build
   # Adjust to ARM and aarch64 so that the libdir is set correctly:
   sed -i 's?armv7hl?arm?g'  $TMPBUILD/nodejs/nodejs.build
   sed -i 's?x86_64?aarch64?g'  $TMPBUILD/nodejs/nodejs.build
   # ARM uses -O2 by default:
   sed -i 's?-O3?-O2?g' $TMPBUILD/nodejs/nodejs.build
   sed -i 's?\$VERSION?*?g' $TMPBUILD/nodejs/nodejs.build
   ( unset VERSION
     cd $TMPBUILD/nodejs
     ./nodejs.build )
 else
   echo "*** nodejs already installed - not building"
fi
#######################################################################

# Extract source:
echo "Extracting source"
tar xf $CWD/firefox-$VERSION*source.tar.!(*sign|*asc|*sig)
#tar xf $PORTCWD/sources/firefox-$VERSION*source*tar*
cd mozilla*/ || cd firefox*/ || exit 1
slackhousekeeping

#######################################################################################
########### Patch & fix  ##############################################################
#######################################################################################

# Delete object directory if it was mistakenly included in the tarball:
rm -rf obj-x86_64-pc-linux-gnu

# Prevent failures building gkrust by suppressing useless warnings:
sed -i.allow-warnings -e '/#!\[deny(warnings)\]/a #![allow(unused_imports)]' \
  servo/components/style/lib.rs

# Retain GTK+ v2 scrolling behavior:
zcat $CWD/ff.ui.scrollToClick.diff.gz | patch -p1 --verbose || exit 1

# Fetch localization, if requested:
if [ ! -z $MOZLOCALIZE ]; then
  LOC_TAG="FIREFOX_$( echo $VERSION | tr \. _ )_RELEASE"
  rm -f $LOC_TAG.tar.!(*sign|*asc|*sig)
  if echo $MOZVERS | grep -q esr ; then LOC_VERS=release ; else LOC_VERS=$MOZVERS ; fi
   wget https://hg.mozilla.org/releases/l10n/mozilla-$MOZVERS/$MOZLOCALIZE/archive/$LOC_TAG.tar.!(*sign|*asc|*sig)
  tar xvf $LOC_TAG.tar.!(*sign|*asc|*sig)
  mv $MOZLOCALIZE-$LOC_TAG $MOZLOCALIZE
fi

# Apply some patches from Fedora for ARM:
for pf in $( cat $PORTCWD/sources/fedorapatches/patchlist ) ; do
       auto_apply_patch $PORTCWD/sources/fedorapatches/${pf} || exit 1
done

##########
########## Patches from Slackware x86
##########

# Don't enable LTO for Rust unless the whole build uses it:
zcat $CWD/0027-LTO-Only-enable-LTO-for-Rust-when-complete-build-use.patch.gz | patch -p1 --verbose || exit 1

# Fix build with wayland >= 1.20.0:
zcat $CWD/d30c921928a12fccd5085888011f899ff1c788cd.patch | patch -p1 --verbose || exit 1

#######################################################################################
########### Configure    ##############################################################
#######################################################################################

# Put Rust objects on a diet to keep the linker from running into memory
# issues (especially on 32-bit):
# These cause a build failure.  rust on Slackware ARM sets these as default also, so they
# may not be needed.
export RUSTFLAGS="-Cdebuginfo=0"
#export RUSTFLAGS="-Cdebuginfo=0 -Copt-level=0"
export MOZ_RUST_DEFAULT_FLAGS="$RUSTFLAGS"

# Disable debuginfo being compiled in. Helps reduce RAM use at build time.
export MOZ_DEBUG_FLAGS="-g0"

# Configure:
# Need to re-generate because of the 'no neon' patch:
# We also need to use autoconf-2.13 (in /extra).
#autoreconf2.13  -vif

# Turn errors back into warnings:
sed -i 's?-Werror?-Wall?g' configure

# Our building options, in a configure-like display ;)
OPTIONS="\
   $SLKCONFARGS \
   --enable-official-branding \
   --prefix=/usr \
   --libdir=/usr/lib${LIBDIRSUFFIX} \
   --with-system-zlib \
   --with-system-nss \
   --with-system-nspr \
   --with-unsigned-addon-scopes=app,system \
   --allow-addon-sideload \
   --enable-alsa \
   --enable-application=browser \
   --enable-default-toolkit=cairo-gtk3-wayland \
   $GOOGLE_API_KEY \
   --enable-cpp-rtti \
   --enable-optimize \
   --disable-strip \
   --disable-tests \
   --disable-install-strip \
   --enable-accessibility \
   --disable-debug-symbols \
   --disable-debug \
   --disable-updater"
   # Complains about missing APNG support in Slackware's libpng:
   #--with-system-png \
   # won't build:
   #--enable-system-cairo \
   #--enable-strip \
   # Trying without on ARM as this may be cause of breakage:
   # As of FF version=90.0.2 this has been removed from Slackware64.
   #--enable-rust-simd \
if [ ! -z $MOZLOCALIZE ]; then
  OPTIONS=$OPTIONS" \
   --enable-ui-locale=$MOZLOCALIZE
   --with-l10n-base=.."
  # There are no dictionaries in localized builds
  sed -i \
    -e "/@BINPATH@\/dictionaries\/\*/d" \
    -e "/@RESPATH@\/dictionaries\/\*/d" \
    browser/installer/package-manifest.in || exit 1
fi

export MACH_USE_SYSTEM_PYTHON="1"
export MOZILLA_OFFICIAL="1"
export BUILD_OFFICIAL="1"
export MOZ_PACKAGE_JSSHELL="1"
export MOZ_PHOENIX="1"
export LDFLAGS="$SLKLDFLAGS"
export MOZ_LINK_FLAGS="$SLKLDFLAGS"
export MOZ_OPT_FLAGS="$SLKCFLAGS"
export CFLAGS="$SLKCFLAGS"
export CXXFLAGS="$SLKCXXFLAGS"
export CPPFLAGS="$SLKCPPFLAGS"
export MOZ_MAKE_FLAGS="$NUMJOBS"
export MOZBUILD_STATE_PATH="$TMPBUILD/firefox-$RELEASEVER/.mozbuild"

# Clear some variables that could break the build
unset DBUS_SESSION_BUS_ADDRESS ORBIT_SOCKETDIR SESSION_MANAGER \
  XDG_SESSION_COOKIE XAUTHORITY MAKEFLAGS

# Assemble our .mozconfig, we use this method for building, seems
# needed for PGO.
echo ". \$topsrcdir/browser/config/mozconfig" > .mozconfig

# Mozilla devs enforce using an objdir for building
# https://developer.mozilla.org/en/Configuring_Build_Options#Building_with_an_objdir
mkdir obj
echo "mk_add_options MOZ_OBJDIR=$(pwd)/obj" >> .mozconfig

if [ "$MOZLOCALIZE" ]; then
  echo "mk_add_options MOZ_CO_LOCALES=\"$MOZLOCALIZE\"" >> .mozconfig
fi

# Write in it the options above
for option in $OPTIONS; do echo "ac_add_options $option" >> .mozconfig; done

cat << EOF >> .mozconfig
export CC=cc
export CXX=c++
#export AR=llvm-ar
#export NM=llvm-nm
#export RANLIB=llvm-ranlib
EOF

#######################################################################################
########### Build        ##############################################################
#######################################################################################

# https://developer.mozilla.org/en-US/docs/Building_with_Profile-Guided_Optimization
# Thanks to ArchLinux and Gentoo for the additional hints.
if [ "$PGO" = "yes" ]; then
  # Do a PGO build, double time and disk space but worth it.
  export MOZ_PGO=1
  echo "mk_add_options PROFILE_GEN_SCRIPT='EXTRA_TEST_ARGS=10 \$(MAKE) -C \$(MOZ_OBJDIR) pgo-profile-run'" >> .mozconfig
  export DISPLAY=:99
  # Launch Xvfb to let the profile scripts run in a X session.
  # Ugly note: if the build breaks you may want to do a "killall Xvfb".
  Xvfb -nolisten tcp -extension GLX -screen 0 1280x1024x24 $DISPLAY &
  dbus-launch --exit-with-session ./mach build -v || exit 1
  kill $! || true
else
  # Do a normal build
  echo "**** Running ./mach build *****"
# TEMP HACK-------------------------------------------------------------------
# TEMP HACK-------------------------------------------------------------------
# TEMP HACK-------------------------------------------------------------------
  ./mach build -v || { disable_distcc ; ./mach build -v ;} || { distcc_cleanup ; exit 1 ;}
  # No need to retry without distcc:
#  ./mach build -v || { distcc_cleanup ; exit 1 ;}
# TEMP HACK-------------------------------------------------------------------
# TEMP HACK-------------------------------------------------------------------
# TEMP HACK-------------------------------------------------------------------
fi

# Install into package framework:
echo "**** Running ./mach buildsymbols *****"
./mach buildsymbols || { disable_distcc ; ./mach buildsymbols ;} || { distcc_cleanup ; exit 1 ;}

echo "**** Running DESTDIR=$PKG ./mach install ***"
echo "*** Disabling distcc for package installation ***"
disable_distcc
DESTDIR=$PKG ./mach install || { distcc_cleanup ; exit 1 ;}

#######################################################################################
########### Installation ##############################################################
#######################################################################################

# We don't need these (just symlinks anyway):
rm -rf $PKG/usr/lib${LIBDIRSUFFIX}/firefox-devel-$RELEASEVER

# Nor these:
rm -rf $PKG/usr/include

# Note : I know that this doesn't work because 'mach install' does not create a versioned 'firefox-xxx'
# dir. However, it doesn't seem to break anything so for now, I'll leave it.
pushd $PKG/usr/lib${LIBDIRSUFFIX}/firefox-$RELEASEVER
#mv defaults/profile/mimeTypes.rdf defaults/profile/mimeTypes.rdf.orig || exit 1
if [ -d defaults/profile ]; then
  zcat $CWD/mimeTypes.rdf > defaults/profile/mimeTypes.rdf || exit 1
fi
# OK, this patch is useless on 7.x.  We'll float without it and see what happens.
# Perhaps it won't make a difference or should be worked around elsewhere.
#zcat $CWD/firefox.moz_plugin_path.diff.gz \
#  | sed -e "s#usr/lib#usr/lib${LIBDIRSUFFIX}#g" \
#  | patch -p1 --verbose --backup --suffix=.orig || exit 1
# Clean up if the above patch was successful:
#rm -f firefox.orig
popd

mkdir -p $PKG/usr/lib${LIBDIRSUFFIX}/mozilla/plugins
mkdir -p $PKG/usr/share/applications
cat $CWD/mozilla-firefox.desktop > $PKG/usr/share/applications/mozilla-firefox.desktop

# These files/directories are usually created if Firefox is run as root,
# which on many systems might (and possibly should) be never.  Therefore, if we
# don't see them we'll put stubs in place to prevent startup errors.
pushd $PKG/usr/lib${LIBDIRSUFFIX}/firefox-$RELEASEVER
  if [ -d extensions/talkback\@mozilla.org ]; then
    if [ ! -r extensions/talkback\@mozilla.org/chrome.manifest ]; then
      echo > extensions/talkback\@mozilla.org/chrome.manifest
    fi
  fi
  if [ ! -d updates ]; then
    mkdir -p updates/0
  fi
popd

# Need some default icons in the right place:
for i in 16 22 24 32 48 256; do
  install -m 0644 -D browser/branding/official/default${i}.png \
    $PKG/usr/share/icons/hicolor/${i}x${i}/apps/firefox.png
done
mkdir -p $PKG/usr/share/pixmaps
( cd $PKG/usr/share/pixmaps ; ln -sf /usr/share/icons/hicolor/256x256/apps/firefox.png . )
mkdir -p $PKG/usr/lib$LIBDIRSUFFIX/firefox-$RELEASEVER/chrome/icons/default
install -m 644 browser/branding/official/default16.png \
  $PKG/usr/lib$LIBDIRSUFFIX/firefox-$RELEASEVER/icons/
install -m 644 browser/branding/official/default16.png \
  $PKG/usr/lib$LIBDIRSUFFIX/firefox-$RELEASEVER/chrome/icons/default/

# Copy over the LICENSE
install -p -c -m 644 LICENSE $PKG/usr/lib${LIBDIRSUFFIX}/firefox-$RELEASEVER/

# If MOZ_ALLOW_DOWNGRADE=YES, replace the /usr/bin/firefox symlink with a
# shell script that sets the MOZ_ALLOW_DOWNGRADE=1 environment variable so
# that a detected browser downgrade does not reset the user profile:
if [ "$MOZ_ALLOW_DOWNGRADE" = "YES" ]; then
  rm -vf $PKG/usr/bin/firefox
  cat << EOF > $PKG/usr/bin/firefox
#!/bin/sh
#
# Shell script to start Mozilla Firefox.
#
# Don't reset the user profile on a detected browser downgrade:
export MOZ_ALLOW_DOWNGRADE=1

# Start Firefox:
exec /usr/lib${LIBDIRSUFFIX}/firefox/firefox "\$@"
EOF
  chown root:root $PKG/usr/bin/firefox
  chmod 755 $PKG/usr/bin/firefox
fi

# Fix duplicate binary, https://bugzilla.mozilla.org/show_bug.cgi?id=658850
( cd $PKG/usr/lib$LIBDIRSUFFIX/firefox
  if cmp firefox firefox-bin ; then
    ln -vsf firefox-bin firefox
  fi )

# Apply generic Slackware packaging policies:
cd $PKG
slackstripall   # strip all .a archives and all ELFs
#slackstriprpaths     # strip rpaths
slack_delete_lafiles # delete usr/lib{,64}/*.la
slackgzpages -i # compress man & info pages and delete usr/info/dir
slackslack      # chown -R root:root, chmod -R og-w, slackchown, slack644docs
slackdesc       # install slack-desc and doinst.sh

if [ ! -z $MOZLOCALIZE ]; then
  BUILD="${BUILD}_${MOZLOCALIZE}"
fi

slackmp         # run makepkg -l y -c n

# Perform any final checks on the package:
cd $PKG

slackhlinks     # search for any hard links

# Cleanup any distcc stuff:
distcc_cleanup
