Skip to content

Instantly share code, notes, and snippets.

@mikeseese
Last active May 12, 2022 18:24
Show Gist options
  • Save mikeseese/db60030638b795b9de47fbdb3c076b2e to your computer and use it in GitHub Desktop.
Save mikeseese/db60030638b795b9de47fbdb3c076b2e to your computer and use it in GitHub Desktop.
Unreal Win/Lin/Mac packaging script with AngelScript support. See comments for assumptions and other notes
#!/bin/bash
# only used in windows for cross compiling
export LINUX_MULTIARCH_ROOT=/c/UnrealToolchains/v19_clang-11.0.1-centos7/
if [ "$(uname)" != "Darwin" ]; then
${LINUX_MULTIARCH_ROOT}x86_64-unknown-linux-gnu/bin/clang++ -v
fi
SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
PROJECT_FILE=$(/usr/bin/find ${SCRIPT_DIR} -maxdepth 1 -name *.uproject)
PROJECT_NAME=$(basename ${PROJECT_FILE} .uproject)
ENGINE_VERSION=UE5_Source
TARGET=$1 # "client" or "server"
CONFIG=$2 # "Debug", "DebugGame", "Development", "Test", or "Shipping"
OS_OPTION=$3 # only "linux" for cross compile
ARCHIVE_DIR=${SCRIPT_DIR}\\builds\\${CONFIG}\\${TARGET}
AS_BASE_DIR=Script
# Parameters for SFTPing builds to another machine
SSH_USER="<INSERT SSH USER>"
SSH_HOST="<INSERT SSH HOST>"
SSH_ARCHIVE_FOLDER="<INSERT SSH FOLDER>"
if [ "$(uname)" == "Darwin" ]; then
UAT_PATH="/Users/<INSERT_MAC_USER>/work/${ENGINE_VERSION}/Engine/Build/BatchFiles/RunUAT.sh"
TARGET_PLATFORM=Mac
PLATFORM_NAME=Mac
EXE_EXT=".app"
SSH_KEY="/Users/<INSERT_MAC_USER>/.ssh/id_ed25519_jenkins"
7ZIP_PATH="/usr/local/bin/7zz"
else
UAT_PATH="/d/epic/engine/${ENGINE_VERSION}/Engine/Build/BatchFiles/RunUAT.bat"
# windows handles linux cross compile
if [ "${OS_OPTION}" == "linux" ]; then
TARGET_PLATFORM=Linux
PLATFORM_NAME=Linux
EXE_EXT=".sh"
else
TARGET_PLATFORM=Win64
PLATFORM_NAME=Windows
EXE_EXT=".exe"
fi
SSH_KEY="/c/Users/<INSERT_WINDOWS_USER>/.ssh/id_ed25519_jenkins"
7ZIP_PATH="/c/Program\ Files/7-Zip/7z"
fi
if [ "${TARGET}" == "server" ]; then
PLATFORM_PARAM="-serverplatform=${TARGET_PLATFORM}"
CLIENT_PARAM="-noclient"
SERVER_PARAM="-server"
TARGET_NAME="Server"
else
PLATFORM_PARAM="-platform=${TARGET_PLATFORM}"
CLIENT_PARAM="-client"
SERVER_PARAM=""
TARGET_NAME="Client"
fi
BUILD_SUBDIR=${PLATFORM_NAME}${TARGET_NAME}
OUT_NAME=${PROJECT_NAME}${TARGET_NAME}
OUT_EXE=${OUT_NAME}${EXE_EXT}
BUILD_DIR=${ARCHIVE_DIR}/${BUILD_SUBDIR}
ExecuteBuild() {
ARGS="\
BuildCookRun \
-project=${PROJECT_FILE} \
-noP4 \
${PLATFORM_PARAM} \
${CLIENT_PARAM} \
${SERVER_PARAM} \
-${TARGET}config=${CONFIG} \
-cook \
-build \
-stage \
-pak \
-iostore \
-cook4iostore \
-archive \
-archivedirectory=${ARCHIVE_DIR} \
-separatedebuginfo \
-unattended"
"${UAT_PATH}" ${ARGS}
return $?
}
ExecuteBuild
buildStatus=$?
if [ "${buildStatus}" != "0" ]; then
exit ${buildStatus}
fi
mkdir -p ${BUILD_DIR}/${PROJECT_NAME}/${AS_BASE_DIR}
# copy the cache for the AS binds
cp ${AS_BASE_DIR}/Binds.Cache* ${BUILD_DIR}/${PROJECT_NAME}/${AS_BASE_DIR}
# find all the unique dirs in AS_BASE_DIR that have AS code
AS_DIRS=()
while IFS= read -r -d $'\0'; do
NEXTDIR=$(echo "${REPLY}" | awk 'BEGIN { FS = "/" } ; { print $2 }')
AS_DIRS+=("$NEXTDIR")
done < <(/usr/bin/find ${AS_BASE_DIR} -name *.as -print0)
AS_DIRS=($(for dir in "${AS_DIRS[@]}"; do echo "${dir}"; done | /usr/bin/sort -u))
# copy AS code to the build dir
for dir in "${AS_DIRS[@]}"; do
cp -r ${AS_BASE_DIR}/${dir} ${BUILD_DIR}/${PROJECT_NAME}/${AS_BASE_DIR}
done
pushd ${BUILD_DIR}
if [ "${OS_OPTION}" == "linux" ]; then
/c/Windows/System32/bash -c "./${OUT_EXE} -nullrhi -as-generate-precompiled-data || echo Finished"
rm ./${PROJECT_NAME}/Binaries/Linux/core || echo "Linux core file was not detected, so it wasn't deleted"
else
./${OUT_EXE} -nullrhi -as-generate-precompiled-data || echo Finished
fi
# remove AS code to the build dir
for dir in "${AS_DIRS[@]}"; do
rm -rf ./${PROJECT_NAME}/${AS_BASE_DIR}/${dir}
done
# remove JITTED code
rm -rf AS_JITTED_CODE
# remove Saved directory
rm -rf ./Engine/Saved
rm -rf ./${PROJECT_NAME}/Saved
cd ..
zipName=${PLASTICSCM_CHANGESET_ID}_${PLATFORM_NAME}_${OUT_NAME}.zip
${7ZIP_PATH} a -r -tzip ${zipName} ${BUILD_SUBDIR}
sftp -i ${SSH_KEY} ${SSH_USER}@${SSH_HOST} <<END
cd ${SSH_ARCHIVE_FOLDER}
put ${zipName}
END
popd
@mikeseese
Copy link
Author

mikeseese commented May 12, 2022

This script has a lot of assumptions and caveats:

  • The reasoning for AS_BASE_DIR being parameterized is I changed my base directory for AngelScript files in my engine to be Source instead of the default Script
  • This script runs on Windows under Git Bash as well with current macOS built-in bash
  • Linux builds are cross compiled from Windows and requires the associated toolchain. Make sure you update LINUX_MULTIARCH_ROOT at the top with your version. You can get the toolchains from https://docs.unrealengine.com/4.27/en-US/SharingAndReleasing/Linux/GettingStarted/
  • Linux AS precompilation happens using WSL with Ubuntu bash on the Windows machine (that's what /c/Windows/System32/bash points to, which is different than the Git Bash shell that's running the script)
  • This script assumes 7zip is installed normally with Windows. For Mac, I downloaded the console binary and then moved 7zz into /usr/local/bin, updating the ownership accordingly
  • The script transfers the builds to a central server using SFTP. SFTP comes with Git Bash and is installed on macOS by default
  • The script assumes the build directory gets wiped in between builds (Jenkins handles this for me)
  • Compiling AngelScript on Mac required me to delete references to FBox3f and FBoxSphereBounds3f in Bind_UStruct.cpp (and delete Bind_FBox3f.cpp and Bind_FBoxSphereBounds3f.cpp) as I couldn't figure out why the linker couldn't find the definitions and I don't need them for now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment