diff --git a/app/Build/Commands/Library.cs b/app/Build/Commands/Library.cs new file mode 100644 index 00000000..354dc504 --- /dev/null +++ b/app/Build/Commands/Library.cs @@ -0,0 +1,3 @@ +namespace Build.Commands; + +public record Library(string Path, string Filename); \ No newline at end of file diff --git a/app/Build/Commands/Pdfium.cs b/app/Build/Commands/Pdfium.cs new file mode 100644 index 00000000..d3e72ef8 --- /dev/null +++ b/app/Build/Commands/Pdfium.cs @@ -0,0 +1,107 @@ +using System.Formats.Tar; +using System.IO.Compression; + +using SharedTools; + +namespace Build.Commands; + +public static class Pdfium +{ + public static async Task InstallAsync(RID rid, string version) + { + Console.Write($"- Installing Pdfium {version} for {rid.ToUserFriendlyName()} ..."); + + var cwd = Environment.GetRustRuntimeDirectory(); + var pdfiumTmpDownloadPath = Path.GetTempFileName(); + var pdfiumTmpExtractPath = Directory.CreateTempSubdirectory(); + var pdfiumUrl = GetPdfiumDownloadUrl(rid, version); + + // + // Download the file: + // + Console.Write(" downloading ..."); + using (var client = new HttpClient()) + { + var response = await client.GetAsync(pdfiumUrl); + if (!response.IsSuccessStatusCode) + { + Console.WriteLine($" failed to download Pdfium {version} for {rid.ToUserFriendlyName()}"); + return; + } + + await using var fileStream = File.Create(pdfiumTmpDownloadPath); + await response.Content.CopyToAsync(fileStream); + } + + // + // Extract the downloaded file: + // + Console.Write(" extracting ..."); + await using(var tgzStream = File.Open(pdfiumTmpDownloadPath, FileMode.Open, FileAccess.Read, FileShare.Read)) + { + await using var uncompressedStream = new GZipStream(tgzStream, CompressionMode.Decompress); + await TarFile.ExtractToDirectoryAsync(uncompressedStream, pdfiumTmpExtractPath.FullName, true); + } + + // + // Copy the library to the target directory: + // + Console.Write(" deploying ..."); + var library = GetLibraryPath(rid); + if (string.IsNullOrEmpty(library.Path)) + { + Console.WriteLine($" failed to find the library path for {rid.ToUserFriendlyName()}"); + return; + } + + var pdfiumLibSourcePath = Path.Join(pdfiumTmpExtractPath.FullName, library.Path); + var pdfiumLibTargetPath = Path.Join(cwd, "target", "resources", library.Filename); + if (!File.Exists(pdfiumLibSourcePath)) + { + Console.WriteLine($" failed to find the library file '{pdfiumLibSourcePath}'"); + return; + } + + Directory.CreateDirectory(Path.Join(cwd, "target", "resources")); + if (File.Exists(pdfiumLibTargetPath)) + File.Delete(pdfiumLibTargetPath); + + File.Copy(pdfiumLibSourcePath, pdfiumLibTargetPath); + + // + // Cleanup: + // + Console.Write(" cleaning up ..."); + File.Delete(pdfiumTmpDownloadPath); + Directory.Delete(pdfiumTmpExtractPath.FullName, true); + + Console.WriteLine(" done."); + } + + private static Library GetLibraryPath(RID rid) => rid switch + { + RID.LINUX_ARM64 or RID.LINUX_X64 => new(Path.Join("lib", "libpdfium.so"), "libpdfium.so"), + RID.OSX_ARM64 or RID.OSX_X64 => new(Path.Join("lib", "libpdfium.dylib"), "libpdfium.dylib"), + RID.WIN_ARM64 or RID.WIN_X64 => new(Path.Join("bin", "pdfium.dll"), "pdfium.dll"), + + _ => new(string.Empty, string.Empty), + }; + + private static string GetPdfiumDownloadUrl(RID rid, string version) + { + var baseUrl = $"https://github.com/bblanchon/pdfium-binaries/releases/download/chromium%2F{version}/pdfium-"; + return rid switch + { + RID.LINUX_ARM64 => $"{baseUrl}linux-arm64.tgz", + RID.LINUX_X64 => $"{baseUrl}linux-x64.tgz", + + RID.OSX_ARM64 => $"{baseUrl}mac-arm64.tgz", + RID.OSX_X64 => $"{baseUrl}mac-x64.tgz", + + RID.WIN_ARM64 => $"{baseUrl}win-arm64.zip", + RID.WIN_X64 => $"{baseUrl}win-x64.zip", + + _ => string.Empty, + }; + } +} \ No newline at end of file diff --git a/app/Build/Commands/UpdateMetadataCommands.cs b/app/Build/Commands/UpdateMetadataCommands.cs index 09592169..b9b01357 100644 --- a/app/Build/Commands/UpdateMetadataCommands.cs +++ b/app/Build/Commands/UpdateMetadataCommands.cs @@ -110,7 +110,10 @@ public sealed partial class UpdateMetadataCommands Console.WriteLine("=============================="); await this.UpdateArchitecture(rid); - Console.Write($"- Start .NET build for '{rid.AsMicrosoftRid()}' ..."); + var pdfiumVersion = await this.ReadPdfiumVersion(); + await Pdfium.InstallAsync(rid, pdfiumVersion); + + Console.Write($"- Start .NET build for {rid.ToUserFriendlyName()} ..."); await this.ReadCommandOutput(pathApp, "dotnet", $"clean --configuration release --runtime {rid.AsMicrosoftRid()}"); var dotnetBuildOutput = await this.ReadCommandOutput(pathApp, "dotnet", $"publish --configuration release --runtime {rid.AsMicrosoftRid()} --disable-build-servers --force"); var dotnetBuildOutputLines = dotnetBuildOutput.Split([global::System.Environment.NewLine], StringSplitOptions.RemoveEmptyEntries); @@ -308,6 +311,18 @@ public sealed partial class UpdateMetadataCommands await File.WriteAllTextAsync(changelogCodePath, changelogCode, Environment.UTF8_NO_BOM); Console.WriteLine(" done."); } + + private async Task ReadPdfiumVersion() + { + const int PDFIUM_VERSION_INDEX = 10; + + var pathMetadata = Environment.GetMetadataPath(); + var lines = await File.ReadAllLinesAsync(pathMetadata, Encoding.UTF8); + var currentPdfiumVersion = lines[PDFIUM_VERSION_INDEX].Trim(); + var shortVersion = currentPdfiumVersion.Split('.')[2]; + + return shortVersion; + } private async Task UpdateArchitecture(RID rid) { @@ -315,7 +330,7 @@ public sealed partial class UpdateMetadataCommands var pathMetadata = Environment.GetMetadataPath(); var lines = await File.ReadAllLinesAsync(pathMetadata, Encoding.UTF8); - Console.Write("- Updating architecture ..."); + Console.Write($"- Updating architecture to {rid.ToUserFriendlyName()} ..."); lines[ARCHITECTURE_INDEX] = rid.AsMicrosoftRid(); await File.WriteAllLinesAsync(pathMetadata, lines, Environment.UTF8_NO_BOM);