If STANDALONE is set then the boot files are left intact. If STANDALONE is not set then the image is unblessed. Addresses #178
217 lines
7 KiB
Bash
Executable file
217 lines
7 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
#
|
|
## WizardKit: Live macOS Build Tool
|
|
|
|
set -o errexit
|
|
set -o errtrace
|
|
set -o nounset
|
|
set -o pipefail
|
|
|
|
# Variables
|
|
BASE_IMAGE=""
|
|
HELP=""
|
|
LINUX_DIR="linux"
|
|
MACOS_DIR="macos"
|
|
ROOT_DIR=".."
|
|
STANDLONE=""
|
|
TOOLS_TO_CHECK=(memtest mprime smc sysbench)
|
|
|
|
# Usage
|
|
function usage() {
|
|
echo "Usage: build_macos [OPTIONS] <image_path>"
|
|
echo ""
|
|
echo "Options:"
|
|
echo " -h --help Show usage"
|
|
exit "${1:-0}"
|
|
}
|
|
|
|
# Check arguments
|
|
while :; do
|
|
case "${1:-}" in
|
|
-h|--help)
|
|
HELP="True"
|
|
;;
|
|
-s|--standalone)
|
|
STANDALONE="True"
|
|
;;
|
|
-hs|-sh)
|
|
HELP="True"
|
|
;;
|
|
*)
|
|
if [[ ! "${1:-}" == "" ]]; then
|
|
BASE_IMAGE="${1}"
|
|
fi
|
|
break
|
|
;;
|
|
esac
|
|
shift
|
|
done
|
|
|
|
# Safety Checks
|
|
if [[ ! "${HELP:-}" == "" ]]; then
|
|
usage
|
|
fi
|
|
if [[ ! "${STANDALONE:-}" == "" ]]; then
|
|
echo "Building standalone image"
|
|
fi
|
|
if [[ "${BASE_IMAGE:-}" == "" ]]; then
|
|
echo "No image specified" 1>&2
|
|
echo ""
|
|
usage 1
|
|
elif [[ ! -f "${BASE_IMAGE:-}" ]]; then
|
|
echo "Invalid image specified" 1>&2
|
|
echo ""
|
|
usage 1
|
|
fi
|
|
for tool in "${TOOLS_TO_CHECK[@]}"; do
|
|
if [[ ! -e "/usr/local/bin/$tool" ]]; then
|
|
echo "Missing tool(s) detected"
|
|
echo " Installing dependencies in 30 seconds, enter CTRL+c to abort."
|
|
sleep 30
|
|
"${MACOS_DIR}/install-deps"
|
|
exit
|
|
fi
|
|
done
|
|
|
|
# Load settings
|
|
while read line; do
|
|
if echo "$line" | grep -Eq "^\w+='"; then
|
|
line="$(echo "$line" | sed -E 's/[\r\n]+//')"
|
|
eval "$line"
|
|
fi
|
|
done < "$ROOT_DIR/scripts/wk/cfg/main.py"
|
|
|
|
# Prep
|
|
echo "Initializing..."
|
|
IMAGE_DEV="$(hdiutil attach -mountpoint /Volumes/BaseSystem "${BASE_IMAGE}" -nobrowse | grep -Eo '(/dev/disk[0-9]+)\b')"
|
|
OS_NAME="$(ls /Volumes/BaseSystem | grep -E 'OS X|macOS' | sed -E 's/Install (OS X|macOS) (.*)\.app/\2/')"
|
|
OS_VERSION="$(defaults read /Volumes/BaseSystem/System/Library/CoreServices/SystemVersion ProductVersion)"
|
|
OUT_NAME="${HOME}/Desktop/macWK ${OS_NAME} ($(date +"%Y-%m-%d"))"
|
|
if [[ "${STANDALONE:-}" == "" ]]; then
|
|
OUT_NAME="${OUT_NAME} (NoBoot)"
|
|
fi
|
|
TIMEZONE="$(grep -F LINUX_TIME_ZONE "${ROOT_DIR}/scripts/wk/cfg/main.py" | cut -d '=' -f 2 | sed "s/'//g")"
|
|
WK_PATH="/Volumes/${KIT_NAME_SHORT}_UFD"
|
|
|
|
# Convert to a 4 GB R/W image
|
|
echo "Creating read-write copy of the ${OS_NAME} Base System image..."
|
|
hdiutil create -srcdevice "${IMAGE_DEV}s1" -format UDSB "${OUT_NAME}.sparsebundle"
|
|
hdiutil detach "${IMAGE_DEV}"
|
|
hdiutil resize -size 4g "${OUT_NAME}.sparsebundle"
|
|
WK_IMAGE_DEV="$(hdiutil attach "${OUT_NAME}.sparsebundle" -nobrowse | grep -Eo '(/dev/disk[0-9]+)\b')"
|
|
if ! diskutil rename "OS X Base System" "${KIT_NAME_SHORT}_UFD"; then
|
|
diskutil rename "macOS Base System" "${KIT_NAME_SHORT}_UFD"
|
|
fi
|
|
|
|
# Remove Install app
|
|
echo "Removing Install app..."
|
|
rm -R "${WK_PATH}"/Install*.app
|
|
|
|
# Update Utilities menu
|
|
echo "Updating Utilities menu..."
|
|
if [[ "${OS_VERSION:0:5}" == "10.11" ]]; then
|
|
cp -a "${MACOS_DIR}/El Capitan/Utilities.plist" "${WK_PATH}/System/Installation/CDIS/OS X Utilities.app/Contents/Resources/Utilities.plist"
|
|
elif [[ "${OS_VERSION:0:5}" == "10.13" ]]; then
|
|
cp -a "${MACOS_DIR}/High Sierra/Utilities.plist" "${WK_PATH}/System/Installation/CDIS/macOS Utilities.app/Contents/Resources/Utilities.plist"
|
|
elif [[ "${OS_VERSION:0:5}" == "10.15" ]]; then
|
|
cp -a "${MACOS_DIR}/Catalina/Utilities.plist" "${WK_PATH}/System/Installation/CDIS/macOS Utilities.app/Contents/Resources/Utilities.plist"
|
|
fi
|
|
|
|
# Dropbear (SSH)
|
|
echo "Installing Dropbear..."
|
|
mkdir -p "${WK_PATH}/etc/dropbear"
|
|
for t in rsa dss ecdsa ed25519; do
|
|
dropbearkey -t "${t}" -f "${WK_PATH}/etc/dropbear/dropbear_${t}_host_key"
|
|
done
|
|
ln -s /Volumes/RAM_Disk/.ssh "${WK_PATH}/var/root"/
|
|
cp -a "${LINUX_DIR}/authorized_keys" "${WK_PATH}/.authorized_keys"
|
|
|
|
# Homebrew
|
|
echo "Installing Hombrew..."
|
|
mkdir -p "${WK_PATH}/usr/local/bin"
|
|
ln -s python3 "${WK_PATH}/usr/local/bin/python"
|
|
rsync -aS /opt/ "${WK_PATH}/opt"/
|
|
rsync -aS --exclude='.git*' /usr/local/{Cellar,Frameworks,Homebrew,bin,etc,include,lib,opt,sbin,share,var} "${WK_PATH}/usr/local"/
|
|
if [[ "${OS_VERSION:3:2}" -lt "15" ]]; then
|
|
rsync -aS --exclude='*.git' /usr/local/libexec "${WK_PATH}/usr/local"/
|
|
fi
|
|
|
|
# Fonts
|
|
echo "Installing Fonts..."
|
|
cp -a /Library/Fonts/Inconsolata*ttf "${WK_PATH}/System/Library/Fonts"/
|
|
|
|
# pipes-sh
|
|
echo "Installing pipes.sh..."
|
|
cp -a /usr/bin/tput "${WK_PATH}/usr/bin"/
|
|
|
|
# Terminal
|
|
echo "Installing Terminal Preferences..."
|
|
cp -a "${MACOS_DIR}/com.apple.Terminal.plist" "${WK_PATH}/var/root/Library/Preferences"/
|
|
|
|
# Timezones
|
|
echo "Installing timezones..."
|
|
if [[ "${OS_VERSION:3:2}" == "11" ]]; then
|
|
rsync -aS /usr/share/zoneinfo/ "${WK_PATH}/usr/share/zoneinfo"/
|
|
ln -sf "/usr/share/zoneinfo/${TIMEZONE}" "${WK_PATH}/etc/localtime"
|
|
elif [[ "${OS_VERSION:3:2}" -gt "11" ]]; then
|
|
sudo mkdir -p "${WK_PATH}/var/db/timezone/zoneinfo"
|
|
sudo rsync -aS /var/db/timezone/zoneinfo/ "${WK_PATH}/var/db/timezone/zoneinfo"/
|
|
ln -sf "/var/db/timezone/zoneinfo/${TIMEZONE}" "${WK_PATH}/etc/localtime"
|
|
fi
|
|
|
|
# zsh
|
|
echo "Installing zsh..."
|
|
cp -a /bin/zsh "${WK_PATH}/bin"/
|
|
cp -a "${MACOS_DIR}/zshenv" "${WK_PATH}/etc"/
|
|
rsync -aS /usr/lib/zsh "${WK_PATH}/usr/lib"/
|
|
rsync -aS /usr/share/zsh "${WK_PATH}/usr/share"/
|
|
rsync -aS /usr/local/share/zsh "${WK_PATH}/usr/local/share"/
|
|
sed -Ei '' 's!^(root.*)/bin/sh!\1/bin/zsh!' "${WK_PATH}/etc/passwd"
|
|
|
|
# memtest
|
|
sudo mv -nv "${WK_PATH}/usr/local/bin/memtest" "${WK_PATH}/usr/sbin"/
|
|
sudo chown 0:0 "${WK_PATH}/usr/sbin/memtest"
|
|
sudo chmod 755 "${WK_PATH}/usr/sbin/memtest"
|
|
|
|
# Misc
|
|
cp -a "${LINUX_DIR}/known_networks" "${WK_PATH}/.known_networks"
|
|
cp -a /usr/bin/rsync "${WK_PATH}/usr/bin"/
|
|
cp -a /usr/sbin/networksetup "${WK_PATH}/usr/sbin"/
|
|
cp -a "${MACOS_DIR}/aliases" "${WK_PATH}/.aliases"
|
|
cp -a "${MACOS_DIR}/bashrc" "${WK_PATH}/etc/profile"
|
|
cp -a "${MACOS_DIR}/vimrc" "${WK_PATH}/.vimrc"
|
|
if [[ "${OS_VERSION:3:2}" == "11" ]]; then
|
|
cp -a /usr/bin/grep "${WK_PATH}/usr/bin"/
|
|
cp -a /usr/bin/locale "${WK_PATH}/usr/bin"/
|
|
rsync -aS /usr/share/locale/ "${WK_PATH}/usr/share/locale"/
|
|
elif [[ "${OS_VERSION:3:2}" == "13" ]]; then
|
|
cp -a /usr/lib/libexpat* "${WK_PATH}/usr/lib"/
|
|
fi
|
|
|
|
# WizardKit
|
|
echo "Installing WizardKit env..."
|
|
touch "${WK_PATH}/.wk-live-macos"
|
|
ln -s /Volumes/RAM_Disk/Logs "${WK_PATH}/var/root/Logs"
|
|
cp -a "${LINUX_DIR}/profile_base/airootfs/etc/skel/.tmux.conf" "${WK_PATH}/etc/tmux.conf"
|
|
rsync -aS /usr/bin/{env,killall} "${WK_PATH}/usr/bin"/
|
|
rsync -aS "${MACOS_DIR}/live-macos-startup" "${ROOT_DIR}/scripts/" "${WK_PATH}/usr/local/bin"/
|
|
if [[ -f "${ROOT_DIR}/images/macOS-${OS_VERSION:0:5}.png" ]]; then
|
|
cp -a "${ROOT_DIR}/images/macOS-${OS_VERSION:0:5}.png" "${WK_PATH}/usr/local/wallpaper.png"
|
|
else
|
|
cp -a "${ROOT_DIR}/images/macOS.png" "${WK_PATH}/usr/local/wallpaper.png"
|
|
fi
|
|
|
|
# Unbless
|
|
if [[ "${STANDALONE:-}" == "" ]]; then
|
|
echo "Unblessing image..."
|
|
sudo bless --unbless "${WK_PATH}"
|
|
sudo bless --unbless "${WK_PATH}/System/Library/CoreServices"
|
|
fi
|
|
|
|
# Unmount sparsebundle
|
|
hdiutil detach "${WK_IMAGE_DEV}"
|
|
|
|
# Convert to compressed read-only image
|
|
echo "Converting to read-only image..."
|
|
hdiutil resize -sectors min "${OUT_NAME}.sparsebundle"
|
|
hdiutil convert -format UDZO -o "${OUT_NAME}.dmg" "${OUT_NAME}.sparsebundle"
|