192 lines
7.9 KiB
C#
192 lines
7.9 KiB
C#
// MonoGame - Copyright (C) The MonoGame Team
|
|
// This file is subject to the terms and conditions defined in
|
|
// file 'LICENSE.txt', which is part of this source code package.
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using Microsoft.Build.Framework;
|
|
using Microsoft.Build.Utilities;
|
|
|
|
namespace MonoGame.Packaging
|
|
{
|
|
public class BuildFlatpakTask : Task
|
|
{
|
|
[Required]
|
|
public string IntermediateDir { get; set; }
|
|
|
|
[Required]
|
|
public string OutputPath { get; set; }
|
|
|
|
[Required]
|
|
public string ProjectDir { get; set; }
|
|
|
|
[Required]
|
|
public string PublishDir { get; set; }
|
|
|
|
[Required]
|
|
public string AssemblyName { get; set; }
|
|
|
|
[Required]
|
|
public string Title { get; set; }
|
|
|
|
[Required]
|
|
public string Id { get; set; }
|
|
|
|
[Required]
|
|
public string IconPath { get; set; }
|
|
|
|
public override bool Execute()
|
|
{
|
|
try
|
|
{
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Starting...");
|
|
|
|
// Ensure that flatpak command is installed
|
|
if (!IsFlatpakInstalled())
|
|
{
|
|
Log.LogMessage(MessageImportance.High, "Flatpak command not found :(");
|
|
return false;
|
|
}
|
|
|
|
// Ensure that flatpak runtimes are installed
|
|
if (!AreFlatpakRuntimesInstalled())
|
|
{
|
|
Log.LogMessage(MessageImportance.High, "Error, the requred flatpak runtime components were not found:");
|
|
Log.LogMessage(MessageImportance.High, " - org.freedesktop.Platform/x86_64/1.6");
|
|
Log.LogMessage(MessageImportance.High, " - org.freedesktop.Sdk/x86_64/1.6");
|
|
return false;
|
|
}
|
|
|
|
// Setup intermediate directory
|
|
var objpath = Path.Combine(ProjectDir, IntermediateDir, "Flatpak");
|
|
if (Directory.Exists(objpath))
|
|
Directory.Delete(objpath, true);
|
|
Directory.CreateDirectory(objpath);
|
|
|
|
// Generate metadata
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Generating metadata");
|
|
var metadatalines = new[] {
|
|
"[Application]",
|
|
"name=" + Id,
|
|
"runtime=org.freedesktop.Platform/x86_64/1.6",
|
|
"command=/app/opt/" + AssemblyName + "/" + AssemblyName,
|
|
"",
|
|
"[Context]",
|
|
"shared=ipc;network;",
|
|
"sockets=x11;wayland;pulseaudio;",
|
|
"devices=all;"
|
|
};
|
|
File.WriteAllLines(Path.Combine(objpath, "metadata"), metadatalines);
|
|
|
|
// Copy over icon
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Copying over icon");
|
|
var icondir = Path.Combine(objpath, "export/share/icons");
|
|
Directory.CreateDirectory(icondir);
|
|
File.Copy(Path.Combine(ProjectDir, IconPath), Path.Combine(icondir, Id + ".png"));
|
|
|
|
// Generate .desktop launcher file
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Generating launcher file");
|
|
var desktopdir = Path.Combine(objpath, "export/share/applications");
|
|
Directory.CreateDirectory(desktopdir);
|
|
var desktoplines = new[] {
|
|
"[Desktop Entry]",
|
|
"Name=" + Title,
|
|
"Exec=/app/opt/" + AssemblyName + "/" + AssemblyName,
|
|
"Type=Application",
|
|
"Icon=" + Id,
|
|
"Categories=Game;"
|
|
};
|
|
File.WriteAllLines(Path.Combine(desktopdir, Id + ".desktop"), desktoplines);
|
|
|
|
// Copy over game
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Copying over game data");
|
|
var sourcegamedir = Path.Combine(ProjectDir, PublishDir);
|
|
var gamedir = Path.Combine(objpath, "files/opt/" + AssemblyName + "/");
|
|
Directory.CreateDirectory(gamedir);
|
|
foreach (var dirpath in Directory.GetDirectories(sourcegamedir, "*", SearchOption.AllDirectories))
|
|
Directory.CreateDirectory(dirpath.Replace(sourcegamedir, gamedir));
|
|
foreach (var filepath in Directory.GetFiles(sourcegamedir, "*.*", SearchOption.AllDirectories))
|
|
File.Copy(filepath, filepath.Replace(sourcegamedir, gamedir));
|
|
|
|
// Copy over suplementary libraries
|
|
var libdir = Path.Combine(Path.GetDirectoryName((new Uri(typeof(BuildFlatpakTask).Assembly.CodeBase)).LocalPath), "../../extra");
|
|
Directory.CreateDirectory(Path.Combine(objpath, "files/lib"));
|
|
File.Copy(Path.Combine(libdir, "libunwind-x86_64.so.8"), Path.Combine(objpath, "files/lib/libunwind-x86_64.so.8"));
|
|
File.Copy(Path.Combine(libdir, "libunwind.so.8"), Path.Combine(objpath, "files/lib/libunwind.so.8"));
|
|
File.Copy(Path.Combine(libdir, "libSDL2-2.0.so.0.8.0"), Path.Combine(objpath, "files/opt/" + AssemblyName + "/libSDL2-2.so"), true);
|
|
|
|
// Generate flatpak
|
|
Log.LogMessage(MessageImportance.Normal, "BuildFlatpakTask: Generating flatpak");
|
|
var repodir = Path.Combine(ProjectDir, IntermediateDir, "FlatpakRepo");
|
|
if (Directory.Exists(repodir))
|
|
Directory.Delete(repodir, true);
|
|
Directory.CreateDirectory(repodir);
|
|
var flatpak = Path.Combine(ProjectDir, OutputPath, AssemblyName + ".flatpak");
|
|
CallFlatpak("build-export " + repodir + " " + objpath);
|
|
CallFlatpak("build-bundle " + repodir + " " + flatpak + " " + Id);
|
|
|
|
Log.LogMessage(MessageImportance.High, "BuildFlatpakTask: Flatpak generated at: " + flatpak);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Log.LogMessage(MessageImportance.High, "An error occured while trying to package the project into a flatpak.");
|
|
Log.LogMessage(MessageImportance.High, "Error Info: " + e.ToString());
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool IsFlatpakInstalled()
|
|
{
|
|
var proc = new Process();
|
|
proc.StartInfo.FileName = "which";
|
|
proc.StartInfo.Arguments = "flatpak";
|
|
proc.StartInfo.UseShellExecute = false;
|
|
proc.StartInfo.RedirectStandardOutput = true;
|
|
proc.Start();
|
|
proc.StandardOutput.ReadToEnd();
|
|
|
|
return proc.ExitCode == 0;
|
|
}
|
|
|
|
private bool AreFlatpakRuntimesInstalled()
|
|
{
|
|
var rt = false;
|
|
var rtsdk = false;
|
|
var proc = new Process();
|
|
proc.StartInfo.FileName = "flatpak";
|
|
proc.StartInfo.Arguments = "list";
|
|
proc.StartInfo.UseShellExecute = false;
|
|
proc.StartInfo.RedirectStandardOutput = true;
|
|
proc.Start();
|
|
|
|
while (!proc.StandardOutput.EndOfStream)
|
|
{
|
|
var line = proc.StandardOutput.ReadLine();
|
|
if (line.Contains("org.freedesktop.Platform/x86_64/1.6"))
|
|
rt = true;
|
|
else if (line.Contains("org.freedesktop.Sdk/x86_64/1.6"))
|
|
rtsdk = true;
|
|
}
|
|
|
|
return rt && rtsdk;
|
|
}
|
|
|
|
private void CallFlatpak(string args)
|
|
{
|
|
var proc = new Process();
|
|
proc.StartInfo.FileName = "flatpak";
|
|
proc.StartInfo.Arguments = args;
|
|
proc.StartInfo.UseShellExecute = false;
|
|
proc.StartInfo.RedirectStandardOutput = true;
|
|
proc.Start();
|
|
|
|
while (!proc.StandardOutput.EndOfStream)
|
|
Log.LogMessage(MessageImportance.Normal, proc.StandardOutput.ReadLine());
|
|
}
|
|
}
|
|
}
|