From ca6c5a8e6f78872862325d3ff509c45766256e54 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 2 Apr 2025 16:41:12 +0200 Subject: [PATCH 1/5] Include all platforms in multi project template --- .../templates/maui-multiproject/MauiApp.1.sln | 16 ++--- .../MultiProjectTemplateTest.cs | 59 +++++++++++++++++++ 2 files changed, 67 insertions(+), 8 deletions(-) diff --git a/src/Templates/src/templates/maui-multiproject/MauiApp.1.sln b/src/Templates/src/templates/maui-multiproject/MauiApp.1.sln index c640ff9da54c..2fdda5bdeccb 100644 --- a/src/Templates/src/templates/maui-multiproject/MauiApp.1.sln +++ b/src/Templates/src/templates/maui-multiproject/MauiApp.1.sln @@ -3,19 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.002.0 MinimumVisualStudioVersion = 10.0.40219.1 -#if (winui) +#if (AllPlatforms || winui) Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiApp.1.WinUI", "MauiApp.1.WinUI\MauiApp.1.WinUI.csproj", "{1AA5F22B-62F8-414F-AE50-635E99EB3F76}" EndProject #endif -#if (maccatalyst) +#if (AllPlatforms || maccatalyst) Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiApp.1.Mac", "MauiApp.1.Mac\MauiApp.1.Mac.csproj", "{C2800ABA-8C19-4553-A552-BFF679BEB039}" EndProject #endif -#if (ios) +#if (AllPlatforms || ios) Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiApp.1.iOS", "MauiApp.1.iOS\MauiApp.1.iOS.csproj", "{7C064C71-30BE-4D8D-9B68-E7249ED18FA1}" EndProject #endif -#if (android) +#if (AllPlatforms || android) Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MauiApp.1.Droid", "MauiApp.1.Droid\MauiApp.1.Droid.csproj", "{9E30318E-74DD-491B-9BAF-814DC9E892B8}" EndProject #endif @@ -33,7 +33,7 @@ Global Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution -#if (winui) +#if (AllPlatforms || winui) {1AA5F22B-62F8-414F-AE50-635E99EB3F76}.Debug|Any CPU.ActiveCfg = Debug|x64 {1AA5F22B-62F8-414F-AE50-635E99EB3F76}.Debug|Any CPU.Build.0 = Debug|x64 {1AA5F22B-62F8-414F-AE50-635E99EB3F76}.Debug|Any CPU.Deploy.0 = Debug|x64 @@ -59,7 +59,7 @@ Global {1AA5F22B-62F8-414F-AE50-635E99EB3F76}.Release|x86.Build.0 = Release|x86 {1AA5F22B-62F8-414F-AE50-635E99EB3F76}.Release|x86.Deploy.0 = Release|x86 #endif -#if (maccatalyst) +#if (AllPlatforms || maccatalyst) {C2800ABA-8C19-4553-A552-BFF679BEB039}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C2800ABA-8C19-4553-A552-BFF679BEB039}.Debug|Any CPU.Build.0 = Debug|Any CPU {C2800ABA-8C19-4553-A552-BFF679BEB039}.Debug|Any CPU.Deploy.0 = Debug|Any CPU @@ -85,7 +85,7 @@ Global {C2800ABA-8C19-4553-A552-BFF679BEB039}.Release|x86.Build.0 = Release|Any CPU {C2800ABA-8C19-4553-A552-BFF679BEB039}.Release|x86.Deploy.0 = Release|Any CPU #endif -#if (ios) +#if (AllPlatforms || ios) {7C064C71-30BE-4D8D-9B68-E7249ED18FA1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7C064C71-30BE-4D8D-9B68-E7249ED18FA1}.Debug|Any CPU.Build.0 = Debug|Any CPU {7C064C71-30BE-4D8D-9B68-E7249ED18FA1}.Debug|Any CPU.Deploy.0 = Debug|Any CPU @@ -111,7 +111,7 @@ Global {7C064C71-30BE-4D8D-9B68-E7249ED18FA1}.Release|x86.Build.0 = Release|Any CPU {7C064C71-30BE-4D8D-9B68-E7249ED18FA1}.Release|x86.Deploy.0 = Release|Any CPU #endif -#if (android) +#if (AllPlatforms || android) {9E30318E-74DD-491B-9BAF-814DC9E892B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9E30318E-74DD-491B-9BAF-814DC9E892B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {9E30318E-74DD-491B-9BAF-814DC9E892B8}.Debug|Any CPU.Deploy.0 = Debug|Any CPU diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs index 67a8774315f6..eb1ffd93a536 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs @@ -50,4 +50,63 @@ public void BuildMultiProjectSinglePlatform(string config, string platformArg) Assert.IsTrue(DotnetInternal.Build(solutionFile, config, properties: BuildProps, msbuildWarningsAsErrors: true), $"Solution {name} failed to build. Check test output/attachments for errors."); } + + [Test] + [TestCase("--android")] + [TestCase("--ios")] + [TestCase("--windows")] + [TestCase("--macos")] + [TestCase("")] // no platform arg means all platforms + // https://github.com/dotnet/maui/issues/28695 + public void VerifyIncludedPlatformsInSln(string platformArg) + { + var projectDir = TestDirectory; + var name = Path.GetFileName(projectDir); + var solutionFile = Path.Combine(projectDir, $"{name}.sln"); + + Assert.IsTrue(DotnetInternal.New($"maui-multiproject {platformArg}", projectDir, DotNetCurrent), + $"Unable to create template maui-multiproject. Check test output for errors."); + + var slnListOutput = DotnetInternal.RunForOutput("sln", $"{solutionFile} list", out int exitCode); + + // Asserts the process completed successfully + Assert.AreEqual(0, exitCode, $"Unable to list projects in solution. Check test output for errors."); + + // Asserts if the shared project is included in the solution, this should always be the case + Assert.IsTrue(slnListOutput.Contains($"{name}.csproj", StringComparison.OrdinalIgnoreCase), + $"Expected shared project (with name {name}.csproj) to be included in the solution."); + + var expectedCsprojFiles = new List { "Droid.csproj", "iOS.csproj", "Mac.csproj", "WinUI.csproj" }; + + switch (platformArg) + { + case "--android": + expectedCsprojFiles.Remove("iOS.csproj"); + expectedCsprojFiles.Remove("WinUI.csproj"); + expectedCsprojFiles.Remove("Mac.csproj"); + break; + case "--ios": + expectedCsprojFiles.Remove("Droid.csproj"); + expectedCsprojFiles.Remove("WinUI.csproj"); + expectedCsprojFiles.Remove("Mac.csproj"); + break; + case "--windows": + expectedCsprojFiles.Remove("Droid.csproj"); + expectedCsprojFiles.Remove("iOS.csproj"); + expectedCsprojFiles.Remove("Mac.csproj"); + break; + case "--macos": + expectedCsprojFiles.Remove("Droid.csproj"); + expectedCsprojFiles.Remove("iOS.csproj"); + expectedCsprojFiles.Remove("WinUI.csproj"); + break; + } + + // Depending on the platform argument, we assert if the expected projects are included in the solution + foreach (var platformCsproj in expectedCsprojFiles) + { + Assert.IsTrue(slnListOutput.Contains(platformCsproj, StringComparison.Ordinal), + $"Expected {platformCsproj} to be included in the solution."); + } + } } From 8883b5d87cdc917c6a14caa3dd4cd821d4ad3b14 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Thu, 3 Apr 2025 10:06:55 +0200 Subject: [PATCH 2/5] Fix invalid Info.plist value --- .../maui-multiproject/.template.config/template.json | 4 ++-- .../src/templates/maui-multiproject/MauiApp.1.Mac/Info.plist | 2 +- .../src/templates/maui-multiproject/MauiApp.1.iOS/Info.plist | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Templates/src/templates/maui-multiproject/.template.config/template.json b/src/Templates/src/templates/maui-multiproject/.template.config/template.json index f6622c2c4714..9ae94ca694f4 100644 --- a/src/Templates/src/templates/maui-multiproject/.template.config/template.json +++ b/src/Templates/src/templates/maui-multiproject/.template.config/template.json @@ -199,13 +199,13 @@ ] } }, - "XmlEncodedAppNameParam": { + "XmlEncodedAppNameParam": { "type": "derived", "valueSource": "name", "valueTransform": "encode", "replaces": "XmlEncodedAppName" }, - "defaultAppId":{ + "defaultAppId":{ "type": "generated", "generator": "join", "parameters": { diff --git a/src/Templates/src/templates/maui-multiproject/MauiApp.1.Mac/Info.plist b/src/Templates/src/templates/maui-multiproject/MauiApp.1.Mac/Info.plist index bfc560a2d2a2..19f8083fea96 100644 --- a/src/Templates/src/templates/maui-multiproject/MauiApp.1.Mac/Info.plist +++ b/src/Templates/src/templates/maui-multiproject/MauiApp.1.Mac/Info.plist @@ -3,7 +3,7 @@ CFBundleDisplayName - MauiApp.1 + XmlEncodedAppName CFBundleIdentifier com.companyname.mauiapp CFBundleShortVersionString diff --git a/src/Templates/src/templates/maui-multiproject/MauiApp.1.iOS/Info.plist b/src/Templates/src/templates/maui-multiproject/MauiApp.1.iOS/Info.plist index 8aec6ac4f45a..3b3a650f4fcb 100644 --- a/src/Templates/src/templates/maui-multiproject/MauiApp.1.iOS/Info.plist +++ b/src/Templates/src/templates/maui-multiproject/MauiApp.1.iOS/Info.plist @@ -3,7 +3,7 @@ CFBundleDisplayName - MauiApp.1 + XmlEncodedAppName CFBundleIdentifier com.companyname.mauiapp CFBundleShortVersionString From e86876c1f98199151551cf301c68ed31e3ecf8fc Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Tue, 8 Apr 2025 16:54:38 +0200 Subject: [PATCH 3/5] Update MultiProjectTemplateTest.cs --- .../MultiProjectTemplateTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs index eb1ffd93a536..e11fc52a26bc 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs @@ -23,6 +23,9 @@ public void BuildMultiProject(string config, string projectName) $"Unable to remove WinUI project from solution. Check test output for errors."); } + // TODO, we should not need this but hitting: https://github.com/dotnet/maui/issues/19840 + BuildProps.Add("ResizetizerErrorOnDuplicateOutputFilename=false"); + Assert.IsTrue(DotnetInternal.Build(solutionFile, config, properties: BuildProps, msbuildWarningsAsErrors: true), $"Solution {name} failed to build. Check test output/attachments for errors."); } From 76b0a6ef1090f3711d4c1df3c34f6b08ce23715b Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Tue, 8 Apr 2025 20:14:36 +0200 Subject: [PATCH 4/5] Update MultiProjectTemplateTest.cs --- .../MultiProjectTemplateTest.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs index e11fc52a26bc..1ebb5d17b4c3 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs @@ -24,9 +24,10 @@ public void BuildMultiProject(string config, string projectName) } // TODO, we should not need this but hitting: https://github.com/dotnet/maui/issues/19840 - BuildProps.Add("ResizetizerErrorOnDuplicateOutputFilename=false"); + var buildProps = BuildProps; + buildProps.Add("ResizetizerErrorOnDuplicateOutputFilename=false"); - Assert.IsTrue(DotnetInternal.Build(solutionFile, config, properties: BuildProps, msbuildWarningsAsErrors: true), + Assert.IsTrue(DotnetInternal.Build(solutionFile, config, properties: buildProps, msbuildWarningsAsErrors: true), $"Solution {name} failed to build. Check test output/attachments for errors."); } From 21192e7a1043465e0b004cf667b62e38ed1ef1f1 Mon Sep 17 00:00:00 2001 From: Gerald Versluis Date: Wed, 9 Apr 2025 12:32:31 +0200 Subject: [PATCH 5/5] Update MultiProjectTemplateTest.cs --- .../MultiProjectTemplateTest.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs index 1ebb5d17b4c3..b4d00a47bb90 100644 --- a/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs +++ b/src/TestUtils/src/Microsoft.Maui.IntegrationTests/MultiProjectTemplateTest.cs @@ -17,7 +17,11 @@ public void BuildMultiProject(string config, string projectName) Assert.IsTrue(DotnetInternal.New("maui-multiproject", projectDir, DotNetCurrent), $"Unable to create template maui-multiproject. Check test output for errors."); - if (!TestEnvironment.IsWindows) + // Always remove WinUI project if the project name contains special characters that cause WinRT source generator issues + // See: https://github.com/microsoft/CsWinRT/issues/1809 (under "Special characters in assembly name" section) + bool containsSpecialChars = projectName.IndexOfAny(new[] { '@', '&', '+', '%', '!', '#', '$', '^', '*', ' ', '-' }) >= 0; + + if (!TestEnvironment.IsWindows || containsSpecialChars) { Assert.IsTrue(DotnetInternal.Run("sln", $"\"{solutionFile}\" remove \"{projectDir}/{name}.WinUI/{name}.WinUI.csproj\""), $"Unable to remove WinUI project from solution. Check test output for errors.");