Artifact [2bc32b4350]

Artifact 2bc32b4350f72a3ba3cd9d93102d9c69701f76aa:


#! /usr/bin/env bash

target='x86_64-generic-linux-musl'

fossil_version='2.12.1'
fossil_url="https://fossil-scm.org/home/uv/fossil-src-${fossil_version}.tar.gz"
fossil_sha256='822326ffcfed3748edaf4cfd5ab45b23225dea840304f765d1d55d2e6c7d6603'
fossil_archive="fossil-${fossil_version}.tar.gz"
fossil_dir='fossil'

libressl_version='3.1.4'
libressl_url="http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/libressl-${libressl_version}.tar.gz"
libressl_sha256='414c149c9963983f805a081db5bd3aec146b5f82d529bb63875ac941b25dcbb6'
libressl_archive="libressl-${libressl_version}.tar.gz"
libressl_dir='libressl'

kitcreator_version="0.12.0"
kitcreator_url="http://www.rkeene.org/devel/kitcreator-${kitcreator_version}.tar.gz"
kitcreator_sha256="ee01de0457653aceb8df503196190c134c8129dc14de5e3cf5520b10844f32bd"
kitcreator_archive="kitcreator-${kitcreator_version}.tar.gz"
kitcreator_dir='kitcreator'

# Base options
fossil_configure_options=( --json )

# Platform-specific options
case "${target}" in
	x86_64-*-linux-musl)
		fossil_configure_options=( "${fossil_configure_options[@]}" --static --disable-fusefs --with-openssl=auto )
		;;
esac

# File to create
result="fossil-${fossil_version}-${target}"

# Clean-up the result file before starting
rm -f "${result}" "${result}.info" "${result}.log"

# Helper functions
function random() {
	openssl rand -base64 6 | tr '/+' 'ZZ'
}

function downloadFile() {
	local downloadProgram downloadProgramPath file urls
	local downloadProgramArgs
	local url
	local authoritativeURL

	downloadProgram="$1"
	downloadProgramPath="$2"
	file="$3"
	shift 3

	urls=("$@")

	authoritativeURL="${urls[@]: -1}"

	case "${downloadProgram}" in
		curl)
			downloadProgramArgs=(--header "X-Cache-URL: ${authoritativeURL}" --location --insecure --fail --output "${file}")
			;;
		wget)
			downloadProgramArgs=(--header="X-Cache-URL: ${authoritativeURL}" --no-check-certificate --output-document="${file}")
			;;
	esac

	for url in "${urls[@]}" __fail__; do
		rm -f "${file}"

		if [ "${url}" = '__fail__' ]; then
			return 1
		fi

		"${downloadProgramPath}" "${downloadProgramArgs[@]}" "${url}" && break
	done

	return 0
}

function verifyHash() {
	local file hash hashMethod
	local checkHash

	file="$1"
	hash="$2"
	hashMethod="$3"

	if [ "${hashMethod}" = 'null' ]; then
		return 0
	fi

	checkHash="$(openssl dgst "-${hashMethod}" "${file}" | sed 's@.*= *@@')"

	if [ "${checkHash}" = "${hash}" ]; then
		return 0
	fi

	echo "Hash (${hashMethod}) mismatch: Got: ${checkHash}; Expected: ${hash}" >&2

	return 1
}

function download() {
	local url file hash
	local tryDownloadProgram tryDownloadProgramPath downloadProgram downloadProgramPath
	local hashMethod
	local urls

	url="$1"
	file="$2"
	hash="$3"
	hashMethod='sha256'

	for tryDownloadProgram in wget curl; do
		tryDownloadProgramPath="$(command -v "${tryDownloadProgram}" 2>/dev/null)"

		if [ -z "${tryDownloadProgramPath}" ]; then
			continue
		fi

		if [ -x "${tryDownloadProgramPath}" ]; then
			downloadProgram="${tryDownloadProgram}"
			downloadProgramPath="${tryDownloadProgramPath}"

			break
		fi
	done


	urls=("${url}")

	if [ "${hashMethod}" != 'null' ]; then
		urls=(
			"http://hashcache.rkeene.org/${hashMethod}/${hash}"
			"${urls[@]}"
		)
	fi

	rm -f "${file}.new" || exit 1
	downloadFile "${downloadProgram}" "${downloadProgramPath}" "${file}.new" "${urls[@]}" || return 1

	verifyHash "${file}.new" "${hash}" "${hashMethod}" || return 1

	mv "${file}.new" "${file}" || return 1

	return 0
}

function extract() {
	local file dir
	local dir_parent
	local decompress extract

	file="$1"
	dir="$2"

	dir_parent="$(cd "$(dirname "${dir}")" && pwd)" || return 1

	case "${file}" in
		*.tar.gz|*.tgz)
			decompress=(gzip -dc)
			extract=(tar -xf -)
			;;
		*.tar.bz2|*.tbz2)
			decompress=(bzip2 -dc)
			extract=(tar -xf -)
			;;
		*.tar.xz|*.tar.xz)
			decompress=(xz -dc)
			extract=(tar -xf -)
			;;
		*)
			echo "Unsupported file type: ${file}" >&2
			return 1
			;;
	esac

	cat "${file}" | (
		cd "${dir_parent}" || exit 1
		tmpdir=".extract-$(random)"

		rm -rf "${tmpdir}" || exit 1
		mkdir "${tmpdir}" || exit 1

		(
			cd "${tmpdir}" || exit 1
			"${decompress[@]}" | "${extract[@]}" || exit 1

			shopt -s dotglob

			check_file="$(echo *)"
			if [ -e "${check_file}" ]; then
				mv "${check_file}"/* .
				rmdir "${check_file}"
			fi
		) || exit 1

		rm -rf "${dir}"
		mv "${tmpdir}" "${dir}" || exit 1
	) || return 1

	return 0
}

workdir="${TMPDIR:-/tmp}/build-fossil-static.$(random)"
mkdir -p "${workdir}" || exit 1
trap cleanup EXIT

function cleanup() {
	if [ -n "${workdir}" ]; then
echo		rm -rf "${workdir}"
		workdir=''
	fi
}

# Begin the build
retval='0'

## Build LibreSSL
echo -n 'Building LibreSSL...'
(
	# Operate this sub-shell in the work directory
	cd "${workdir}"

	download "${libressl_url}" "${libressl_archive}" "${libressl_sha256}" || exit 1

	extract "${libressl_archive}" "${libressl_dir}" || exit 1
	cd "${libressl_dir}" || exit 1

	# Setup cross-compiler
	## From Build-CC 0.9+
	eval $(~/root/cross-compilers/setup-cc "${target}") || exit 1

	# This defeats hardening attempts that break on various platforms
	CFLAGS=' -g -O0 '
	export CFLAGS

	./configure --with-pic --disable-shared --enable-static  --host="${target}" "${libressl_configure_options[@]}" --prefix="$(pwd)/INST" --with-openssldir=/etc/ssl || exit 1

	# Disable building the apps -- they do not get used
	rm -rf apps
	mkdir apps
	cat << \_EOF_ > apps/Makefile
%:
	@echo Nothing to do
_EOF_

	${MAKE:-make} V=1 || exit 1

	${MAKE:-make} V=1 install || exit 1
) > "${result}.log" 2>&1 || retval='1'
if [ "${retval}" = '0' ]; then
	# Notify of success
	echo ' success!'
else
	echo ' failed.'
	exit 1
fi

## Build static KitDLL
echo -n 'Building KitDLL...'
(
	# Operate this sub-shell in the work directory
	cd "${workdir}"

	download "${kitcreator_url}" "${kitcreator_archive}" "${kitcreator_sha256}" || exit 1

	extract "${kitcreator_archive}" "${kitcreator_dir}" || exit 1
	cd "${kitcreator_dir}" || exit 1

	# Setup cross-compiler
	## From Build-CC 0.9+
	eval $(~/root/cross-compilers/setup-cc "${target}") || exit 1

	export KITCREATOR_PKGS=' kitdll '
	export KITCREATOR_STATIC_KITDLL='1'
	export KITCREATOR_MINBUILD='1'

	./kitcreator --host="${target}" tcl_cv_strtoul_unbroken=ok || exit 1

	mv libtclkit-sdk-*.tar.gz libtclkit-sdk.tar.gz || exit 1

	# Extract to INST directory
	extract libtclkit-sdk.tar.gz INST || exit 1

	# Replace TCLKIT_SDK_DIR to allow Fossil's naive parser to handle it
	export TCLKIT_SDK_DIR="${workdir}/kitcreator/INST/"
	sed 's|${TCLKIT_SDK_DIR}|'"${TCLKIT_SDK_DIR}"'|g' < "${TCLKIT_SDK_DIR}/lib/tclConfig.sh" > "${TCLKIT_SDK_DIR}/lib/tclConfig.sh.1"
	mv "${TCLKIT_SDK_DIR}/lib/tclConfig.sh.1" "${TCLKIT_SDK_DIR}/lib/tclConfig.sh"

	# Dump logs
	grep '^' */build.log
) >> "${result}.log" 2>&1 || retval='1'
if [ "${retval}" = '0' ]; then
	# Notify of success
	echo ' success!'
else
	echo ' failed.'
	exit 1
fi

## Give status
echo -n 'Building Fossil...'

## Really build
(
	# Operate this sub-shell in the work directory
	cd "${workdir}"

	# Download the archive
	download "${fossil_url}" "${fossil_archive}" "${fossil_sha256}" || exit 1

	# Extract the archive
	extract "${fossil_archive}" "${fossil_dir}" || exit 1
	cd "${fossil_dir}" || exit 1

	# Setup cross-compiler
	## From Build-CC 0.9+
	eval $(~/root/cross-compilers/setup-cc "${target}") || exit 1

	# Setup to use LibreSSL we just compiled
	export PKG_CONFIG_PATH="${workdir}/libressl/INST/lib/pkgconfig"

	# Setup to use KitCreator's KitDLL
	export TCLKIT_SDK_DIR="${workdir}/kitcreator/INST/"

	# Configure fossil as required for this platform
	./configure --host="${target}" --with-tcl="${TCLKIT_SDK_DIR}/lib" "${fossil_configure_options[@]}" || exit 1

	# Build fossil
	make || exit 1

	# Strip executable of debugging symbols
	"${target}-strip" fossil
) >> "${result}.log" 2>&1 || retval='1'

if [ "${retval}" = '0' ]; then
	# Notify of success
	echo ' success!'

	# Copy built executable to current directory
	cp "${workdir}/${fossil_dir}/fossil" "${result}" || exit 1

	# Print out information related to the build
	(
		ls -lh "${result}" || exit 1
		file "${result}" || exit 1
		openssl sha256 "${result}" || exit 1
		strings "${result}" | egrep '^(TLSv1 part of |LibreSSL)' | head -n 1
	) | tee "${result}.info"
else
	# Notify of failure
	echo ' failed.'
fi

# Exit
exit "${retval}"