Last active
June 8, 2025 23:51
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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