Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1944,5 +1944,41 @@ public void BuildPropsBreaksConvertResourcesCasesOnSecondBuild ([Values] Android
}
}

[Test]
public void AfterILLinkAdditionalStepsIsSkippedOnSecondBuild ([Values] AndroidRuntime runtime)
{
bool isRelease = runtime == AndroidRuntime.NativeAOT;
if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) {
return;
}

var proj = new XamarinAndroidApplicationProject {
IsRelease = isRelease,
};
proj.SetRuntime (runtime);
proj.SetProperty ("PublishTrimmed", "true");

using (var b = CreateApkBuilder ()) {
Assert.IsTrue (b.Build (proj), "first build should succeed");
b.Output.AssertTargetIsNotSkipped ("_RunAfterILLinkAdditionalSteps");
b.Output.AssertTargetIsNotSkipped ("_AfterILLinkAdditionalSteps");

// Verify afterlink/ output directory was created with per-ABI subdirectories containing assemblies
var afterlinkDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "afterlink");
Assert.IsTrue (Directory.Exists (afterlinkDir), "afterlink/ directory should exist after first build");
var abiDirs = Directory.GetDirectories (afterlinkDir);
Assert.IsTrue (abiDirs.Length > 0, "afterlink/ should contain ABI subdirectories");
foreach (var abiDir in abiDirs) {
var afterlinkFiles = Directory.GetFiles (abiDir, "*.dll");
Assert.IsTrue (afterlinkFiles.Length > 0, $"afterlink/{Path.GetFileName (abiDir)}/ should contain assemblies");
}

Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
b.Output.AssertTargetIsSkipped ("_RunAfterILLinkAdditionalSteps");
// The outer target must always run to update assembly itemgroups for downstream targets
b.Output.AssertTargetIsNotSkipped ("_AfterILLinkAdditionalSteps");
}
}

}
}
31 changes: 28 additions & 3 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidApkPerAbiFlagFile>$(IntermediateOutputPath)android\bin\apk_per_abi.flag</_AndroidApkPerAbiFlagFile>
<_AndroidDebugKeyStoreFlag>$(IntermediateOutputPath)android_debug_keystore.flag</_AndroidDebugKeyStoreFlag>
<_AdditionalPostLinkerStepsFlag>$(_AndroidStampDirectory)_AdditionalPostLinkerSteps.stamp</_AdditionalPostLinkerStepsFlag>
<_AfterILLinkOutputDir>$(IntermediateOutputPath)afterlink\</_AfterILLinkOutputDir>
<_AcwMapFile>$(IntermediateOutputPath)acw-map.txt</_AcwMapFile>
<_CustomViewMapFile>$(IntermediateOutputPath)customview-map.txt</_CustomViewMapFile>
<AndroidResgenNamespace Condition="'$(AndroidResgenNamespace)'==''" >$(RootNamespace)</AndroidResgenNamespace>
Expand Down Expand Up @@ -1465,16 +1466,17 @@ because xbuild doesn't support framework reference assemblies.
</Target>

<!-- Runs additional steps after ILLink runs (_LinkAssemblies) -->
<Target Name="_AfterILLinkAdditionalSteps"
<Target Name="_RunAfterILLinkAdditionalSteps"
DependsOnTargets="_LinkAssembliesNoShrinkInputs"
Condition="'$(PublishTrimmed)' == 'true' and '$(_AndroidTypeMapImplementation)' != 'trimmable'"
Inputs="$(_AndroidLinkFlag)"
Outputs="$(_AdditionalPostLinkerStepsFlag)">
<MakeDir Directories="$(_AfterILLinkOutputDir)" />
<AssemblyModifierPipeline
ApplicationJavaClass="$(AndroidApplicationJavaClass)"
CodeGenerationTarget="$(_AndroidJcwCodegenTarget)"
Debug="$(AndroidIncludeDebugSymbols)"
DestinationFiles="@(ResolvedAssemblies)"
DestinationFiles="@(ResolvedAssemblies->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')"
Deterministic="$(Deterministic)"
Comment thread
sbomer marked this conversation as resolved.
EnableMarshalMethods="$(_AndroidUseMarshalMethods)"
ErrorOnCustomJavaObject="$(AndroidErrorOnCustomJavaObject)"
Expand All @@ -1485,8 +1487,31 @@ because xbuild doesn't support framework reference assemblies.
SourceFiles="@(ResolvedAssemblies)"
TargetName="$(TargetName)">
</AssemblyModifierPipeline>

<Touch Files="$(_AdditionalPostLinkerStepsFlag)" AlwaysCreate="true" />
<ItemGroup>
<FileWrites Include="$(_AfterILLinkOutputDir)**" />
</ItemGroup>
</Target>

<!-- Updates assembly itemgroups to point to afterlink/ outputs.
Runs even when _RunAfterILLinkAdditionalSteps is skipped for incrementalism,
so downstream targets always see the correct paths. -->
<Target Name="_AfterILLinkAdditionalSteps"
DependsOnTargets="_RunAfterILLinkAdditionalSteps"
Condition="'$(PublishTrimmed)' == 'true' and '$(_AndroidTypeMapImplementation)' != 'trimmable'">
<ItemGroup>
<_OrigResolvedAssemblies Include="@(ResolvedAssemblies)" />
<ResolvedAssemblies Remove="@(ResolvedAssemblies)" />
<ResolvedAssemblies Include="@(_OrigResolvedAssemblies->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" />

Comment thread
sbomer marked this conversation as resolved.
<_OrigResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" />
<ResolvedUserAssemblies Remove="@(ResolvedUserAssemblies)" />
<ResolvedUserAssemblies Include="@(_OrigResolvedUserAssemblies->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" />

<_OrigResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" />
<ResolvedFrameworkAssemblies Remove="@(ResolvedFrameworkAssemblies)" />
<ResolvedFrameworkAssemblies Include="@(_OrigResolvedFrameworkAssemblies->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" />
</ItemGroup>
</Target>

<!-- _PrepareAssemblies lives in Microsoft.Android.Sdk.AssemblyResolution.targets -->
Expand Down