Skip to content

Commit bf4c1a9

Browse files
authored
Update documentation for PublishAot (#107)
1 parent 15f7db2 commit bf4c1a9

File tree

1 file changed

+19
-30
lines changed

1 file changed

+19
-30
lines changed

articles/getting_started/packaging_games.md

+19-30
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ To publish desktop games, it is recommended that you build your project as a [se
1313

1414
From the .NET CLI:
1515

16-
`dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false -p:PublishAot=true --self-contained`
17-
18-
> [!IMPORTANT]
19-
> We are making use of the `PublishAot` option. Using `Aot` has some restrictions which may require changes to your game code. Especially if you are using Reflection.
16+
`dotnet publish -c Release -r win-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false --self-contained`
2017

2118
You can then zip the content of the publish folder and distribute the archive as-is.
2219

@@ -47,13 +44,10 @@ mkdir -p bin/Release/YourGame.app/Contents/Resources/Content
4744
Next we need to publish our application for both `arm64` (Apple Silicon) and `x64` (Intel). From the .NET CLI:
4845

4946
```cli
50-
dotnet publish -c Release -r osx-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false -p:PublishAot=true --self-contained
51-
dotnet publish -c Release -r osx-arm64 -p:PublishReadyToRun=false -p:TieredCompilation=false -p:PublishAot=true --self-contained
47+
dotnet publish -c Release -r osx-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false --self-contained
48+
dotnet publish -c Release -r osx-arm64 -p:PublishReadyToRun=false -p:TieredCompilation=false --self-contained
5249
```
5350

54-
> [!IMPORTANT]
55-
> We are making use of the `PublishAot` option. Using `Aot` has some restrictions which may require changes to your game code. Especially if you are using Reflection.
56-
5751
Next we need to combine the two binaries into one Universal Binary which will work on both arm64 and x64 machines.
5852
We can do this using the `xcode` utility `lipo`.
5953

@@ -145,10 +139,7 @@ For archiving, we recommend using the `.tar.gz` format to preserve the execution
145139

146140
From the .NET CLI:
147141

148-
`dotnet publish -c Release -r linux-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false -p:PublishAot=true --self-contained`
149-
150-
> [!IMPORTANT]
151-
> We are making use of the `PublishAot` option. Using `Aot` has some restrictions which may require changes to your game code. Especially if you are using Reflection.
142+
`dotnet publish -c Release -r linux-x64 -p:PublishReadyToRun=false -p:TieredCompilation=false --self-contained`
152143

153144
You can then archive the content of the publish folder and distribute the archive as-is.
154145

@@ -160,37 +151,33 @@ We recommend using the `.tar.gz` archiving format to preserve the execution perm
160151

161152
.NET proposes several parameters when publishing apps that may sound helpful, but have many issues when it comes to games (because they were never meant for games in the first place, but for small lightweight applications).
162153

163-
### PublishAot
154+
### PublishAot and PublishTrimmed
164155

165-
This option optimises your game code "Ahead of Time". It allows you to ship your game without the need to JIT (Just In Time compile).
166-
However, you do need to currently add some additional settings to your `.csproj`.
156+
The ```PublishAot``` option optimises your game code "Ahead of Time" for performance. It allows you to ship your game without the need to JIT (Just In Time compile), and will basically natively compile your game.
167157

168-
```xml
169-
<ItemGroup>
170-
<TrimmerRootAssembly Include="MonoGame.Framework" />
171-
<TrimmerRootAssembly Include="mscorlib" />
172-
</ItemGroup>
173-
```
158+
```PublishAot``` binaries are much faster, which is typically desired for games. It however comes with limitations, like the inability to use runtime reflection and runtime code generation (IL emition).
174159

175-
The `TrimmerRootAssembly` stops the trimmer removing code from these assemblies. This should allow the game to run without
176-
any issues. However if you are using any Third Party or additional assemblies, you might need to add them to this list or fix your code to be `Aot` compliant.
177-
It is recommended that you publish using AOT as it simplifies the app bundle.
160+
```PublishAot``` makes use of ```PublishTrimmed```, which is another option that strip binaries of unused code to make much lighter executables and assemblies. Trimming can be aggressive and might remove types if the compiler can't detect if they are used (e.g. if you are using reflection or generics).
178161

179-
You may see some trim and AOT analysis warnings related to MonoGame when using PublishAOT, even after adding `TrimmerRootAssembly` - these are normal and should not present any issue.
162+
MonoGame is mostly compatible with ```PublishAot``` and ```PublishTrimmed```, and will just work in most cases. It may however crash at runtime if you are using custom content importers that use generic collections. If you are using ```PublishAot``` and you are running into runtime exceptions occuring when loading content saying that a type is missing, the solution is to call ```ContentTypeReaderManager.AddTypeCreator()``` on that type before trying to load your content. This will tell the AOT compiler to include that type.
180163

181-
See [Trim self-contained deployments and executables](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained) for more information.
164+
Besides MonoGame itself, it may happen that the third party libraries that you are using are not compatible with AOT or trimming. In that case, you should refer to those libraries maintainers for workarounds, or replace them with compatible libraries.
182165

183-
There are some known areas you need to watchout for:
166+
Overall, AOT and trimming have similar limitations you need to watchout for:
184167

185168
1. Using `XmlSerializer` in your game will probably cause issues. Since it uses reflection it will be difficult for the Trimmer to figure out what needs to be kept.
186169
It is recommended that, instead of using the `Deserialize` method, you write your own custom deserializer using `XDocument` or `XmlReader`.
187170
Alternatively you can use the Content Pipeline and create a custom `Processor` and `Reader` to convert the Xml into a binary format that can be loaded via the usual `Content.Load<T>` method.
188171
2. Dynamically loading assemblies via `Assembly.LoadFile`.
189172
3. No run-time code generation, for example, System.Reflection.Emit.
190173

174+
You can also refer to the [Preparing for consoles](preparing_for_consoles.md) documentation, which leverage AOT and has the same limitations. If your game runs with ```PublishAot```, you'll be well ahead into porting your game to consoles.
175+
176+
For more information, please see [Native AOT deployment](https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/) and [Trim self-contained deployments](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained).
177+
191178
### ReadyToRun (R2R)
192179

193-
[ReadyToRun](https://docs.microsoft.com/en-us/dotnet/core/whats-new/dotnet-core-3-0#readytorun-images) is advertised as improving application startup time, but slightly increasing binary size. We recommend not using it for games because it produces micro stutters when your game is running.
180+
[ReadyToRun](https://learn.microsoft.com/en-us/dotnet/core/deploying/ready-to-run) is advertised as improving application startup time, but slightly increasing binary size. We recommend not using it for games because it produces micro stutters when your game is running.
194181

195182
ReadyToRun code is of low quality and makes the Just-In-Time compiler (JIT) trigger regularly to promote the code to a higher quality. Whenever the JIT runs, it produces potentially very visible stutters.
196183

@@ -209,12 +196,14 @@ MonoGame templates for .NET projects explicitly set this to `false`.
209196

210197
### PublishSingleFile
211198

212-
PublishSingleFile packages your game into a single executable file with all dependencies and content integrated.
199+
[PublishSingleFile](https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file/overview) packages your game into a single executable file with all dependencies and content integrated.
213200

214201
While it sounds very convenient, be aware that it's not magical and is in fact a hidden self-extracting zip archive. As such, it may make app startup take **a lot** longer if your game is large, and may fail to launch on systems where user permissions don't allow extracting files (or if there is not enough storage space available).
215202

216203
We highly recommend not using it for better compatibility across systems.
217204

205+
If you need to reduce the footprint of your game, please refer to ```PublishAot``` and ```PublishTrimmed``` instead.
206+
218207
## Mobile games
219208

220209
Please refer to the Xamarin documentation:

0 commit comments

Comments
 (0)