diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
index 4be55630c91..2ce0fe4f1db 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.LlvmIr.targets
@@ -24,25 +24,21 @@
_PrepareNativeAssemblySources;
$(_AfterPrepareAssemblies);
_GetGenerateJavaStubsInputs;
+ _GetGenerateJavaCallableWrappersInputs;
+ _GetGenerateJavaStubsCoreInputs;
+ _GetGenerateTypeMappingsInputs;
+ _GetGenerateAndroidManifestInputs;
+ _GenerateJavaCallableWrappers;
+ _GenerateJavaStubsCore;
+ _GenerateTypeMappings;
+ _GenerateAndroidManifest;
-
-
-
- <_ManifestOutput Condition=" '$(AndroidManifestMerger)' == 'legacy' ">$(IntermediateOutputPath)android\AndroidManifest.xml
- <_ManifestOutput Condition=" '$(AndroidManifestMerger)' != 'legacy' ">$(IntermediateOutputPath)AndroidManifest.xml
- <_LinkingEnabled Condition=" '$(AndroidLinkMode)' != 'None'">True
- <_LinkingEnabled Condition=" '$(AndroidLinkMode)' == 'None'">False
- <_HaveMultipleRIDs Condition=" '$(RuntimeIdentifiers)' != '' ">True
- <_HaveMultipleRIDs Condition=" '$(RuntimeIdentifiers)' == '' ">False
-
-
- <_MergedManifestDocuments Condition=" '$(AndroidManifestMerger)' == 'legacy' " Include="@(ExtractedManifestDocuments)" />
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ManifestOutput Condition=" '$(AndroidManifestMerger)' == 'legacy' ">$(IntermediateOutputPath)android\AndroidManifest.xml
+ <_ManifestOutput Condition=" '$(AndroidManifestMerger)' != 'legacy' ">$(IntermediateOutputPath)AndroidManifest.xml
+
+
+ <_MergedManifestDocuments Condition=" '$(AndroidManifestMerger)' == 'legacy' " Include="@(ExtractedManifestDocuments)" />
+
+
-
-
-
-
+
+
+
+
+
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets
index 51cae6aab85..3b2162ce8d4 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.TypeMap.Trimmable.targets
@@ -17,12 +17,42 @@
tasks needed by all typemap paths, but they currently depend on NativeCodeGenState
from the Cecil-based GenerateJavaStubs task. Extracting them into a shared target
requires decoupling from NativeCodeGenState first. See #10807. -->
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ DependsOnTargets="_SetLatestTargetFrameworkVersion;_PrepareAssemblies;_GetGenerateJavaStubsInputs;_GenerateJavaCallableWrappers;_GenerateJavaStubsCore;_GenerateTypeMappings;_GenerateAndroidManifest">
+
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs
index 49402865722..6bc20afbf9f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CompileNativeAssembly.cs
@@ -22,6 +22,7 @@ sealed class Config
public string? AssemblerPath;
public string? AssemblerOptions;
public string? InputSource;
+ public string? OutputFile;
}
[Required]
@@ -43,6 +44,14 @@ public override System.Threading.Tasks.Task RunTaskAsync ()
void RunAssembler (Config config)
{
+ if (config.OutputFile is not null && File.Exists (config.OutputFile)) {
+ string sourceFile = Path.Combine (WorkingDirectory, Path.GetFileName (config.InputSource));
+ if (File.Exists (sourceFile) && File.GetLastWriteTimeUtc (config.OutputFile) >= File.GetLastWriteTimeUtc (sourceFile)) {
+ LogDebugMessage ($"[LLVM llc] Skipping '{Path.GetFileName (config.InputSource)}' because '{Path.GetFileName (config.OutputFile)}' is up to date");
+ return;
+ }
+ }
+
var stdout_completed = new ManualResetEvent (false);
var stderr_completed = new ManualResetEvent (false);
var psi = new ProcessStartInfo () {
@@ -118,10 +127,13 @@ IEnumerable GetAssemblerConfigs ()
string executableDir = Path.GetDirectoryName (llcPath);
string executableName = MonoAndroidHelper.GetExecutablePath (executableDir, Path.GetFileName (llcPath));
+ string outputFilePath = Path.Combine (WorkingDirectory, sourceFile.Replace (".ll", ".o"));
+
yield return new Config {
InputSource = item.ItemSpec,
AssemblerPath = Path.Combine (executableDir, executableName),
AssemblerOptions = $"{assemblerOptions} -o={outputFile} {QuoteFileName (sourceFile)}",
+ OutputFile = outputFilePath,
};
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
index a17945d8cee..c0249a1a4a1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateNativeApplicationConfigSources.cs
@@ -57,6 +57,7 @@ public class GenerateNativeApplicationConfigSources : AndroidTask
public bool EnableMarshalMethods { get; set; }
public bool EnableManagedMarshalMethodsLookup { get; set; }
+ public bool JniAddNativeMethodRegistrationAttributePresent { get; set; }
public string? RuntimeConfigBinFilePath { get; set; }
public string ProjectRuntimeConfigFilePath { get; set; } = String.Empty;
public string? BoundExceptionType { get; set; }
@@ -251,7 +252,7 @@ public override bool RunTask ()
UsesAssemblyPreload = envBuilder.Parser.UsesAssemblyPreload,
AndroidPackageName = AndroidPackageName,
PackageNamingPolicy = pnp,
- JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent,
+ JniAddNativeMethodRegistrationAttributePresent = JniAddNativeMethodRegistrationAttributePresent,
NumberOfAssembliesInApk = assemblyCount,
BundledAssemblyNameWidth = assemblyNameWidth,
NativeLibraries = uniqueNativeLibraries,
@@ -277,7 +278,7 @@ public override bool RunTask ()
BrokenExceptionTransitions = envBuilder.Parser.BrokenExceptionTransitions,
PackageNamingPolicy = pnp,
BoundExceptionType = boundExceptionType,
- JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent,
+ JniAddNativeMethodRegistrationAttributePresent = JniAddNativeMethodRegistrationAttributePresent,
HaveRuntimeConfigBlob = haveRuntimeConfigBlob,
NumberOfAssembliesInApk = assemblyCount,
BundledAssemblyNameWidth = assemblyNameWidth,
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.cs
index 70a6a60f5a9..beacfd442a3 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateTypeMappings.cs
@@ -31,6 +31,9 @@ public class GenerateTypeMappings : AndroidTask
[Required]
public string IntermediateOutputDirectory { get; set; } = "";
+ [Output]
+ public bool JniAddNativeMethodRegistrationAttributePresent { get; set; }
+
public bool SkipJniAddNativeMethodRegistrationAttributeScan { get; set; }
[Required]
@@ -102,6 +105,7 @@ void GenerateTypeMap (AndroidTargetArch arch, List assemblies)
// Set for use by task later
NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent = state.JniAddNativeMethodRegistrationAttributePresent;
+ JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent;
AddOutputTypeMaps (tmg, state.TargetArch);
}
@@ -126,8 +130,10 @@ void GenerateAllTypeMappingsFromNativeState (bool useMarshalMethods)
throw new InvalidOperationException ($"Internal error: no native code generator state defined");
// Set for use by task later
- if (useMarshalMethods)
+ if (useMarshalMethods) {
NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent = templateCodeGenState.JniAddNativeMethodRegistrationAttributePresent;
+ JniAddNativeMethodRegistrationAttributePresent = NativeCodeGenState.TemplateJniAddNativeMethodRegistrationAttributePresent;
+ }
}
void GenerateTypeMapFromNativeState (NativeCodeGenState state, bool useMarshalMethods)
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
index f04aabcb3dd..87d656b3a45 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs
@@ -543,7 +543,7 @@ protected override void OnClick()
Assert.IsFalse (StringAssertEx.ContainsText (b.LastBuildOutput, "AndroidResgen: Warning while updating Resource XML"),
"Warning while processing resources should not have been raised.");
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "Build should have succeeded.");
- Assert.IsTrue (b.Output.IsTargetSkipped ("_GenerateJavaStubs"), "Target _GenerateJavaStubs should have been skipped");
+ Assert.IsTrue (b.Output.IsTargetSkipped ("_GenerateJavaStubsCore"), "Target _GenerateJavaStubsCore should have been skipped");
lib.Touch ("CustomTextView.cs");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
index 8e3600f20dd..1b4e3314598 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
@@ -746,7 +746,7 @@ public void ProduceReferenceAssembly ([Values] AndroidRuntime runtime)
appBuilder.Output.AssertTargetIsSkipped ("CoreCompile");
appBuilder.Output.AssertTargetIsSkipped ("_BuildLibraryImportsCache");
appBuilder.Output.AssertTargetIsSkipped ("_ResolveLibraryProjectImports");
- appBuilder.Output.AssertTargetIsSkipped ("_GenerateJavaStubs");
+ appBuilder.Output.AssertTargetIsSkipped ("_GenerateJavaStubsCore");
appBuilder.Output.AssertTargetIsPartiallyBuilt (KnownTargets.LinkAssembliesNoShrink);
@@ -1237,7 +1237,10 @@ public void GenerateJavaStubsAndAssembly ([Values] bool isRelease, [Values] Andr
}
var targets = new [] {
- "_GenerateJavaStubs",
+ "_GenerateJavaCallableWrappers",
+ "_GenerateJavaStubsCore",
+ "_GenerateTypeMappings",
+ "_GenerateAndroidManifest",
"_GeneratePackageManagerJava",
};
var proj = new XamarinAndroidApplicationProject {
@@ -1289,6 +1292,34 @@ public void GenerateJavaStubsAndAssembly ([Values] bool isRelease, [Values] Andr
}
}
+ [Test]
+ public void GenerateJavaStubsSubTargetIncrementality ([Values (false, true)] bool isRelease)
+ {
+ // Test that all sub-targets correctly skip on no-change rebuilds.
+ var targets = new [] {
+ "_GenerateJavaCallableWrappers",
+ "_GenerateJavaStubsCore",
+ "_GenerateTypeMappings",
+ "_GenerateAndroidManifest",
+ };
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = isRelease,
+ };
+
+ using (var b = CreateApkBuilder ()) {
+ Assert.IsTrue (b.Build (proj), "first build should have succeeded.");
+ foreach (var target in targets) {
+ Assert.IsFalse (b.Output.IsTargetSkipped (target), $"first build: `{target}` should *not* be skipped!");
+ }
+
+ // No-change rebuild: all sub-targets should skip
+ Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "no-change rebuild should have succeeded.");
+ foreach (var target in targets) {
+ Assert.IsTrue (b.Output.IsTargetSkipped (target), $"no-change: `{target}` should be skipped!");
+ }
+ }
+ }
+
readonly string [] ExpectedAssemblyFiles = new [] {
Path.Combine ("android", "environment.@ABI@.o"),
Path.Combine ("android", "environment.@ABI@.ll"),
@@ -1683,7 +1714,7 @@ public void AndroidResourceChange ([Values] AndroidRuntime runtime)
// TODO: NativeAOT doesn't skip this target
if (runtime != AndroidRuntime.NativeAOT) {
- builder.Output.AssertTargetIsSkipped ("_GenerateJavaStubs");
+ builder.Output.AssertTargetIsSkipped ("_GenerateJavaStubsCore");
}
builder.Output.AssertTargetIsSkipped ("_CompileJava");
builder.Output.AssertTargetIsSkipped ("_CompileToDalvik");
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index e2cd6eeca42..2c244a226f0 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1493,6 +1493,48 @@ because xbuild doesn't support framework reference assemblies.
+
+
+ <_GenerateJavaCallableWrappersInputs Include="@(_AndroidMSBuildAllProjects)" />
+ <_GenerateJavaCallableWrappersInputs Include="$(_AndroidBuildPropertiesCache)" />
+ <_GenerateJavaCallableWrappersInputs Include="@(_ResolvedAssemblies->'$([System.IO.Path]::ChangeExtension("%(Identity)", ".jlo.xml"))')" />
+
+
+
+
+
+ <_GenerateJavaStubsCoreInputs Include="@(_AndroidMSBuildAllProjects)" />
+ <_GenerateJavaStubsCoreInputs Include="$(_ResolvedUserAssembliesHashFile)" />
+ <_GenerateJavaStubsCoreInputs Include="@(_ResolvedUserMonoAndroidAssemblies)" />
+ <_GenerateJavaStubsCoreInputs Include="$(_AndroidBuildPropertiesCache)" />
+ <_GenerateJavaStubsCoreInputs Include="$(_AndroidManifestAbs)" />
+ <_GenerateJavaStubsCoreInputs Include="@(AndroidEnvironment);@(LibraryEnvironments)" Condition=" '$(_AndroidFastDeployEnvironmentFiles)' != 'true' " />
+
+
+
+
+
+ <_GenerateTypeMappingsInputs Include="@(_AndroidMSBuildAllProjects)" />
+ <_GenerateTypeMappingsInputs Include="$(_AndroidBuildPropertiesCache)" />
+ <_GenerateTypeMappingsInputs Include="@(_ResolvedAssemblies->'$([System.IO.Path]::ChangeExtension("%(Identity)", ".typemap.xml"))')" />
+ <_GenerateTypeMappingsInputs
+ Condition=" '$(_AndroidUseMarshalMethods)' == 'true' Or '$(_AndroidJLOCheckedBuild)' == 'true' "
+ Include="$(_AndroidStampDirectory)_GenerateJavaStubsCore.stamp" />
+
+
+
+
+
+ <_GenerateAndroidManifestInputs Include="@(_AndroidMSBuildAllProjects)" />
+ <_GenerateAndroidManifestInputs Include="$(_AndroidManifestAbs)" />
+ <_GenerateAndroidManifestInputs Include="$(_AndroidBuildPropertiesCache)" />
+ <_GenerateAndroidManifestInputs Include="@(_ResolvedUserMonoAndroidAssemblies)" />
+ <_GenerateAndroidManifestInputs Include="@(AndroidEnvironment);@(LibraryEnvironments)" Condition=" '$(_AndroidFastDeployEnvironmentFiles)' != 'true' " />
+
+ <_GenerateAndroidManifestInputs Include="$(_AndroidStampDirectory)_GenerateJavaStubsCore.stamp" />
+
+
+
+
+
+
+
+