Skip to content

Commit fa7c367

Browse files
pjcollinsjonathanpeppers
authored andcommitted
[Build.Tasks] Better handle gradle project custom output paths (#9480)
The AndroidGradleProject targets have been updated to fix some issues we ran into when trying to use this new build action in the MAUI build. The default output path property will now check to see if it is rooted before adding a `$(MSBuildProjectDirectory)` prefix to make it an absolute path. The property name has also been shortened. This fixes projects/builds that set `$(BaseIntermediateOutputPath)` or `$(IntermediateOutputPath)` to an absolute path that would hit an error along the lines of: D:\a\_work\1\s\.dotnet\packs\Microsoft.Android.Sdk.Windows\35.0.0-rc.2.152\tools\Microsoft.Android.Sdk.Bindings.Gradle.targets(73,5): error XACPR7024: System.IO.IOException: The filename, directory name, or volume label syntax is incorrect. : 'D:\a\_work\1\s\src\Core\src\D:\a\_work\1\s\artifacts\obj\Core\Release\net9.0-android35.0\gradle'. Projects which set the `%(AndroidGradleProject.OutputPath)` metadata to use a custom gradle output path have been fixed to ensure a trailing slash is always used. While looking through binlogs I also noticed the following message: MSB4120: Item '_AndroidGradleProjectLibraryOutputs' definition within target references itself via (qualified or unqualified) metadatum 'Bind'. This can lead to unintended expansion and cross-applying of pre-existing items. More info: https://aka.ms/msbuild/metadata-self-ref This has been fixed by qualifying the metadata that is added when creating `@(_AndroidGradleProjectLibraryOutputs)` items. A test has also been added for `$(UseArtifactsOutput)`: https://learn.microsoft.com/dotnet/core/sdk/artifacts-output
1 parent d4eb6f1 commit fa7c367

File tree

2 files changed

+76
-9
lines changed

2 files changed

+76
-9
lines changed

src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Microsoft.Android.Sdk.Bindings.Gradle.targets

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ This file contains MSBuild targets that support building and operating on Androi
1212
<UsingTask TaskName="Xamarin.Android.Tasks.Gradle" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
1313

1414
<PropertyGroup>
15-
<_AndroidGradleDefaultOutputPathRoot>$(MSBuildProjectDirectory)/$(IntermediateOutputPath)gradle/</_AndroidGradleDefaultOutputPathRoot>
16-
<_AndroidGradleBuildDirInitScriptPath>$(_AndroidGradleDefaultOutputPathRoot)net.android.init.gradle.kts</_AndroidGradleBuildDirInitScriptPath>
15+
<_AGPOutDirAbs>$(IntermediateOutputPath)gradle/</_AGPOutDirAbs>
16+
<_AGPOutDirAbs Condition=" !$([System.IO.Path]::IsPathRooted('$(_AGPOutDirAbs)')) ">$(MSBuildProjectDirectory)/$(_AGPOutDirAbs)</_AGPOutDirAbs>
17+
<_AGPInitScriptPath>$(_AGPOutDirAbs)net.android.init.gradle.kts</_AGPInitScriptPath>
1718
<_BuildAndroidGradleProjectsStamp>$(_AndroidStampDirectory)_BuildAndroidGradleProjects.stamp</_BuildAndroidGradleProjectsStamp>
1819
</PropertyGroup>
1920

@@ -56,7 +57,10 @@ This file contains MSBuild targets that support building and operating on Androi
5657
</Hash>
5758
<ItemGroup>
5859
<AndroidGradleProject Condition=" '%(AndroidGradleProject.OutputPath)' == '' " >
59-
<OutputPath>$(_AndroidGradleDefaultOutputPathRoot)%(ModuleName)%(Configuration)-$([System.String]::Copy($(_AndroidGradleProjectHash)).Substring(0, 5))/</OutputPath>
60+
<OutputPath>$(_AGPOutDirAbs)%(ModuleName)%(Configuration)-$([System.String]::Copy($(_AndroidGradleProjectHash)).Substring(0, 5))</OutputPath>
61+
</AndroidGradleProject>
62+
<AndroidGradleProject>
63+
<OutputPath>$([MSBuild]::EnsureTrailingSlash('%(OutputPath)'))</OutputPath>
6064
</AndroidGradleProject>
6165
</ItemGroup>
6266
</Target>
@@ -72,12 +76,12 @@ This file contains MSBuild targets that support building and operating on Androi
7276
<!-- Create the net.android.init.gradle.kts script used to override the Gradle project output directory -->
7377
<CopyResource
7478
ResourceName="net.android.init.gradle.kts"
75-
OutputPath="$(_AndroidGradleBuildDirInitScriptPath)"
79+
OutputPath="$(_AGPInitScriptPath)"
7680
/>
7781

7882
<!-- Run assemble task for project outputs, android app and library project outputs are currently supported -->
7983
<Gradle ToolPath="%(AndroidGradleProject.RootDir)%(AndroidGradleProject.Directory)"
80-
BuildDirInitScriptPath="$(_AndroidGradleBuildDirInitScriptPath)"
84+
BuildDirInitScriptPath="$(_AGPInitScriptPath)"
8185
Command="assemble%(AndroidGradleProject.Configuration)"
8286
ModuleName="%(AndroidGradleProject.ModuleName)"
8387
OutputPath="%(AndroidGradleProject.OutputPath)"
@@ -89,9 +93,9 @@ This file contains MSBuild targets that support building and operating on Androi
8993
<_AndroidGradleProjectAppOutputs Include="%(AndroidGradleProject.OutputPath)outputs/**/*.apk" />
9094
<_AndroidGradleProjectLibraryOutputs Include="%(AndroidGradleProject.OutputPath)outputs/**/*.aar"
9195
Condition=" '%(CreateAndroidLibrary)' == 'true' "
92-
Bind="%(Bind)"
93-
Pack="%(Pack)"
94-
Visible="%(Visible)" />
96+
Bind="%(AndroidGradleProject.Bind)"
97+
Pack="%(AndroidGradleProject.Pack)"
98+
Visible="%(AndroidGradleProject.Visible)" />
9599
</ItemGroup>
96100

97101
<AndroidMessage ResourceName="XAGRDLRefLibraryOutputs"
@@ -113,7 +117,7 @@ This file contains MSBuild targets that support building and operating on Androi
113117
Condition=" '@(AndroidGradleProject->Count())' != '0' "
114118
DependsOnTargets="_CalculateAndroidGradleProjectOutputPath" >
115119
<Gradle ToolPath="%(AndroidGradleProject.RootDir)%(AndroidGradleProject.Directory)"
116-
BuildDirInitScriptPath="$(_AndroidGradleBuildDirInitScriptPath)"
120+
BuildDirInitScriptPath="%(AndroidGradleProject.OutputPath)$(_AGPInitScriptPath)"
117121
Command="clean"
118122
ModuleName="%(AndroidGradleProject.ModuleName)"
119123
OutputPath="%(AndroidGradleProject.OutputPath)"

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidGradleProjectTests.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,69 @@ public void BuildIncremental ()
209209
StringAssert.Contains (@"uses-sdk android:minSdkVersion=""30""", packagedManifestContent);
210210
}
211211

212+
[Test]
213+
public void BuildCustomOutputPaths ()
214+
{
215+
var gradleProject = AndroidGradleProject.CreateDefault (GradleTestProjectDir);
216+
var moduleName = gradleProject.Modules.First ().Name;
217+
218+
using var builder = CreateDllBuilder ();
219+
var customOutputPathsRoot = Path.Combine (Root, builder.ProjectDirectory, "customout");
220+
var gradleOutputPath = Path.Combine (customOutputPathsRoot, "gradleoutdir");
221+
222+
var proj = new XamarinAndroidLibraryProject {
223+
OtherBuildItems = {
224+
new BuildItem (KnownProperties.AndroidGradleProject, gradleProject.BuildFilePath) {
225+
Metadata = {
226+
{ "ModuleName", moduleName },
227+
{ "OutputPath", gradleOutputPath },
228+
},
229+
},
230+
},
231+
OutputPath = Path.Combine (customOutputPathsRoot, "outdir"),
232+
IntermediateOutputPath = Path.Combine (customOutputPathsRoot, "intermediatedir"),
233+
};
234+
235+
Assert.IsTrue (builder.Build (proj), "Build should have succeeded.");
236+
FileAssert.Exists (Path.Combine (proj.OutputPath, $"{moduleName}-release.aar"));
237+
}
238+
239+
[Test]
240+
public void BuildArtifactsOutputPaths ()
241+
{
242+
var gradleProject = AndroidGradleProject.CreateDefault (GradleTestProjectDir);
243+
var moduleName = gradleProject.Modules.First ().Name;
244+
245+
using var builder = CreateDllBuilder ();
246+
var customOutputPathsRoot = Path.Combine (Root, builder.ProjectDirectory, "customout");
247+
248+
var proj = new XamarinAndroidLibraryProject {
249+
OtherBuildItems = {
250+
new BuildItem (KnownProperties.AndroidGradleProject, gradleProject.BuildFilePath) {
251+
Metadata = {
252+
{ "ModuleName", moduleName },
253+
},
254+
},
255+
},
256+
Imports = {
257+
new Import ("Directory.Build.props") {
258+
TextContent = () =>
259+
$@"<Project>
260+
<PropertyGroup>
261+
<UseArtifactsOutput>true</UseArtifactsOutput>
262+
<ArtifactsPath>{customOutputPathsRoot}</ArtifactsPath>
263+
</PropertyGroup>
264+
</Project>"
265+
},
266+
},
267+
OutputPath = "",
268+
IntermediateOutputPath = "",
269+
};
270+
271+
Assert.IsTrue (builder.Build (proj), "Build should have succeeded.");
272+
FileAssert.Exists (Path.Combine (customOutputPathsRoot, "bin", "UnnamedProject", "Debug", $"{moduleName}-release.aar"));
273+
}
274+
212275
[Test]
213276
public void BuildMultipleModules ()
214277
{

0 commit comments

Comments
 (0)