├── .github
└── FUNDING.yml
├── .gitignore
├── Banner.png
├── GameBundle.sln
├── GameBundle
├── .config
│ └── dotnet-tools.json
├── GameBundle.csproj
├── Options.cs
└── Program.cs
├── LICENSE
├── Logo.png
├── README.md
└── Test
├── Bundle.bat
├── Content
├── Content.mgcb
└── Textures
│ ├── Anim.png
│ ├── AutoTiling.png
│ ├── Test.png
│ └── Tree.png
├── GameImpl.cs
├── Program.cs
├── Test.csproj
└── macmain.txt
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | github: Ellpeck
2 | ko_fi: Ellpeck
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | bin
3 | obj
4 | packages
5 | *.user
--------------------------------------------------------------------------------
/Banner.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Banner.png
--------------------------------------------------------------------------------
/GameBundle.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GameBundle", "GameBundle\GameBundle.csproj", "{18B83BC9-B35C-4E04-AA1C-85057CB2B6BB}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{6FD8768A-7F59-4815-BF41-33DA9ACDB81A}"
6 | EndProject
7 | Global
8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
9 | Debug|Any CPU = Debug|Any CPU
10 | Release|Any CPU = Release|Any CPU
11 | EndGlobalSection
12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
13 | {18B83BC9-B35C-4E04-AA1C-85057CB2B6BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14 | {18B83BC9-B35C-4E04-AA1C-85057CB2B6BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
15 | {18B83BC9-B35C-4E04-AA1C-85057CB2B6BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
16 | {18B83BC9-B35C-4E04-AA1C-85057CB2B6BB}.Release|Any CPU.Build.0 = Release|Any CPU
17 | {6FD8768A-7F59-4815-BF41-33DA9ACDB81A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {6FD8768A-7F59-4815-BF41-33DA9ACDB81A}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {6FD8768A-7F59-4815-BF41-33DA9ACDB81A}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {6FD8768A-7F59-4815-BF41-33DA9ACDB81A}.Release|Any CPU.Build.0 = Release|Any CPU
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/GameBundle/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "nulastudio.ncbeauty": {
6 | "version": "1.2.9.5",
7 | "commands": [
8 | "ncbeauty"
9 | ]
10 | },
11 | "nulastudio.nbeauty": {
12 | "version": "2.1.5.0",
13 | "commands": [
14 | "nbeauty2"
15 | ]
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/GameBundle/GameBundle.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | Major
7 |
8 | Ellpeck
9 | A tool to package MonoGame and other .NET applications into several distributable formats
10 | windows linux mac bundler build monogame build-tool release-automation mono xna netcore dotnet publish bundle tool
11 | https://github.com/Ellpeck/GameBundle
12 | https://github.com/Ellpeck/GameBundle
13 | MIT
14 | README.md
15 | Logo.png
16 | true
17 | gamebundle
18 | 1.8.0
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | PreserveNewest
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/GameBundle/Options.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using CommandLine;
4 | using CommandLine.Text;
5 |
6 | namespace GameBundle;
7 |
8 | public class Options {
9 |
10 | [Option('s', "source", HelpText = "The location of the .csproj file that should be built and bundled. By default, the current directory is scanned for one")]
11 | public string SourceFile { get; set; }
12 | [Option('o', "output", Default = "bin/Bundled", HelpText = "The location of the directory that the bundles should be stored in")]
13 | public string OutputDirectory { get; set; }
14 | [Option('v', "verbose", HelpText = "Display verbose output while building")]
15 | public bool Verbose { get; set; }
16 |
17 | [Option('w', "win", HelpText = "Bundle for windows")]
18 | public bool BuildWindows { get; set; }
19 | [Option('l', "linux", HelpText = "Bundle for linux")]
20 | public bool BuildLinux { get; set; }
21 | [Option('m', "mac", HelpText = "Bundle for mac")]
22 | public bool BuildMac { get; set; }
23 | [Option("win-rid", Default = "win-x64", HelpText = "The RID to use for windows builds")]
24 | public string WindowsRid { get; set; }
25 | [Option("linux-rid", Default = "linux-x64", HelpText = "The RID to use for linux builds")]
26 | public string LinuxRid { get; set; }
27 | [Option("mac-rid", Default = "osx-x64", HelpText = "The RID to use for mac builds")]
28 | public string MacRid { get; set; }
29 |
30 | [Option('W', "win-arm", HelpText = "Bundle for windows arm")]
31 | public bool BuildWindowsArm { get; set; }
32 | [Option('L', "linux-arm", HelpText = "Bundle for linux arm")]
33 | public bool BuildLinuxArm { get; set; }
34 | [Option('M', "mac-arm", HelpText = "Bundle for mac arm")]
35 | public bool BuildMacArm { get; set; }
36 | [Option("win-arm-rid", Default = "win-arm64", HelpText = "The RID to use for windows arm builds")]
37 | public string WindowsArmRid { get; set; }
38 | [Option("linux-arm-rid", Default = "linux-arm64", HelpText = "The RID to use for linux arm builds")]
39 | public string LinuxArmRid { get; set; }
40 | [Option("mac-arm-rid", Default = "osx-arm64", HelpText = "The RID to use for mac arm builds")]
41 | public string MacArmRid { get; set; }
42 |
43 | [Option('z', "zip", HelpText = "Store the build results in zip files instead of folders")]
44 | public bool Zip { get; set; }
45 | [Option('b', "mac-bundle", HelpText = "Create an app bundle for mac")]
46 | public bool MacBundle { get; set; }
47 | [Option("mac-bundle-resources", Default = new[] {"Content", "*.icns"}, HelpText = "When creating an app bundle for mac, things that should go into the Resources folder rather than the MacOS folder")]
48 | public IEnumerable MacBundleResources { get; set; }
49 | [Option("mac-bundle-ignore", HelpText = "When creating an app bundle for mac, things that should be left out of the mac bundle and stay in the output folder")]
50 | public IEnumerable MacBundleIgnore { get; set; }
51 |
52 | [Option("nbeauty2", HelpText = "Use NetBeauty2 for beautifying instead of NetCoreBeauty")]
53 | public bool NBeauty2 { get; set; }
54 | [Option("skip-lib", HelpText = "When bundling, skip beautifying the output by moving files to the library folder")]
55 | public bool SkipLib { get; set; }
56 | [Option('e', "exclude", HelpText = "Files that should not be moved to the library folder")]
57 | public IEnumerable ExcludedFiles { get; set; }
58 | [Option("mg", HelpText = $"Exclude MonoGame's native libraries from being moved to the library folder, which is a requirement for DesktopGL version 3.8.2.1105 or later.\nThis has the same behavior as supplying the --exclude arguments {Program.MonoGameExclusions}")]
59 | public bool MonoGameExclusions { get; set; }
60 | [Option("lib-name", Default = "Lib", HelpText = "The name of the library folder that is created")]
61 | public string LibFolder { get; set; }
62 |
63 | [Option('t', "trim", HelpText = "Trim the application when publishing")]
64 | public bool Trim { get; set; }
65 | [Option('A', "aot", HelpText = "Use NativeAOT compilation mode")]
66 | public bool Aot { get; set; }
67 | [Option('c', "config", Default = "Release", HelpText = "The build configuration to use")]
68 | public string BuildConfig { get; set; }
69 | [Option('a', "build-args", HelpText = "Additional arguments that should be passed to the dotnet publish command")]
70 | public string BuildArgs { get; set; }
71 | [Option('n', "name-builds", HelpText = "Name the build output directories by the name of the executable")]
72 | public bool NameBuilds { get; set; }
73 | [Option('N', "name-addition", HelpText = "An additional string of text that should be included in the names of the output directories")]
74 | public string NameAddition { get; set; }
75 | [Option('V', "include-version", HelpText = "Include the project's version in the names of the output directories")]
76 | public bool IncludeVersion { get; set; }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/GameBundle/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.IO.Compression;
6 | using System.IO.Enumeration;
7 | using System.Linq;
8 | using CommandLine;
9 |
10 | namespace GameBundle;
11 |
12 | internal static class Program {
13 |
14 | public const string MonoGameExclusions =
15 | "soft_oal.dll, openal.dll, SDL2.dll, " + // win
16 | "libopenal.so.1, libopenal.so, libSDL2-2.0.so.0, " + // linux
17 | "libopenal.1.dylib, libopenal.dylib, libSDL2.dylib, libSDL2-2.0.0.dylib"; // mac
18 |
19 | private static int Main(string[] args) {
20 | return new Parser(c => {
21 | c.HelpWriter = Console.Error;
22 | c.EnableDashDash = true;
23 | }).ParseArguments(args).MapResult(Program.Run, _ => -1);
24 | }
25 |
26 | private static int Run(Options options) {
27 | // make sure all of the required tools are installed
28 | if (Program.RunProcess(options, "dotnet", "tool restore", AppDomain.CurrentDomain.BaseDirectory) != 0) {
29 | Console.WriteLine("dotnet tool restore failed, aborting");
30 | return -1;
31 | }
32 |
33 | var proj = Program.GetProjectFile(options);
34 | if (proj == null || !proj.Exists) {
35 | Console.WriteLine("Project file not found, aborting");
36 | return -1;
37 | }
38 | Console.WriteLine($"Bundling project {proj.FullName}");
39 |
40 | var builtAnything = false;
41 | var toBuild = new List {
42 | // regular builds
43 | new("windows", "win", options.WindowsRid, options.BuildWindows),
44 | new("linux", "linux", options.LinuxRid, options.BuildLinux),
45 | new("mac", "mac", options.MacRid, options.BuildMac, false, d => options.MacBundle ? Program.CreateMacBundle(options, d) : 0),
46 | // arm builds
47 | new("windows arm", "win-arm", options.WindowsArmRid, options.BuildWindowsArm, true),
48 | new("linux arm", "linux-arm", options.LinuxArmRid, options.BuildLinuxArm, true),
49 | new("mac arm", "mac-arm", options.MacArmRid, options.BuildMacArm, true, d => options.MacBundle ? Program.CreateMacBundle(options, d) : 0)
50 | };
51 | foreach (var config in toBuild) {
52 | if (config.ShouldBuild) {
53 | Console.WriteLine($"Bundling for {config.DisplayName}");
54 | var res = Program.Publish(options, proj, config);
55 | if (res != 0)
56 | return res;
57 | builtAnything = true;
58 | }
59 | }
60 | if (!builtAnything)
61 | Console.WriteLine("No build took place. Supply -w, -l or -m arguments or see available arguments using --help.");
62 |
63 | Console.WriteLine("Done");
64 | return 0;
65 | }
66 |
67 | private static int Publish(Options options, FileInfo proj, BuildConfig config) {
68 | var buildDir = Program.GetBuildDir(options, config.DirectoryName);
69 | var publishResult = Program.RunProcess(options, "dotnet", string.Join(' ',
70 | $"publish \"{proj.FullName}\"",
71 | $"-o \"{buildDir.FullName}\"",
72 | $"-r {config.Rid}",
73 | "--self-contained",
74 | $"-c {options.BuildConfig}",
75 | $"/p:PublishTrimmed={options.Trim || options.Aot}",
76 | $"/p:PublishAot={options.Aot}",
77 | $"{options.BuildArgs}"));
78 | if (publishResult != 0)
79 | return publishResult;
80 |
81 | // Run beauty
82 | if (!options.SkipLib && !config.SkipLib && !options.Aot) {
83 | var exclude = options.ExcludedFiles.ToList();
84 | if (options.MonoGameExclusions)
85 | exclude.AddRange(Program.MonoGameExclusions.Split(',').Select(s => s.Trim()));
86 | var excludeString = exclude.Count > 0 ? $"\"{string.Join(";", exclude)}\"" : "";
87 | var log = options.Verbose ? "Detail" : "Error";
88 | var baseCommand = options.NBeauty2 ? "nbeauty2" : "ncbeauty --force=True --noflag=True";
89 | var beautyResult = Program.RunProcess(options, "dotnet", $"{baseCommand} --loglevel={log} \"{buildDir.FullName}\" \"{options.LibFolder}\" {excludeString}", AppDomain.CurrentDomain.BaseDirectory);
90 | if (beautyResult != 0) {
91 | Console.WriteLine("NetBeauty failed, likely because the artifact for the specified RID does not exist. See https://github.com/nulastudio/NetBeauty2/discussions/36 for more information, and run GameBundle with the --verbose option to see more details.");
92 | return beautyResult;
93 | }
94 | }
95 |
96 | // Add version if named builds are enabled
97 | if (options.IncludeVersion) {
98 | var version = Program.GetBuildVersion(buildDir);
99 | if (version == null) {
100 | Console.WriteLine("Couldn't determine build version, aborting");
101 | return -1;
102 | }
103 | var dest = Path.Combine(buildDir.Parent.FullName, $"{version}-{buildDir.Name}");
104 | Program.MoveDirectory(options, buildDir, dest);
105 | }
106 |
107 | // Rename build folder if named builds are enabled
108 | if (options.NameBuilds) {
109 | var name = Program.GetBuildName(buildDir);
110 | if (name == null) {
111 | Console.WriteLine("Couldn't determine build name, aborting");
112 | return -1;
113 | }
114 | var dest = Path.Combine(buildDir.Parent.FullName, $"{name}-{buildDir.Name}");
115 | Program.MoveDirectory(options, buildDir, dest);
116 | }
117 |
118 | // Run any additional actions like creating the mac bundle
119 | if (config.AdditionalAction != null) {
120 | var result = config.AdditionalAction.Invoke(buildDir);
121 | if (result != 0)
122 | return result;
123 | }
124 |
125 | // Zip the output if required
126 | if (options.Zip) {
127 | var zipLocation = Path.Combine(buildDir.Parent.FullName, $"{buildDir.Name}.zip");
128 | if (File.Exists(zipLocation))
129 | File.Delete(zipLocation);
130 | ZipFile.CreateFromDirectory(buildDir.FullName, zipLocation, CompressionLevel.Optimal, true);
131 | buildDir.Delete(true);
132 | if (options.Verbose)
133 | Console.WriteLine($"Zipped build to {zipLocation}");
134 | }
135 | return 0;
136 | }
137 |
138 | private static int RunProcess(Options options, string program, string args, string workingDir = "") {
139 | if (options.Verbose)
140 | Console.WriteLine($"> {program} {args}");
141 | var info = new ProcessStartInfo(program, args) {WorkingDirectory = workingDir};
142 | if (!options.Verbose)
143 | info.CreateNoWindow = true;
144 | var process = Process.Start(info);
145 | process.WaitForExit();
146 | if (options.Verbose)
147 | Console.WriteLine($"{program} finished with exit code {process.ExitCode}");
148 | return process.ExitCode;
149 | }
150 |
151 | private static FileInfo GetProjectFile(Options options) {
152 | if (!string.IsNullOrEmpty(options.SourceFile))
153 | return new FileInfo(options.SourceFile);
154 | var dir = new DirectoryInfo(".");
155 | foreach (var file in dir.EnumerateFiles()) {
156 | if (Path.GetExtension(file.FullName).Contains("proj"))
157 | return file;
158 | }
159 | return null;
160 | }
161 |
162 | private static int CreateMacBundle(Options options, DirectoryInfo buildDir) {
163 | var buildName = Program.GetBuildName(buildDir);
164 | var app = buildDir.CreateSubdirectory($"{buildName}.app");
165 | var contents = app.CreateSubdirectory("Contents");
166 | var resources = contents.CreateSubdirectory("Resources");
167 | var macOs = contents.CreateSubdirectory("MacOS");
168 |
169 | if (options.Verbose)
170 | Console.WriteLine($"Creating app bundle {app}");
171 |
172 | foreach (var file in buildDir.GetFiles()) {
173 | if (options.MacBundleIgnore.Any(g => FileSystemName.MatchesSimpleExpression(g, file.Name)))
174 | continue;
175 | var destDir = options.MacBundleResources.Any(g => FileSystemName.MatchesSimpleExpression(g, file.Name)) ? resources : macOs;
176 | if (file.Name.EndsWith("plist") || file.Name == "PkgInfo")
177 | destDir = contents;
178 | file.MoveTo(Path.Combine(destDir.FullName, file.Name), true);
179 | }
180 | foreach (var sub in buildDir.GetDirectories()) {
181 | if (sub.Name == app.Name || options.MacBundleIgnore.Any(g => FileSystemName.MatchesSimpleExpression(g, sub.Name)))
182 | continue;
183 | var destDir = options.MacBundleResources.Any(g => FileSystemName.MatchesSimpleExpression(g, sub.Name)) ? resources : macOs;
184 | var dest = new DirectoryInfo(Path.Combine(destDir.FullName, sub.Name));
185 | if (dest.Exists)
186 | dest.Delete(true);
187 | sub.MoveTo(dest.FullName);
188 | }
189 |
190 | var info = Path.Combine(contents.FullName, "PkgInfo");
191 | if (!File.Exists(info)) {
192 | File.WriteAllText(info, "APPL????");
193 | if (options.Verbose)
194 | Console.WriteLine($"Creating package info at {info}");
195 | }
196 |
197 | return 0;
198 | }
199 |
200 | private static DirectoryInfo GetBuildDir(Options options, string name) {
201 | if (options.NameAddition != null)
202 | name = $"{options.NameAddition}-{name}";
203 | return new DirectoryInfo(Path.Combine(Path.GetFullPath(options.OutputDirectory), name));
204 | }
205 |
206 | private static string GetBuildName(DirectoryInfo buildDir) {
207 | return Path.GetFileNameWithoutExtension(Program.GetAssemblyFile(buildDir)?.Name);
208 | }
209 |
210 | private static string GetBuildVersion(DirectoryInfo buildDir) {
211 | var assemblyFile = Program.GetAssemblyFile(buildDir);
212 | if (assemblyFile == null)
213 | return null;
214 | var version = FileVersionInfo.GetVersionInfo(assemblyFile.FullName);
215 | return version.ProductVersion;
216 | }
217 |
218 | private static FileInfo GetAssemblyFile(DirectoryInfo buildDir) {
219 | var files = buildDir.GetFiles();
220 |
221 | foreach (var file in files) {
222 | if (file.Extension != ".dll")
223 | continue;
224 | // the assembly is (most likely) the dll file that has a matching binary or exe file in the same location
225 | if (files.Any(f => f.Extension is ".exe" or "" && Path.GetFileNameWithoutExtension(f.Name) == Path.GetFileNameWithoutExtension(file.Name)))
226 | return file;
227 | }
228 |
229 | // if we didn't find a file, try to see if there is a single exe in the directory (which will be the case with AOT builds)
230 | var exes = files.Where(f => f.Extension is ".exe" or "").ToArray();
231 | if (exes.Length == 1)
232 | return exes[0];
233 |
234 | return null;
235 | }
236 |
237 | private static void MoveDirectory(Options options, DirectoryInfo dir, string dest) {
238 | if (Directory.Exists(dest))
239 | Directory.Delete(dest, true);
240 | dir.MoveTo(dest!);
241 | if (options.Verbose)
242 | Console.WriteLine($"Moved build directory to {dir.FullName}");
243 | }
244 |
245 | private readonly struct BuildConfig {
246 |
247 | public readonly string DisplayName;
248 | public readonly string DirectoryName;
249 | public readonly string Rid;
250 | public readonly bool ShouldBuild;
251 | public readonly bool SkipLib;
252 | public readonly Func AdditionalAction;
253 |
254 | public BuildConfig(string displayName, string directoryName, string rid, bool shouldBuild, bool skipLib = false, Func additionalAction = null) {
255 | this.DisplayName = displayName;
256 | this.DirectoryName = directoryName;
257 | this.Rid = rid;
258 | this.ShouldBuild = shouldBuild;
259 | this.SkipLib = skipLib;
260 | this.AdditionalAction = additionalAction;
261 | }
262 |
263 | }
264 |
265 | }
266 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Ellpeck
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Logo.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | **GameBundle** is a tool to package MonoGame and other .NET applications into several distributable formats.
4 |
5 | # Installing
6 | GameBundle is a `dotnet` tool, meaning you can install it very easily like so:
7 | ```
8 | dotnet tool install --global GameBundle
9 | ```
10 |
11 | # Using
12 | By default, GameBundle builds the `.csproj` file that it finds in the directory that it is run from. The bundled outputs go into `bin/Bundled` by default.
13 |
14 | To build and bundle your app for Windows, Linux and Mac, all you have to do is run the following command from the directory that contains your project file:
15 | ```
16 | gamebundle -wlm
17 | ```
18 |
19 | GameBundle will then build a self-contained release of your application for each system using `dotnet publish` and clean up the output directory using [NetBeauty](https://github.com/nulastudio/NetBeauty2) by moving most of the libraries into a `Lib` subdirectory.
20 |
21 | ## Building a MonoGame Project
22 | If you're building a MonoGame project using MonoGame's DesktopGL version 3.8.2.1105 or later, you can additionally supply the `--mg` argument to automatically exclude MonoGame's native libraries from being moved into the `Lib` subdirectory, which is a requirement for your game to run.
23 |
24 | # Configuring
25 | GameBundle takes several optional arguments to modify the way it works. To see a list of all possible arguments, simply run
26 | ```
27 | gamebundle --help
28 | ```
29 |
30 | Here is a list of them as of GameBundle version 1.8.0:
31 | ```
32 | -s, --source The location of the .csproj file that should be built and bundled. By default, the current directory is scanned for one
33 |
34 | -o, --output (Default: bin/Bundled) The location of the directory that the bundles should be stored in
35 |
36 | -v, --verbose Display verbose output while building
37 |
38 | -w, --win Bundle for windows
39 |
40 | -l, --linux Bundle for linux
41 |
42 | -m, --mac Bundle for mac
43 |
44 | --win-rid (Default: win-x64) The RID to use for windows builds
45 |
46 | --linux-rid (Default: linux-x64) The RID to use for linux builds
47 |
48 | --mac-rid (Default: osx-x64) The RID to use for mac builds
49 |
50 | -W, --win-arm Bundle for windows arm
51 |
52 | -L, --linux-arm Bundle for linux arm
53 |
54 | -M, --mac-arm Bundle for mac arm
55 |
56 | --win-arm-rid (Default: win-arm64) The RID to use for windows arm builds
57 |
58 | --linux-arm-rid (Default: linux-arm64) The RID to use for linux arm builds
59 |
60 | --mac-arm-rid (Default: osx-arm64) The RID to use for mac arm builds
61 |
62 | -z, --zip Store the build results in zip files instead of folders
63 |
64 | -b, --mac-bundle Create an app bundle for mac
65 |
66 | --mac-bundle-resources (Default: Content *.icns) When creating an app bundle for mac, things that should go into the Resources folder rather than the MacOS folder
67 |
68 | --mac-bundle-ignore When creating an app bundle for mac, things that should be left out of the mac bundle and stay in the output folder
69 |
70 | --nbeauty2 Use NetBeauty2 for beautifying instead of NetCoreBeauty
71 |
72 | --skip-lib When bundling, skip beautifying the output by moving files to the library folder
73 |
74 | -e, --exclude Files that should not be moved to the library folder
75 |
76 | --mg Exclude MonoGame's native libraries from being moved to the library folder, which is a requirement for DesktopGL version 3.8.2.1105 or later.
77 | This has the same behavior as supplying the --exclude arguments soft_oal.dll, openal.dll, SDL2.dll, libopenal.so.1, libopenal.so, libSDL2-2.0.so.0, libopenal.1.dylib,
78 | libopenal.dylib, libSDL2.dylib, libSDL2-2.0.0.dylib
79 |
80 | --lib-name (Default: Lib) The name of the library folder that is created
81 |
82 | -t, --trim Trim the application when publishing
83 |
84 | -A, --aot Use NativeAOT compilation mode
85 |
86 | -c, --config (Default: Release) The build configuration to use
87 |
88 | -a, --build-args Additional arguments that should be passed to the dotnet publish command
89 |
90 | -n, --name-builds Name the build output directories by the name of the executable
91 |
92 | -N, --name-addition An additional string of text that should be included in the names of the output directories
93 |
94 | -V, --include-version Include the project's version in the names of the output directories
95 |
96 | --help Display this help screen.
97 |
98 | --version Display version information.
99 | ```
100 |
--------------------------------------------------------------------------------
/Test/Bundle.bat:
--------------------------------------------------------------------------------
1 | dotnet build ../GameBundle/GameBundle.csproj
2 | rmdir /S /Q "bin/Bundled"
3 | "../GameBundle/bin/Debug/net8.0/GameBundle.exe" -wlmWL -bnV --mg -s Test.csproj -o bin/Bundled -v --mac-bundle-ignore macmain.txt -N ncbeauty
4 | "../GameBundle/bin/Debug/net8.0/GameBundle.exe" -wlmWL -bnV --mg -s Test.csproj -o bin/Bundled -v --mac-bundle-ignore macmain.txt -N nbeauty2 --nbeauty2
5 |
--------------------------------------------------------------------------------
/Test/Content/Content.mgcb:
--------------------------------------------------------------------------------
1 |
2 | #----------------------------- Global Properties ----------------------------#
3 |
4 | /outputDir:bin
5 | /intermediateDir:obj
6 | /platform:DesktopGL
7 | /config:
8 | /profile:Reach
9 | /compress:False
10 |
11 | #-------------------------------- References --------------------------------#
12 |
13 |
14 | #---------------------------------- Content ---------------------------------#
15 |
16 | #begin Textures/Anim.png
17 | /importer:TextureImporter
18 | /processor:TextureProcessor
19 | /processorParam:ColorKeyColor=255,0,255,255
20 | /processorParam:ColorKeyEnabled=True
21 | /processorParam:GenerateMipmaps=False
22 | /processorParam:PremultiplyAlpha=True
23 | /processorParam:ResizeToPowerOfTwo=False
24 | /processorParam:MakeSquare=False
25 | /processorParam:TextureFormat=Color
26 | /build:Textures/Anim.png
27 |
28 | #begin Textures/AutoTiling.png
29 | /importer:TextureImporter
30 | /processor:TextureProcessor
31 | /processorParam:ColorKeyColor=255,0,255,255
32 | /processorParam:ColorKeyEnabled=True
33 | /processorParam:GenerateMipmaps=False
34 | /processorParam:PremultiplyAlpha=True
35 | /processorParam:ResizeToPowerOfTwo=False
36 | /processorParam:MakeSquare=False
37 | /processorParam:TextureFormat=Color
38 | /build:Textures/AutoTiling.png
39 |
40 | #begin Textures/Test.png
41 | /importer:TextureImporter
42 | /processor:TextureProcessor
43 | /processorParam:ColorKeyColor=255,0,255,255
44 | /processorParam:ColorKeyEnabled=True
45 | /processorParam:GenerateMipmaps=False
46 | /processorParam:PremultiplyAlpha=True
47 | /processorParam:ResizeToPowerOfTwo=False
48 | /processorParam:MakeSquare=False
49 | /processorParam:TextureFormat=Color
50 | /build:Textures/Test.png
51 |
52 | #begin Textures/Tree.png
53 | /importer:TextureImporter
54 | /processor:TextureProcessor
55 | /processorParam:ColorKeyColor=255,0,255,255
56 | /processorParam:ColorKeyEnabled=True
57 | /processorParam:GenerateMipmaps=False
58 | /processorParam:PremultiplyAlpha=True
59 | /processorParam:ResizeToPowerOfTwo=False
60 | /processorParam:MakeSquare=False
61 | /processorParam:TextureFormat=Color
62 | /build:Textures/Tree.png
63 |
64 |
--------------------------------------------------------------------------------
/Test/Content/Textures/Anim.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Test/Content/Textures/Anim.png
--------------------------------------------------------------------------------
/Test/Content/Textures/AutoTiling.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Test/Content/Textures/AutoTiling.png
--------------------------------------------------------------------------------
/Test/Content/Textures/Test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Test/Content/Textures/Test.png
--------------------------------------------------------------------------------
/Test/Content/Textures/Tree.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Ellpeck/GameBundle/00bff9817bb6fb3b238e7e12f727217bcf332fca/Test/Content/Textures/Tree.png
--------------------------------------------------------------------------------
/Test/GameImpl.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using Microsoft.Xna.Framework.Graphics;
3 | using MLEM.Startup;
4 |
5 | namespace Test;
6 |
7 | public class GameImpl : MlemGame {
8 |
9 | public static GameImpl Instance { get; private set; }
10 | private Texture2D texture;
11 |
12 | public GameImpl() {
13 | GameImpl.Instance = this;
14 | }
15 |
16 | protected override void LoadContent() {
17 | base.LoadContent();
18 | this.texture = MlemGame.LoadContent("Textures/Test");
19 | }
20 |
21 | protected override void DoDraw(GameTime gameTime) {
22 | this.GraphicsDevice.Clear(Color.Black);
23 | base.DoDraw(gameTime);
24 | this.SpriteBatch.Begin(samplerState: SamplerState.PointClamp, transformMatrix: Matrix.CreateScale(10));
25 | this.SpriteBatch.Draw(this.texture, Vector2.Zero, Color.White);
26 | this.SpriteBatch.End();
27 | }
28 |
29 | }
--------------------------------------------------------------------------------
/Test/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Xna.Framework;
2 | using MLEM.Misc;
3 |
4 | namespace Test;
5 |
6 | public static class Program {
7 |
8 | public static void Main() {
9 | TextInputWrapper.Current = new TextInputWrapper.DesktopGl((w, c) => w.TextInput += c);
10 | using var game = new GameImpl();
11 | game.Run();
12 | }
13 |
14 | }
--------------------------------------------------------------------------------
/Test/Test.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | false
7 | false
8 | Test Project
9 | 1.2.3
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Test/macmain.txt:
--------------------------------------------------------------------------------
1 | This file should not be added to the mac bundle
--------------------------------------------------------------------------------