Skip to content
Merged
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
70 changes: 2 additions & 68 deletions build-tools/xaprepare/xaprepare/Steps/Step_Get_Windows_Binutils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using System.Text;
using System.Threading.Tasks;

using Force.Crc32;

namespace Xamarin.Android.Prepare
{
class Step_Get_Windows_Binutils : Step
Expand Down Expand Up @@ -679,72 +681,4 @@ uint ReadUInt (BinaryReader br, long dataLength, ref long nread, out bool succes
return (true, resp.Content.Headers.ContentLength.Value);
}
}

//
// Taken from:
// https://github.com/force-net/Crc32.NET/blob/fbc1061b0cb53df2322d5aed33167a2e6335970b/Crc32.NET/SafeProxy.cs
//
// License: MIT
// https://github.com/force-net/Crc32.NET/blob/fbc1061b0cb53df2322d5aed33167a2e6335970b/LICENSE
//
class CRC32
{
const uint Poly = 0xedb88320u;

readonly uint[] _table = new uint[16 * 256];

internal CRC32 ()
{
Init (Poly);
}

protected void Init (uint poly)
{
var table = _table;
for (uint i = 0; i < 256; i++) {
uint res = i;
for (int t = 0; t < 16; t++) {
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? poly ^ (res >> 1) : (res >> 1);
table[(t * 256) + i] = res;
}
}
}

public uint Append (uint crc, byte[] input, int offset, int length)
{
uint crcLocal = uint.MaxValue ^ crc;

uint[] table = _table;
while (length >= 16) {
var a = table[(3 * 256) + input[offset + 12]]
^ table[(2 * 256) + input[offset + 13]]
^ table[(1 * 256) + input[offset + 14]]
^ table[(0 * 256) + input[offset + 15]];

var b = table[(7 * 256) + input[offset + 8]]
^ table[(6 * 256) + input[offset + 9]]
^ table[(5 * 256) + input[offset + 10]]
^ table[(4 * 256) + input[offset + 11]];

var c = table[(11 * 256) + input[offset + 4]]
^ table[(10 * 256) + input[offset + 5]]
^ table[(9 * 256) + input[offset + 6]]
^ table[(8 * 256) + input[offset + 7]];

var d = table[(15 * 256) + ((byte)crcLocal ^ input[offset])]
^ table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])]
^ table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])]
^ table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])];

crcLocal = d ^ c ^ b ^ a;
offset += 16;
length -= 16;
}

while (--length >= 0)
crcLocal = table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8;

return crcLocal ^ uint.MaxValue;
}
}
}
3 changes: 3 additions & 0 deletions build-tools/xaprepare/xaprepare/xaprepare.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,9 @@
<Compile Include="Steps\Step_PrepareExternal.Windows.cs" />
<Compile Include="Steps\Step_PrepareExternalJavaInterop.Windows.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\src-ThirdParty\crc32.net\SafeProxy.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="app.manifest">
Expand Down
97 changes: 97 additions & 0 deletions src-ThirdParty/android-platform-tools-base/SymbolWriter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Xamarin.Android.Tools;
using Xamarin.Build;

namespace Xamarin.Android.Tasks
{
public partial class GenerateLibraryResources
{
/// <summary>
/// NOTE: all file paths used in this method should be full paths. (Or use AsyncTask.WorkingDirectory)
/// </summary>
void GenerateJava (Package package)
{
// In some cases (such as ancient support libraries), R.txt does not exist.
// We can just use the main app's R.txt file and write *all fields* in this case.
foreach (var r_txt in package.TextFiles) {
if (!File.Exists (r_txt)) {
LogDebugMessage ($"Using main R.txt, R.txt does not exist: {r_txt}");
package.TextFiles.Clear ();
package.TextFiles.Add (main_r_txt);
break;
}
}

var lines = LoadValues (package);
using (var writer = MemoryStreamPool.Shared.CreateStreamWriter ()) {
// This code is based on the Android gradle plugin
// https://android.googlesource.com/platform/tools/base/+/908b391a9c006af569dfaff08b37f8fdd6c4da89/build-system/builder/src/main/java/com/android/builder/internal/SymbolWriter.java

writer.WriteLine ("/* AUTO-GENERATED FILE. DO NOT MODIFY.");
writer.WriteLine (" *");
writer.WriteLine (" * This class was automatically generated by");
writer.WriteLine (" * Xamarin.Android from the resource data it found.");
writer.WriteLine (" * It should not be modified by hand.");
writer.WriteLine (" */");

writer.Write ("package ");
writer.Write (package.Name);
writer.WriteLine (';');
writer.WriteLine ();
writer.WriteLine ("public final class R {");

string currentClass = null;
foreach (var line in lines) {
var type = line [Index.Type];
var clazz = line [Index.Class];
var name = line [Index.Name];
var value = line [Index.Value];
if (clazz != currentClass) {
// If not the first inner class
if (currentClass != null) {
writer.WriteLine ("\t}");
}

currentClass = clazz;
writer.Write ("\tpublic static final class ");
writer.Write (currentClass);
writer.WriteLine (" {");
}

writer.Write ("\t\tpublic static final ");
writer.Write (type);
writer.Write (' ');
writer.Write (name);
writer.Write (" = ");
// It may be an int[]
if (value.StartsWith ("{", StringComparison.Ordinal)) {
writer.Write ("new ");
writer.Write (type);
writer.Write (' ');
}
writer.Write (value);
writer.WriteLine (';');
}

// If we wrote at least one inner class
if (currentClass != null) {
writer.WriteLine ("\t}");
}
writer.WriteLine ('}');

writer.Flush ();
var r_java = Path.Combine (output_directory, package.Name.Replace ('.', Path.DirectorySeparatorChar), "R.java");
if (MonoAndroidHelper.CopyIfStreamChanged (writer.BaseStream, r_java)) {
LogDebugMessage ($"Writing: {r_java}");
} else {
LogDebugMessage ($"Up to date: {r_java}");
}
}
}
}
}
85 changes: 85 additions & 0 deletions src-ThirdParty/crc32.net/SafeProxy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//
// Taken from:
// https://github.com/force-net/Crc32.NET/blob/fbc1061b0cb53df2322d5aed33167a2e6335970b/Crc32.NET/SafeProxy.cs
//
// License: MIT
// https://github.com/force-net/Crc32.NET/blob/fbc1061b0cb53df2322d5aed33167a2e6335970b/LICENSE
//

/* This is .NET safe implementation of Crc32 algorithm.
* This implementation was investigated as fastest from different variants. It based on Robert Vazan native implementations of Crc32C
* Also, it is good for x64 and for x86, so, it seems, there is no sense to do 2 different realizations.
*
* Addition: some speed increase was found with splitting xor to 4 independent blocks. Also, some attempts to optimize unaligned tails was unsuccessfull (JIT limitations?).
*
*
* Max Vysokikh, 2016-2017
*/

namespace Force.Crc32
{
class CRC32 : SafeProxy
{
}

internal class SafeProxy
{
const uint Poly = 0xedb88320u;

readonly uint[] _table = new uint[16 * 256];

internal SafeProxy ()
{
Init (Poly);
}

protected void Init (uint poly)
{
var table = _table;
for (uint i = 0; i < 256; i++) {
uint res = i;
for (int t = 0; t < 16; t++) {
for (int k = 0; k < 8; k++) res = (res & 1) == 1 ? poly ^ (res >> 1) : (res >> 1);
table[(t * 256) + i] = res;
}
}
}

public uint Append (uint crc, byte[] input, int offset, int length)
{
uint crcLocal = uint.MaxValue ^ crc;

uint[] table = _table;
while (length >= 16) {
var a = table[(3 * 256) + input[offset + 12]]
^ table[(2 * 256) + input[offset + 13]]
^ table[(1 * 256) + input[offset + 14]]
^ table[(0 * 256) + input[offset + 15]];

var b = table[(7 * 256) + input[offset + 8]]
^ table[(6 * 256) + input[offset + 9]]
^ table[(5 * 256) + input[offset + 10]]
^ table[(4 * 256) + input[offset + 11]];

var c = table[(11 * 256) + input[offset + 4]]
^ table[(10 * 256) + input[offset + 5]]
^ table[(9 * 256) + input[offset + 6]]
^ table[(8 * 256) + input[offset + 7]];

var d = table[(15 * 256) + ((byte)crcLocal ^ input[offset])]
^ table[(14 * 256) + ((byte)(crcLocal >> 8) ^ input[offset + 1])]
^ table[(13 * 256) + ((byte)(crcLocal >> 16) ^ input[offset + 2])]
^ table[(12 * 256) + ((crcLocal >> 24) ^ input[offset + 3])];

crcLocal = d ^ c ^ b ^ a;
offset += 16;
length -= 16;
}

while (--length >= 0)
crcLocal = table[(byte)(crcLocal ^ input[offset++])] ^ crcLocal >> 8;

return crcLocal ^ uint.MaxValue;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Xamarin.Android.Tasks
/// <summary>
/// We used to invoke aapt/aapt2 per library (many times!), this task does the work to generate R.java for libraries without calling aapt/aapt2.
/// </summary>
public class GenerateLibraryResources : AndroidAsyncTask
public partial class GenerateLibraryResources : AndroidAsyncTask
{
public override string TaskPrefix => "GLR";

Expand Down Expand Up @@ -97,89 +97,6 @@ class Package
public string Name { get; set; }
}

/// <summary>
/// NOTE: all file paths used in this method should be full paths. (Or use AsyncTask.WorkingDirectory)
/// </summary>
void GenerateJava (Package package)
{
// In some cases (such as ancient support libraries), R.txt does not exist.
// We can just use the main app's R.txt file and write *all fields* in this case.
foreach (var r_txt in package.TextFiles) {
if (!File.Exists (r_txt)) {
LogDebugMessage ($"Using main R.txt, R.txt does not exist: {r_txt}");
package.TextFiles.Clear ();
package.TextFiles.Add (main_r_txt);
break;
}
}

var lines = LoadValues (package);
using (var writer = MemoryStreamPool.Shared.CreateStreamWriter ()) {
// This code is based on the Android gradle plugin
// https://android.googlesource.com/platform/tools/base/+/908b391a9c006af569dfaff08b37f8fdd6c4da89/build-system/builder/src/main/java/com/android/builder/internal/SymbolWriter.java

writer.WriteLine ("/* AUTO-GENERATED FILE. DO NOT MODIFY.");
writer.WriteLine (" *");
writer.WriteLine (" * This class was automatically generated by");
writer.WriteLine (" * Xamarin.Android from the resource data it found.");
writer.WriteLine (" * It should not be modified by hand.");
writer.WriteLine (" */");

writer.Write ("package ");
writer.Write (package.Name);
writer.WriteLine (';');
writer.WriteLine ();
writer.WriteLine ("public final class R {");

string currentClass = null;
foreach (var line in lines) {
var type = line [Index.Type];
var clazz = line [Index.Class];
var name = line [Index.Name];
var value = line [Index.Value];
if (clazz != currentClass) {
// If not the first inner class
if (currentClass != null) {
writer.WriteLine ("\t}");
}

currentClass = clazz;
writer.Write ("\tpublic static final class ");
writer.Write (currentClass);
writer.WriteLine (" {");
}

writer.Write ("\t\tpublic static final ");
writer.Write (type);
writer.Write (' ');
writer.Write (name);
writer.Write (" = ");
// It may be an int[]
if (value.StartsWith ("{", StringComparison.Ordinal)) {
writer.Write ("new ");
writer.Write (type);
writer.Write (' ');
}
writer.Write (value);
writer.WriteLine (';');
}

// If we wrote at least one inner class
if (currentClass != null) {
writer.WriteLine ("\t}");
}
writer.WriteLine ('}');

writer.Flush ();
var r_java = Path.Combine (output_directory, package.Name.Replace ('.', Path.DirectorySeparatorChar), "R.java");
if (MonoAndroidHelper.CopyIfStreamChanged (writer.BaseStream, r_java)) {
LogDebugMessage ($"Writing: {r_java}");
} else {
LogDebugMessage ($"Up to date: {r_java}");
}
}
}

/// <summary>
/// There can be multiple AndroidManifest.xml with the same package name.
/// We must merge the combination of the resource IDs to be generated in a "merged" R.java file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,15 @@
</Compile>
</ItemGroup>

<ItemGroup>
<Compile Include="..\..\src-ThirdParty\android-platform-tools-base\PackagingUtils.cs">
<Link>Utilities\%(Filename)%(Extension)</Link>
</Compile>
<Compile Include="..\..\src-ThirdParty\android-platform-tools-base\SymbolWriter.cs">
<Link>Utilities\%(Filename)%(Extension)</Link>
</Compile>
</ItemGroup>

<ItemGroup>
<None Include="Resources\LayoutBinding.cs">
<Link>LayoutBinding.cs</Link>
Expand Down
Loading