#!/bin/bash # created by vector sigma on July 15 2019 # modified by LAbyOne on My 2021 # github version # Linux users should be able to use this wrapper, although the following are needed: # (Ubuntu alike) # sudo apt-get install build-essential uuid-dev iasl git gcc-10 nasm python3-distutils # $1 argument override MYTOOLCHAIN variable, in case you want GCC53 for example # ====== COLORS ====== COL_BLACK="\x1b[30;01m" COL_RED="\x1b[31;01m" COL_GREEN="\x1b[32;01m" COL_YELLOW="\x1b[33;01m" COL_MAGENTA="\x1b[35;01m" COL_CYAN="\x1b[36;01m" COL_WHITE="\x1b[37;01m" COL_BLUE="\x1b[34;01m" COL_RESET="\x1b[39;49;00m" cd "$(dirname $([ -L $0 ] && readlink $0 || echo $0))" declare -r CLOVERROOT="$PWD" declare -r SYSNAME="$(uname)" MYTOOLCHAIN=${1:-GCC53} # Functions pathmunge() { if [[ ! $PATH =~ (^|:)$1(:|$) ]]; then if [[ "${2:-}" = "after" ]]; then export PATH=$PATH:$1 else export PATH=$1:$PATH fi fi } checkXCODE() { echo "[CHECK XCODE]" if [[ ! -x /usr/bin/xcodebuild ]]; then echo "ERROR: Install Xcode Tools from Apple before using this script." exit 1 fi if [[ ! -d "$(xcode-select --print-path)" ]]; then echo "ERROR: Xcode Command Line Tools not selected:" echo " open Xcode.app and go in Preferences->Locations," echo " and select the Command Line Tools" exit 1 fi } checkGETTEXT() { exportPaths local locations=($(which msgmerge)) if [ "${#locations[@]}" -eq 0 ]; then export GETTEXT_PREFIX="${TOOLCHAIN_DIR}" "${CLOVERROOT}"/buildgettext.sh else # export gettex prefix to ensure buildpkg.sh will use it # without the need to install it again export GETTEXT_PREFIX="$(dirname "${locations[0]}")" fi } exportPaths() { if [[ "$SYSNAME" == Linux ]]; then TOOLCHAIN_DIR=${TOOLCHAIN_DIR:-/usr} elif [[ "$SYSNAME" == Darwin ]]; then pathmunge "$(xcode-select --print-path)"/usr/bin if [[ -d ~/src/opt/local ]]; then TOOLCHAIN_DIR=~/src/opt/local else TOOLCHAIN_DIR=${TOOLCHAIN_DIR:-"$CLOVERROOT"/toolchain} fi fi pathmunge "$TOOLCHAIN_DIR"/bin export TOOLCHAIN_DIR=$TOOLCHAIN_DIR export DIR_MAIN=${DIR_MAIN:-"$CLOVERROOT"/toolchain} export DIR_TOOLS=${DIR_TOOLS:-$DIR_MAIN/tools} export DIR_DOWNLOADS=${DIR_DOWNLOADS:-$DIR_TOOLS/download} export DIR_LOGS=${DIR_LOGS:-$DIR_TOOLS/logs} export PREFIX=${TOOLCHAIN_DIR} } checkTools() { # export any env vars before building anything if [[ "$SYSNAME" == Darwin ]]; then checkXCODE exportPaths local GCC53_BIN="$PREFIX/cross/bin/x86_64-clover-linux-gnu-gcc" if [[ $MYTOOLCHAIN == GCC* ]] && [[ ! -x "${GCC53_BIN}" ]]; then if [[ $MYTOOLCHAIN == GCC53 ]]; then cd "${CLOVERROOT}" ./build_gcc11.sh else MYTOOLCHAIN=XCODE8 fi fi else exportPaths fi } export DIR_OUT=${DIR_OUT:-"$CLOVERROOT"/toolchain/tools/output} if [[ ! -d "${DIR_OUT}" ]]; then mkdir -p "${DIR_OUT}" fi updateClover() { echo "[UPDATE CLOVER]" cd "${CLOVERROOT}" if [[ -d .git ]]; then git fetch --all --recurse-submodules git pull --recurse-submodules origin master else echo "Error: this is not a git repository, can't update!" fi } updateResetClover() { echo "[UPDATE RESET CLOVER]" cd "${CLOVERROOT}" if [[ -d .git ]]; then git fetch --all --recurse-submodules git submodule foreach --recursive git clean -d -f -f git clean -d -f -f git submodule foreach --recursive git reset --hard origin/master git reset --hard origin/master git pull --recurse-submodules origin master else echo "Error: this is not a git repository, can't update!" fi } buildCloverHFSPlus() { if [[ -f "${CLOVERROOT}"/FileSystems/HFSPlus/X64/HFSPlus.efi ]]; then echo "building Clover with HFSPlus" buildClover HFSPlus else echo "${CLOVERROOT}/FileSystems/HFSPlus/X64/HFSPlus.efi: no such file!" sleep 3 menu fi } makeRelease() { checkTools # to force recreation of the Conf folder. You can still use a custom CONF_PATH if you don't want recreation. rm -rf "$CLOVERROOT"/Conf mkdir "$CLOVERROOT"/Conf cd "${CLOVERROOT}" if [[ -z "$WORKSPACE" ]]; then export EDK_TOOLS_PATH="${PWD}"/BaseTools set +u source ./edksetup.sh BaseTools set -u cd "$CLOVERROOT" WORKSPACE="${PWD}" fi echo "[BUILD CLOVER RELEASE]" ./ebuild.sh -fr -mc --no-usb -D NO_GRUB_DRIVERS_EMBEDDED -t $MYTOOLCHAIN ./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -D LESS_DEBUG -t $MYTOOLCHAIN } buildCCPV() { cd "${CLOVERROOT}"/Xcode/CloverConfigPlistValidator make } BLC() { if [[ ! -d "${CLOVERROOT}"/CloverPackage/BootLoaderChooser ]]; then mkdir -p "${CLOVERROOT}"/CloverPackage/BootLoaderChooser fi curl -sLq https://github.com/jief666/BootloaderChooser/releases/download/0.5/BootX64.efi > "${CLOVERROOT}"/CloverPackage/BootLoaderChooser/BootX64.efi chmod 775 "${CLOVERROOT}"/CloverPackage/BootLoaderChooser/BootX64.efi } buildClover() { checkTools # to force recreation of the Conf folder. You can still use a custom CONF_PATH if you don't want recreation. rm -rf "$CLOVERROOT"/Conf mkdir "$CLOVERROOT"/Conf cd "${CLOVERROOT}" if [[ -z "$WORKSPACE" ]]; then export EDK_TOOLS_PATH="${PWD}"/BaseTools set +u source ./edksetup.sh BaseTools set -u cd "$CLOVERROOT" WORKSPACE="${PWD}" fi echo "[BUILD CLOVER]" # Run a custom build script if exist (~/src/tools/Scripts/build.sh) # This allow the user to run ebuild.sh with own parameters if [[ -x "${DIR_TOOLS}"/Scripts/build.sh ]]; then echo "Running custom build script" "${DIR_TOOLS}"/Scripts/build.sh "${CLOVERROOT}" $MYTOOLCHAIN else local parameter=${1:-none} if [[ "${parameter}" == HFSPlus ]]; then #./ebuild.sh -fr -mc --no-usb -D NO_GRUB_DRIVERS_EMBEDDED -D USE_APPLE_HFSPLUS_DRIVER -t $MYTOOLCHAIN ./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -D USE_APPLE_HFSPLUS_DRIVER -t $MYTOOLCHAIN else #./ebuild.sh -fr -mc --no-usb -D NO_GRUB_DRIVERS_EMBEDDED -t $MYTOOLCHAIN ./ebuild.sh -fr -D NO_GRUB_DRIVERS_EMBEDDED -D LESS_DEBUG -t $MYTOOLCHAIN fi fi # Run a post build script if exist (~/src/tools/Scripts/postbuild.sh) if [[ -x "${DIR_TOOLS}"/Scripts/postbuild.sh ]]; then echo "Running postbuild script" "${DIR_TOOLS}"/Scripts/postbuild.sh "${CLOVERROOT}" $MYTOOLCHAIN fi } buildtestsix() { checkTools # to force recreation of the Conf folder. You can still use a custom CONF_PATH if you don't want recreation. rm -rf "$CLOVERROOT"/Conf mkdir "$CLOVERROOT"/Conf cd "${CLOVERROOT}" echo "[BUILD CLOVERDB]" ./hebuild.sh } buildtestsev() { checkTools # to force recreation of the Conf folder. You can still use a custom CONF_PATH if you don't want recreation. rm -rf "$CLOVERROOT"/Conf mkdir "$CLOVERROOT"/Conf cd "${CLOVERROOT}" echo "[BUILD CLOVERDB]" ./ebuild.sh -t GCC53 -mc } buildCloverTest() { checkTools cd "${CLOVERROOT}" if [[ -z "$WORKSPACE" ]]; then export EDK_TOOLS_PATH="${PWD}"/BaseTools set +u source ./edksetup.sh BaseTools set -u cd "$CLOVERROOT" WORKSPACE="${PWD}" fi echo "[BUILD CLOVER TEST]" ./ebuild.sh -nb -t $MYTOOLCHAIN } buildPkg() { if [[ "$SYSNAME" == Darwin ]]; then cd "${CLOVERROOT}"/CloverPackage echo "[BUILD PKG]" checkXCODE checkGETTEXT make pkg else echo && echo "can't build pkg on a non Darwin OS!" fi } buildApp() { local withClover=${1-"none"} if [[ "$SYSNAME" == Darwin ]]; then if [[ -f "${CLOVERROOT}"/CloverPackage/CloverV2/EFI/CLOVER/CLOVERX64.efi ]]; then rm -f "${CLOVERROOT}"/CloverPackage/sym/.withV2 mkdir -p "${CLOVERROOT}"/CloverPackage/sym if [[ $withClover == withV2 ]]; then touch "${CLOVERROOT}"/CloverPackage/sym/.withV2 fi cd "${CLOVERROOT}"/CloverApp echo "[BUILD APP]" checkXCODE make else echo && echo "please, build Clover first!" sleep 3 fi else echo && echo "Clover.app can only be built in macOS!" fi } buildIso() { cd "${CLOVERROOT}"/CloverPackage echo "[BUILD ISO]" make iso } makeV2() { cd "${CLOVERROOT}"/CloverPackage echo "[BUILD CloverV2]" make zip } checkStatus() { revision=r$(git describe --tags $(git rev-list --tags --max-count=1)) cd "${CLOVERROOT}" if [[ -d .git ]]; then git fetch --recurse-submodules origin git log -n 1 > "${DIR_OUT}"/status_${revision}-$(date +%Y%m%d-%H.%M.%S).txt git status >> "${DIR_OUT}"/status_${revision}-$(date +%Y%m%d-%H.%M.%S).txt git submodule foreach --recursive "git log -n 1 && git status" >> "${DIR_OUT}"/status_${revision}-$(date +%Y%m%d-%H.%M.%S).txt && open "${DIR_OUT}"/status_${revision}-*.txt else echo "Error: this is not a git repository, can't get info!" fi } showdiff() { revision=r$(git describe --tags $(git rev-list --tags --max-count=1)) cd "${CLOVERROOT}" if [[ -d .git ]]; then git fetch --recurse-submodules origin git diff > "${DIR_OUT}"/diff_${revision}-$(date +%Y%m%d-%H.%M.%S).txt && open "${DIR_OUT}"/diff_${revision}-*.txt else echo "Error: this is not a git repository, can't get info!" fi } cleanBaseTools() { cd "${CLOVERROOT}"/BaseTools make clean } ## Utilities buildCPV() { revision=r$(git describe --tags $(git rev-list --tags --max-count=1)) if [[ -d "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator ]]; then rm -Rf "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator fi mkdir -p "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator cd "${CLOVERROOT}"/Xcode/CloverConfigPlistValidator checkXCODE xcodebuild -project ./CloverConfigPlistValidator.xcodeproj -quiet CONFIGURATION_BUILD_DIR="${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator mv -f "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator/CloverConfigPlistValidator "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator/CloverConfigPlistValidator_${revision} rm -r "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator/*.dSYM open "${CLOVERROOT}"/CloverPackage/CloverConfigPlistValidator } PlistEDPlus() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && curl -qsSLk https://github.com/ic005k/PlistEDPlus/releases/download/1.0.64/PlistEDPlus_Mac.dmg > PlistEDPlus_Mac.dmg hdiutil attach -quiet -noverify -nobrowse PlistEDPlus_Mac.dmg && cp -Rf /Volumes/bin\:release\:PlistEDPlus/PlistEDPlus.app $HOME/Desktop/ClovUtils hdiutil detach -force /Volumes/bin\:release\:PlistEDPlus rm -r $HOME/Desktop/ClovUtils/PlistEDPlus_Mac.dmg && open $HOME/Desktop/ClovUtils } Hackintool() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && curl -sLq https://github.com/headkaze/Hackintool/releases/download/3.6.2/Hackintool.zip -o Hackintool.zip unzip -q Hackintool.zip && rm -r Hackintool.zip && open $HOME/Desktop/ClovUtils } BitmaskDecode() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/corpnewt/BitmaskDecode && open $HOME/Desktop/ClovUtils } MaciASL() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && curl -sLq https://github.com/acidanthera/MaciASL/releases/download/1.6.2/MaciASL-1.6.2-RELEASE.dmg > MaciASL-1.6.2-RELEASE.dmg hdiutil attach -quiet -noverify -nobrowse MaciASL-1.6.2-RELEASE.dmg && cp -Rf /Volumes/MaciASL/MaciASL.app $HOME/Desktop/ClovUtils hdiutil detach -force /Volumes/MaciASL rm -r $HOME/Desktop/ClovUtils/MaciASL-1.6.2-RELEASE.dmg && open $HOME/Desktop/ClovUtils } dmidecode() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils/dmidecode fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/acidanthera/dmidecode dmi-decode && xcodebuild -project ./dmi-decode/dmidecode.xcodeproj -quiet cp -r dmi-decode/dmidecode $HOME/Desktop/ClovUtils/dmidecode && rm -Rf $HOME/Desktop/ClovUtils/dmi-decode && open $HOME/Desktop/ClovUtils } Get-IOReg-Devices() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/LAbyOne/Get-IOReg-Devices mv -f Get-IOReg-Devices/Get\ IOReg\ Devices $HOME/Desktop/ClovUtils/Get\ IOReg-Devices && chmod a+x $HOME/Desktop/ClovUtils/Get\ IOReg-Devices/*.command rm -rf Get-IOReg-Devices && open $HOME/Desktop/ClovUtils } NDBrightness () { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/KAMIKAZEUA/NativeDisplayBrightness NDBrightness xcodebuild -project ./NDBrightness/NativeDisplayBrightness.xcodeproj -quiet -configuration Release clean build ARCHS=x86_64 ONLY_ACTIVE_ARCH=YES CONFIGURATION_BUILD_DIR=$HOME/Desktop/ClovUtils rm -Rf $HOME/Desktop/ClovUtils/NDBrightness && rm -r $HOME/Desktop/ClovUtils/*.dSYM && open $HOME/Desktop/ClovUtils } SSDTTime() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/corpnewt/SSDTTime && open $HOME/Desktop/ClovUtils } USBMap() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/corpnewt/USBMap open $HOME/Desktop/ClovUtils } QtiASL() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && curl -sLq https://github.com/ic005k/QtiASL/releases/download/1.0.63/QtiASL_Mac.dmg > QtiASL_Mac.dmg hdiutil attach -quiet -noverify -nobrowse QtiASL_Mac.dmg && cp -Rf /Volumes/bin\:release\:QtiASL/QtiASL.app $HOME/Desktop/ClovUtils hdiutil detach -force /Volumes/bin\:release\:QtiASL rm -r $HOME/Desktop/ClovUtils/QtiASL_Mac.dmg && open $HOME/Desktop/ClovUtils } CsrDecode() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils/CsrDecode fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/corpnewt/CsrDecode && open $HOME/Desktop/ClovUtils } gibMacOS() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && git clone -q https://github.com/corpnewt/gibMacOS && open $HOME/Desktop/ClovUtils } mountR/W() { if [[ ! -d $HOME/Desktop/ClovUtils ]]; then mkdir -p $HOME/Desktop/ClovUtils fi cd $HOME/Desktop/ClovUtils && curl -sLq https://github.com/jacklukem/BigSurmountsrw/releases/download/1.0/BigSurmountsrw2.app.zip -o BigSurmountsrw2.app.zip && open $HOME/Desktop/ClovUtils unzip -q $HOME/Desktop/ClovUtils/BigSurmountsrw2.app.zip && rm -r $HOME/Desktop/ClovUtils/BigSurmountsrw2.app.zip $HOME/Desktop/ClovUtils/__MACOSX } testing() { clear echo echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET cd "${CLOVERROOT}" local lsha1="not a git repo" if [[ -d .git ]]; then lsha1=$(git rev-parse --short HEAD) fi echo -e " 🍀$COL_GREEN Clover r$(git describe --tags $(git rev-list --tags --max-count=1))$COL_WHITE (SHA: $lsha1)"$COL_RESET echo -e $COL_CYAN" $COL_CYAN Test Builds "$COL_RESET echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET echo -e "\n\n\n\n\n\n\n\n\n\n\n" PS3=' Please enter your choice: ' options=( 'test Clover with boot6' 'test Clover with boot7' 'test build (no autogen, no boot files)' 'back to buildme' 'quit') select opt in "${options[@]}" do case $opt in "test Clover with boot6") buildtestsix break ;; "test Clover with boot7") buildtestsev break ;; "test build (no autogen, no boot files)") buildCloverTest break ;; "back to buildme") menu break ;; "quit") exit break ;; *) echo "invalid option $REPLY" break ;; esac done testing } Utilities() { echo echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET cd "${CLOVERROOT}" local lsha1="not a git repo" if [[ -d .git ]]; then lsha1=$(git rev-parse --short HEAD) fi echo -e " 🍀$COL_GREEN Clover r$(git describe --tags $(git rev-list --tags --max-count=1))$COL_WHITE (SHA: $lsha1)"$COL_RESET echo -e $COL_CYAN" $COL_CYAN Utilities "$COL_RESET echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET echo -e "\n\n\n\n\n\n\n\n" PS3=' Files will be put on Desktop/ClovUtils: ' options=( 'Get CloverConfigPlistValidator' 'Get PlistEDPlus' 'Get Hackintool' 'Get BitmaskDecode' 'Get MaciASL' 'Get dmidecode' 'Get IOReg-Devices' 'Get NativeDisplayBrightness' 'Get SSDTTime' 'Get USBMap' 'Get QtiASL' 'Get CsrDecode' 'Get gibMacOS' 'Get mountR/W' 'back to buildme' 'quit') select opt in "${options[@]}" do case $opt in "Get CloverConfigPlistValidator") buildCPV break ;; "Get PlistEDPlus") PlistEDPlus break ;; "Get Hackintool") Hackintool break ;; "Get BitmaskDecode") BitmaskDecode break ;; "Get MaciASL") MaciASL break ;; "Get dmidecode") dmidecode break ;; "Get IOReg-Devices") Get-IOReg-Devices break ;; "Get NativeDisplayBrightness") NDBrightness break ;; "Get SSDTTime") SSDTTime break ;; "Get USBMap") USBMap break ;; "Get QtiASL") QtiASL break ;; "Get CsrDecode") CsrDecode break ;; "Get gibMacOS") gibMacOS break ;; "Get mountR/W") mountR/W break ;; "back to buildme") menu break ;; "quit") exit break ;; *) echo "invalid option $REPLY" break ;; esac done Utilities } menu() { echo echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET cd "${CLOVERROOT}" local lsha1="not a git repo" if [[ -d .git ]]; then lsha1=$(git rev-parse --short HEAD) fi echo -e " 🍀$COL_GREEN Clover r$(git describe --tags $(git rev-list --tags --max-count=1))$COL_WHITE (SHA: $lsha1)"$COL_RESET echo -e "$COL_CYAN TOOLCHAIN: $MYTOOLCHAIN (override example: './buildme XCODE8')" echo -e $COL_GREEN"-----------------------------------------------------------"$COL_RESET echo -e "\n\n\n\n\n\n\n\n" PS3=' Please enter your choice: ' options=( 'build Clover' 'update Clover' 'build Clover with HFSPlus' 'make pkg' 'make iso' 'make app' 'build all' 'make Release' 'test Clover' 'check status' 'show diff' 'open CloverV2/EFI/CLOVER directory' 'update Clover (reset changes)' 'clean BaseTools' 'Utilities' 'quit') select opt in "${options[@]}" do case $opt in "build Clover") buildClover break ;; "update Clover") updateClover break ;; "build Clover with HFSPlus") buildCloverHFSPlus break ;; "make pkg") buildCCPV BLC buildPkg break ;; "make iso") buildIso break ;; "make app") buildApp withV2 break ;; # "make app (with Clover)") # buildApp withV2 # break # ;; "build all") buildClover buildCCPV BLC buildPkg buildIso makeV2 break ;; "make Release") makeRelease buildCCPV BLC buildPkg buildIso makeV2 break ;; "test Clover") testing break ;; "check status") checkStatus break ;; "show diff") showdiff break ;; "open CloverV2/EFI/CLOVER directory") if [[ -d "${CLOVERROOT}"/CloverPackage/CloverV2/EFI/CLOVER ]]; then open "${CLOVERROOT}"/CloverPackage/CloverV2/EFI/CLOVER else echo && echo "Directory not found. Compile Clover first!!" sleep 2 fi break ;; "update Clover (reset changes)") read -p "Are you sure? (type y to confirm or any other to negate) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then updateResetClover fi break ;; "clean BaseTools") read -p "Are you sure? (type y to confirm or any other to negate) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then cleanBaseTools fi break ;; "Utilities") Utilities break ;; "quit") exit 0 ;; *) echo "invalid option $REPLY" break ;; esac done menu } # Main set -e if [[ "$2" == ci ]]; then buildClover buildCCPV BLC buildPkg buildIso buildApp else menu fi