Skip to content

Use AssemblyLoadContext to customize native dependency load #50

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 15, 2018
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
6 changes: 6 additions & 0 deletions SourceLink.sln
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SourceLink.GitHub
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.SourceLink.Vsts.Git.UnitTests", "src\SourceLink.Vsts.Git.UnitTests\Microsoft.SourceLink.Vsts.Git.UnitTests.csproj", "{60C82684-6A13-4AEF-A4F5-C429BEDE1913}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Build.Tasks.Git.Operations", "src\Microsoft.Build.Tasks.Git.Operations\Microsoft.Build.Tasks.Git.Operations.csproj", "{BC24CED9-324E-4AF9-939F-BDB0C2C5F644}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -87,6 +89,10 @@ Global
{60C82684-6A13-4AEF-A4F5-C429BEDE1913}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60C82684-6A13-4AEF-A4F5-C429BEDE1913}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60C82684-6A13-4AEF-A4F5-C429BEDE1913}.Release|Any CPU.Build.0 = Release|Any CPU
{BC24CED9-324E-4AF9-939F-BDB0C2C5F644}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BC24CED9-324E-4AF9-939F-BDB0C2C5F644}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BC24CED9-324E-4AF9-939F-BDB0C2C5F644}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BC24CED9-324E-4AF9-939F-BDB0C2C5F644}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
24 changes: 14 additions & 10 deletions eng/SignToolData.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,27 @@
"certificate": "MicrosoftSHA2",
"strongName": "MsSharedLib72",
"values": [
"bin/Microsoft.Build.Tasks.Git/net461/Microsoft.Build.Tasks.Git.dll",
"bin/Microsoft.Build.Tasks.Git/net461/*/Microsoft.Build.Tasks.Git.resources.dll",
"bin/Microsoft.Build.Tasks.Git/netcoreapp2.0/Microsoft.Build.Tasks.Git.dll",
"bin/Microsoft.Build.Tasks.Git/netcoreapp2.0/*/Microsoft.Build.Tasks.Git.resources.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/net461/Microsoft.Build.Tasks.Git.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/net461/Microsoft.Build.Tasks.Git.Operations.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/net461/*/Microsoft.Build.Tasks.Git.resources.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/netcoreapp2.0/publish/Microsoft.Build.Tasks.Git.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/netcoreapp2.0/publish/Microsoft.Build.Tasks.Git.Operations.dll",
"bin/Microsoft.Build.Tasks.Git.Operations/netcoreapp2.0/publish/*/Microsoft.Build.Tasks.Git.resources.dll",
"bin/Microsoft.Build.Tasks.Tfvc/net46/Microsoft.Build.Tasks.Tfvc.dll",
"bin/Microsoft.SourceLink.Common/net461/Microsoft.SourceLink.Common.dll",
"bin/Microsoft.SourceLink.Common/net461/*/Microsoft.SourceLink.Common.resources.dll",
"bin/Microsoft.SourceLink.Common/netcoreapp2.0/Microsoft.SourceLink.Common.dll",
"bin/Microsoft.SourceLink.Common/netcoreapp2.0/*/Microsoft.SourceLink.Common.resources.dll",
"bin/Microsoft.SourceLink.Common/netcoreapp2.0/publish/Microsoft.SourceLink.Common.dll",
"bin/Microsoft.SourceLink.Common/netcoreapp2.0/publish/*/Microsoft.SourceLink.Common.resources.dll",
"bin/Microsoft.SourceLink.GitHub/net461/Microsoft.SourceLink.GitHub.dll",
"bin/Microsoft.SourceLink.GitHub/net461/*/Microsoft.SourceLink.GitHub.resources.dll",
"bin/Microsoft.SourceLink.GitHub/netcoreapp2.0/Microsoft.SourceLink.GitHub.dll",
"bin/Microsoft.SourceLink.GitHub/netcoreapp2.0/*/Microsoft.SourceLink.GitHub.resources.dll",
"bin/Microsoft.SourceLink.GitHub/netcoreapp2.0/publish/Microsoft.SourceLink.GitHub.dll",
"bin/Microsoft.SourceLink.GitHub/netcoreapp2.0/publish/*/Microsoft.SourceLink.GitHub.resources.dll",
"bin/Microsoft.SourceLink.Vsts.Git/net461/Microsoft.SourceLink.Vsts.Git.dll",
"bin/Microsoft.SourceLink.Vsts.Git/netcoreapp2.0/Microsoft.SourceLink.Vsts.Git.dll",
"bin/Microsoft.SourceLink.Vsts.Git/net461/*/Microsoft.SourceLink.Vsts.Git.resources.dll",
"bin/Microsoft.SourceLink.Vsts.Git/netcoreapp2.0/publish/Microsoft.SourceLink.Vsts.Git.dll",
"bin/Microsoft.SourceLink.Vsts.Git/netcoreapp2.0/publish/*/Microsoft.SourceLink.Vsts.Git.resources.dll",
"bin/Microsoft.SourceLink.Vsts.Tfvc/net461/Microsoft.SourceLink.Vsts.Tfvc.dll",
"bin/Microsoft.SourceLink.Vsts.Tfvc/netcoreapp2.0/Microsoft.SourceLink.Vsts.Tfvc.dll"
"bin/Microsoft.SourceLink.Vsts.Tfvc/netcoreapp2.0/publish/Microsoft.SourceLink.Vsts.Tfvc.dll"
]
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using LibGit2Sharp;
using Microsoft.Build.Framework;
Expand All @@ -17,50 +19,6 @@ internal static class GitOperations
{
private const string SourceControlName = "git";

static GitOperations()
{
// .NET Core apps that depend on native libraries load them directly from paths specified
// in .deps.json file of that app and the native library loader just works.
// However, .NET Core currently doesn't support .deps.json for plugins such as msbuild tasks.
if (IsRunningOnNetCore())
{
var dir = Path.GetDirectoryName(typeof(GitOperations).Assembly.Location);
GlobalSettings.NativeLibraryPath = Path.Combine(dir, "runtimes", GetNativeLibraryRuntimeId(), "native");
}
}

/// <summary>
/// Returns true if the runtime is .NET Core.
/// </summary>
private static bool IsRunningOnNetCore()
=> typeof(object).Assembly.GetName().Name != "mscorlib";

/// <summary>
/// Determines the RID to use when loading libgit2 native library.
/// This method only supports RIDs that are currently used by LibGit2Sharp.NativeBinaries.
/// </summary>
private static string GetNativeLibraryRuntimeId()
{
var processorArchitecture = IntPtr.Size == 8 ? "x64" : "x86";

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
return "win7-" + processorArchitecture;
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
return "osx";
}

if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
return "linux-" + processorArchitecture;
}

throw new PlatformNotSupportedException();
}

public static string LocateRepository(string directory)
{
// Repository.Discover returns the path to .git directory for repositories with a working directory.
Expand All @@ -69,7 +27,7 @@ public static string LocateRepository(string directory)
return Repository.Discover(directory);
}

public static string GetRepositoryUrl(this IRepository repository, string remoteName = null)
public static string GetRepositoryUrl(IRepository repository, string remoteName = null)
{
var remotes = repository.Network.Remotes;
var remote = string.IsNullOrEmpty(remoteName) ? (remotes["origin"] ?? remotes.FirstOrDefault()) : remotes[remoteName];
Expand Down Expand Up @@ -153,7 +111,7 @@ private static bool TryParseScp(string value, out Uri uri)
return Uri.TryCreate(url, UriKind.Absolute, out uri);
}

public static string GetRevisionId(this IRepository repository)
public static string GetRevisionId(IRepository repository)
{
// An empty repository doesn't have a tip commit:
return repository.Head.Tip?.Sha;
Expand All @@ -178,7 +136,7 @@ private static bool SubmodulesSupported(IRepository repository, Func<string, boo
return true;
}

public static ITaskItem[] GetSourceRoots(this IRepository repository, Action<string, object[]> logWarning, Func<string, bool> fileExists)
public static ITaskItem[] GetSourceRoots(IRepository repository, Action<string, object[]> logWarning, Func<string, bool> fileExists)
{
var result = new List<TaskItem>();
var repoRoot = GetRepositoryRoot(repository);
Expand Down Expand Up @@ -249,14 +207,14 @@ public static ITaskItem[] GetSourceRoots(this IRepository repository, Action<str
return result.ToArray();
}

private static string GetRepositoryRoot(this IRepository repository)
private static string GetRepositoryRoot(IRepository repository)
{
Debug.Assert(!repository.Info.IsBare);
return Path.GetFullPath(repository.Info.WorkingDirectory).EndWithSeparator();
}

public static ITaskItem[] GetUntrackedFiles(
this IRepository repository,
IRepository repository,
ITaskItem[] files,
string projectDirectory,
Func<string, IRepository> repositoryFactory)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="RoslynTools.RepoToolset">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.0;net461</TargetFrameworks>

<!-- Using an explicit nuspec file since NuGet Pack target currently doesn't support including dependencies in tools packages -->
<IsPackable>true</IsPackable>
<PackageId>Microsoft.Build.Tasks.Git</PackageId>
<NuspecFile>Microsoft.Build.Tasks.Git.nuspec</NuspecFile>
<NuspecBasePath>$(OutputPath)</NuspecBasePath>

<Description>MSBuild tasks providing git repository information.</Description>
<PackageTags>MSBuild Tasks source control git</PackageTags>
<DevelopmentDependency>true</DevelopmentDependency>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="LibGit2Sharp" Version="$(LibGit2SharpVersion)" />
<PackageReference Include="Microsoft.Build" Version="$(MicrosoftBuildVersion)" />
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildTasksCore)" />
</ItemGroup>
<ItemGroup>
<InternalsVisibleTo Include="Microsoft.Build.Tasks.Git.UnitTests" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Build.Tasks.Git\Microsoft.Build.Tasks.Git.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,12 @@
<file src="netcoreapp2.0\publish\runtimes\osx\native\*.dylib" target="tools\netcoreapp2.0\runtimes\osx\native" />
<file src="netcoreapp2.0\publish\runtimes\win7-x86\native\*.dll" target="tools\netcoreapp2.0\runtimes\win7-x86\native" />
<file src="netcoreapp2.0\publish\runtimes\win7-x64\native\*.dll" target="tools\netcoreapp2.0\runtimes\win7-x64\native" />

<!--
Workaround for Core CLR loader bug on Linux/MacOS: DllImport doesn't seem to be able to find libraries that are already
loaded explicitly from a path. They must be next to the dll. This is gonna break once we have support for more Linux flavors.
-->
<file src="netcoreapp2.0\publish\runtimes\linux-x64\native\*.so" target="tools\netcoreapp2.0" />
<file src="netcoreapp2.0\publish\runtimes\osx\native\*.dylib" target="tools\netcoreapp2.0" />

<file src="netcoreapp2.0\publish\LibGit2Sharp.dll" target="tools\netcoreapp2.0" />
<file src="netcoreapp2.0\publish\Microsoft.Build.Tasks.Git.*" target="tools\netcoreapp2.0" />
<file src="netcoreapp2.0\publish\LibGit2Sharp.dll" target="tools\netcoreapp2.0" />
<file src="netcoreapp2.0\publish\Microsoft.Build.Tasks.Git.dll" target="tools\netcoreapp2.0" />
<file src="netcoreapp2.0\publish\**\Microsoft.Build.Tasks.Git.resources.dll" target="tools\netcoreapp2.0" />

<file src="net461\Microsoft.Build.Tasks.Git.*" target="tools\net461" />
<file src="net461\**\Microsoft.Build.Tasks.Git.resources.dll" target="tools\net461" />
<file src="net461\LibGit2Sharp.*" target="tools\net461" />
<file src="net461\lib\**\*.dll" target="tools\net461\lib" />
<file src="net461\lib\**\*.so" target="tools\net461\lib" />
Expand Down
84 changes: 84 additions & 0 deletions src/Microsoft.Build.Tasks.Git.Operations/RepositoryTasks.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System;
using System.IO;
using LibGit2Sharp;

namespace Microsoft.Build.Tasks.Git
{
internal static class RepositoryTasks
{
private static bool Execute<T>(T task, Action<Repository, T> action)
where T: RepositoryTask
{
var log = task.Log;

Repository repo;
try
{
repo = new Repository(task.LocalRepositoryId);
}
catch (RepositoryNotFoundException e)
{
log.LogErrorFromException(e);
return false;
}

if (repo.Info.IsBare)
{
log.LogError(Resources.BareRepositoriesNotSupported, task.LocalRepositoryId);
return false;
}

using (repo)
{
try
{
action(repo, task);
}
catch (LibGit2SharpException e)
{
log.LogErrorFromException(e);
}
}

return !log.HasLoggedErrors;
}

public static bool LocateRepository(LocateRepository task)
{
task.Id = GitOperations.LocateRepository(task.Directory);

if (task.Id == null)
{
task.Log.LogError(Resources.UnableToLocateRepository, task.Directory);
}

return !task.Log.HasLoggedErrors;
}

public static bool GetRepositoryUrl(GetRepositoryUrl task) =>
Execute(task, (repo, t) =>
{
t.Url = GitOperations.GetRepositoryUrl(repo, t.RemoteName);
});

public static bool GetSourceRevisionId(GetSourceRevisionId task) =>
Execute(task, (repo, t) =>
{
t.RevisionId = GitOperations.GetRevisionId(repo);
});

public static bool GetSourceRoots(GetSourceRoots task) =>
Execute(task, (repo, t) =>
{
t.Roots = GitOperations.GetSourceRoots(repo, t.Log.LogWarning, File.Exists);
});

public static bool GetUntrackedFiles(GetUntrackedFiles task) =>
Execute(task, (repo, t) =>
{
t.UntrackedFiles = GitOperations.GetUntrackedFiles(repo, t.Files, t.ProjectDirectory, dir => new Repository(dir));
});
}
}
4 changes: 2 additions & 2 deletions src/Microsoft.Build.Tasks.Git.UnitTests/GitOperationsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ public void GetUntrackedFiles_ProjectInMainRepoIncludesFilesInSubmodules()
{ subRoot2, new TestRepository(subRoot2, commitSha: null, ignoredPaths: new[] { gitRoot + @"/sub/2/obj/b.cs" }) },
};

var actual = repo.GetUntrackedFiles(
var actual = GitOperations.GetUntrackedFiles(repo,
new[]
{
new MockItem(@"c.cs"), // not ignored
Expand Down Expand Up @@ -523,7 +523,7 @@ public void GetUntrackedFiles_ProjectInSubmodule()
{ subRoot2, new TestRepository(subRoot2, commitSha: null, ignoredPaths: new[] { gitRoot + "/sub/2/obj/b.cs" }) },
};

var actual = repo.GetUntrackedFiles(
var actual = GitOperations.GetUntrackedFiles(repo,
new[]
{
new MockItem(@"c.cs"), // not ignored
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<TargetFrameworks>net461;netcoreapp2.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Microsoft.Build.Tasks.Git.Operations\Microsoft.Build.Tasks.Git.Operations.csproj" />
<ProjectReference Include="..\Microsoft.Build.Tasks.Git\Microsoft.Build.Tasks.Git.csproj" />
<ProjectReference Include="..\TestUtilities\TestUtilities.csproj" />
</ItemGroup>
Expand Down
8 changes: 2 additions & 6 deletions src/Microsoft.Build.Tasks.Git/GetRepositoryUrl.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using LibGit2Sharp;
using Microsoft.Build.Framework;

namespace Microsoft.Build.Tasks.Git
Expand All @@ -10,11 +9,8 @@ public sealed class GetRepositoryUrl : RepositoryTask
public string RemoteName { get; set; }

[Output]
public string Url { get; private set; }
public string Url { get; internal set; }

protected override void Execute(Repository repo)
{
Url = repo.GetRepositoryUrl(RemoteName);
}
public override bool Execute() => TaskImplementation.GetRepositoryUrl(this);
}
}
8 changes: 2 additions & 6 deletions src/Microsoft.Build.Tasks.Git/GetSourceRevisionId.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,14 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using LibGit2Sharp;
using Microsoft.Build.Framework;

namespace Microsoft.Build.Tasks.Git
{
public sealed class GetSourceRevisionId : RepositoryTask
{
[Output]
public string RevisionId { get; private set; }
public string RevisionId { get; internal set; }

protected override void Execute(Repository repo)
{
RevisionId = repo.GetRevisionId();
}
public override bool Execute() => TaskImplementation.GetSourceRevisionId(this);
}
}
9 changes: 2 additions & 7 deletions src/Microsoft.Build.Tasks.Git/GetSourceRoots.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using LibGit2Sharp;
using Microsoft.Build.Framework;
using System.IO;

namespace Microsoft.Build.Tasks.Git
{
Expand All @@ -20,11 +18,8 @@ public sealed class GetSourceRoots : RepositoryTask
/// NestedRoot: For a submodule root, a path of the submodule root relative to the repository root. Ends with a slash.
/// </summary>
[Output]
public ITaskItem[] Roots { get; private set; }
public ITaskItem[] Roots { get; internal set; }

protected override void Execute(Repository repo)
{
Roots = repo.GetSourceRoots(Log.LogWarning, File.Exists);
}
public override bool Execute() => TaskImplementation.GetSourceRoots(this);
}
}
Loading