From d98c1f87244e5b451818fb5f847468cd10c12706 Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 6 May 2016 14:32:50 -0500 Subject: [PATCH] dotnet build raises errors MVC apps target net46. The issue is when the ProjectContextBuilder sees a CompileTimePlaceholder "_._" file on a full framework, it assumes that dependency has to come from the "Reference Assemblies" directory. If it can't be found there, an error is raised. However, there are other reasons "_._" placeholders are created (when a NuGet package doesn't want its dependencies to be exposed in the Compile dependencies of its consumers). And these placeholders can exist for assemblies that aren't in the full framework - in this case System.Diagnostics.FileVersionInfo and others. To fix this, if the reference can't be resolved from the "Reference Assemblies" folder, it is just skipped. If the compiler really needs that assembly, it will raise an error to the user. Dotnet build shouldn't raise the error. Fix #2906 --- .../AppWithNet46AndRoslyn/.noautobuild | 1 + .../AppWithNet46AndRoslyn/Program.cs | 10 ++++++++++ .../AppWithNet46AndRoslyn/project.json | 11 +++++++++++ .../ProjectContextBuilder.cs | 18 ++++++++++++------ .../GivenDotnetBuildBuildsProjects.cs | 15 +++++++++++++++ 5 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 TestAssets/TestProjects/AppWithNet46AndRoslyn/.noautobuild create mode 100644 TestAssets/TestProjects/AppWithNet46AndRoslyn/Program.cs create mode 100644 TestAssets/TestProjects/AppWithNet46AndRoslyn/project.json diff --git a/TestAssets/TestProjects/AppWithNet46AndRoslyn/.noautobuild b/TestAssets/TestProjects/AppWithNet46AndRoslyn/.noautobuild new file mode 100644 index 000000000..8f7edc4ac --- /dev/null +++ b/TestAssets/TestProjects/AppWithNet46AndRoslyn/.noautobuild @@ -0,0 +1 @@ +noautobuild \ No newline at end of file diff --git a/TestAssets/TestProjects/AppWithNet46AndRoslyn/Program.cs b/TestAssets/TestProjects/AppWithNet46AndRoslyn/Program.cs new file mode 100644 index 000000000..d168553bf --- /dev/null +++ b/TestAssets/TestProjects/AppWithNet46AndRoslyn/Program.cs @@ -0,0 +1,10 @@ +namespace AppWithNet46AndRoslyn +{ + public class MyApp + { + public static void Main() + { + System.Console.WriteLine("Hello, World!"); + } + } +} \ No newline at end of file diff --git a/TestAssets/TestProjects/AppWithNet46AndRoslyn/project.json b/TestAssets/TestProjects/AppWithNet46AndRoslyn/project.json new file mode 100644 index 000000000..47850f11e --- /dev/null +++ b/TestAssets/TestProjects/AppWithNet46AndRoslyn/project.json @@ -0,0 +1,11 @@ +{ + "buildOptions": { + "emitEntryPoint": true + }, + "dependencies": { + "Microsoft.CodeAnalysis.CSharp": "1.3.0-beta1-20160429-01" + }, + "frameworks": { + "net46": { } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 7f8291c7d..db8410a3d 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -440,15 +440,21 @@ namespace Microsoft.DotNet.ProjectModel package.HasCompileTimePlaceholder && !TargetFramework.IsPackageBased) { + // requiresFrameworkAssemblies is true whenever we find a CompileTimePlaceholder in a non-package based framework, even if + // the reference is unresolved. This ensures the best error experience when someone is building on a machine without + // the target framework installed. + requiresFrameworkAssemblies = true; + var newKey = new LibraryKey(library.Identity.Name, LibraryType.ReferenceAssembly); var dependency = new LibraryRange(library.Identity.Name, LibraryType.ReferenceAssembly); - // If the framework assembly can't be resolved then mark it as unresolved but still replace the package - // dependency - var replacement = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework) ?? - UnresolvedDependencyProvider.GetDescription(dependency, TargetFramework); - - requiresFrameworkAssemblies = true; + var replacement = referenceAssemblyDependencyResolver.GetDescription(dependency, TargetFramework); + + // If the reference is unresolved, just skip it. Don't replace the package dependency + if (replacement == null) + { + continue; + } // Remove the original package reference libraries.Remove(pair.Key); diff --git a/test/dotnet-build.Tests/GivenDotnetBuildBuildsProjects.cs b/test/dotnet-build.Tests/GivenDotnetBuildBuildsProjects.cs index a4ef1f97b..ea537a75e 100644 --- a/test/dotnet-build.Tests/GivenDotnetBuildBuildsProjects.cs +++ b/test/dotnet-build.Tests/GivenDotnetBuildBuildsProjects.cs @@ -100,5 +100,20 @@ namespace Microsoft.DotNet.Tools.Builder.Tests "TestLibraryWithXmlDoc.xml" }); } + + [WindowsOnlyFact] + public void It_builds_projects_targeting_net46_and_Roslyn() + { + var testInstance = TestAssetsManager + .CreateTestInstance("AppWithNet46AndRoslyn") + .WithLockFiles(); + + var testProject = Path.Combine(testInstance.TestRoot, "project.json"); + + new BuildCommand(testProject) + .Execute() + .Should() + .Pass(); + } } }