Skip to content

Instantly share code, notes, and snippets.

@mklabs
Last active January 17, 2025 04:26
Show Gist options
  • Save mklabs/e5585852589ffc4efec832be817728de to your computer and use it in GitHub Desktop.
Save mklabs/e5585852589ffc4efec832be817728de to your computer and use it in GitHub Desktop.
Useful Makefile for unreal plugins (Windows / PowerShell)
# Unreal Engine Plugin Makefile (Windows / PowerShell)
#
# Assumes Makefile is put next to .uplugin file, and make run at the root of plugin directory
#
# $(shell powershell ...) variables commented out below are useful but can add a significant delay
#
# Tweak UE_ROOT, PLUGIN_NAME and PROJECT_DIR to your setup.
# Variables
# ---------
#
# Nice read on Makefile variables: https://earthly.dev/blog/makefile-variables/
# Current working directory - Works in Windows cmd or Make
CWD := $(shell echo %CD%)
# Change to your Unreal Engine root path
# UE_ROOT := C:/Path/To/UnrealEngine
UE_ROOT := F:/Engines/UE_5.5
UAT := $(UE_ROOT)/Engine/Build/BatchFiles/RunUAT.bat
UE_EDITOR := $(UE_ROOT)/Engine/Binaries/Win64/UnrealEditor.exe
UE_CMD := $(UE_ROOT)/Engine/Binaries/Win64/UnrealEditor-Cmd.exe
PROJECT_DIR := E:/Projects/GBA/CheckRefHandler_55
# Matches the .uproject file in $PROJECT_DIR
PROJECT_NAME := CheckRefHandler_55
# Change to your plugin name
PLUGIN_NAME := BlueprintAttributes
# Or use this to infer PLUGIN_NANE from the .uplugin file found in current directory
# PLUGIN_NAME := $(shell powershell -Command "Get-ChildItem *.uplugin | Select-Object -ExpandProperty BaseName")
# Change to correct path to plugin root dir
# PLUGIN_DIR := $(PROJECT_DIR)/Plugins/BlueprintAttributes/BlueprintAttributes
PLUGIN_DIR := $(CWD)
# Used for the test target, to only run automation tests with prefix
# Default to plugin name, but can be changed with `make test FILTER_TESTS="CustomFilter"`
FILTER_TESTS ?= $(PLUGIN_NAME)
# Or use the variables below to infer PROJECT_DIR and PROJECT_NAME from the .uproject file found in 3 directories
# above the current working directory (assuming here plugin is installed at Plugins/Subdir/PluginName, but 2 folders
# deep is more common)
#
# PROJECT_DIR := $(shell powershell -Command '(Join-Path $(CWD) ../../..) | Resolve-Path | Select-Object -ExpandProperty Path')
# PROJECT_NAME := $(shell powershell -Command 'Get-ChildItem $(PROJECT_DIR)\*.uproject | Select-Object -ExpandProperty BaseName')
# PLUGIN_DIR := $(CWD)
# DOCKER_IMG = ghcr.io/epicgames/unreal-engine:dev-slim-5.5
DOCKER_UE_VERSION ?= 5.5
DOCKER_REGISTRY = ghcr.io/epicgames/unreal-engine
DOCKER_IMG = $(DOCKER_REGISTRY):dev-slim-$(DOCKER_UE_VERSION)
# Targets
# -------
all: help
# Tweak UAT flags with `make uat UAT_FLAGS="BuildPlugin -Help"`
# make uat defaults to -Help, unless overriden via UAT_FLAGS="..." on the command line
# make build defaults to "", unless overriden via UAT_FLAGS="..." on the command line
uat: UAT_FLAGS ?= -Help
uat:
"$(UAT)" $(UAT_FLAGS)
# Build
# may want to add --strict-includes with: make build UAT_FLAGS="-StrictIncludes"
build:
@echo "Building plugin $(PLUGIN_NAME)..."
"$(UAT)" BuildPlugin \
-Plugin="$(PLUGIN_DIR)/$(PLUGIN_NAME).uplugin" \
-TargetPlatforms=Win64 \
-Package="$(PLUGIN_DIR)/Packaged/Win64" \
$(UAT_FLAGS)
# Docker Build
DOCKER_TARGETS = build-docker-5.3 build-docker-5.4 build-docker-5.5
# build-docker-all: build-docker-55 build-docker-54 build-docker-53
build-docker-all: $(DOCKER_TARGETS)
# This target runs RunUAT.sh BuildPlugin within a container for target unreal version (5.3, 5.4, 5.5, ...)
# using the current working directory as a workspace, and mounted in the container as /workspace.
#
# Result of the build is put in Packaged/Linux/$(DOCKER_UE_VERSION)
# Logs are put in Packaged/Logs/unreal-$(DOCKER_UE_VERSION)-$(PLUGIN_NAME).txt
#
# Ephemeral container, automatically removed via --rm flag with docker run
#
# Note: -Package="" is not bind mounted to prevent uat from trying to copy artifacts from other engine version builds when
# building via docker in // against all engine version targets (5.3, 5.4, 5.5). Mainly interrested in log output and exit code,
# rather than build artifacts.
$(DOCKER_TARGETS): DOCKER_UE_VERSION=$(subst build-docker-,,$@)
$(DOCKER_TARGETS):
@echo "Building plugin $(PLUGIN_NAME) via docker (DOCKER_UE_VERSION: $(DOCKER_UE_VERSION))..."
powershell -Command "New-Item Packaged/Logs -ItemType Directory -Force"
powershell -Command '\
docker run --rm --name unreal-$(DOCKER_UE_VERSION)-$(PLUGIN_NAME) ` \
-v $(CWD):/workspace ` \
--workdir /workspace ` \
$(DOCKER_IMG) ` \
/home/ue4/UnrealEngine/Engine/Build/BatchFiles/RunUAT.sh BuildPlugin -Plugin="/workspace/$(PLUGIN_NAME).uplugin" -Package="/tmp/packaged/Linux/$(DOCKER_UE_VERSION)" ` \
$(UAT_FLAGS) ` \
| Tee-Object -file Packaged/Logs/unreal-$(DOCKER_UE_VERSION)-$(PLUGIN_NAME).txt'
ci: clean
make build-docker-all -j 3
logs:
docker logs -f unreal-$(DOCKER_UE_VERSION)-$(PLUGIN_NAME)
# Clean build artifacts
clean:
powershell -Command "if (Test-Path Packaged/) { Remove-Item -Recurse -Force Packaged/ }"
# clean:
# @echo "Cleaning build artifacts..."
# @powershell -Command "& { \
# $$paths = @('$(PLUGIN_DIR)/Intermediate', '$(PLUGIN_DIR)/Binaries', '$(PLUGIN_DIR)/Packaged'); \
# foreach ($$path in $$paths) { \
# if (Test-Path $$path) { Remove-Item -Recurse -Force $$path } \
# } \
# }"
# Package the plugin for distribution
package: clean build
@echo "Packaging plugin $(PLUGIN_NAME)..."
powershell -Command 'New-Item -ItemType Directory -Force -Path "$(PLUGIN_DIR)/Releases"'
powershell -Command 'Move-Item -Force "$(PLUGIN_DIR)/Packaged/Win64" "$(PLUGIN_DIR)/Releases/$(PLUGIN_NAME)"'
test-list:
@echo "Listing tests available..."
"$(UE_CMD)" $(PROJECT_DIR)/$(PROJECT_NAME).uproject \
-ExecCmds="Automation List;quit" \
-Log \
-unattended \
-nopause \
-nosplash \
-nullrhi
# Run tests (if applicable)
test:
@echo "Running tests with: Automation RunTests $(FILTER_TESTS)"
"$(UE_CMD)" $(PROJECT_DIR)/$(PROJECT_NAME).uproject \
-ExecCmds="Automation RunTests $(FILTER_TESTS);quit" \
-Log \
-unattended \
-nopause \
-nosplash \
-nullrhi
## Run the editor
# TODO walk up dir until valid .uproject is found
#
# Outputting logs in UnrealEditor-cmd: https://forums.unrealengine.com/t/outputting-logs-in-unrealeditor-cmd/1538861
run:
@echo "Launching Unreal Editor..."
"$(UE_CMD)" "$(PROJECT_DIR)/$(PROJECT_NAME).uproject" \
-Log
# Help
help:
@echo Available targets:
@echo.
@echo uat - Invokes RunUAT.bat with UAT_FLAGS (Default: -Help, Current Value: $(UAT_FLAGS))
@echo Example: make uat UAT_FLAGS="BuildPlugin -Help"
@echo build - Build the plugin
@echo build-docker-55 - Build the plugin in a docker container for Linux targets
@echo DOCKER_IMG: $(DOCKER_REGISTRY):dev-slim-5.5
@echo build-docker-54 - Build the plugin in a docker container for Linux targets
@echo DOCKER_IMG: $(DOCKER_REGISTRY):dev-slim-5.4
@echo build-docker-53 - Build the plugin in a docker container for Linux targets
@echo DOCKER_IMG: $(DOCKER_REGISTRY):dev-slim-5.3
@echo clean - Clean build artifacts
@echo package - Package the plugin for distribution
@echo test - Run tests for the plugin
@echo help - Show this help message
@echo.
# .PHONY: all uat build build-docker logs build-docker-all build-docker-53 build-docker-54 build-docker-55 clean package test test-list run help
.PHONY: all ci uat build build-docker logs clean package test test-list run help
[Core.Log]
LoadingProfiler = all off
LocalizationService = all off
LogActorFactory = all off
LogAnalytics = all off
LogAndroidPermission = all off
LogAudio = all off
LogAudioCaptureCore = all off
LogAudioMixer = all off
LogChaosDD = all off
LogCollectionManager = all off
LogConfig = all off
LogCsvProfiler = all off
LogDerivedDataCache = all off
LogDevObjectVersion = all off
LogDeviceProfileManager = all off
LogEOSSDK = all off
LogEditorDataStorage = all off
LogEditorDomain = all off
LogEditorServer = all off
LogFab = all off
LogFileCache = all off
LogGameProjectGeneration = all off
LogInit = all off
LogLevelSequenceEditor = all off
LogMemoryProfiler = all off
LogMeshMerging = all off
LogMeshReduction = all off
LogMetaSound = all off
LogNFORDenoise = all off
LogNNEDenoiser = all off
LogNNERuntimeORT = all off
LogNetVersion = all off
LogNetworkingProfiler = all off
LogNiagara = all off
LogNiagaraDebuggerClient = all off
LogOnline = all off
LogPakFile = all off
LogPython = all off
LogRendererCore = all off
LogShaderCompilers = all off
LogSlate= all off
LogSourceControl = all off
LogStreaming = all off
LogStudioTelemetry = all off
LogTargetPlatformManager = all off
LogTcpMessaging = all off
LogTextureEncodingSettings = all off
LogTextureFormatManager = all off
LogTextureFormatOodle = all off
LogTimingProfiler = all off
LogUObjectArray = all off
LogUdpMessaging = all off
LogUsd = all off
LogVRS = all off
LogVirtualization = all off
LogWindows = all off
LogWindowsTextInputMethodSystem = all off
LogWorldPartition = all off
LogXGEController = all off
LogZenServiceInstance = all off
PixWinPlugin = all off
RenderDocPlugin = all off
SourceControl = all off
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment