diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets
index 37a058a8ded..5d3ee2ba295 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Bindings.Core.targets
@@ -44,23 +44,31 @@ It is shared between "legacy" binding projects and .NET 5 projects.
/>
+
+
+ <_LibrariesToBind Include="@(EmbeddedJar)" />
+ <_LibrariesToBind Include="@(InputJar)" />
+ <_LibrariesToBind Include="@(LibraryProjectZip)" />
+ <_LibrariesToBind Include="@(_JavaBindingSource)" Condition=" '%(_JavaBindingSource.Bind)' == 'true' "/>
+
+
+
+ Condition=" '@(_LibrariesToBind->Count())' != '0' ">
<_AndroidGenerateManagedBindings>true
-
+
<_GeneratedManagedBindingFiles Include="$(GeneratedOutputPath)**\*.cs" />
@@ -75,7 +83,6 @@ It is shared between "legacy" binding projects and .NET 5 projects.
@@ -135,14 +142,17 @@ It is shared between "legacy" binding projects and .NET 5 projects.
+
+
+
+ >
true
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets
index b932c578336..4c2a8ed5173 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Javac.targets
@@ -21,7 +21,9 @@ It is shared between "legacy" binding projects and .NET 7+ projects.
<_AndroidIntermediateBindingClassesZip>$(IntermediateOutputPath)binding\bin\$(MSBuildProjectName).jar
<_AndroidIntermediateBindingClassesDocs>$(IntermediateOutputPath)binding\bin\$(MSBuildProjectName)-docs.xml
<_AndroidCompileJavaStampFile>$(_AndroidStampDirectory)_CompileJava.stamp
+ <_AndroidCompileJavaFileList>$(IntermediateOutputPath)_CompileJava.FileList.txt
<_AndroidCompileBindingJavaStampFile>$(_AndroidStampDirectory)_CompileBindingJava.stamp
+ <_AndroidCompileBindingJavaFileList>$(IntermediateOutputPath)_CompileBindingJava.FileList.txt
@@ -74,18 +76,36 @@ It is shared between "legacy" binding projects and .NET 7+ projects.
<_JavaBindingSource Include="@(AndroidJavaSource)" Condition=" '%(AndroidJavaSource.Bind)' == 'True' " />
+
+
+
+
<_JavaSource Include="@(AndroidJavaSource)" Condition=" '%(AndroidJavaSource.Bind)' != 'True' " />
+
+
+
+
@@ -132,7 +152,7 @@ It is shared between "legacy" binding projects and .NET 7+ projects.
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
index 31c9442e8e9..df4dab646d8 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets
@@ -120,9 +120,6 @@ properties that determine build ordering.
UpdateAndroidResources;
_BuildResourceDesigner;
UpdateAndroidInterfaceProxies;
- _SetAndroidGenerateManagedBindings;
- _ClearGeneratedManagedBindings;
- AddBindingsToCompile;
_CheckForInvalidDesignerConfig;
@@ -144,6 +141,13 @@ properties that determine build ordering.
_AddAndroidDefines;
_IncludeLayoutBindingSources;
AddLibraryJarsToBind;
+ _CollectLibrariesToBind;
+ _SetAndroidGenerateManagedBindings;
+ ExportJarToXml;
+ GenerateBindings;
+ _CollectGeneratedManagedBindingFiles;
+ _ClearGeneratedManagedBindings;
+ AddBindingsToCompile;
_BuildResourceDesigner;
_AddResourceDesignerFiles;
$(CompileDependsOn);
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs
index bb76b585a1d..15f04ccf5e6 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs
@@ -6,7 +6,9 @@
using System.Linq;
using System.Xml;
using System.Xml.Linq;
+using System.Xml.XPath;
using Microsoft.Build.Framework;
+using Microsoft.Build.Utilities;
using Microsoft.Android.Build.Tasks;
namespace Xamarin.Android.Tasks
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs
index 58d8012352a..81acffd0fb1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs
@@ -39,7 +39,7 @@ public void DotNetBuildBinding ()
proj.OtherBuildItems.Add (new BuildItem ("JavaSourceJar", "javaclasses-sources.jar") {
BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar,
});
- proj.OtherBuildItems.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") {
+ proj.AndroidJavaSources.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") {
Encoding = Encoding.ASCII,
TextContent = () => ResourceData.JavaSourceTestExtension,
Metadata = { { "Bind", "True"} },
@@ -75,6 +75,7 @@ public void BindingLibraryIncremental (string classParser)
"_ResolveLibraryProjectImports",
"CoreCompile",
"_CreateAar",
+ "_ClearGeneratedManagedBindings",
};
var proj = new XamarinAndroidBindingProject () {
@@ -112,6 +113,23 @@ public void BindingLibraryIncremental (string classParser)
foreach (var target in targets) {
Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!");
}
+
+ Assert.IsTrue (b.DesignTimeBuild (proj, target: "UpdateGeneratedFiles"), "DTB should have succeeded.");
+ var cs_file = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "generated", "src", "Com.Larvalabs.Svgandroid.SVGParser.cs");
+ FileAssert.Exists (cs_file);
+ Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "third build should succeed");
+ foreach (var target in targets) {
+ Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!");
+ }
+ // Fast Update Check Build
+ Assert.IsTrue (b.DesignTimeBuild (proj, target: "PrepareResources;_GenerateCompileInputs"), "DTB should have succeeded.");
+ cs_file = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "generated", "src", "Com.Larvalabs.Svgandroid.SVGParser.cs");
+ FileAssert.Exists (cs_file);
+ Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "forth build should succeed");
+ foreach (var target in targets) {
+ Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should be skipped on second build!");
+ }
+
}
}
@@ -671,6 +689,10 @@ public void BindingWithAndroidJavaSource ()
StringAssertEx.ContainsText (File.ReadAllLines (generatedIface), "string GreetWithQuestion (string name, global::Java.Util.Date date, string question);");
Assert.IsTrue (libBuilder.Build (lib), "Library build should have succeeded.");
Assert.IsTrue (libBuilder.Output.IsTargetSkipped ("_CompileBindingJava"), $"`_CompileBindingJava` should be skipped on second build!");
+ Assert.IsTrue (libBuilder.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings"), $"`_ClearGeneratedManagedBindings` should be skipped on second build!");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on second build.");
+ Assert.IsTrue (libBuilder.DesignTimeBuild (lib, target: "UpdateGeneratedFiles"), "DTB should have succeeded.");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on DTB build.");
Assert.IsTrue (appBuilder.Build (app), "App build should have succeeded.");
appBuilder.Target = "SignAndroidPackage";
Assert.IsTrue (appBuilder.Build (app), "App SignAndroidPackage should have succeeded.");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
index b0b69ff759b..fce460a2c6d 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
@@ -70,7 +70,7 @@ public void DotNetBuild (string runtimeIdentifiers, bool isRelease, bool aot, bo
proj.OtherBuildItems.Add (new BuildItem ("JavaSourceJar", "javaclasses-sources.jar") {
BinaryContent = () => ResourceData.JavaSourceJarTestSourcesJar,
});
- proj.OtherBuildItems.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") {
+ proj.AndroidJavaSources.Add (new AndroidItem.AndroidJavaSource ("JavaSourceTestExtension.java") {
Encoding = Encoding.ASCII,
TextContent = () => ResourceData.JavaSourceTestExtension,
Metadata = { { "Bind", "True"} },
@@ -1511,7 +1511,7 @@ public void BuildApplicationWithJavaSourceUsingAndroidX ([Values(true, false)] b
{
var proj = new XamarinAndroidApplicationProject () {
IsRelease = isRelease,
- OtherBuildItems = {
+ AndroidJavaSources = {
new BuildItem (AndroidBuildActions.AndroidJavaSource, "ToolbarEx.java") {
TextContent = () => @"package com.unnamedproject.unnamedproject;
import android.content.Context;
@@ -1556,11 +1556,11 @@ public void BuildApplicationCheckThatAddStaticResourcesTargetDoesNotRerun ()
public void CheckJavaError ()
{
var proj = new XamarinAndroidApplicationProject ();
- proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe.java") {
+ proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe.java") {
TextContent = () => "public classo TestMe { }",
Encoding = Encoding.ASCII
});
- proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe2.java") {
+ proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "TestMe2.java") {
TextContent = () => "public class TestMe2 {" +
"public vod Test ()" +
"}",
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
index 8e625dc3ab7..83d47a85bdc 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs
@@ -1000,14 +1000,14 @@ public void BuildProguardEnabledProject (string rid)
XamarinAndroidApplicationProject CreateMultiDexRequiredApplication (string debugConfigurationName = "Debug", string releaseConfigurationName = "Release")
{
var proj = new XamarinAndroidApplicationProject (debugConfigurationName, releaseConfigurationName);
- proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") {
+ proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods.java") {
TextContent = () => "public class ManyMethods { \n"
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
+ "}",
Encoding = Encoding.ASCII,
Metadata = { { "Bind", "False "}},
});
- proj.OtherBuildItems.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") {
+ proj.AndroidJavaSources.Add (new BuildItem (AndroidBuildActions.AndroidJavaSource, "ManyMethods2.java") {
TextContent = () => "public class ManyMethods2 { \n"
+ string.Join (Environment.NewLine, Enumerable.Range (0, 32768).Select (i => "public void method" + i + "() {}"))
+ "}",
@@ -1064,8 +1064,8 @@ public void BuildAfterMultiDexIsNotRequired ()
}
//Now build project again after it no longer requires multidex, remove the *HUGE* AndroidJavaSource build items
- while (proj.OtherBuildItems.Count > 1)
- proj.OtherBuildItems.RemoveAt (proj.OtherBuildItems.Count - 1);
+ while (proj.AndroidJavaSources.Count > 1)
+ proj.AndroidJavaSources.RemoveAt (proj.AndroidJavaSources.Count - 1);
proj.SetProperty ("AndroidEnableMultiDex", "False");
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true), "Build should have succeeded.");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs
index 853003056f7..a5692e315ba 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/BuildOutput.cs
@@ -52,9 +52,9 @@ public List GetAssemblyMapCache ()
return File.ReadLines (path).ToList ();
}
- public bool IsTargetSkipped (string target) => IsTargetSkipped (Builder.LastBuildOutput, target);
+ public bool IsTargetSkipped (string target, bool defaultIfNotUsed = false) => IsTargetSkipped (Builder.LastBuildOutput, target, defaultIfNotUsed);
- public static bool IsTargetSkipped (IEnumerable output, string target)
+ public static bool IsTargetSkipped (IEnumerable output, string target, bool defaultIfNotUsed = false)
{
bool found = false;
foreach (var line in output) {
@@ -69,7 +69,7 @@ public static bool IsTargetSkipped (IEnumerable output, string target)
if (found)
return true;
}
- return false;
+ return defaultIfNotUsed;
}
///
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs
index 32425e363c0..30ae44a3628 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/DotNetXamarinProject.cs
@@ -17,10 +17,12 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string
Sources = new List ();
OtherBuildItems = new List ();
+ AndroidJavaSources = new List ();
ItemGroupList.Add (References);
ItemGroupList.Add (OtherBuildItems);
ItemGroupList.Add (Sources);
+ ItemGroupList.Add (AndroidJavaSources);
SetProperty ("RootNamespace", () => RootNamespace ?? ProjectName);
SetProperty ("AssemblyName", () => AssemblyName ?? ProjectName);
@@ -40,6 +42,7 @@ protected DotNetXamarinProject (string debugConfigurationName = "Debug", string
public IList OtherBuildItems { get; private set; }
public IList Sources { get; private set; }
+ public IList AndroidJavaSources { get; private set; }
public IList ActiveConfigurationProperties {
get { return IsRelease ? ReleaseProperties : DebugProperties; }
diff --git a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs
index 20f9de4f0e6..c7e625c0707 100644
--- a/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs
+++ b/tests/MSBuildDeviceIntegration/Tests/InstallTests.cs
@@ -611,5 +611,73 @@ public void AdbTargetChangesAppBundle ()
var after = File.GetLastWriteTimeUtc (apkset);
Assert.AreNotEqual (before, after, $"{apkset} should change!");
}
+
+ [Test]
+ public void AppWithAndroidJavaSource ()
+ {
+ var path = Path.Combine ("temp", TestName);
+ var itemToDelete = new AndroidItem.AndroidJavaSource ("TestJavaClass2.java") {
+ Encoding = Encoding.ASCII,
+ TextContent = () => @"package com.test.java;
+
+public class TestJavaClass2 {
+
+ public String test(){
+
+ return ""Java is called"";
+ }
+}",
+ Metadata = {
+ { "Bind", "True" },
+ },
+ };
+ var proj = new XamarinAndroidApplicationProject {
+ EnableDefaultItems = true,
+ AndroidJavaSources = {
+ new AndroidItem.AndroidJavaSource ("TestJavaClass.java") {
+ Encoding = Encoding.ASCII,
+ TextContent = () => @"package com.test.java;
+
+public class TestJavaClass {
+
+ public String test(){
+
+ return ""Java is called"";
+ }
+}",
+ Metadata = {
+ { "Bind", "True" },
+ },
+ },
+ itemToDelete,
+ },
+ };
+ using (var b = CreateApkBuilder ()) {
+ b.ThrowOnBuildFailure = false;
+ Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
+ b.AssertHasNoWarnings ();
+ var generatedCode = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
+ "generated", "src", "Com.Test.Java.TestJavaClass.cs");
+ var generatedCode2 = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath,
+ "generated", "src", "Com.Test.Java.TestJavaClass2.cs");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have been generated.");
+ FileAssert.Exists (generatedCode2, $"'{generatedCode2}' should have been generated.");
+ Assert.IsTrue (b.DesignTimeBuild (proj, target: "UpdateGeneratedFiles"), "DTB should have succeeded.");
+ Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings", defaultIfNotUsed: true), $"`_ClearGeneratedManagedBindings` should be skipped on DTB build!");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on DTB build.");
+ FileAssert.Exists (generatedCode2, $"'{generatedCode2}' should have not be deleted on DTB build.");
+ proj.AndroidJavaSources.Remove (itemToDelete);
+ File.Delete (Path.Combine (Root, b.ProjectDirectory, itemToDelete.Include ()));
+ Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "Second build should have succeeded.");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on second build.");
+ FileAssert.DoesNotExist (generatedCode2, $"'{generatedCode2}' should have be deleted on second build.");
+ Assert.IsFalse (b.Output.IsTargetSkipped ("_CompileBindingJava"), $"`_CompileBindingJava` should run on second build!");
+ Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings"), $"`_ClearGeneratedManagedBindings` should be skipped on second build!");
+ // Call Install directly so Build does not get called automatically
+ Assert.IsTrue (b.RunTarget (proj, "Install", doNotCleanupOnUpdate: true, saveProject: false), "Install build should have succeeded.");
+ FileAssert.Exists (generatedCode, $"'{generatedCode}' should have not be deleted on Install build.");
+ Assert.IsTrue (b.Output.IsTargetSkipped ("_ClearGeneratedManagedBindings", defaultIfNotUsed: true), $"`_ClearGeneratedManagedBindings` should be skipped on Install build!");
+ }
+ }
}
}