In a previous blog post we introduced the work we have done, in collaboration with Epic Games, migrating Unreal Engine cook workloads to Wine. The WineResources repo on GitHub provides a set of patches for Wine to support Unreal Engine workloads, and scripts to build containers using this patched version of Wine. At AWS re:Invent 2024 Epic Games shared how they have migrated some of their Windows cloud infrastructure to Linux environments. Since then TensorWorks has been collaborating with Epic Games to add patches to Wine to support C++ compilation. Due to the complexities of Wine and Unreal Engine compilation this is not easily accessible to the majority of Unreal Engine licencees, which is why we have scripted a streamlined process to build Unreal Engine, or Unreal projects, for Windows under Linux. We are very excited to make this process available to the Unreal community, and hope it helps you migrate your build environments whether you are building in the cloud, or just want to develop for Windows on a Linux machine.
Contents
Building Unreal Engine
AutoSDK
Unreal Engine includes a mechanism called AutoSDK to manage platform SDKs, making it easy to manage and maintain multiple versions of different SDKs for different platforms. It provides an easy way to gather all your SDK files in one place, and make them available for use by Unreal Engine. This is what Epic recommends for use with their Horde CI/CD system, and we chose to use it in our work because having everything in one place allows us to decouple the Wine prefix from the SDK itself. The typical process of setting up an AutoSDK environment requires copying files from installations of Visual Studio and the Windows SDK. At the time of this writing, the Visual Studio installer does not work under Wine and so we use the open-source msvc-wine project to automate this process under Linux.
Looking through Epic’s documentation on this we are able to see that the core components required by AutoSDK are:
- MSVC
- Windows SDK
- Including the NETFX SDK
- DIA SDK
- LLVM/Clang
MSVC Tools and SDK
The msvc-wine tool provides two basic modes of operation:
- Specify versions of the MSVC tools, the MSVC SDK and the Windows SDK
- Provide a list of specific packages to install
Since version 5.4 the Unreal Engine source code has included a file (Windows_SDK.json) which specifies recommended versions of everything needed for AutoSDK (and building under Windows in general), as well as all recommended Visual Studio components and workloads. This file seemed to provide the information needed for either approach, so we investigated both options.
Determining which version of Visual Studio and the Windows SDK were needed was relatively straightforward. However, the MSVC toolchain posed a different problem. The versions specified in the JSON config file follow the MSVC version codes, but msvc-wine expects versions using the Visual Studio patterns (e.g. MSVC version 14.44.35207 maps to VS version 17.14). This meant that without providing a mechanism to convert versions, which would be brittle and require regular updates, we would not be able to use the approach of specifying a version for the MSVC toolchain.
We then tested the other approach, passing the list of components from the JSON file to msvc-wine. This worked reliably, with only one outstanding issue to resolve.
Missing components - NETFX and .Net SDK
Comparing the results of running msvc-wine with a Visual Studio installation on a Windows machine revealed that the folders for the NETFX SDK were not being fetched. This is part of the .NET Framework, and we can see that Windows_SDK.json lists the Microsoft.. However, the MSI files fetched for that component did not contain the files required for AutoSDK to function correctly. Further investigation revealed that they are to be found in Microsoft.. To ensure that this AutoSDK requirement is met we parse the .NET Framework Targeting Pack identifier specified in the JSON file and fetch the corresponding .NET Framework SDK.
Installed Build Dependencies
An Installed Build of Unreal Engine is the most comprehensive test of building the engine, building all available plugins and cooking all assets to populate the DDC. In addition it is entirely portable, making it easy to migrate from one machine to another, or share between a host machine and containers.
ADOSupport Plugin
Initial tests building Unreal Engine failed with compilation issues in the ADOSupport plugin. This plugin has a dependency on msado15.dll, and the version of this file available under Wine is missing some key components. For most engine builds this is not a problem, as plugins that are not used are not built, and the ADOSupport plugin has not been used for years. However, an Installed Build will build all plugins that are present, so this needs to be resolved if we want to support this use-case.
Fortunately Epic have now removed this plugin from Unreal Engine. As of this commit, the ue5-main branch of the Engine source code on git no longer includes this plugin, and it is not used or referenced by any other part of the Engine. This change will be included in UE 5.8, and in order to support other branches of the UE source, our script removes this plugin before building the Engine.
Debugging Tools
When creating an Installed Build there is a step immediately after compiling the C++ components, which copies PDB files and strips symbols from them. This step was failing due to a dependency on pdbcopy.exe, a tool installed as part of the Debugging Tools for Windows. The installation approach recommended by Epic under Windows uses a GUI, but this method is not suited to headless installation in a Wine container. These tools are an optional component of the Windows SDK, and the SDK installer is already being cached by msvc-wine. We investigated the command-line arguments for the SDK installer needed to specify a particular component, and to download the files rather than installing them. Running the Windows SDK installer under Wine with those flags we were able to download the MSI files containing the Debugging Tools for Windows, and make them available for AutoSDK.
Packaging projects
We tested packaging Unreal Engine projects containing C++ code under Wine with two separate Installed Builds, one built under Wine (UE 5.7) and one copied from a Windows machine (UE 5.6). This testing confirmed that both projects were successfully packaged, and produced executables which ran under Windows with no discernable differences to binaries built natively under Windows.
Getting Started
We have developed a series of quickstart examples to take you from having the Unreal Engine source code and a project, through to building that project for Windows inside a container with Unreal Engine, all on a Linux machine. You will need to clone or download the cpp-compilation branch of the TensorWorks fork of the WineResources repository (https://github.com/TensorWorks/WineResources/tree/cpp-compilation) as well as your chosen branch of the Unreal Engine source (we support building UE 5.7 and above). If you cloned the Unreal Engine source code from GitHub then ensure that you have run Setup.sh in your Unreal Engine folder in order to download all the large binary assets.
AutoSDK
The assemble script in the autosdk folder will build an AutoSDK enabled Wine image that can be used to build Unreal Engine from source, or to build an Unreal project for Windows using an Installed Build of the engine. This script can run under Linux, Windows, or macOS. Run either assemble.sh or assemble.bat (depending on your host OS) and pass the path to the Unreal Engine source code (the top-level folder containing the ‘Engine’ folder). This script will produce an image containing Wine, built with our mitigations in place to support C++ compilation, and the required AutoSDK components to build your version of Unreal Engine and its projects.
Standard Usage:
- Linux / macOS:
./assemble.sh </path/to/UE/source> - Windows:
./assemble.bat </path/to/UE/source>
Create Installed Build
The compile script in the create-installed-build folder will use the script above to build a suitable AutoSDK image, if one does not already exist, and use that image to compile the provided Unreal Engine source code, producing an Installed Build. Note that this script can only be run under Linux, due to issues with Wine launching executables from Windows hosted filesystems under docker. For the same reason, if you are running this script under WSL2 then you must ensure that the Unreal Engine source is stored on the Linux filesystem, and not the host (Windows) filesystem. This script requires the path to the Unreal Engine source code, just like the AutoSDK script above, and can optionally accept the --wrap flag. If this flag is provided then once the Installed Build is built, the Wrap Installed Build script below will be called to containerise it, after the Installed Build is automatically copied into place for you.
Standard Usage:
- Build:
./compile.sh </path/to/UE/source> - Build and wrap:
./compile.sh --wrap </path/to/UE/source>
Wrap Installed Build
We have updated the existing wrap script in the wrap-installed-build folder to use the AutoSDK base image, rather than the original Wine image. It will call the assemble script above, and will then create a new image including the Installed Build of the engine. This image can then be used to build C++ Unreal Engine projects for Windows, using the script below. This script can run under Linux, Windows, or macOS. Run either wrap.sh or wrap.bat (depending on your host OS). Note that this script requires an Installed Build to be provided, either from a Windows machine or one produced using the Create Installed Build script above. Like the original version, the updated wrap script does not copy any files for you, you must place the Installed Build files in the context/UnrealEngine folder manually.
Standard Usage:
- Linux / macOS:
./wrap.sh </path/to/Installed/Build> - Windows:
./wrap.bat </path/to/Installed/Build>
Package Project
The package script in the package-project folder packages an Unreal Engine project inside a container. Like the Create Installed Build script above, this script can only be run under Linux (and for the same reasons). This script requires the path to the Unreal Engine project you wish to build (with the --project argument), as well as either the path to an Installed Build of the engine on the host filesystem (with the --engine argument), or an image containing one (with the --image argument). If you provide the path to an Installed Build then the script will ensure that a suitable AutoSDK image is built, using the assemble script above, and will then run a build command inside that image with both the Installed Build and the project source bind-mounted in. Alternatively, if you provide the image to use then the build command will run inside that image, with only the project source mounted in.
Standard Usage:
- Use mounted engine:
./package.sh --engine </path/to/Installed/Build> --project </path/to/project> - Use container image:
./package.sh --image epicgames/unreal-engine:dev-wine-<VERSION> --project </path/to/project>
Compiling Unreal Engine under Wine is possible today
All of the Wine patches required for compiling C++ workloads under Wine are already available under Epic Games’ WineResources repository. All of the scripts described above are currently available on our fork of WineResources, and we are working to get them merged upstream. We hope you try these out, and are inspired to think about what other workloads can be migrated to Linux environments. At TensorWorks we are passionate about supporting developers to work the way they want, on the platforms they want, and if you have a particularly thorny Wine problem we’d love to hear from you. For now, try out the sample scripts and see what is already possible with the work we’ve done so far.
Get started today: https://github.com/TensorWorks/WineResources/tree/cpp-compilation