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
149 changes: 1 addition & 148 deletions build-tools/xaprepare/xaprepare/Application/Utilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -867,154 +867,7 @@ void LogError (string message)

public static string GetRelativePath (string relativeTo, string path)
{
return GetRelativePath (relativeTo, path, Context.Instance.OS.DefaultStringComparison);
return Xamarin.Android.Tools.PathUtil.GetRelativePath (relativeTo, path, Context.Instance.OS.DefaultStringComparison);
}

// Adapted from CoreFX sources
public static string GetRelativePath (string relativeTo, string path, StringComparison comparisonType)
{
if (String.IsNullOrEmpty (relativeTo))
throw new ArgumentException ("must not be null or empty", nameof (relativeTo));

if (String.IsNullOrEmpty (path))
throw new ArgumentException ("must not be null or empty", nameof (path));

relativeTo = Path.GetFullPath (relativeTo);
path = Path.GetFullPath (path);

// Need to check if the roots are different- if they are we need to return the "to" path.
if (!AreRootsEqual (relativeTo, path, comparisonType))
return path;

int commonLength = GetCommonPathLength (relativeTo, path, ignoreCase: comparisonType == StringComparison.OrdinalIgnoreCase);

// If there is nothing in common they can't share the same root, return the "to" path as is.
if (commonLength == 0)
return path;

// Trailing separators aren't significant for comparison
int relativeToLength = relativeTo.Length;
if (EndsInDirectorySeparator (relativeTo))
relativeToLength--;

bool pathEndsInSeparator = EndsInDirectorySeparator (path);
int pathLength = path.Length;
if (pathEndsInSeparator)
pathLength--;

// If we have effectively the same path, return "."
if (relativeToLength == pathLength && commonLength >= relativeToLength)
return ".";

// We have the same root, we need to calculate the difference now using the
// common Length and Segment count past the length.
//
// Some examples:
//
// C:\Foo C:\Bar L3, S1 -> ..\Bar
// C:\Foo C:\Foo\Bar L6, S0 -> Bar
// C:\Foo\Bar C:\Bar\Bar L3, S2 -> ..\..\Bar\Bar
// C:\Foo\Foo C:\Foo\Bar L7, S1 -> ..\Bar

var sb = new StringBuilder (Math.Max (relativeTo.Length, path.Length));

// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength) {
sb.Append ("..");

for (int i = commonLength + 1; i < relativeToLength; i++) {
if (IsDirectorySeparator (relativeTo[i])) {
sb.Append (Path.DirectorySeparatorChar);
sb.Append ("..");
}
}
} else if (IsDirectorySeparator (path[commonLength])) {
// No parent segments and we need to eat the initial separator
// (C:\Foo C:\Foo\Bar case)
commonLength++;
}

// Now add the rest of the "to" path, adding back the trailing separator
int differenceLength = pathLength - commonLength;
if (pathEndsInSeparator)
differenceLength++;

if (differenceLength > 0) {
if (sb.Length > 0) {
sb.Append (Path.DirectorySeparatorChar);
}

sb.Append(path, commonLength, differenceLength);
}

return sb.ToString ();
}

// Adapted from CoreFX sources
static bool AreRootsEqual (string first, string second, StringComparison comparisonType)
{
int firstRootLength = GetRootLength (first);
int secondRootLength = GetRootLength (second);

return firstRootLength == secondRootLength
&& String.Compare (
strA: first,
indexA: 0,
strB: second,
indexB: 0,
length: firstRootLength,
comparisonType: comparisonType) == 0;
}

// Adapted from CoreFX sources
static int GetCommonPathLength (string first, string second, bool ignoreCase)
{
int commonChars = EqualStartingCharacterCount (first, second, ignoreCase: ignoreCase);

// If nothing matches
if (commonChars == 0)
return commonChars;

// Or we're a full string and equal length or match to a separator
if (commonChars == first.Length && (commonChars == second.Length || IsDirectorySeparator (second[commonChars])))
return commonChars;

if (commonChars == second.Length && IsDirectorySeparator (first[commonChars]))
return commonChars;

// It's possible we matched somewhere in the middle of a segment e.g. C:\Foodie and C:\Foobar.
while (commonChars > 0 && !IsDirectorySeparator (first[commonChars - 1]))
commonChars--;

return commonChars;
}

// Adapted from CoreFX sources
static unsafe int EqualStartingCharacterCount (string first, string second, bool ignoreCase)
{
if (String.IsNullOrEmpty (first) || string.IsNullOrEmpty (second))
return 0;

int commonChars = 0;
fixed (char* f = first) {
fixed (char* s = second) {
char* l = f;
char* r = s;
char* leftEnd = l + first.Length;
char* rightEnd = r + second.Length;

while (l != leftEnd && r != rightEnd && (*l == *r || (ignoreCase && char.ToUpperInvariant ((*l)) == char.ToUpperInvariant ((*r))))) {
commonChars++;
l++;
r++;
}
}
}

return commonChars;
}

// Adapted from CoreFX sources
static bool EndsInDirectorySeparator (string path) => path.Length > 0 && IsDirectorySeparator (path[path.Length - 1]);
}
}
4 changes: 4 additions & 0 deletions build-tools/xaprepare/xaprepare/xaprepare.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@
<Compile Include="../../../tools/vswhere/VisualStudioInstance.cs" />
</ItemGroup>

<ItemGroup>
<Compile Include="../../../src/Xamarin.Android.Build.Tasks/Utilities/PathUtil.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="7-Zip.CommandLine" Version="18.1.0" GeneratePathProperty="true" />
<PackageReference Include="Kajabity.Tools.Java" Version="0.2.6862.30334" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,19 @@ It is shared between "legacy" binding projects and .NET 5 projects.
</PropertyGroup>
</Target>

<Target Name="_CollectGeneratedManagedBindingFiles">
<ItemGroup>
<_GeneratedManagedBindingFiles Include="$(GeneratedOutputPath)**\*.cs" />
</ItemGroup>
</Target>

<Target Name="_ClearGeneratedManagedBindings"
Condition=" '@(InputJar->Count())' == '0' And '@(EmbeddedJar->Count())' == '0' And '@(LibraryProjectZip->Count())' == '0' And '@(_JavaBindingSource->Count())' == '0' "
DependsOnTargets="_CollectGeneratedManagedBindingFiles"
>
<Delete Files="@(_GeneratedManagedBindingFiles)" />
</Target>

<Target Name="ExportJarToXml"
Condition=" '$(_AndroidGenerateManagedBindings)' == 'true' "
DependsOnTargets="$(ExportJarToXmlDependsOnTargets)">
Expand Down Expand Up @@ -107,14 +120,23 @@ It is shared between "legacy" binding projects and .NET 5 projects.
<!-- Write a flag so we won't redo this target if nothing changed -->
<Touch Files="$(_GeneratorStampFile)" AlwaysCreate="true" />

<ItemGroup>
<FileWrites Include="$(GeneratedOutputPath)**\*.cs" />
<FileWrites Include="$(_GeneratorStampFile)" />
</ItemGroup>

</Target>

<Target Name="AddBindingsToCompile"
Condition=" '$(_AndroidGenerateManagedBindings)' == 'true' "
DependsOnTargets="GenerateBindings">
Condition=" '$(_AndroidGenerateManagedBindings)' == 'true' Or '@(_GeneratedManagedBindingFiles->Count())' != '0' "
DependsOnTargets="GenerateBindings;_CollectGeneratedManagedBindingFiles">
<!-- bindings need AllowUnsafeBlocks -->
<PropertyGroup>
<AllowUnsafeBlocks Condition=" '$(AllowUnsafeBlocks)' != 'true' ">true</AllowUnsafeBlocks>
</PropertyGroup>
<!-- Add the files to list of things to be compiled -->
<ItemGroup>
<Compile Include="$(IntermediateOutputPath)generated\*\*.cs" />
<Compile Include="@(_GeneratedManagedBindingFiles)" Condition="Exists ('%(_GeneratedManagedBindingFiles.Identity)')" />
</ItemGroup>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ properties that determine build ordering.
_BuildResourceDesigner;
UpdateAndroidInterfaceProxies;
_SetAndroidGenerateManagedBindings;
_ClearGeneratedManagedBindings;
AddBindingsToCompile;
_CheckForInvalidDesignerConfig;
</ResolveReferencesDependsOn>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public State BeginPartialClassFile (StreamWriter writer, string bindingClassName
return state;
}

public abstract void SetCodeBehindDir (string path);

protected abstract void BeginPartialClassFile (State state, string classNamespace, string className);
public abstract void EndPartialClassFile (State state);
public abstract void WritePartialClassProperty (State state, LayoutWidget widget);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using System;
using System.IO;
using System.Linq;
using Xamarin.Android.Tasks.LLVMIR;
using Xamarin.Android.Tools;

namespace Xamarin.Android.Tasks
{
Expand All @@ -10,6 +12,7 @@ sealed class CSharpBindingGenerator : BindingGenerator
{
const string BindingPartialClassBackingFieldName = "__layout_binding";

string codebehindDir = string.Empty;
protected override string LineCommentString => "//";
protected override string DocCommentString => "///";
public override string LanguageName => "C#";
Expand All @@ -28,6 +31,11 @@ protected override void BeginPartialClassFile (State state, string classNamespac
state.WriteLine ();
}

public override void SetCodeBehindDir(string path)
{
codebehindDir = Path.GetFullPath (path);
}

public override void EndPartialClassFile (State state)
{
EndBindingFile (state); // currently they're identical
Expand Down Expand Up @@ -239,7 +247,8 @@ protected override void WriteLocationDirective (State state, LayoutWidget widget
if (loc == null)
return;

WriteLineIndent (state, $"#line {loc.Line} \"{loc.FilePath}\"");
var relativePath = PathUtil.GetRelativePath (codebehindDir, Path.GetFullPath (loc.FilePath));
WriteLineIndent (state, $"#line {loc.Line} \"{relativePath}\"");
state.WriteLine ();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ public async override System.Threading.Tasks.Task RunTaskAsync ()
return;
}

generator.SetCodeBehindDir (MonoAndroidCodeBehindDir);

LogDebugMessage ($"Generating {generator.LanguageName} binding sources");

var layoutGroups = new Dictionary <string, LayoutGroup> (StringComparer.Ordinal);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1247,9 +1247,9 @@ protected override void OnCreate (Bundle bundle)
proj.SetProperty ("AndroidGenerateLayoutBindings", "True");
using (var builder = CreateApkBuilder (path)) {
Assert.IsTrue (builder.Build (proj), "Build should have succeeded.");
FileAssert.Exists (Path.Combine (Root, path, proj.IntermediateOutputPath, "generated", "Binding.Main.g.cs"));
FileAssert.Exists (Path.Combine (Root, path, proj.IntermediateOutputPath, "codebehind", "Binding.Main.g.cs"));
Assert.IsTrue (builder.Build (proj), "Second build should have succeeded.");
FileAssert.Exists (Path.Combine (Root, path, proj.IntermediateOutputPath, "generated", "Binding.Main.g.cs"));
FileAssert.Exists (Path.Combine (Root, path, proj.IntermediateOutputPath, "codebehind", "Binding.Main.g.cs"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ public void AppWithSingleJar ()

var builder = CreateApkBuilder ();
Assert.IsTrue (builder.Build (proj), "first build should succeed");
Assert.IsTrue (builder.DesignTimeBuild (proj), "Design time build should succeed.");
Assert.IsFalse (builder.Output.IsTargetSkipped ("AddBindingsToCompile"), "AddBindingsToCompile should run.");

var assemblyPath = Path.Combine (Root, builder.ProjectDirectory, proj.OutputPath, $"{proj.ProjectName}.dll");
var typeName = "Com.Xamarin.Android.Test.Msbuildtest.JavaSourceJarTest";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public TestProjectInfo (string projectName, string testName, string rootDirector
ProjectName = projectName;

ObjPath = Path.Combine (rootDirectory, "obj");
GeneratedPath = Path.Combine (ObjPath, XABuildPaths.Configuration, "generated");
GeneratedPath = Path.Combine (ObjPath, XABuildPaths.Configuration, "codebehind");
BinPath = Path.Combine (rootDirectory, "bin", XABuildPaths.Configuration);
ProjectPath = Path.Combine (rootDirectory, $"{projectName}.csproj");

Expand Down
Loading