UE Module & Build System
Target engine: UE 5.8. APIs below are verified against the 5.8 headers and UnrealBuildTool sources; older forms are listed under "Deprecated — do not use".
This skill covers UnrealBuildTool (UBT) ModuleRules (*.Build.cs) and TargetRules (*.Target.cs), the .uproject and .uplugin descriptors, module registration (IModuleInterface and IMPLEMENT_MODULE in Modules/ModuleManager.h, module Core), plugin discovery (IPluginManager in Interfaces/IPluginManager.h, module Projects), and the compiler, linker, UHT and UBT errors those files cause.
Context
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
Build.cs Anatomy
Every module has <ModuleName>.Build.cs next to its Public/ and Private/ folders. The class name must equal the module name.
Public vs Private Dependencies
Start private and promote to public only when a public header forces it. Everything-public inflates compile time for every downstream module.
Include Paths and IWYU
UBT discovers Public/, Internal/ and Private/ automatically; PublicIncludePaths/PrivateIncludePaths exist for extra subfolders only. Under BuildSettingsVersion.V2 and later, bLegacyPublicIncludePaths is false, so headers from other modules are written relative to that module's Public/ (or Classes/) root:
IWYUSupport defaults to IWYUSupport.Full, which lets UnrealBuildTool -Mode=IWYU rewrite the module's includes; set IWYUSupport = IWYUSupport.KeepAsIs for code you maintain by hand.
API Export Macro
UBT defines <MODULENAME>_API (module name upper-cased plus _API) as DLLEXPORT while compiling the module and DLLIMPORT for importers; monolithic builds define it empty. Anything referenced from another module needs it:
Engine headers wrap this as #define UE_API CORE_API at the top of a file and #undef UE_API at the bottom (Async/Mutex.h). That is an engine-only convention; project code writes MYGAME_API directly. Missing MYGAME_API on a class another module references is the most common cause of LNK2019.
Warnings and Compiler Flags
Every ModuleRules field, the RuntimeDependencies API, platform conditionals and the full engine module table are in references/build-cs-reference.md [blocked].
Target.cs
Source/MyGame.Target.cs and Source/MyGameEditor.Target.cs. The class must be named <FileName>Target; UBT otherwise fails with "Expecting to find a type to be declared in a target rules named 'MyGameTarget'".
Source/MyGameEditor.Target.cs declares MyGameEditorTarget with the same body except Type = TargetType.Editor; and ExtraModuleNames.AddRange(new string[] { "MyGame", "MyGameEditor" });.
BuildSettingsVersion.V7is what 5.8 project templates emit (Latestalso equalsV7). Pin the explicit value;Latestchanges meaning on every engine upgrade.EngineIncludeOrderVersion.Unreal5_8selects theUE_ENABLE_INCLUDE_ORDER_DEPRECATED_IN_5_8define that keeps removed implicit engine includes available to your code.Unreal5_1–Unreal5_5are[Obsolete]and unsupported;Unreal5_6is deprecated. A module may override withModuleRules.IncludeOrderVersion.
Build configurations (UnrealTargetConfiguration): Debug, DebugGame (engine optimized, game unoptimized), Development (default), Test, Shipping. Useful target switches: bUseUnityBuild, bUseLoggingInShipping, bUseChecksInShipping, bWithLiveCoding, LinkType = TargetLinkType.Monolithic, GlobalDefinitions/ProjectDefinitions, and bOverrideBuildEnvironment = true to "ignore violations to the shared build environment (eg. editor targets modifying definitions)".
.uproject File
AdditionalDependencies is the descriptor's "list of additional dependencies for building this module". Plugin references accept Name, Enabled, Optional, TargetAllowList/TargetDenyList, PlatformAllowList/PlatformDenyList, TargetConfigurationAllowList.
Module Types (ModuleHostType)
Loading Phases (ModuleLoadingPhase)
Creating a New Module
FDefaultModuleImpl and FDefaultGameModuleImpl are ready-made classes for modules with no startup logic; FDefaultGameModuleImpl::IsGameModule() returns true so hot-reload tooling treats it as game code. The second macro argument must equal the Build.cs module name; both the monolithic and modular forms of the macro check it against UE_MODULE_NAME with UE_STATIC_ASSERT_WARN (ModuleManager.h:950, :968), which emits a "Module name mismatch" deprecation-style warning, an error only under bWarningsAsErrors. Other IModuleInterface hooks: PreUnloadCallback(), PostLoadCallback(), SupportsDynamicReloading(), SupportsAutomaticShutdown().
Then register the module in three places: the .uproject (or .uplugin) Modules array, ExtraModuleNames in every Target.cs that should build it, and the dependency lists of modules that use it. Editor-only modules ("Type": "Editor", PrivateDependencyModuleNames.Add("UnrealEd") inside if (Target.bBuildEditor)) are covered in ue-editor-tools.
Creating a Plugin
- Declare every plugin whose modules you depend on in
Plugins; UBT warns "Plugin 'MyPlugin' does not list plugin 'X' as a dependency, but module 'MyPlugin' depends on module 'Y'" otherwise. IsExperimentalVersion/IsBetaVersionare what the editor shows as maturity;EnabledByDefault: trueenables the plugin in every project without a.uprojectentry.- Content-only plugins omit
Modulesentirely and keep"CanContainContent": true. - Game Feature plugins (
UGameFeatureData, actions) are owned byue-game-features.
The runtime module never includes editor headers; gate editor code with #if WITH_EDITOR and editor dependencies with if (Target.bBuildEditor).
Engine vs project plugins: Engine/Plugins/ is shared by every project on that install; <Project>/Plugins/ travels with the project and wins on a name clash. Installed (Launcher) engines ship only precompiled engine modules: depending on an engine module that was not precompiled fails with "Missing precompiled manifest for 'X'. This module can not be referenced in a monolithic precompiled build, remove this reference or migrate to a fully compiled source build."
Which Module Provides This Type
The full table, including editor and networking modules, is in references/build-cs-reference.md [blocked].
Resolving Build Errors
Full messages, causes, MSVC warning-level mapping, Live Coding limits and cooking failures are in references/common-build-errors.md [blocked].
Deprecated — do not use
Common Mistakes
Everything in PublicDependencyModuleNames: every downstream module inherits the include paths and recompiles more often. Keep a dependency private until one of your Public/ headers needs it.
Missing MYGAME_API: the class compiles inside its own module and fails with LNK2019 from any other module. Add the macro to the class or free-function declaration, not the definition.
IMPLEMENT_MODULE name mismatch: IMPLEMENT_MODULE(FMyModule, MyGameplay) in a module whose Build.cs is MyModule emits the "Module name mismatch" warning (UE_STATIC_ASSERT_WARN, not a hard error) and, separately, fails to load in monolithic builds because the linker looks for IMPLEMENT_MODULE_MyModule. The second argument is the module name, not the class.
Editor code in a runtime module: #include "Editor.h" or UnrealEd in PublicDependencyModuleNames breaks Game, Client and Server targets. Wrap with #if WITH_EDITOR and if (Target.bBuildEditor), or move the code to an Editor-type module.
Module registered in one place only: a module must appear in .uproject/.uplugin Modules and in ExtraModuleNames of each Target.cs; missing either gives "Could not find definition for module" or a module that never loads.
Wrong LoadingPhase for registration: asset types, custom UClass registrations and console variables that other modules read at Default must load at PreDefault.
Plugin dependency not declared: a .uplugin module depending on another plugin's module without a Plugins entry produces the UBT dependency warning and breaks when the other plugin is disabled.
Relying on transitive includes: a header that compiled because Engine/World.h happened to pull it in breaks when that engine header trims its includes under a newer IncludeOrderVersion. Include what you use.
Wrong header path: including Actor.h or Engine/Actor.h fails with C1083; the file is GameFramework/Actor.h under Engine/Classes.
Related Skills
ue-cpp-foundations—UCLASS/UPROPERTY/UFUNCTIONspecifiers,GENERATED_BODY, what UHT needs in public headersue-editor-tools— editor-only modules,UnrealEd/ToolMenus/PropertyEditordependencies,UEditorSubsystemue-testing-debugging—UE_LOGcategories andbUseLoggingInShipping, automation test modules and targetsue-game-features— Game Feature plugins,UGameFeatureData,UGameFeatureAction, Modular Gameplayue-project-context— the.agents/ue-project-context.mdfile that records module names, targets and enabled pluginsue-data-assets-tables— UDataAsset, UDataTable, soft references, Asset Manager and async loading


