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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Microsoft.Extensions.Internal;
|
||||||
|
|
||||||
namespace Microsoft.DotNet.ProjectModel.Compilation
|
namespace Microsoft.DotNet.ProjectModel.Compilation
|
||||||
{
|
{
|
||||||
|
@ -19,5 +20,27 @@ namespace Microsoft.DotNet.ProjectModel.Compilation
|
||||||
RelativePath = relativePath;
|
RelativePath = relativePath;
|
||||||
ResolvedPath = resolvedPath;
|
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.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using Microsoft.Extensions.PlatformAbstractions;
|
||||||
|
|
||||||
namespace Microsoft.Extensions.DependencyModel
|
namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
|
@ -12,6 +13,10 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
private static Lazy<Assembly> _entryAssembly = new Lazy<Assembly>(GetEntryAssembly);
|
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)
|
public CompilationLibrary(string libraryType, string packageName, string version, string hash, string[] assemblies, Dependency[] dependencies, bool serviceable)
|
||||||
: base(libraryType, packageName, version, hash, dependencies, serviceable)
|
: base(libraryType, packageName, version, hash, dependencies, serviceable)
|
||||||
{
|
{
|
||||||
|
@ -24,24 +29,126 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
{
|
{
|
||||||
var entryAssembly = _entryAssembly.Value;
|
var entryAssembly = _entryAssembly.Value;
|
||||||
var entryAssemblyName = entryAssembly.GetName().Name;
|
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;
|
var assemblyFile = Path.GetFileName(assembly);
|
||||||
continue;
|
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));
|
var hashAlgorithm = Hash.Substring(0, hashSplitterPos);
|
||||||
if (!File.Exists(fullName))
|
|
||||||
|
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()
|
private static Assembly GetEntryAssembly()
|
||||||
{
|
{
|
||||||
var entryAssembly = (Assembly)typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetEntryAssembly").Invoke(null, null);
|
var entryAssembly = (Assembly)typeof(Assembly).GetTypeInfo().GetDeclaredMethod("GetEntryAssembly").Invoke(null, null);
|
||||||
|
@ -51,10 +158,5 @@ namespace Microsoft.Extensions.DependencyModel
|
||||||
}
|
}
|
||||||
return entryAssembly;
|
return entryAssembly;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetRefsLocation()
|
|
||||||
{
|
|
||||||
return Path.Combine(Path.GetDirectoryName(_entryAssembly.Value.Location), "refs");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -10,7 +10,8 @@
|
||||||
"keyFile": "../../tools/Key.snk"
|
"keyFile": "../../tools/Key.snk"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Newtonsoft.Json": "7.0.1"
|
"Newtonsoft.Json": "7.0.1",
|
||||||
|
"Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16530"
|
||||||
},
|
},
|
||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net451": { },
|
"net451": { },
|
||||||
|
|
|
@ -249,18 +249,6 @@ namespace Microsoft.DotNet.Tools.Compiler
|
||||||
}
|
}
|
||||||
|
|
||||||
compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\"");
|
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))
|
if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath))
|
||||||
|
|
|
@ -133,6 +133,11 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
|
PublishFiles(export.RuntimeAssemblies, outputPath, nativeSubdirectories: false);
|
||||||
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
|
PublishFiles(export.NativeLibraries, outputPath, nativeSubdirectories);
|
||||||
PublishFiles(export.RuntimeAssets, outputPath);
|
PublishFiles(export.RuntimeAssets, outputPath);
|
||||||
|
|
||||||
|
if (options.PreserveCompilationContext.GetValueOrDefault())
|
||||||
|
{
|
||||||
|
PublishRefs(export, outputPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CopyContents(context, outputPath);
|
CopyContents(context, outputPath);
|
||||||
|
@ -151,6 +156,26 @@ namespace Microsoft.DotNet.Tools.Publish
|
||||||
return true;
|
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)
|
private static int PublishHost(ProjectContext context, string outputPath)
|
||||||
{
|
{
|
||||||
if (context.TargetFramework.IsDesktop())
|
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");
|
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]
|
[Fact]
|
||||||
public void CompilationFailedTest()
|
public void CompilationFailedTest()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue