diff --git a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets index 7a0ad2adaa4a..59ab282bd3cb 100644 --- a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets +++ b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets @@ -11,6 +11,8 @@ + + @@ -45,7 +47,7 @@ + Condition="'$(DesignTimeBuild)' != 'true'"> @@ -178,16 +180,51 @@ + + + + + <_UnoUpriResource Condition="'%(GeneratedFiles.UnoResourceTarget)' == 'Uno'" Include="@(GeneratedFiles->'%(LogicalName)')"> + %(GeneratedFiles.Language) + + + + + + + + + + + + + + + + + + + + + + + + - @@ -195,49 +232,61 @@ <_SubstitutionFiles Include="$(IntermediateOutputPath)\Substitutions\*.Substitutions.xml" /> + + + + + TargetDefinitionFile="$(IntermediateOutputPath)ILLink.Substitutions.xml" /> - + + + $(TargetsTriggeredByCompilation);_UnoSetupEmbeddedResourcesInjection + + + + + + <_UnoRequiresEmbeddedResourcesInjection>true + + + + <_UnoEmbeddedResourcesInjectionAfterTargets Include="CoreCompile" /> - <_UnoEmbeddedResourcesInjectionAfterTargets Include="_UnoLinkerHintsSubstitutionsMerge" /> - <_UnoEmbeddedResourcesInjectionAssembliesForReferencePaths - Include="@(ReferencePath)" - Condition="'%(Extension)' == '.dll'" /> + <_UnoEmbeddedResourcesInjectionAssembliesForReferencePaths Include="@(ReferencePath)" Condition="'%(Extension)' == '.dll'" /> + ReferencePath="@(_UnoEmbeddedResourcesInjectionAssembliesForReferencePaths)" /> + + + Encoding.UTF8; - } } } diff --git a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs index 36fb8e8bd18a..aa3119ceb429 100644 --- a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs +++ b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs @@ -165,7 +165,8 @@ string buildBasePath() new Dictionary() { { "UnoResourceTarget", "Uno" }, - { "LogicalName", logicalTargetPath.Replace(Path.DirectorySeparatorChar, '.') } + { "LogicalName", logicalTargetPath.Replace(Path.DirectorySeparatorChar, '.') }, + { "Language", language } } ); } diff --git a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriFeaturesGeneratorTask.cs b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriFeaturesGeneratorTask.cs new file mode 100644 index 000000000000..0309d78fb660 --- /dev/null +++ b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriFeaturesGeneratorTask.cs @@ -0,0 +1,58 @@ +#nullable enable + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Uno.UI.Tasks.ResourcesGenerator +{ + public class UpriFeaturesGeneratorTask_v0 : Task + { + public ITaskItem[]? Languages { get; set; } + + [Output] + public ITaskItem[]? OutputFeatures { get; set; } + + public override bool Execute() + { + // Debugger.Launch(); + + if (Languages != null && Languages.Length > 0) + { + // Get all cultures except Invariant and legacy Chinese (superseded by zh-Hans and zh-Hant) + var allCultures = + CultureInfo + .GetCultures(CultureTypes.NeutralCultures | CultureTypes.SpecificCultures) + .Where(c => c.IetfLanguageTag != string.Empty && c.Name != "zh-CHS" && c.Name != "zh-CHT") + .ToDictionary(c => c.IetfLanguageTag, c => "false"); + + foreach (var language in Languages) + { + var culture = new CultureInfo(language.ItemSpec); + + while (culture.IetfLanguageTag != string.Empty) + { + allCultures[culture.IetfLanguageTag] = "true"; + + culture = culture.Parent; + } + } + + OutputFeatures = + allCultures + .Select(kvp => new TaskItem($"UPRI_{kvp.Key.Replace('-', '_').ToLowerInvariant()}", new Dictionary() { ["Value"] = kvp.Value })) + .ToArray(); + } + else + { + OutputFeatures = Array.Empty(); + } + + return true; + } + } +} diff --git a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriSubstitutionsGeneratorTask.cs b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriSubstitutionsGeneratorTask.cs new file mode 100644 index 000000000000..e3404be4f55d --- /dev/null +++ b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UpriSubstitutionsGeneratorTask.cs @@ -0,0 +1,69 @@ +#nullable enable + +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Xml; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Uno.UI.Tasks.ResourcesGenerator +{ + /// + /// Generates a linker substitution file for UPRI resources. + /// This allows the linker to trim unused localization resources. + /// + public class UpriSubstitutionsGeneratorTask_v0 : Task + { + [Required] + public string? AssemblyName { get; set; } + + [Required] + public ITaskItem[]? Resources { get; set; } + + [Required] + public string? OutputFile { get; set; } + + public override bool Execute() + { + // Debugger.Launch(); + + if (!string.IsNullOrEmpty(AssemblyName) && Resources != null && !string.IsNullOrEmpty(OutputFile)) + { + var xml = new XmlDocument(); + + var linkerNode = xml.CreateElement(string.Empty, "linker", string.Empty); + + xml.AppendChild(linkerNode); + + foreach (var resourceGroup in Resources.GroupBy(r => r.GetMetadata("Language").Replace('-', '_').ToLowerInvariant())) + { + var assemblyNode = xml.CreateElement(string.Empty, "assembly", string.Empty); + assemblyNode.SetAttribute("fullname", AssemblyName); + assemblyNode.SetAttribute("feature", $"UPRI_{resourceGroup.Key}"); + assemblyNode.SetAttribute("featurevalue", "false"); + + linkerNode.AppendChild(assemblyNode); + + foreach (var resource in resourceGroup) + { + var resourceNode = xml.CreateElement(string.Empty, "resource", string.Empty); + resourceNode.SetAttribute("name", resource.ItemSpec); + resourceNode.SetAttribute("action", "remove"); + + assemblyNode.AppendChild(resourceNode); + } + } + + Directory.CreateDirectory(Path.GetDirectoryName(OutputFile)); + + using var sw = new StreamWriter(OutputFile, append: false, Encoding.UTF8); + + xml.Save(sw); + } + + return true; + } + } +} diff --git a/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj b/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj index fd0ab4811b3c..d11cd78b5620 100644 --- a/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj +++ b/src/Uno.UI.Wasm.Tests/Uno.UI.Wasm.Tests.csproj @@ -6,9 +6,6 @@ $(MSBuildThisFileDirectory)tsbindings $(DefineConstants);__WASM__ - - true - true false @@ -83,10 +80,6 @@ - - <_UnoEmbeddedResourcesInjectionAfterTargets Include="CompileTypeScriptWithTSConfig" /> - -