Skip to content

Instantly share code, notes, and snippets.

@kala13x
Last active June 8, 2025 23:51
Show Gist options
  • Save kala13x/228986e225e7be08b987ffc00359c888 to your computer and use it in GitHub Desktop.
Save kala13x/228986e225e7be08b987ffc00359c888 to your computer and use it in GitHub Desktop.
Unreal Engine 5 helper script to generate project files, build and run project on Linux
#!/bin/bash
# This source is part of "XAction" project
# 2024-2025 Sun Dro ([email protected])
# NOTE: Modify following variables to match your UE5 installation
# These paths are default and can be overridden with command line
# options or with the project.ini file from the same directory
UE5_PATH="/opt/ue5/UnrealEngine"
PROJECTS_DIR="/opt/ue5/projects"
PACKAGES_DIR="/opt/ue5/packages"
# Do not modify below this line unless you know what you are doing
UE5_EDITOR="$UE5_PATH/Engine/Binaries/Linux/UnrealEditor"
UE5_BATCH_FILES="$UE5_PATH/Engine/Build/BatchFiles"
UE5_GENERATE="$UE5_BATCH_FILES/Linux/GenerateProjectFiles.sh"
UE5_BUILD="$UE5_BATCH_FILES/Linux/Build.sh"
UE5_PACK="$UE5_BATCH_FILES/RunUAT.sh"
UE5_TARGET="Linux Development"
PROJECT_INI="./project.ini"
PROJECT_EDITOR=""
PROJECT_NAME=""
PROJECT_PATH=""
PROJECT_FILE=""
BUILD_OPTIONS=""
RUN_OPTIONS=""
UPDATE_VSCODE=0
GENERATE_FILES=0
BUILD_PROJECT=0
CLEAN_PROJECT=0
CREATE_CONFIG=0
PACK_PROJECT=0
RUN_PROJECT=0
RUN_LOGS=0
CLANG_DB=0
BUILD_UE5=0
print_usage() {
[ $# -eq 1 ] && echo ""
echo "Usage: $0 [options]"
echo "Options:"
echo " --engine=<dir>, -e=<dir> Unreal Engine 5 root directory"
echo " --workdir=<dir>, -w=<dir> Specify working directory"
echo " --project=<name>, -p=<name> Specify project name"
echo " --editor=<name>, -n=<name> Specify project editor name"
echo " --output=<dir>, -o=<dir> Specify output directory for packages"
echo " --initialize, -i Initialize project configuration"
echo " --generate, -g Generate project files"
echo " --vscode, -v Update VSCode project files"
echo " --unreal, -u Build Unreal Engine 5"
echo " --build, -b Build the project"
echo " --clean, -c Clean project build files"
echo " --full, -f Run full build sequence"
echo " --run, -r Run the project"
echo " --pack, -a Package and archive the project"
echo " --meta, -m Generate compiler metadata"
echo " --logs, -l Enable logs during run"
echo " --help, -h Show this help message"
exit 1
}
parse_arguments() {
for arg in "$@"; do
if [[ $arg == --engine=* || $arg == -e=* ]]; then
UE5_PATH="${arg#*=}"
fi
if [[ $arg == --project=* || $arg == -p=* ]]; then
PROJECT_NAME="${arg#*=}"
fi
if [[ $arg == --editor=* || $arg == -n=* ]]; then
PROJECT_EDITOR="${arg#*=}"
fi
if [[ $arg == --output=* || $arg == -o=* ]]; then
PACKAGES_DIR="${arg#*=}"
fi
if [[ $arg == --workdir=* || $arg == -w=* ]]; then
PROJECTS_DIR="${arg#*=}"
fi
if [[ $arg == --ini=* || $arg == -i=* ]]; then
PROJECT_INI="${arg#*=}"
fi
if [[ $arg == "--initialize" || $arg == "-i" ]]; then
CREATE_CONFIG=1
fi
if [[ $arg == "--generate" || $arg == "-g" ]]; then
GENERATE_FILES=1
fi
if [[ $arg == "--build" || $arg == "-b" ]]; then
BUILD_PROJECT=1
fi
if [[ $arg == "--clean" || $arg == "-c" ]]; then
CLEAN_PROJECT=1
fi
if [[ $arg == "--unreal" || $arg == "-u" ]]; then
BUILD_UE5=1
fi
if [[ $arg == "--run" || $arg == "-r" ]]; then
RUN_PROJECT=1
fi
if [[ $arg == "--package" || $arg == "-a" ]]; then
PACK_PROJECT=1
fi
if [[ $arg == "--vscode" || $arg == "-v" ]]; then
UPDATE_VSCODE=1
fi
if [[ $arg == "--meta" || $arg == "-m" ]]; then
CLANG_DB=1
fi
if [[ $arg == "--logs" || $arg == "-l" ]]; then
RUN_LOGS=1
fi
if [[ $arg == "--full" || $arg == "-f" ]]; then
FULL_BUILD=1
fi
if [[ $arg == "--help" || $arg == "-h" ]]; then
print_usage
exit 0
fi
done
}
parse_project_config() {
if [[ -f "$PROJECT_INI" ]]; then
while IFS='=' read -r key value; do
key=$(echo "$key" | xargs) # Trim whitespace
value=$(echo "$value" | xargs) # Trim whitespace
# Skip empty lines and comments
[[ -z "$key" || "$key" =~ ^# ]] && continue
case "$key" in
engine) UE5_PATH="$value" ;;
workdir) PROJECTS_DIR="$value" ;;
project) PROJECT_NAME="$value" ;;
editor) PROJECT_EDITOR="$value" ;;
output) PACKAGES_DIR="$value" ;;
generate) [[ "$value" == "1" ]] && GENERATE_FILES=1 ;;
build) [[ "$value" == "1" ]] && BUILD_PROJECT=1 ;;
clean) [[ "$value" == "1" ]] && CLEAN_PROJECT=1 ;;
unreal) [[ "$value" == "1" ]] && BUILD_UE5=1 ;;
run) [[ "$value" == "1" ]] && RUN_PROJECT=1 ;;
package) [[ "$value" == "1" ]] && PACK_PROJECT=1 ;;
meta) [[ "$value" == "1" ]] && CLANG_DB=1 ;;
vscode) [[ "$value" == "1" ]] && UPDATE_VSCODE=1 ;;
logs) [[ "$value" == "1" ]] && RUN_LOGS=1 ;;
full) [[ "$value" == "1" ]] && FULL_BUILD=1 ;;
esac
done < "$PROJECT_INI"
fi
}
create_config() {
echo "Creating project.ini file: $PROJECT_INI"
{
echo "# Project configuration for Unreal Engine 5"
printf "engine=%s\n" "$UE5_PATH"
printf "workdir=%s\n" "$PROJECTS_DIR"
printf "output=%s\n" "$PACKAGES_DIR"
printf "project=%s\n" "$PROJECT_NAME"
printf "editor=%s\n" "$PROJECT_EDITOR"
printf "package=0\n"
printf "vscode=0\n"
printf "build=1\n"
printf "clean=0\n"
printf "meta=0\n"
printf "logs=1\n"
printf "run=1\n"
} > "$PROJECT_INI"
echo "Project configuration saved to $PROJECT_INI"
}
configure_project() {
UE5_EDITOR="$UE5_PATH/Engine/Binaries/Linux/UnrealEditor"
UE5_BATCH_FILES="$UE5_PATH/Engine/Build/BatchFiles"
UE5_GENERATE="$UE5_BATCH_FILES/Linux/GenerateProjectFiles.sh"
UE5_BUILD="$UE5_BATCH_FILES/Linux/Build.sh"
UE5_PACK="$UE5_BATCH_FILES/RunUAT.sh"
if [[ "$BUILD_UE5" -eq 1 ]]; then
echo "Building Unreal Engine 5..."
echo "Skipping project configuration..."
return
fi
if [[ ! -n "$PROJECT_NAME" ]]; then
echo "Required project name (--project or -p)"
echo "Example: $0 --project=ActionGame"
print_usage 1
exit 1
fi
if [[ ! -n "$PROJECTS_DIR" ]]; then
echo "Required project name (--dir or -d)"
echo "Example: $0 --dir=/opt/ue5/projects"
print_usage 1
exit 1
fi
if [[ "$FULL_BUILD" -eq 1 ]]; then
GENERATE_FILES=1
CLEAN_PROJECT=1
BUILD_PROJECT=1
CREATE_CONFIG=1
UPDATE_VSCODE=1
RUN_PROJECT=1
CLANG_DB=1
fi
[ "$RUN_LOGS" -eq 1 ] && RUN_OPTIONS="$RUN_OPTIONS -log"
[ "$CLANG_DB" -eq 1 ] && BUILD_OPTIONS="$BUILD_OPTIONS -mode=GenerateClangDatabase"
PROJECT_PATH="$PROJECTS_DIR/$PROJECT_NAME"
PROJECT_FILE="$PROJECT_PATH/$PROJECT_NAME.uproject"
if [[ ! -f "$PROJECT_FILE" ]]; then
echo "Project file not found: $PROJECT_FILE"
echo "Please ensure the project exists."
print_usage 1
exit 1
fi
if [[ ! -n "$PROJECT_EDITOR" ]]; then
PROJECT_EDITOR="${PROJECT_NAME}Editor"
echo "Using auto generated editor name: $PROJECT_EDITOR"
echo "Project editor can be specified with --editor or -e"
fi
}
update_vscode() {
local VSCODE_DIR="$PROJECT_PATH/.vscode"
local C_CPP_CONF="$VSCODE_DIR/c_cpp_properties.json"
local COMPILER_CMD="$UE5_PATH/compile_commands.json"
local COMPILER_CMD_ARGS=""
if [[ -f "$COMPILER_CMD" ]]; then
echo "Compiler metadata found: $COMPILER_CMD"
COMPILER_CMD_ARGS="--arg cmd $COMPILER_CMD"
else
echo "Compiler command file not found: $COMPILER_CMD"
echo "Generating default VSCode configuration: $C_CPP_CONF"
fi
echo "Updating VSCode project files: $VSCODE_DIR"
[ ! -d "$VSCODE_DIR" ] && mkdir -p "$VSCODE_DIR"
jq -n $COMPILER_CMD_ARGS '{
configurations: [
{
name: "Linux",
cStandard: "c17",
cppStandard: "c++20",
intelliSenseMode: "clang-x64",
includePath: [
"${workspaceFolder}/Source/**"
]
}
+ ( $cmd? | {compileCommands: .} )
],
version: 4
}' > "$C_CPP_CONF"
echo "Generated $C_CPP_CONF"
echo -e "\033[2m$(cat "$C_CPP_CONF")\033[0m"
}
build_unreal_engine() {
echo "Building Unreal Engine 5: $UE5_PATH"
cd $UE5_PATH || exit 1
if [[ ! -f "./Setup.sh" ]] || [[ ! -f "./GenerateProjectFiles.sh" ]]; then
echo "Unreal Engine 5 setup scripts not found in $UE5_PATH"
echo "Please ensure the path is correct."
exit 1
fi
./Setup.sh || exit 1
./GenerateProjectFiles.sh || exit 1
local CPU_COUNT=$(nproc)
make -j $CPU_COUNT || exit 1
make -j $CPU_COUNT UnrealEngine
if [[ ! -f "$UE5_EDITOR" ]]; then
echo "Failed to build Unreal Engine 5."
exit 1
fi
echo "Unreal Engine 5 built successfully."
exit 0
}
generate_project() {
echo "Generating project files: $PROJECT_FILE"
$UE5_GENERATE -project $PROJECT_FILE
}
build_project() {
echo "Building project: $PROJECT_FILE"
$UE5_BUILD $PROJECT_EDITOR $UE5_TARGET $PROJECT_FILE $BUILD_OPTIONS || exit 1
if [[ -n "$BUILD_OPTIONS" ]]; then
echo "Final rebuild without options"
$UE5_BUILD $PROJECT_EDITOR $UE5_TARGET $PROJECT_FILE || exit 1
fi
}
pack_project() {
local OUTPUT_DIR="$PACKAGES_DIR/$PROJECT_NAME"
[ ! -d "$OUTPUT_DIR" ] && mkdir -p "$OUTPUT_DIR"
echo "Packing project: $PROJECT_FILE -> $OUTPUT_DIR"
$UE5_PACK BuildCookRun -project="$PROJECT_FILE" \
-noP4 -platform=Linux -clientconfig=Development \
-serverconfig=Development -cook -allmaps -build \
-stage -pak -archive -archivedirectory="$OUTPUT_DIR"
}
run_project() {
echo "Running project: $PROJECT_FILE"
$UE5_EDITOR $PROJECT_FILE $RUN_OPTIONS
}
clean_project() {
echo "Cleaning project build files: $PROJECT_PATH"
rm -rf "$PROJECT_PATH/DerivedDataCache"
rm -rf "$PROJECT_PATH/Intermediate"
rm -rf "$PROJECT_PATH/Binaries"
rm -rf "$PROJECT_PATH/Saved"
echo "Project build files cleaned."
}
parse_project_config
parse_arguments "$@"
configure_project
[ "$BUILD_UE5" -eq 1 ] && build_unreal_engine
[ "$CLEAN_PROJECT" -eq 1 ] && clean_project
[ "$GENERATE_FILES" -eq 1 ] && generate_project
[ "$BUILD_PROJECT" -eq 1 ] && build_project
[ "$UPDATE_VSCODE" -eq 1 ] && update_vscode
[ "$CREATE_CONFIG" -eq 1 ] && create_config
[ "$RUN_PROJECT" -eq 1 ] && run_project
[ "$PACK_PROJECT" -eq 1 ] && pack_project
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment