diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs
index fd88a337d04..be286992a62 100644
--- a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs
+++ b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs
@@ -90,6 +90,7 @@ void CopyExtraBuildFiles (string destinationRoot, Context context)
"*log",
"TestOutput-*.txt",
"Timing_*",
+ "*.runsettings",
};
void CopyExtraTestFiles (string destinationRoot, Context context)
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
index d1bfde205de..be0c6c61539 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets
@@ -27,7 +27,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
-
+
<_SetLatestTargetFrameworkVersionDependsOnTargets>
$(_SetLatestTargetFrameworkVersionDependsOnTargets);
_CreateAapt2VersionCache;
diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
index 3fa46d4a2b9..fc1dea7a636 100644
--- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
+++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets
@@ -45,6 +45,8 @@ Copyright (C) 2016 Xamarin. All rights reserved.
per TargetFramework.
-->
<_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' ">$(_OuterIntermediateOutputPath)
+ <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' And '$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'true' ">$(_OuterIntermediateOutputPath)designtime\
+ <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'true' ">$(IntermediateOutputPath)designtime\
<_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' ">$(IntermediateOutputPath)
<_GenerateResourceDesignerAssemblyOutput>$(_DesignerIntermediateOutputPath)$(_DesignerAssemblyName).dll
<_GenerateResourceDesignerClassFile Condition=" '$(Language)' == 'F#' ">$(_DesignerIntermediateOutputPath)_$(_DesignerAssemblyName).fs
@@ -56,15 +58,45 @@ Copyright (C) 2016 Xamarin. All rights reserved.
+
+
+ <_ProjectReferenceResourceDirectory Include="$(MSBuildProjectDirectory)\$(MonoAndroidResourcePrefix)"
+ StampFile="$(MSBuildProjectFile)"
+ Condition="!Exists('$(OutputPath)$(TargetName).aar')"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DesignTimeAarFiles Include="@(AndroidAarLibrary)" Condition=" '@(LibraryResourceDirectories->Count())' == '0' " />
+ <_DesignTimeAarFiles Include="@(LibraryProjectZip)" Condition="'%(LibraryProjectZip.Extension)' == '.aar' and '@(LibraryResourceDirectories->Count())' == '0'" />
+
+
+
<_BuildResourceDesignerDependsOn>
_SetupDesignerProperties;
+ _ResolveAars;
+ _CalculateDesignTimeAars;
_GenerateResourceCaseMap;
_GenerateRtxt;
_GenerateResourceDesignerIntermediateClass;
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets
index 14b9e8c2dee..e678933ab8b 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets
@@ -18,7 +18,7 @@ projects.
<_AarOutputPath>$(OutputPath)$(TargetName).aar
-
+
<_AarSearchDirectory Include="@(_ReferencePath->'%(RootDir)%(Directory)')" />
<_AarSearchDirectory Include="@(_ReferenceDependencyPaths->'%(RootDir)%(Directory)')" />
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
index 5bb9041cb5f..afda07d8c7d 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets
@@ -90,6 +90,7 @@ _ResolveAssemblies MSBuild target.
<_AdditionalProperties>
_ComputeFilesToPublishForRuntimeIdentifiers=true
;SelfContained=true
+ ;DesignTimeBuild=$(DesignTimeBuild)
;AppendRuntimeIdentifierToOutputPath=true
;ResolveAssemblyReferencesFindRelatedSatellites=false
;SkipCompilerExecution=true
@@ -105,6 +106,7 @@ _ResolveAssemblies MSBuild target.
<_ProjectToBuild Include="$(MSBuildProjectFile)" AdditionalProperties="RuntimeIdentifier=%(_RIDs.Identity);$(_AdditionalProperties)" />
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 ee627e65d03..f54dd4f15d6 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
@@ -112,14 +112,9 @@ properties that determine build ordering.
$(CoreResolveReferencesDependsOn);
UpdateAndroidResources;
- _BuildResourceDesigner;
UpdateAndroidInterfaceProxies;
_CheckForInvalidDesignerConfig;
-
- $(DesignTimeResolveAssemblyReferencesDependsOn);
- _BuildResourceDesigner;
-
<_UpdateAndroidResourcesDependsOn>
$(CoreResolveReferencesDependsOn);
_CreatePropertiesCache;
@@ -127,7 +122,6 @@ properties that determine build ordering.
_ComputeAndroidResourcePaths;
_UpdateAndroidResgen;
_CreateAar;
- _BuildResourceDesigner;
_SetupMSBuildAllProjects;
@@ -142,9 +136,9 @@ properties that determine build ordering.
_CollectGeneratedManagedBindingFiles;
_ClearGeneratedManagedBindings;
AddBindingsToCompile;
+ $(CompileDependsOn);
_BuildResourceDesigner;
_AddResourceDesignerFiles;
- $(CompileDependsOn);
_CheckAndroidHttpClientHandlerType;
@@ -171,6 +165,7 @@ properties that determine build ordering.
_ResolveMonoAndroidSdks;
+ ResolveAssemblyReferences;
_ExtractLibraryProjectImports;
_GetLibraryImports;
_ExtractAar;
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets
index 31755d131e8..a48a9b20058 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets
@@ -26,7 +26,7 @@
-
+ Condition="Exists('$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props') And '$(DesignTimeBuild)' != 'true'"/>
+
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
index bf6aa0563aa..fe617657044 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs
@@ -3,9 +3,13 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Microsoft.Android.Build.Tasks;
+using Xamarin.Android.Tools;
+//using Xamarin.Tools.Zip;
+using System.IO.Compression;
namespace Xamarin.Android.Tasks
{
@@ -22,6 +26,8 @@ public class GenerateResourceCaseMap : AndroidTask
public ITaskItem[] AdditionalResourceDirectories { get; set; }
+ public string[] AarLibraries { get; set; }
+
[Required]
public ITaskItem OutputFile { get; set; }
@@ -64,6 +70,42 @@ public override bool RunTask ()
AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar));
}
}
+ var resmap = ".net/__res_name_case_map.txt";
+ foreach (var aar in AarLibraries ?? Array.Empty()) {
+ Log.LogDebugMessage ($"Processing Aar file {aar}");
+ if (!File.Exists (aar)) {
+ Log.LogDebugMessage ($"Skipping non-existent aar: {aar}");
+ continue;
+ }
+ using (var file = File.OpenRead (aar)) {
+ using var zip = new ZipArchive (file);
+ var entry = zip.GetEntry (resmap);
+ if (entry is null) {
+ Log.LogDebugMessage ($"Skipping non-existent file: {resmap}");
+ continue;
+ }
+ Log.LogDebugMessage ($"Found: {entry.FullName}");
+ var ms = MemoryStreamPool.Shared.Rent ();
+ try {
+ using (var entryStream = entry.Open ()) {
+ entryStream.CopyTo (ms);
+ }
+ ms.Position = 0;
+ using (var reader = new StreamReader (ms, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: -1, leaveOpen: true)) {
+ string line;
+ // Read each line until the end of the file
+ while ((line = reader.ReadLine()) != null) {
+ if (string.IsNullOrEmpty (line))
+ continue;
+ string [] tok = line.Split (';');
+ AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar));
+ }
+ }
+ } finally {
+ MemoryStreamPool.Shared.Return (ms);
+ }
+ }
+ }
if (MonoAndroidHelper.SaveMapFile (BuildEngine4, Path.GetFullPath (OutputFile.ItemSpec), resource_fixup)) {
Log.LogDebugMessage ($"Writing to: {OutputFile.ItemSpec}");
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
index 563318d357c..5de36f9cd7c 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs
@@ -17,6 +17,8 @@ public class GenerateRtxt : AndroidTask
public string ResourceDirectory { get; set; }
public string[] AdditionalResourceDirectories { get; set; }
+ public string[] AarLibraries { get; set; }
+
public string JavaPlatformJarPath { get; set; }
public string ResourceFlagFile { get; set; }
@@ -31,7 +33,7 @@ public override bool RunTask ()
var javaPlatformDirectory = string.IsNullOrEmpty (JavaPlatformJarPath) ? "" : Path.GetDirectoryName (JavaPlatformJarPath);
var parser = new FileResourceParser () { Log = Log, JavaPlatformDirectory = javaPlatformDirectory, ResourceFlagFile = ResourceFlagFile};
- var resources = parser.Parse (ResourceDirectory, AdditionalResourceDirectories, resource_fixup);
+ var resources = parser.Parse (ResourceDirectory, AdditionalResourceDirectories, AarLibraries, resource_fixup);
// only update if it changed.
writer.Write (RTxtFile, resources);
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 07e6be2bf72..4b3dfa5594a 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
@@ -1029,7 +1029,7 @@ public void BuildAppWithManagedResourceParserAndLibraries ()
Assert.LessOrEqual (libBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds.");
Assert.IsFalse (libProj.CreateBuildOutput (libBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"),
"Target '_ManagedUpdateAndroidResgen' should have run.");
- Assert.IsFalse (appBuilder.DesignTimeBuild (appProj), "Application project should have built");
+ Assert.IsTrue (appBuilder.DesignTimeBuild (appProj), "Application project should have built");
Assert.LessOrEqual (appBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds.");
Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"),
"Target '_ManagedUpdateAndroidResgen' should have run.");
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 14e72a467b4..7e7b749df8f 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
@@ -544,11 +544,8 @@ public void DesignTimeBuild (string classParser)
Assert.IsNotNull (element, "api.xml should contain an `api` element!");
Assert.IsTrue (element.HasElements, "api.xml should contain elements!");
- var assemblyFile = Path.Combine (intermediate, proj.ProjectName + ".dll");
- using (var assembly = AssemblyDefinition.ReadAssembly (assemblyFile)) {
- var typeName = "Com.Balysv.Material.Drawable.Menu.MaterialMenuView";
- Assert.IsTrue (assembly.MainModule.Types.Any (t => t.FullName == typeName), $"Type `{typeName}` should exist!");
- }
+ var sourceFile = Path.Combine (intermediate, "generated", "src", "Com.Balysv.Material.Drawable.Menu.MaterialMenuView.cs");
+ FileAssert.Exists (sourceFile, $"'{sourceFile}' should have been generated.");
}
}
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 47f6c3dbff5..48c1ed3685b 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
@@ -752,6 +752,7 @@ public void BuildAfterUpgradingNuget ()
}
[Test]
+ [Category ("SmokeTests")]
public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser)
{
var proj = new XamarinAndroidApplicationProject () {
@@ -762,20 +763,20 @@ public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser)
builder.Target = "UpdateAndroidResources";
builder.Build (proj, parameters: new string[] { "DesignTimeBuild=true" });
Assert.IsFalse (builder.Output.IsTargetSkipped ("_CreatePropertiesCache"), "target \"_CreatePropertiesCache\" should have been run.");
- Assert.IsFalse (builder.Output.IsTargetSkipped ("_ResolveLibraryProjectImports"), "target \"_ResolveLibraryProjectImports\' should have been run.");
+ Assert.IsFalse (builder.Output.IsTargetSkipped ("_GenerateRtxt"), "target \"_GenerateRtxt\' should have been run.");
var intermediate = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath);
- var librarycache = Path.Combine (intermediate, "designtime", "libraryprojectimports.cache");
- Assert.IsTrue (File.Exists (librarycache), $"'{librarycache}' should exist.");
- librarycache = Path.Combine (intermediate, "libraryprojectimports.cache");
- Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist.");
+ var rTxtFile = Path.Combine (intermediate, "designtime", "R.txt");
+ Assert.IsTrue (File.Exists (rTxtFile), $"'{rTxtFile}' should exist.");
+ rTxtFile = Path.Combine (intermediate, "R.txt");
+ Assert.IsFalse (File.Exists (rTxtFile), $"'{rTxtFile}' should not exist.");
builder.Build (proj, parameters: new string[] { "DesignTimeBuild=true" });
Assert.IsFalse (builder.Output.IsTargetSkipped ("_CreatePropertiesCache"), "target \"_CreatePropertiesCache\" should have been run.");
- Assert.IsTrue (builder.Output.IsTargetSkipped ("_ResolveLibraryProjectImports"), "target \"_ResolveLibraryProjectImports\' should have been skipped.");
+ Assert.IsTrue (builder.Output.IsTargetSkipped ("_GenerateRtxt"), "target \"_GenerateRtxt\' should have been skipped.");
Assert.IsTrue (builder.Clean (proj), "Clean Should have succeeded");
builder.Target = "_CleanDesignTimeIntermediateDir";
Assert.IsTrue (builder.Build (proj), "_CleanDesignTimeIntermediateDir should have succeeded");
- librarycache = Path.Combine (intermediate, "designtime", "libraryprojectimports.cache");
- Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist.");
+ rTxtFile = Path.Combine (intermediate, "designtime", "R.txt");
+ Assert.IsFalse (File.Exists (rTxtFile), $"'{rTxtFile}' should not exist.");
}
}
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 75f45a1d833..32b79d45e83 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
@@ -1199,17 +1199,26 @@ public void DesignTimeBuild ()
{
var proj = new XamarinAndroidApplicationProject ();
using (var b = CreateApkBuilder (Path.Combine ("temp", $"{nameof (IncrementalBuildTest)}{TestName}"))) {
+ b.BuildLogFile = "dtb1.log";
Assert.IsTrue (b.DesignTimeBuild (proj), "first dtb should have succeeded.");
- var target = "_ResolveLibraryProjectImports";
+ var target = "_GenerateResourceDesignerAssembly";
Assert.IsFalse (b.Output.IsTargetSkipped (target), $"`{target}` should not have been skipped.");
+ var importsTarget = "_ResolveLibraryProjectImports";
+ Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped.");
// DesignTimeBuild=true lowercased
var parameters = new [] { "DesignTimeBuild=true" };
+ b.BuildLogFile = "compile.log";
Assert.IsTrue (b.RunTarget (proj, "Compile", doNotCleanupOnUpdate: true, parameters: parameters), "second dtb should have succeeded.");
- Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should have been skipped.");
+ Assert.IsTrue (b.Output.IsTargetSkipped (target, defaultIfNotUsed: true), $"`{target}` should have been skipped.");
+ Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped.");
+ b.BuildLogFile = "updategeneratedfiles.log";
Assert.IsTrue (b.RunTarget (proj, "UpdateGeneratedFiles", doNotCleanupOnUpdate: true, parameters: parameters), "UpdateGeneratedFiles should have succeeded.");
- Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should have been skipped.");
+ Assert.IsTrue (b.Output.IsTargetSkipped (target, defaultIfNotUsed: true), $"`{target}` should have been skipped.");
+ Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped.");
+ b.BuildLogFile = "build.log";
Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "full build should have succeeded.");
Assert.IsFalse (b.Output.IsTargetSkipped (target), $"`{target}` should not have been skipped.");
+ Assert.IsFalse (b.Output.IsTargetSkipped (importsTarget), $"`{importsTarget}` should not have been skipped.");
}
}
@@ -1234,7 +1243,7 @@ public void DesignTimeBuildSignAndroidPackage ()
Assert.IsTrue (builder.RunTarget (proj, "SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed");
builder.Output.AssertTargetIsNotSkipped ("_GenerateResourceCaseMap", occurrence: 2);
builder.Output.AssertTargetIsSkipped ("_GenerateRtxt", occurrence: 1);
- builder.Output.AssertTargetIsSkipped ("_GenerateResourceDesignerIntermediateClass", occurrence: 1);
+ builder.Output.AssertTargetIsNotSkipped ("_GenerateResourceDesignerIntermediateClass");
builder.Output.AssertTargetIsSkipped ("_GenerateResourceDesignerAssembly", occurrence: 2);
builder.BuildLogFile = "build2.log";
Assert.IsTrue (builder.RunTarget (proj, "SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed 2");
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
index 1ce0280f232..1d3d5dca3fe 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
@@ -35,7 +35,9 @@ public void AssertCommercialBuild (bool fail = false)
{
if (!TestEnvironment.CommercialBuildAvailable) {
var message = $"'{TestName}' requires a commercial build of .NET for Android.";
- if (fail) {
+ var runningOnCI = false;
+ bool.TryParse (Environment.GetEnvironmentVariable ("RunningOnCI"), out runningOnCI);
+ if (fail || runningOnCI) {
Assert.Fail (message);
} else {
Assert.Ignore (message);
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs
index 514c16f7312..c601a43d897 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs
@@ -101,11 +101,12 @@ public bool UpdateAndroidResources (XamarinProject project, bool doNotCleanupOnU
public bool DesignTimeBuild (XamarinProject project, string target = "Compile", bool doNotCleanupOnUpdate = false, string [] parameters = null)
{
if (parameters == null) {
- return RunTarget (project, target, doNotCleanupOnUpdate, parameters: new string [] { "DesignTimeBuild=True" });
+ return RunTarget (project, target, doNotCleanupOnUpdate, parameters: new string [] { "DesignTimeBuild=True", "SkipCompilerExecution=true" });
} else {
- var designTimeParameters = new string [parameters.Length + 1];
+ var designTimeParameters = new string [parameters.Length + 2];
parameters.CopyTo (designTimeParameters, 0);
- designTimeParameters [parameters.Length] = "DesignTimeBuild=True";
+ designTimeParameters [designTimeParameters.Length - 2] = "DesignTimeBuild=True";
+ designTimeParameters [designTimeParameters.Length - 1] = "SkipCompilerExecution=true";
return RunTarget (project, target, doNotCleanupOnUpdate, parameters: designTimeParameters);
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs
index 52f4a8ba835..a52ce07494f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs
@@ -148,7 +148,17 @@ public static bool UseLocalBuildOutput {
}
}
- public static bool CommercialBuildAvailable => File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets"));
+ public static bool CommercialBuildAvailable {
+ get {
+ var result = File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets"));
+ Console.WriteLine ($"DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`: {result}.");
+ if (!result) {
+ Console.WriteLine ($"DEBUG! checking `{LocalDotNetAndroidSdkDirectory}\tools` for `Xamarin.Android.Common.Debugging.targets`: {result}.");
+ result = File.Exists (Path.Combine (LocalDotNetAndroidSdkDirectory, "tools", "Xamarin.Android.Common.Debugging.targets"));
+ }
+ return result;
+ }
+ }
public static string OSBinDirectory {
get {
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
index cfac54ddb42..a5e75a0e4be 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs
@@ -1,5 +1,6 @@
using System;
using System.CodeDom;
+using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -11,6 +12,7 @@
using System.Text.RegularExpressions;
using Microsoft.Build.Utilities;
using Microsoft.Android.Build.Tasks;
+using System.IO.Compression;
namespace Xamarin.Android.Tasks
{
@@ -43,7 +45,7 @@ protected XDocument LoadPublicXml () {
return null;
}
- public IList Parse (string resourceDirectory, IEnumerable additionalResourceDirectories, Dictionary resourceMap)
+ public IList Parse (string resourceDirectory, IEnumerable additionalResourceDirectories, IEnumerable aarLibraries, Dictionary resourceMap)
{
Log.LogDebugMessage ($"Parsing Directory {resourceDirectory}");
publicXml = LoadPublicXml ();
@@ -71,6 +73,40 @@ public IList Parse (string resourceDirectory, IEnumerable additionalR
Log.LogDebugMessage ($"Skipping non-existent directory: {dir}");
}
}
+ foreach (var aar in aarLibraries ?? Array.Empty()) {
+ Log.LogDebugMessage ($"Processing Aar file {aar}");
+ if (!File.Exists (aar)) {
+ Log.LogDebugMessage ($"Skipping non-existent aar: {aar}");
+ continue;
+ }
+ using (var file = File.Open (aar, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) {
+ using var zip = new ZipArchive (file);
+ foreach (var entry in zip.Entries) {
+ if (entry.IsDirectory ())
+ continue;
+ if (!entry.FullName.StartsWith ("res"))
+ continue;
+ var ext = Path.GetExtension (entry.FullName);
+ var path = Directory.GetParent (entry.FullName).Name;
+ if (ext == ".xml" || ext == ".axml") {
+ if (string.Compare (path, "raw", StringComparison.OrdinalIgnoreCase) != 0) {
+ var ms = MemoryStreamPool.Shared.Rent ();
+ try {
+ using (var entryStream = entry.Open ()) {
+ entryStream.CopyTo (ms);
+ }
+ ms.Position = 0;
+ using XmlReader reader = XmlReader.Create (ms);
+ ProcessXmlFile (reader, resources);
+ } finally {
+ MemoryStreamPool.Shared.Return (ms);
+ }
+ }
+ }
+ ProcessResourceFile (entry.FullName, resources, processXml: false);
+ }
+ }
+ }
// now generate the Id's we need in a specific order
List declarationIds = new List ();
@@ -172,7 +208,7 @@ int GetId (ICollection resources, string identifier)
return -1;
}
- void ProcessResourceFile (string file, Dictionary> resources)
+ void ProcessResourceFile (string file, Dictionary> resources, bool processXml = true)
{
Log.LogDebugMessage ($"{nameof(ProcessResourceFile)} {file}");
var fileName = Path.GetFileNameWithoutExtension (file);
@@ -181,6 +217,10 @@ void ProcessResourceFile (string file, Dictionary> resour
if (fileName.EndsWith (".9", StringComparison.OrdinalIgnoreCase))
fileName = Path.GetFileNameWithoutExtension (fileName);
var path = Directory.GetParent (file).Name;
+ if (!processXml) {
+ CreateResourceField (path, fileName, resources);
+ return;
+ }
var ext = Path.GetExtension (file);
switch (ext) {
case ".xml":
@@ -299,8 +339,6 @@ void ProcessStyleable (XmlReader reader, Dictionary> reso
fields.Add (r);
}
}
- if (field.Type != RType.Array)
- return;
arrayMapping.Add (field, fields.ToArray ());
field.Ids = new int [attribs.Count];
@@ -321,72 +359,81 @@ resources [field.ResourceTypeName].Add (new R () {
void ProcessXmlFile (string file, Dictionary> resources)
{
- Log.LogDebugMessage ($"{nameof(ProcessXmlFile)}");
using (var reader = XmlReader.Create (file)) {
- while (reader.Read ()) {
- if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment)
- continue;
- if (reader.IsStartElement ()) {
- var elementName = reader.Name;
- var elementNS = reader.NamespaceURI;
- if (!string.IsNullOrEmpty (elementNS)) {
- if (elementNS != "http://schemas.android.com/apk/res/android")
- continue;
- }
- if (elementName == "declare-styleable" || elementName == "configVarying" || elementName == "add-resource") {
- ProcessStyleable (reader.ReadSubtree (), resources);
+ ProcessXmlFile (reader, resources);
+ }
+ }
+
+ void ProcessXmlFile (XmlReader reader, Dictionary> resources)
+ {
+ Log.LogDebugMessage ($"{nameof(ProcessXmlFile)}");
+ while (reader.Read ()) {
+ if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment)
+ continue;
+ if (reader.IsStartElement ()) {
+ var elementName = reader.Name;
+ var elementNS = reader.NamespaceURI;
+ if (!string.IsNullOrEmpty (elementNS)) {
+ if (elementNS != "http://schemas.android.com/apk/res/android")
continue;
+ }
+ if (elementName == "declare-styleable" || elementName == "configVarying" || elementName == "add-resource") {
+ try {
+ ProcessStyleable (reader.ReadSubtree (), resources);
+ } catch (Exception ex) {
+ Log.LogErrorFromException (ex);
}
- if (reader.HasAttributes) {
- string name = null;
- string type = null;
- string id = null;
- string custom_id = null;
- while (reader.MoveToNextAttribute ()) {
- if (reader.LocalName == "name")
- name = reader.Value;
- if (reader.LocalName == "type")
- type = reader.Value;
- if (reader.LocalName == "id") {
- string[] values = reader.Value.Split ('/');
- if (values.Length != 2) {
- id = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
- } else {
- if (values [0] != "@+id" && values [0] != "@id" && !values [0].Contains ("android:")) {
- custom_id = values [0].Replace ("@", "").Replace ("+", "");
- }
- id = values [1];
+ continue;
+ }
+ if (reader.HasAttributes) {
+ string name = null;
+ string type = null;
+ string id = null;
+ string custom_id = null;
+ while (reader.MoveToNextAttribute ()) {
+ if (reader.LocalName == "name")
+ name = reader.Value;
+ if (reader.LocalName == "type")
+ type = reader.Value;
+ if (reader.LocalName == "id") {
+ string[] values = reader.Value.Split ('/');
+ if (values.Length != 2) {
+ id = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
+ } else {
+ if (values [0] != "@+id" && values [0] != "@id" && !values [0].Contains ("android:")) {
+ custom_id = values [0].Replace ("@", "").Replace ("+", "");
}
-
- }
- if (reader.LocalName == "inflatedId") {
- string inflateId = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
- var r = new R () {
- ResourceTypeName = "id",
- Identifier = inflateId,
- Id = -1,
- };
- Log.LogDebugMessage ($"Adding 1 {r}");
- resources[r.ResourceTypeName].Add (r);
+ id = values [1];
}
+
}
- if (name?.Contains ("android:") ?? false)
- continue;
- if (id?.Contains ("android:") ?? false)
- continue;
- // Move the reader back to the element node.
- reader.MoveToElement ();
- if (!string.IsNullOrEmpty (name)) {
- CreateResourceField (type ?? elementName, name, resources);
- }
- if (!string.IsNullOrEmpty (custom_id) && !resources.ContainsKey (custom_id)) {
- resources.Add (custom_id, new SortedSet (new RComparer ()));
- custom_types.Add (custom_id);
- }
- if (!string.IsNullOrEmpty (id)) {
- CreateResourceField (custom_id ?? "id", id.Replace ("-", "_").Replace (".", "_"), resources);
+ if (reader.LocalName == "inflatedId") {
+ string inflateId = reader.Value.Replace ("@+id/", "").Replace ("@id/", "");
+ var r = new R () {
+ ResourceTypeName = "id",
+ Identifier = inflateId,
+ Id = -1,
+ };
+ Log.LogDebugMessage ($"Adding 1 {r}");
+ resources[r.ResourceTypeName].Add (r);
}
}
+ if (name?.Contains ("android:") ?? false)
+ continue;
+ if (id?.Contains ("android:") ?? false)
+ continue;
+ // Move the reader back to the element node.
+ reader.MoveToElement ();
+ if (!string.IsNullOrEmpty (name)) {
+ CreateResourceField (type ?? elementName, name, resources);
+ }
+ if (!string.IsNullOrEmpty (custom_id) && !resources.ContainsKey (custom_id)) {
+ resources.Add (custom_id, new SortedSet (new RComparer ()));
+ custom_types.Add (custom_id);
+ }
+ if (!string.IsNullOrEmpty (id)) {
+ CreateResourceField (custom_id ?? "id", id.Replace ("-", "_").Replace (".", "_"), resources);
+ }
}
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/ZipArchiveEntryExtensions.cs b/src/Xamarin.Android.Build.Tasks/Utilities/ZipArchiveEntryExtensions.cs
new file mode 100644
index 00000000000..5d1743580c3
--- /dev/null
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/ZipArchiveEntryExtensions.cs
@@ -0,0 +1,8 @@
+using System;
+using System.IO.Compression;
+public static class ZipArchiveEntryExtensions {
+ public static bool IsDirectory (this ZipArchiveEntry entry)
+ {
+ return entry.Length == 0 && entry.FullName.EndsWith ("/", StringComparison.Ordinal);
+ }
+}
\ No newline at end of file
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index ba56eff5b92..65f767b5325 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -118,7 +118,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
-->
+ Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Installer.Common.props') And '$(DesignTimeBuild)' != 'true'"/>
@@ -361,7 +361,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
-
+
@@ -2865,14 +2865,14 @@ because xbuild doesn't support framework reference assemblies.
+ Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Android.Common.Debugging.targets') And '$(DesignTimeBuild)' != 'true' "/>
+ Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Installer.Common.targets') And '$(DesignTimeBuild)' != 'true' "/>