Files
FlaxEngine/Source/Tools/Flax.Build/Deploy/Deployment.Editor.cs
2023-09-23 14:42:05 +02:00

310 lines
16 KiB
C#

// Copyright (c) 2012-2023 Flax Engine. All rights reserved.
#define USE_STD
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text;
using Flax.Build;
using Flax.Build.Platforms;
namespace Flax.Deploy
{
partial class Deployment
{
private static void CodeSign(string file)
{
if (string.IsNullOrEmpty(Configuration.DeployCert))
return;
Log.Info("Code signing file: " + file);
switch (Platform.BuildTargetPlatform)
{
case TargetPlatform.Windows:
VCEnvironment.CodeSign(file, Configuration.DeployCert, Configuration.DeployCertPass);
break;
case TargetPlatform.Mac:
MacPlatform.CodeSign(file, Configuration.DeployCert);
break;
}
}
public class Editor
{
private static string RootPath;
private static string OutputPath;
public static void Package()
{
// Prepare
RootPath = Globals.EngineRoot;
OutputPath = Path.Combine(Deployer.PackageOutputPath, "Editor");
Utilities.DirectoryDelete(OutputPath);
Directory.CreateDirectory(OutputPath);
Log.Info(string.Empty);
Log.Info("Deploy editor files");
Log.Info(string.Empty);
// Deploy binaries
foreach (var configuration in Deployer.Configurations)
DeployEditorBinaries(configuration);
{
var binariesSubDir = "Binaries/Tools";
var src = Path.Combine(RootPath, binariesSubDir);
var dst = Path.Combine(OutputPath, binariesSubDir);
var buildToolExe = Platform.BuildTargetPlatform == TargetPlatform.Windows ? "Flax.Build.exe" : "Flax.Build";
DeployFile(src, dst, buildToolExe);
CodeSign(Path.Combine(dst, buildToolExe));
var buildToolDll = "Flax.Build.dll";
DeployFile(src, dst,buildToolDll);
CodeSign(Path.Combine(dst, buildToolDll));
DeployFile(src, dst, "Flax.Build.xml", true);
DeployFile(src, dst, "Flax.Build.pdb");
DeployFile(src, dst, "Flax.Build.deps.json");
DeployFile(src, dst, "Flax.Build.runtimeconfig.json");
DeployFile(src, dst, "Ionic.Zip.Reduced.dll");
DeployFile(src, dst, "Mono.Cecil.dll");
DeployFile(src, dst, "Microsoft.CodeAnalysis.dll");
DeployFile(src, dst, "Microsoft.CodeAnalysis.CSharp.dll");
DeployFile(src, dst, "Microsoft.VisualStudio.Setup.Configuration.Interop.dll");
}
// Deploy content
DeployFolder(RootPath, OutputPath, "Content");
// Deploy DotNet deps
{
var subDir = "Source/Platforms/DotNet";
DeployFile(RootPath, OutputPath, subDir, "Newtonsoft.Json.dll");
DeployFile(RootPath, OutputPath, subDir, "Newtonsoft.Json.xml");
DeployFile(RootPath, OutputPath, Path.Combine(subDir, "AOT"), "Newtonsoft.Json.dll");
}
// Deploy sources
{
// Modules public files
var rules = Builder.GenerateRulesAssembly();
var files = new List<string>();
foreach (var module in rules.Modules)
{
if (!module.Deploy)
continue;
module.GetFilesToDeploy(files);
files.Add(module.FilePath);
foreach (var file in files)
{
var src = Path.GetDirectoryName(file);
var dst = Path.Combine(OutputPath, Utilities.MakePathRelativeTo(src, RootPath));
var filename = Path.GetFileName(file);
DeployFile(src, dst, filename);
}
files.Clear();
}
// Shader includes
var shaders = Directory.GetFiles(Path.Combine(RootPath, "Source/Shaders"), "*.hlsl", SearchOption.AllDirectories);
foreach (var shader in shaders)
{
var localPath = Utilities.MakePathRelativeTo(shader, RootPath);
DeployFile(shader, Path.Combine(OutputPath, localPath));
}
// Custom engine files
DeployFile(RootPath, OutputPath, "Source/ThirdParty", "concurrentqueue.h");
DeployFile(RootPath, OutputPath, "Source", ".editorconfig");
DeployFile(RootPath, OutputPath, "Source", "flax.natvis");
DeployFile(RootPath, OutputPath, "Source", "FlaxEditor.Build.cs");
DeployFile(RootPath, OutputPath, "Source", "FlaxEngine.Gen.h");
DeployFile(RootPath, OutputPath, "Source", "FlaxGame.Build.cs");
// Mark deployed sources as already prebuilt
Utilities.ReplaceInFile(Path.Combine(OutputPath, "Source/FlaxEditor.Build.cs"), "IsPreBuilt = false;", "IsPreBuilt = true;");
Utilities.ReplaceInFile(Path.Combine(OutputPath, "Source/FlaxGame.Build.cs"), "IsPreBuilt = false;", "IsPreBuilt = true;");
}
// Deploy project
DeployFile(RootPath, OutputPath, "Flax.flaxproj");
// Package Editor into macOS app
if (Platform.BuildTargetPlatform == TargetPlatform.Mac)
{
var arch = Platform.BuildTargetArchitecture;
Log.Info(string.Empty);
Log.Info("Creating macOS app...");
var appPath = Path.Combine(Deployer.PackageOutputPath, "FlaxEditor.app");
var appContentsPath = Path.Combine(appPath, "Contents");
var appBinariesPath = Path.Combine(appContentsPath, "MacOS");
Utilities.DirectoryDelete(appPath);
Directory.CreateDirectory(appPath);
Directory.CreateDirectory(appContentsPath);
Directory.CreateDirectory(appBinariesPath);
// Copy icons set
Directory.CreateDirectory(Path.Combine(appContentsPath, "Resources"));
Utilities.FileCopy(Path.Combine(Globals.EngineRoot, "Source/Platforms/Mac/Default.icns"), Path.Combine(appContentsPath, "Resources/icon.icns"));
// Create PkgInfo file
File.WriteAllText(Path.Combine(appContentsPath, "PkgInfo"), "APPL???", Encoding.ASCII);
// Create Info.plist
var plist = File.ReadAllText(Path.Combine(Globals.EngineRoot, "Source/Platforms/Mac/Default.plist"));
var flaxProject = EngineTarget.EngineProject;
plist = plist.Replace("{Version}", flaxProject.Version.ToString());
plist = plist.Replace("{Copyright}", flaxProject.Copyright);
plist = plist.Replace("{Executable}", "FlaxEditor");
plist = plist.Replace("{Arch}", arch == TargetArchitecture.ARM64 ? "arm64" : "x86_64");
File.WriteAllText(Path.Combine(appContentsPath, "Info.plist"), plist, Encoding.ASCII);
// Copy output editor files
Utilities.DirectoryCopy(OutputPath, appContentsPath);
// Copy native binaries for app execution
var defaultEditorConfig = "Development";
var ediotrBinariesPath = Path.Combine(appContentsPath, "Binaries/Editor/Mac", defaultEditorConfig);
Utilities.DirectoryCopy(ediotrBinariesPath, appBinariesPath, true, true);
}
// Compress
if (Configuration.DontCompress)
return;
Log.Info(string.Empty);
Log.Info("Compressing editor files...");
string editorPackageZipPath;
var unix = Platform.BuildTargetPlatform == TargetPlatform.Linux || Platform.BuildTargetPlatform == TargetPlatform.Mac;
if (unix)
{
var zipEofPath = UnixPlatform.Which("zip");
unix = File.Exists(zipEofPath);
if (!unix)
Log.Verbose("Using .NET compressing");
}
if (unix)
{
// Use system tool (preserves executable file attributes and link files)
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, $"FlaxEditor{Enum.GetName(typeof(TargetPlatform), Platform.BuildTargetPlatform)}.zip");
Utilities.FileDelete(editorPackageZipPath);
Utilities.Run("zip", "Editor.zip -r .", null, OutputPath, Utilities.RunOptions.ThrowExceptionOnError);
File.Move(Path.Combine(OutputPath, "Editor.zip"), editorPackageZipPath);
}
else
{
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "Editor.zip");
Utilities.FileDelete(editorPackageZipPath);
#if USE_STD
System.IO.Compression.ZipFile.CreateFromDirectory(OutputPath, editorPackageZipPath, System.IO.Compression.CompressionLevel.Optimal, false);
#else
using (var zip = new Ionic.Zip.ZipFile())
{
zip.AddDirectory(OutputPath);
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zip.Comment = string.Format("Flax Editor {0}.{1}.{2}\nDate: {3}", Deployer.VersionMajor, Deployer.VersionMinor, Deployer.VersionBuild, DateTime.UtcNow);
zip.Save(editorPackageZipPath);
}
#endif
}
Log.Info("Compressed editor package size: " + Utilities.GetFileSize(editorPackageZipPath));
if (Platform.BuildTargetPlatform == TargetPlatform.Windows)
{
Log.Info("Compressing editor debug symbols files...");
editorPackageZipPath = Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols.zip");
Utilities.FileDelete(editorPackageZipPath);
#if USE_STD
System.IO.Compression.ZipFile.CreateFromDirectory(Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols"), editorPackageZipPath, System.IO.Compression.CompressionLevel.Optimal, false);
#else
using (var zip = new Ionic.Zip.ZipFile())
{
zip.AddDirectory(Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols"));
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.BestCompression;
zip.Comment = string.Format("Flax Editor {0}.{1}.{2}\nDate: {3}", Deployer.VersionMajor, Deployer.VersionMinor, Deployer.VersionBuild, DateTime.UtcNow);
zip.Save(editorPackageZipPath);
}
#endif
Log.Info("Compressed editor debug symbols package size: " + Utilities.GetFileSize(editorPackageZipPath));
}
// Cleanup
Utilities.DirectoryDelete(OutputPath);
Utilities.DirectoryDelete(Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols"));
}
private static void DeployEditorBinaries(TargetConfiguration configuration)
{
var binariesSubDir = Path.Combine(Platform.GetEditorBinaryDirectory(), configuration.ToString());
var src = Path.Combine(RootPath, binariesSubDir);
var dst = Path.Combine(OutputPath, binariesSubDir);
Directory.CreateDirectory(dst);
DeployFile(src, dst, "FlaxEditor.Build.json");
DeployFile(src, dst, "FlaxEngine.CSharp.runtimeconfig.json");
DeployFile(src, dst, "FlaxEngine.CSharp.pdb");
DeployFile(src, dst, "FlaxEngine.CSharp.xml");
DeployFile(src, dst, "Newtonsoft.Json.pdb");
if (Platform.BuildTargetPlatform == TargetPlatform.Windows)
{
var dstDebug = Path.Combine(Deployer.PackageOutputPath, "EditorDebugSymbols/Win64/" + configuration);
Directory.CreateDirectory(dstDebug);
// Validate that build editor app has a valid version number
var editorExeName = "FlaxEditor.exe";
var version = FileVersionInfo.GetVersionInfo(Path.Combine(src, editorExeName));
if (version.FileMajorPart != Deployer.VersionMajor || version.FileMinorPart != Deployer.VersionMinor || version.FileBuildPart != Deployer.VersionBuild)
{
throw new InvalidDataException("Invalid engine build number. Output " + editorExeName + " has not matching version number.");
}
// Deploy binaries
DeployFile(src, dst, editorExeName);
CodeSign(Path.Combine(dst, editorExeName));
DeployFile(src, dst, "FlaxEditor.lib");
DeployFiles(src, dst, "*.dll");
CodeSign(Path.Combine(dst, "FlaxEngine.CSharp.dll"));
// Deploy debug symbols files
DeployFiles(src, dstDebug, "*.pdb");
File.Delete(Path.Combine(dstDebug, "FlaxEngine.CSharp.pdb"));
File.Delete(Path.Combine(dstDebug, "Newtonsoft.Json.pdb"));
if (configuration == TargetConfiguration.Development)
{
// Deploy Editor executable debug file for Development configuration to improve crash reporting
DeployFile(src, dst, "FlaxEditor.pdb");
}
}
else if (Platform.BuildTargetPlatform == TargetPlatform.Linux)
{
// Deploy binaries
DeployFile(src, dst, "FlaxEditor");
DeployFiles(src, dst, "*.dll");
DeployFiles(src, dst, "*.so");
DeployFile(src, dst, "Logo.png");
// Optimize package size
Utilities.Run("strip", "FlaxEditor", null, dst, Utilities.RunOptions.None);
Utilities.Run("strip", "libFlaxEditor.so", null, dst, Utilities.RunOptions.None);
}
else if (Platform.BuildTargetPlatform == TargetPlatform.Mac)
{
// Deploy binaries
DeployFile(src, dst, "FlaxEditor");
DeployFile(src, dst, "MoltenVK_icd.json");
DeployFiles(src, dst, "*.dll");
DeployFiles(src, dst, "*.dylib");
// Optimize package size
Utilities.Run("strip", "FlaxEditor", null, dst, Utilities.RunOptions.None);
Utilities.Run("strip", "FlaxEditor.dylib", null, dst, Utilities.RunOptions.None);
Utilities.Run("strip", "libMoltenVK.dylib", null, dst, Utilities.RunOptions.None);
CodeSign(Path.Combine(dst, "FlaxEditor"));
CodeSign(Path.Combine(dst, "FlaxEditor.dylib"));
CodeSign(Path.Combine(dst, "libMoltenVK.dylib"));
}
}
}
}
}