Merge pull request #960 from dotnet/pakrym/publishrefs
Copy refs only on publish
This commit is contained in:
commit
07fbb3d967
9 changed files with 257 additions and 27 deletions
|
@ -4,6 +4,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.Extensions.Internal;
|
||||
|
||||
namespace Microsoft.DotNet.ProjectModel.Compilation
|
||||
{
|
||||
|
@ -19,5 +20,27 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
|||
RelativePath = relativePath;
|
||||
ResolvedPath = resolvedPath;
|
||||
}
|
||||
|
||||
public bool Equals(LibraryAsset other)
|
||||
{
|
||||
return string.Equals(Name, other.Name)
|
||||
&& string.Equals(RelativePath, other.RelativePath)
|
||||
&& string.Equals(ResolvedPath, other.ResolvedPath);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
return obj is LibraryAsset && Equals((LibraryAsset) obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
var combiner = HashCodeCombiner.Start();
|
||||
combiner.Add(Name);
|
||||
combiner.Add(RelativePath);
|
||||
combiner.Add(ResolvedPath);
|
||||
return combiner.CombinedHash;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.PlatformAbstractions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyModel
|
||||
{
|
||||
|
@ -12,6 +13,10 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
{
|
||||
private static Lazy<Assembly> _entryAssembly = new Lazy<Assembly>(GetEntryAssembly);
|
||||
|
||||
private static string _nugetPackages = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? GetDefaultPackageDirectory();
|
||||
|
||||
private static string _packageCache = Environment.GetEnvironmentVariable("DOTNET_PACKAGES_CACHE");
|
||||
|
||||
public CompilationLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
|
||||
: base(libraryType, packageName, version, hash, dependencies, serviceable)
|
||||
{
|
||||
|
@ -24,24 +29,126 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
{
|
||||
var entryAssembly = _entryAssembly.Value;
|
||||
var entryAssemblyName = entryAssembly.GetName().Name;
|
||||
var basePath = GetRefsLocation();
|
||||
|
||||
foreach (var assembly in Assemblies)
|
||||
string basePath;
|
||||
string fullName;
|
||||
|
||||
var appBase = Path.GetDirectoryName(entryAssembly.Location);
|
||||
var refsDir = Path.Combine(appBase, "refs");
|
||||
var hasRefs = Directory.Exists(refsDir);
|
||||
var isProject = string.Equals(LibraryType, "project", StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
if (hasRefs || isProject)
|
||||
{
|
||||
if (Path.GetFileNameWithoutExtension(assembly) == entryAssemblyName)
|
||||
foreach (var assembly in Assemblies)
|
||||
{
|
||||
yield return entryAssembly.Location;
|
||||
continue;
|
||||
var assemblyFile = Path.GetFileName(assembly);
|
||||
if (hasRefs && TryResolveAssemblyFile(refsDir, assemblyFile, out fullName))
|
||||
{
|
||||
yield return fullName;
|
||||
}
|
||||
else if (TryResolveAssemblyFile(appBase, assemblyFile, out fullName))
|
||||
{
|
||||
yield return fullName;
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorMessage = $"Can not find assembly file {assemblyFile} at '{appBase}'";
|
||||
if (hasRefs)
|
||||
{
|
||||
errorMessage += $", '{refsDir}'";
|
||||
}
|
||||
throw new InvalidOperationException(errorMessage);
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
else if (TryResolvePackagePath(out basePath))
|
||||
{
|
||||
foreach (var assembly in Assemblies)
|
||||
{
|
||||
if (!TryResolveAssemblyFile(basePath, assembly, out fullName))
|
||||
{
|
||||
throw new InvalidOperationException($"Can not find assembly file at '{fullName}'");
|
||||
}
|
||||
yield return fullName;
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
throw new InvalidOperationException($"Can not find compilation library location for package '{PackageName}'");
|
||||
}
|
||||
|
||||
private bool TryResolveAssemblyFile(string basePath, string assemblyPath, out string fullName)
|
||||
{
|
||||
fullName = Path.Combine(basePath, assemblyPath);
|
||||
if (File.Exists(fullName))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryResolvePackagePath(out string packagePath)
|
||||
{
|
||||
packagePath = null;
|
||||
|
||||
if (!string.IsNullOrEmpty(_packageCache))
|
||||
{
|
||||
var hashSplitterPos = Hash.IndexOf('-');
|
||||
if (hashSplitterPos <= 0 || hashSplitterPos == Hash.Length - 1)
|
||||
{
|
||||
throw new InvalidOperationException($"Invalid hash entry '{Hash}' for package '{PackageName}'");
|
||||
}
|
||||
|
||||
var fullName = Path.Combine(basePath, Path.GetFileName(assembly));
|
||||
if (!File.Exists(fullName))
|
||||
var hashAlgorithm = Hash.Substring(0, hashSplitterPos);
|
||||
|
||||
var cacheHashPath = Path.Combine(_packageCache, $"{PackageName}.{Version}.nupkg.{hashAlgorithm}");
|
||||
|
||||
if (File.Exists(cacheHashPath) &&
|
||||
File.ReadAllText(cacheHashPath) == Hash.Substring(hashSplitterPos + 1))
|
||||
{
|
||||
throw new InvalidOperationException($"Can not resolve assembly {assembly} location");
|
||||
if (TryResolvePackagePath(_nugetPackages, out packagePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
yield return fullName;
|
||||
}
|
||||
if (!string.IsNullOrEmpty(_nugetPackages) &&
|
||||
TryResolvePackagePath(_nugetPackages, out packagePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryResolvePackagePath(string basePath, out string packagePath)
|
||||
{
|
||||
packagePath = Path.Combine(basePath, PackageName, Version);
|
||||
if (Directory.Exists(packagePath))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static string GetDefaultPackageDirectory()
|
||||
{
|
||||
string basePath;
|
||||
if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows)
|
||||
{
|
||||
basePath = Environment.GetEnvironmentVariable("USERPROFILE");
|
||||
}
|
||||
else
|
||||
{
|
||||
basePath = Environment.GetEnvironmentVariable("HOME");
|
||||
}
|
||||
if (string.IsNullOrEmpty(basePath))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return Path.Combine(basePath, ".nuget", "packages");
|
||||
}
|
||||
|
||||
private static Assembly GetEntryAssembly()
|
||||
{
|
||||
var entryAssembly = (Assembly)typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetEntryAssembly").Invoke(null, null);
|
||||
|
@ -51,10 +158,5 @@ namespace Microsoft.Extensions.DependencyModel
|
|||
}
|
||||
return entryAssembly;
|
||||
}
|
||||
|
||||
private static string GetRefsLocation()
|
||||
{
|
||||
return Path.Combine(Path.GetDirectoryName(_entryAssembly.Value.Location), "refs");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,8 @@
|
|||
"keyFile": "../../tools/Key.snk"
|
||||
},
|
||||
"dependencies": {
|
||||
"Newtonsoft.Json": "7.0.1"
|
||||
"Newtonsoft.Json": "7.0.1",
|
||||
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16530"
|
||||
},
|
||||
"frameworks": {
|
||||
"net451": { },
|
||||
|
|
|
@ -249,18 +249,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
|||
}
|
||||
|
||||
compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\"");
|
||||
|
||||
var refsFolder = Path.Combine(outputPath, "refs");
|
||||
if (Directory.Exists(refsFolder))
|
||||
{
|
||||
Directory.Delete(refsFolder, true);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(refsFolder);
|
||||
foreach (var reference in references)
|
||||
{
|
||||
File.Copy(reference, Path.Combine(refsFolder, Path.GetFileName(reference)));
|
||||
}
|
||||
}
|
||||
|
||||
if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath))
|
||||
|
|
|
@ -133,6 +133,11 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
|
||||
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
|
||||
PublishFiles(export.RuntimeAssets, outputPath);
|
||||
|
||||
if (options.PreserveCompilationContext.GetValueOrDefault())
|
||||
{
|
||||
PublishRefs(export, outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
CopyContents(context, outputPath);
|
||||
|
@ -151,6 +156,26 @@ namespace Microsoft.DotNet.Tools.Publish
|
|||
return true;
|
||||
}
|
||||
|
||||
private static void PublishRefs(LibraryExport export, string outputPath)
|
||||
{
|
||||
var refsPath = Path.Combine(outputPath, "refs");
|
||||
if (!Directory.Exists(refsPath))
|
||||
{
|
||||
Directory.CreateDirectory(refsPath);
|
||||
}
|
||||
|
||||
// Do not copy compilation assembly if it's in runtime assemblies
|
||||
var runtimeAssemblies = new HashSet<LibraryAsset>(export.RuntimeAssemblies);
|
||||
foreach (var compilationAssembly in export.CompilationAssemblies)
|
||||
{
|
||||
if (!runtimeAssemblies.Contains(compilationAssembly))
|
||||
{
|
||||
var destFileName = Path.Combine(refsPath, Path.GetFileName(compilationAssembly.ResolvedPath));
|
||||
File.Copy(compilationAssembly.ResolvedPath, destFileName, overwrite: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int PublishHost(ProjectContext context, string outputPath)
|
||||
{
|
||||
if (context.TargetFramework.IsDesktop())
|
||||
|
|
20
test/TestProjects/TestAppCompilationContext/NuGet.Config
Normal file
20
test/TestProjects/TestAppCompilationContext/NuGet.Config
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<!--To inherit the global NuGet package sources remove the <clear/> line below -->
|
||||
<clear />
|
||||
<add key="dotnet-core" value="https://www.myget.org/F/dotnet-core/api/v3/index.json" />
|
||||
<add key="nugetbuild" value="https://www.myget.org/F/nugetbuild/api/v3/index.json" />
|
||||
<add key="AspNetCIDev" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
||||
<add key="roslyn-nightly" value="https://www.myget.org/F/roslyn-nightly/api/v3/index.json" />
|
||||
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
<add key="dotnet-corefxlab" value="https://www.myget.org/F/dotnet-corefxlab/api/v3/index.json" />
|
||||
<add key="corefxlab" value="https://www.myget.org/F/netcore-package-prototyping/api/v3/index.json" />
|
||||
<add key="corert" value="https://www.myget.org/F/dotnet/api/v2" />
|
||||
<add key="dotnet-buildtools" value="https://www.myget.org/F/dotnet-buildtools/api/v3/index.json" />
|
||||
<add key="fsharp-daily" value="https://www.myget.org/F/fsharp-daily/api/v3/index.json" />
|
||||
</packageSources>
|
||||
<activePackageSource>
|
||||
<add key="AspNetCIDev" value="https://www.myget.org/F/aspnetcidev/api/v3/index.json" />
|
||||
</activePackageSource>
|
||||
</configuration>
|
17
test/TestProjects/TestAppCompilationContext/Program.cs
Normal file
17
test/TestProjects/TestAppCompilationContext/Program.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace TestApp
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
Console.WriteLine(TestLibrary.Helper.GetMessage());
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
}
|
23
test/TestProjects/TestAppCompilationContext/project.json
Normal file
23
test/TestProjects/TestAppCompilationContext/project.json
Normal file
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"version": "1.0.0-*",
|
||||
"compilationOptions": {
|
||||
"emitEntryPoint": true,
|
||||
"preserveCompilationContext": true
|
||||
},
|
||||
|
||||
"dependencies": {
|
||||
"TestLibrary": "1.0.0-*",
|
||||
|
||||
"NETStandard.Library": "1.0.0-rc2-23704",
|
||||
"Microsoft.NETCore.Platforms": "1.0.1-rc2-23704"
|
||||
},
|
||||
|
||||
"frameworks": {
|
||||
"dnxcore50": { }
|
||||
},
|
||||
|
||||
"scripts": {
|
||||
"prepublish" : ["echo prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"],
|
||||
"postpublish" : ["echo postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"]
|
||||
}
|
||||
}
|
|
@ -169,6 +169,37 @@ namespace Microsoft.DotNet.Tools.Publish.Tests
|
|||
publishCommand.GetOutputDirectory().Should().HaveFile("Newtonsoft.Json.dll");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RefsPublishTest()
|
||||
{
|
||||
// create unique directories in the 'temp' folder
|
||||
var root = Temp.CreateDirectory();
|
||||
root.CopyFile(Path.Combine(_testProjectsRoot, "global.json"));
|
||||
var testAppDir = root.CreateDirectory("TestAppCompilationContext");
|
||||
var testLibDir = root.CreateDirectory("TestLibrary");
|
||||
|
||||
// copy projects to the temp dir
|
||||
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestAppCompilationContext"), testAppDir);
|
||||
CopyProjectToTempDir(Path.Combine(_testProjectsRoot, "TestLibrary"), testLibDir);
|
||||
|
||||
RunRestore(testAppDir.Path);
|
||||
RunRestore(testLibDir.Path);
|
||||
|
||||
var testProject = GetProjectPath(testAppDir);
|
||||
var publishCommand = new PublishCommand(testProject);
|
||||
publishCommand.Execute().Should().Pass();
|
||||
|
||||
publishCommand.GetOutputDirectory().Should().HaveFile("TestAppCompilationContext.dll");
|
||||
publishCommand.GetOutputDirectory().Should().HaveFile("TestLibrary.dll");
|
||||
|
||||
var refsDirectory = new DirectoryInfo(Path.Combine(publishCommand.GetOutputDirectory().FullName, "refs"));
|
||||
// Should have compilation time assemblies
|
||||
refsDirectory.Should().HaveFile("System.IO.dll");
|
||||
// Libraries in which lib==ref should be deduped
|
||||
refsDirectory.Should().NotHaveFile("TestLibrary.dll");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CompilationFailedTest()
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue