diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json new file mode 100644 index 000000000..d803c7d2c --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.fragment.lock.json @@ -0,0 +1,25 @@ +{ + "version": 2, + "exports": { + "ClassLibrary2/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary2.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary2.dll": {} + } + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary3.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary3.dll": {} + } + } + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json new file mode 100644 index 000000000..1323d5f29 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { + "dependencies": { + "ClassLibrary1": { + "target": "project" + }, + "ClassLibrary2": { + "target": "project" + }, + "ClassLibrary3": { + "target": "project" + } + } + } + } +} diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json new file mode 100644 index 000000000..244c3771b --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missing-exports/project.lock.json @@ -0,0 +1,61 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x64": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x86": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + } + }, + "libraries": { + "ClassLibrary1/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj" + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj" + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj" + } + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [ + "ClassLibrary1", + "ClassLibrary2", + "ClassLibrary3" + ] + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json new file mode 100644 index 000000000..7b6738e49 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.fragment.lock.json @@ -0,0 +1,35 @@ +{ + "version": 3, + "exports": { + "ClassLibrary1/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.5.2", + "compile": { + "bin/Debug/ClassLibrary1.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary1.dll": {} + } + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary2.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary2.dll": {} + } + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary3.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary3.dll": {} + } + } + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json new file mode 100644 index 000000000..1323d5f29 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { + "dependencies": { + "ClassLibrary1": { + "target": "project" + }, + "ClassLibrary2": { + "target": "project" + }, + "ClassLibrary3": { + "target": "project" + } + } + } + } +} diff --git a/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json new file mode 100644 index 000000000..244c3771b --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_missmatching-versions/project.lock.json @@ -0,0 +1,61 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x64": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x86": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + } + }, + "libraries": { + "ClassLibrary1/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj" + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj" + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj" + } + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [ + "ClassLibrary1", + "ClassLibrary2", + "ClassLibrary3" + ] + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json new file mode 100644 index 000000000..1323d5f29 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { + "dependencies": { + "ClassLibrary1": { + "target": "project" + }, + "ClassLibrary2": { + "target": "project" + }, + "ClassLibrary3": { + "target": "project" + } + } + } + } +} diff --git a/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json new file mode 100644 index 000000000..244c3771b --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/invalid_nofragment/project.lock.json @@ -0,0 +1,61 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x64": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x86": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + } + }, + "libraries": { + "ClassLibrary1/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj" + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj" + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj" + } + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [ + "ClassLibrary1", + "ClassLibrary2", + "ClassLibrary3" + ] + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json new file mode 100644 index 000000000..415fc75d8 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid/project.fragment.lock.json @@ -0,0 +1,35 @@ +{ + "version": 2, + "exports": { + "ClassLibrary1/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.5.2", + "compile": { + "bin/Debug/ClassLibrary1.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary1.dll": {} + } + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary2.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary2.dll": {} + } + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary3.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary3.dll": {} + } + } + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.json b/TestAssets/LockFiles/ExportFiles/valid/project.json new file mode 100644 index 000000000..1323d5f29 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { + "dependencies": { + "ClassLibrary1": { + "target": "project" + }, + "ClassLibrary2": { + "target": "project" + }, + "ClassLibrary3": { + "target": "project" + } + } + } + } +} diff --git a/TestAssets/LockFiles/ExportFiles/valid/project.lock.json b/TestAssets/LockFiles/ExportFiles/valid/project.lock.json new file mode 100644 index 000000000..244c3771b --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid/project.lock.json @@ -0,0 +1,61 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x64": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x86": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + } + }, + "libraries": { + "ClassLibrary1/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj" + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj" + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj" + } + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [ + "ClassLibrary1", + "ClassLibrary2", + "ClassLibrary3" + ] + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json new file mode 100644 index 000000000..415fc75d8 --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.fragment.lock.json @@ -0,0 +1,35 @@ +{ + "version": 2, + "exports": { + "ClassLibrary1/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.5.2", + "compile": { + "bin/Debug/ClassLibrary1.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary1.dll": {} + } + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary2.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary2.dll": {} + } + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary3.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary3.dll": {} + } + } + } +} \ No newline at end of file diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json new file mode 100644 index 000000000..2959f5fbc --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.json @@ -0,0 +1,10 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { } + } +} diff --git a/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json new file mode 100644 index 000000000..e7b45e57d --- /dev/null +++ b/TestAssets/LockFiles/ExportFiles/valid_staleFragment/project.lock.json @@ -0,0 +1,13 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { } + }, + "libraries": { + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [] + } +} \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore new file mode 100644 index 000000000..497f0e325 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/.gitignore @@ -0,0 +1,3 @@ +# Negates the lock file +# MSBuiild references' project model server tests requires these lock files, since they can't be created without VS tooling. +!project.lock.json diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs new file mode 100644 index 000000000..08281c64a --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClassLibrary1 +{ + public class Class1 + { + } +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj new file mode 100644 index 000000000..7364cb64d --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/ClassLibrary1.csproj @@ -0,0 +1,62 @@ + + + + + Debug + AnyCPU + {FD073258-550B-4E57-86AE-DC4874015EB1} + Library + Properties + ClassLibrary1 + ClassLibrary1 + v4.5.2 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll + True + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..6437643a7 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClassLibrary1")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ClassLibrary1")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("fd073258-550b-4e57-86ae-dc4874015eb1")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config new file mode 100644 index 000000000..1975352b1 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary1/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs new file mode 100644 index 000000000..ad2fff55e --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClassLibrary2 +{ + public class Class1 + { + } +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj new file mode 100644 index 000000000..fb17ee317 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/ClassLibrary2.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + 0f2d2a48-e867-496c-85a7-e97b64cfeda4 + Library + Properties + ClassLibrary2 + ClassLibrary2 + v4.6 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..b40cfab4c --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary2/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClassLibrary2")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ClassLibrary2")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0f2d2a48-e867-496c-85a7-e97b64cfeda4")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs new file mode 100644 index 000000000..21384c5b2 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Class1.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ClassLibrary3 +{ + public class Class1 + { + } +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj new file mode 100644 index 000000000..0bcde3dfe --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/ClassLibrary3.csproj @@ -0,0 +1,61 @@ + + + + + Debug + AnyCPU + 428e95cb-8435-414b-a313-9d734c633b3e + Library + Properties + ClassLibrary3 + ClassLibrary3 + v4.6 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0eadf724e --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ClassLibrary3/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("ClassLibrary3")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ClassLibrary3")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("428e95cb-8435-414b-a313-9d734c633b3e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln new file mode 100644 index 000000000..1ac8ff099 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/ConsoleApp13.sln @@ -0,0 +1,53 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25029.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1443ACE0-3065-4C20-AD59-D561798AE0A5}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{0AE82780-22C8-4DC8-8F1E-86977FDD092F}" + ProjectSection(SolutionItems) = preProject + global.json = global.json + EndProjectSection +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "ConsoleApp13", "src\ConsoleApp13\ConsoleApp13.xproj", "{767D3038-AC3A-4722-B21F-F85F2CBC3AA3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary1", "ClassLibrary1\ClassLibrary1.csproj", "{FD073258-550B-4E57-86AE-DC4874015EB1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary2", "ClassLibrary2\ClassLibrary2.csproj", "{0F2D2A48-E867-496C-85A7-E97B64CFEDA4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClassLibrary3", "ClassLibrary3\ClassLibrary3.csproj", "{428E95CB-8435-414B-A313-9D734C633B3E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {767D3038-AC3A-4722-B21F-F85F2CBC3AA3}.Release|Any CPU.Build.0 = Release|Any CPU + {FD073258-550B-4E57-86AE-DC4874015EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FD073258-550B-4E57-86AE-DC4874015EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FD073258-550B-4E57-86AE-DC4874015EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FD073258-550B-4E57-86AE-DC4874015EB1}.Release|Any CPU.Build.0 = Release|Any CPU + {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0F2D2A48-E867-496C-85A7-E97B64CFEDA4}.Release|Any CPU.Build.0 = Release|Any CPU + {428E95CB-8435-414B-A313-9D734C633B3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {428E95CB-8435-414B-A313-9D734C633B3E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {428E95CB-8435-414B-A313-9D734C633B3E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {428E95CB-8435-414B-A313-9D734C633B3E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {767D3038-AC3A-4722-B21F-F85F2CBC3AA3} = {1443ACE0-3065-4C20-AD59-D561798AE0A5} + {FD073258-550B-4E57-86AE-DC4874015EB1} = {1443ACE0-3065-4C20-AD59-D561798AE0A5} + {0F2D2A48-E867-496C-85A7-E97B64CFEDA4} = {1443ACE0-3065-4C20-AD59-D561798AE0A5} + {428E95CB-8435-414B-A313-9D734C633B3E} = {1443ACE0-3065-4C20-AD59-D561798AE0A5} + EndGlobalSection +EndGlobal diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json new file mode 100644 index 000000000..5e6422e6d --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ "src", "test" ] +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj new file mode 100644 index 000000000..ec559dc46 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/MainApp.xproj @@ -0,0 +1,24 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 767d3038-ac3a-4722-b21f-f85f2cbc3aa3 + ConsoleApp13 + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\ + v4.6 + + + 2.0 + + + + + + + + \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs new file mode 100644 index 000000000..6723332b1 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Program.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace ConsoleApp13 +{ + public class Program + { + public static void Main(string[] args) + { + var q = new ClassLibrary1.Class1(); + } + } +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..83e8803f8 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/Properties/AssemblyInfo.cs @@ -0,0 +1,19 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("ConsoleApp13")] +[assembly: AssemblyTrademark("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("767d3038-ac3a-4722-b21f-f85f2cbc3aa3")] diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json new file mode 100644 index 000000000..1efff4670 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.fragment.lock.json @@ -0,0 +1,36 @@ +{ + "version": 2, + "exports": { + "ClassLibrary1/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.5.2", + "compile": { + "bin/Debug/ClassLibrary1.dll": {} + }, + "runtime": { + "../packages/Newtonsoft.Json.8.0.3/lib/net45/Newtonsoft.Json.dll": {}, + "bin/Debug/ClassLibrary1.dll": {} + } + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary2.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary2.dll": {} + } + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "framework": ".NETFramework,Version=v4.6", + "compile": { + "bin/Debug/ClassLibrary3.dll": {} + }, + "runtime": { + "bin/Debug/ClassLibrary3.dll": {} + } + } + } +} \ No newline at end of file diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json new file mode 100644 index 000000000..1323d5f29 --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "frameworks": { + "net46": { + "dependencies": { + "ClassLibrary1": { + "target": "project" + }, + "ClassLibrary2": { + "target": "project" + }, + "ClassLibrary3": { + "target": "project" + } + } + } + } +} diff --git a/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json new file mode 100644 index 000000000..244c3771b --- /dev/null +++ b/TestAssets/ProjectModelServer/MSBuildReferencesProjects/ValidCase01/src/MainApp/project.lock.json @@ -0,0 +1,61 @@ +{ + "locked": false, + "version": 2, + "targets": { + ".NETFramework,Version=v4.6": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x64": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + }, + ".NETFramework,Version=v4.6/win7-x86": { + "ClassLibrary1/1.0.0": { + "type": "project" + }, + "ClassLibrary2/1.0.0": { + "type": "project" + }, + "ClassLibrary3/1.0.0": { + "type": "project" + } + } + }, + "libraries": { + "ClassLibrary1/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary1/ClassLibrary1.csproj" + }, + "ClassLibrary2/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary2/ClassLibrary2.csproj" + }, + "ClassLibrary3/1.0.0": { + "type": "project", + "msbuildProject": "../../ClassLibrary3/ClassLibrary3.csproj" + } + }, + "projectFileDependencyGroups": { + "": [], + ".NETFramework,Version=v4.6": [ + "ClassLibrary1", + "ClassLibrary2", + "ClassLibrary3" + ] + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index d83638068..ce43b4b0b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -140,11 +140,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return LibraryExportBuilder.Create(library).Build(); } - if (Equals(LibraryType.Package, library.Identity.Type)) + var libraryType = library.Identity.Type; + if (Equals(LibraryType.Package, libraryType) || Equals(LibraryType.MSBuildProject, libraryType)) { - return ExportPackage((PackageDescription)library); + return ExportPackage((TargetLibraryWithAssets)library); } - else if (Equals(LibraryType.Project, library.Identity.Type)) + else if (Equals(LibraryType.Project, libraryType)) { return ExportProject((ProjectDescription)library); } @@ -154,22 +155,26 @@ namespace Microsoft.DotNet.ProjectModel.Compilation } } - private LibraryExport ExportPackage(PackageDescription package) + private LibraryExport ExportPackage(TargetLibraryWithAssets library) { - var builder = LibraryExportBuilder.Create(package); - builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(package, package.NativeLibraries))); - builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(package, package.RuntimeAssemblies))); - builder.WithCompilationAssemblies(PopulateAssets(package, package.CompileTimeAssemblies)); - builder.WithSourceReferences(GetSharedSources(package)); - builder.WithAnalyzerReference(GetAnalyzerReferences(package)); + var builder = LibraryExportBuilder.Create(library); + builder.AddNativeLibraryGroup(new LibraryAssetGroup(PopulateAssets(library, library.NativeLibraries))); + builder.AddRuntimeAssemblyGroup(new LibraryAssetGroup(PopulateAssets(library, library.RuntimeAssemblies))); + builder.WithCompilationAssemblies(PopulateAssets(library, library.CompileTimeAssemblies)); - if (package.ContentFiles.Any()) + if (library.Identity.Type.Equals(LibraryType.Package)) + { + builder.WithSourceReferences(GetSharedSources((PackageDescription) library)); + builder.WithAnalyzerReference(GetAnalyzerReferences((PackageDescription) library)); + } + + if (library.ContentFiles.Any()) { var parameters = PPFileParameters.CreateForProject(_rootProject.Project); Action transform = (input, output) => PPFilePreprocessor.Preprocess(input, output, parameters); var sourceCodeLanguage = _rootProject.Project.GetSourceCodeLanguage(); - var languageGroups = package.ContentFiles.GroupBy(file => file.CodeLanguage); + var languageGroups = library.ContentFiles.GroupBy(file => file.CodeLanguage); var selectedGroup = languageGroups.FirstOrDefault(g => g.Key == sourceCodeLanguage) ?? languageGroups.FirstOrDefault(g => g.Key == null); if (selectedGroup != null) @@ -184,14 +189,14 @@ namespace Microsoft.DotNet.ProjectModel.Compilation var fileTransform = contentFile.PPOutputPath != null ? transform : null; - var fullPath = Path.Combine(package.Path, contentFile.Path); + var fullPath = Path.Combine(library.Path, contentFile.Path); if (contentFile.BuildAction == BuildAction.Compile) { - builder.AddSourceReference(LibraryAsset.CreateFromRelativePath(package.Path, contentFile.Path, fileTransform)); + builder.AddSourceReference(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform)); } else if (contentFile.BuildAction == BuildAction.EmbeddedResource) { - builder.AddEmbedddedResource(LibraryAsset.CreateFromRelativePath(package.Path, contentFile.Path, fileTransform)); + builder.AddEmbedddedResource(LibraryAsset.CreateFromRelativePath(library.Path, contentFile.Path, fileTransform)); } if (contentFile.CopyToOutput) { @@ -200,9 +205,9 @@ namespace Microsoft.DotNet.ProjectModel.Compilation } } } - if (package.RuntimeTargets.Any()) + if (library.RuntimeTargets.Any()) { - foreach (var targetGroup in package.RuntimeTargets.GroupBy(t => t.Runtime)) + foreach (var targetGroup in library.RuntimeTargets.GroupBy(t => t.Runtime)) { var runtime = new List(); var native = new List(); @@ -211,11 +216,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation { if (string.Equals(lockFileRuntimeTarget.AssetType, "native", StringComparison.OrdinalIgnoreCase)) { - native.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path)); + native.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path)); } else if (string.Equals(lockFileRuntimeTarget.AssetType, "runtime", StringComparison.OrdinalIgnoreCase)) { - runtime.Add(LibraryAsset.CreateFromRelativePath(package.Path, lockFileRuntimeTarget.Path)); + runtime.Add(LibraryAsset.CreateFromRelativePath(library.Path, lockFileRuntimeTarget.Path)); } } @@ -342,7 +347,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IEnumerable GetSharedSources(PackageDescription package) { return package - .Library + .PackageLibrary .Files .Where(path => path.StartsWith("shared" + Path.DirectorySeparatorChar)) .Select(path => LibraryAsset.CreateFromRelativePath(package.Path, path)); @@ -351,11 +356,12 @@ namespace Microsoft.DotNet.ProjectModel.Compilation private IEnumerable GetAnalyzerReferences(PackageDescription package) { var analyzers = package - .Library + .PackageLibrary .Files .Where(path => path.StartsWith("analyzers" + Path.DirectorySeparatorChar) && path.EndsWith(".dll")); + var analyzerRefs = new List(); // See https://docs.nuget.org/create/analyzers-conventions for the analyzer // NuGet specification @@ -416,12 +422,11 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return analyzerRefs; } - - private IEnumerable PopulateAssets(PackageDescription package, IEnumerable section) + private IEnumerable PopulateAssets(TargetLibraryWithAssets library, IEnumerable section) { foreach (var assemblyPath in section) { - yield return LibraryAsset.CreateFromRelativePath(package.Path, assemblyPath.Path); + yield return LibraryAsset.CreateFromRelativePath(library.Path, assemblyPath.Path); } } diff --git a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs index b5111adbb..21b105ae5 100644 --- a/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/DependencyContextBuilder.cs @@ -115,7 +115,7 @@ namespace Microsoft.Extensions.DependencyModel { var type = export.Library.Identity.Type; - var serviceable = (export.Library as PackageDescription)?.Library.IsServiceable ?? false; + var serviceable = (export.Library as PackageDescription)?.PackageLibrary.IsServiceable ?? false; var libraryDependencies = new HashSet(); foreach (var libraryDependency in export.Library.Dependencies) diff --git a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs index 095bbf9b2..83e229eef 100644 --- a/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs +++ b/src/Microsoft.DotNet.ProjectModel/ErrorCodes.DotNet.cs @@ -13,5 +13,8 @@ namespace Microsoft.DotNet.ProjectModel // Multiple libraries marked as "platform" public static readonly string DOTNET1013 = nameof(DOTNET1013); + + // Failed to read lock file + public static readonly string DOTNET1014 = nameof(DOTNET1014); } } diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs b/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs new file mode 100644 index 000000000..933742559 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Graph/ExportFile.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.ProjectModel.Graph +{ + public class ExportFile + { + public static readonly string ExportFileName = "project.fragment.lock.json"; + + public int Version { get; } + public string ExportFilePath { get; } + + public IList Exports { get; } + + public ExportFile(string exportFilePath, int version, IList exports) + { + ExportFilePath = exportFilePath; + Version = version; + Exports = exports.Any() ? exports : new List(0); + } + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs index 1398b0a88..4a18dccbe 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LibraryType.cs @@ -11,11 +11,13 @@ namespace Microsoft.DotNet.ProjectModel.Graph public static readonly LibraryType Package = new LibraryType(nameof(Package)); public static readonly LibraryType Project = new LibraryType(nameof(Project)); public static readonly LibraryType ReferenceAssembly = new LibraryType(nameof(ReferenceAssembly)); + public static readonly LibraryType MSBuildProject = new LibraryType(nameof(MSBuildProject)); // Default value public static readonly LibraryType Unspecified = new LibraryType(); public string Value { get; } + private LibraryType(string value) { diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs index 99e41df88..9f9db6459 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFile.cs @@ -4,9 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using Microsoft.DotNet.ProjectModel.Utilities; -using NuGet.Versioning; namespace Microsoft.DotNet.ProjectModel.Graph { @@ -22,6 +19,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph public IList PackageLibraries { get; set; } = new List(); public IList ProjectLibraries { get; set; } = new List(); public IList Targets { get; set; } = new List(); + public ExportFile ExportFile { get; set; } public LockFile(string lockFilePath) { diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs new file mode 100644 index 000000000..a0f7c0c0e --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFilePatcher.cs @@ -0,0 +1,128 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.DotNet.ProjectModel.Resolution; + +namespace Microsoft.DotNet.ProjectModel.Graph +{ + public class LockFilePatcher + { + private readonly LockFile _lockFile; + private Dictionary> _msbuildTargetLibraries; + + public LockFilePatcher(LockFile lockFile) + { + _lockFile = lockFile; + + var msbuildProjectLibraries = lockFile.ProjectLibraries.Where(MSBuildDependencyProvider.IsMSBuildProjectLibrary); + _msbuildTargetLibraries = msbuildProjectLibraries.ToDictionary(GetProjectLibraryKey, l => GetTargetsForLibrary(_lockFile, l)); + } + + public void PatchIfNecessary() + { + var exportFilePath = GetExportFilePath(_lockFile.LockFilePath); + + if (File.Exists(exportFilePath) && _msbuildTargetLibraries.Any()) + { + var exportFile = LockFileReader.ReadExportFile(exportFilePath); + PatchLockWithExport(exportFile); + } + else + { + ThrowIfAnyMsbuildLibrariesPresent(); + } + } + + public void ThrowIfAnyMsbuildLibrariesPresent() + { + if (_msbuildTargetLibraries.Any()) + { + throw new LockFilePatchingException($"Lock file {_lockFile} contains msbuild projects but there is no export file"); + } + } + + private void PatchLockWithExport(ExportFile exportFile) + { + if (_lockFile.Version != exportFile.Version) + { + throw new LockFilePatchingException($"Export file {exportFile.ExportFilePath} has a different version than the lock file {_lockFile.LockFilePath}"); + } + + var exportDict = exportFile.Exports.ToDictionary(GetTargetLibraryKey); + + var uncoveredLibraries = _msbuildTargetLibraries.Keys.Except(exportDict.Keys); + if (uncoveredLibraries.Any()) + { + throw new LockFilePatchingException($"Export {exportFile.ExportFilePath} does not provide exports for all the msbuild projects in {_lockFile.LockFilePath}"); + } + + foreach(var exportKey in exportDict.Keys) + { + var export = exportDict[exportKey]; + var librariesToPatch = _msbuildTargetLibraries[exportKey]; + + foreach (var libraryToPatch in librariesToPatch) + { + Patch(libraryToPatch, export); + } + } + + _lockFile.ExportFile = exportFile; + } + + private static void Patch(LockFileTargetLibrary libraryToPatch, LockFileTargetLibrary export) + { + libraryToPatch.CompileTimeAssemblies = export.CompileTimeAssemblies; + libraryToPatch.ContentFiles = export.ContentFiles; + libraryToPatch.FrameworkAssemblies = export.FrameworkAssemblies; + libraryToPatch.NativeLibraries = export.NativeLibraries; + libraryToPatch.ResourceAssemblies = export.ResourceAssemblies; + libraryToPatch.RuntimeAssemblies = export.RuntimeAssemblies; + } + + private static IList GetTargetsForLibrary(LockFile lockFile, LockFileProjectLibrary library) + { + return lockFile.Targets + .SelectMany( + t => t.Libraries + .Where( + l => string.Equals(GetProjectLibraryKey(library), (GetTargetLibraryKey(l))) + ) + ) + .ToList(); + } + + private static object TypeName(LockFileTargetLibrary library) + { + return library.Name + "/" + library.Version + "/" + library.Type; + } + + private static string GetTargetLibraryKey(LockFileTargetLibrary library) + { + return library.Name + "/" + library.Version; + } + + private static string GetProjectLibraryKey(LockFileProjectLibrary library) + { + return library.Name + "/" + library.Version; + } + + private static string GetExportFilePath(string masterLockFilePath) + { + var parentDirectory = Directory.GetParent(masterLockFilePath).FullName; + return Path.Combine(parentDirectory, ExportFile.ExportFileName); + } + } + + internal class LockFilePatchingException : Exception + { + public LockFilePatchingException(string message) : base(message) + { + } + } + +} diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs index 7a1b9d632..bdc459235 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileProjectLibrary.cs @@ -12,5 +12,7 @@ namespace Microsoft.DotNet.ProjectModel.Graph public NuGetVersion Version { get; set; } public string Path { get; set; } + + public string MSBuildProject { get; set; } } } \ No newline at end of file diff --git a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs index cb9d176dd..84fea0ada 100644 --- a/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/Graph/LockFileReader.cs @@ -15,13 +15,13 @@ namespace Microsoft.DotNet.ProjectModel.Graph { public static class LockFileReader { - public static LockFile Read(string lockFilePath) + public static LockFile Read(string lockFilePath, bool patchWithExportFile = true) { using (var stream = ResilientFileStreamOpener.OpenFile(lockFilePath)) { try { - return Read(lockFilePath, stream); + return Read(lockFilePath, stream, patchWithExportFile); } catch (FileFormatException ex) { @@ -34,21 +34,36 @@ namespace Microsoft.DotNet.ProjectModel.Graph } } - public static LockFile Read(string lockFilePath, Stream stream) + public static LockFile Read(string lockFilePath, Stream stream, bool patchWithExportFile = true) { try { var reader = new StreamReader(stream); var jobject = JsonDeserializer.Deserialize(reader) as JsonObject; - if (jobject != null) - { - return ReadLockFile(lockFilePath, jobject); - } - else + if (jobject == null) { throw new InvalidDataException(); } + + var lockFile = ReadLockFile(lockFilePath, jobject); + + var patcher = new LockFilePatcher(lockFile); + + if (patchWithExportFile) + { + patcher.PatchIfNecessary(); + } + else + { + patcher.ThrowIfAnyMsbuildLibrariesPresent(); + } + + return lockFile; + } + catch (LockFilePatchingException) + { + throw; } catch { @@ -60,6 +75,36 @@ namespace Microsoft.DotNet.ProjectModel.Graph } } + public static ExportFile ReadExportFile(string fragmentLockFilePath) + { + using (var stream = ResilientFileStreamOpener.OpenFile(fragmentLockFilePath)) + { + try + { + var rootJObject = JsonDeserializer.Deserialize(new StreamReader(stream)) as JsonObject; + + if (rootJObject == null) + { + throw new InvalidDataException(); + } + + var version = ReadInt(rootJObject, "version", defaultValue: int.MinValue); + var exports = ReadObject(rootJObject.ValueAsJsonObject("exports"), ReadTargetLibrary); + + return new ExportFile(fragmentLockFilePath, version, exports); + + } + catch (FileFormatException ex) + { + throw ex.WithFilePath(fragmentLockFilePath); + } + catch (Exception ex) + { + throw FileFormatException.Create(ex, fragmentLockFilePath); + } + } + } + private static LockFile ReadLockFile(string lockFilePath, JsonObject cursor) { var lockFile = new LockFile(lockFilePath); @@ -105,12 +150,19 @@ namespace Microsoft.DotNet.ProjectModel.Graph } else if (type == "project") { - lockFile.ProjectLibraries.Add(new LockFileProjectLibrary + var projectLibrary = new LockFileProjectLibrary { Name = name, - Version = version, - Path = ReadString(value.Value("path")) - }); + Version = version + }; + + var pathValue = value.Value("path"); + projectLibrary.Path = pathValue == null ? null : ReadString(pathValue); + + var buildTimeDependencyValue = value.Value("msbuildProject"); + projectLibrary.MSBuildProject = buildTimeDependencyValue == null ? null : ReadString(buildTimeDependencyValue); + + lockFile.ProjectLibraries.Add(projectLibrary); } } } diff --git a/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs b/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs new file mode 100644 index 000000000..71e613ea4 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/MSBuildProjectDescription.cs @@ -0,0 +1,49 @@ +// 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.Collections.Generic; +using System.Linq; +using Microsoft.DotNet.ProjectModel.Graph; + +namespace Microsoft.DotNet.ProjectModel +{ + /// + /// Represents an MSBuild project. + /// It has been invisibly built by MSBuild, so it behaves like a package: can provide all assets up front + /// + /// Path points to the project's directory + /// MSBuildPRojectPath points to the csproj file + /// + public class MSBuildProjectDescription : TargetLibraryWithAssets + { + public MSBuildProjectDescription( + string path, + string msbuildProjectPath, + LockFileProjectLibrary projectLibrary, + LockFileTargetLibrary lockFileLibrary, + Project projectFile, + IEnumerable dependencies, + bool compatible, + bool resolved) + : base( + new LibraryIdentity(projectLibrary.Name, projectLibrary.Version, LibraryType.MSBuildProject), + string.Empty, //msbuild projects don't have hashes + path, + lockFileLibrary, + dependencies, + resolved: resolved, + compatible: compatible, + framework: null) + { + MSBuildProjectPath = msbuildProjectPath; + ProjectFile = projectFile; + ProjectLibrary = projectLibrary; + } + + public LockFileProjectLibrary ProjectLibrary { get; } + + public string MSBuildProjectPath { get; set; } + + public Project ProjectFile { get; } + } +} diff --git a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs index ab050b72b..b52e0aa54 100644 --- a/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs +++ b/src/Microsoft.DotNet.ProjectModel/PackageDescription.cs @@ -1,7 +1,6 @@ // 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.Collections.Generic; using System.Linq; using Microsoft.DotNet.ProjectModel.Graph; @@ -9,7 +8,7 @@ using Microsoft.DotNet.ProjectModel.Resolution; namespace Microsoft.DotNet.ProjectModel { - public class PackageDescription : LibraryDescription + public class PackageDescription : TargetLibraryWithAssets { public PackageDescription( string path, @@ -22,32 +21,22 @@ namespace Microsoft.DotNet.ProjectModel new LibraryIdentity(package.Name, package.Version, LibraryType.Package), "sha512-" + package.Sha512, path, - dependencies: dependencies, - framework: null, + lockFileLibrary, + dependencies, resolved: resolved, - compatible: compatible) + compatible: compatible, + framework: null) { - Library = package; - Target = lockFileLibrary; + PackageLibrary = package; } - private LockFileTargetLibrary Target { get; } + public LockFilePackageLibrary PackageLibrary { get; } - public LockFilePackageLibrary Library { get; } + public override IEnumerable RuntimeAssemblies => FilterPlaceholders(base.RuntimeAssemblies); - public IEnumerable RuntimeAssemblies => FilterPlaceholders(Target.RuntimeAssemblies); + public override IEnumerable CompileTimeAssemblies => FilterPlaceholders(base.CompileTimeAssemblies); - public IEnumerable CompileTimeAssemblies => FilterPlaceholders(Target.CompileTimeAssemblies); - - public IEnumerable ResourceAssemblies => Target.ResourceAssemblies; - - public IEnumerable NativeLibraries => Target.NativeLibraries; - - public IEnumerable ContentFiles => Target.ContentFiles; - - public IEnumerable RuntimeTargets => Target.RuntimeTargets; - - private IEnumerable FilterPlaceholders(IList items) + private static IEnumerable FilterPlaceholders(IEnumerable items) { return items.Where(a => !PackageDependencyProvider.IsPlaceholderFile(a)); } diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs index b920e857c..7fe2e7622 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContext.cs @@ -151,7 +151,11 @@ namespace Microsoft.DotNet.ProjectModel .Where(t => t.TargetFramework.Equals(TargetFramework)) .Any(t => !string.IsNullOrEmpty(t.RuntimeIdentifier)); - var context = Create(ProjectFile.ProjectFilePath, TargetFramework, standalone ? runtimeIdentifiers : Enumerable.Empty()); + var context = CreateBuilder(ProjectFile.ProjectFilePath, TargetFramework) + .WithRuntimeIdentifiers(standalone ? runtimeIdentifiers : Enumerable.Empty()) + .WithLockFile(LockFile) + .Build(); + if (standalone && context.RuntimeIdentifier == null) { // We are standalone, but don't support this runtime diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs index 6e2d6b58f..4548a0ad4 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectContextBuilder.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.ProjectModel.Resolution; using Microsoft.Extensions.Internal; @@ -138,6 +139,8 @@ namespace Microsoft.DotNet.ProjectModel public ProjectContext Build() { + var diagnostics = new List(); + ProjectDirectory = Project?.ProjectDirectory ?? ProjectDirectory; if (GlobalSettings == null && ProjectDirectory != null) @@ -159,7 +162,7 @@ namespace Microsoft.DotNet.ProjectModel LockFileLookup lockFileLookup = null; EnsureProjectLoaded(); - LockFile = LockFile ?? LockFileResolver(ProjectDirectory); + ReadLockFile(diagnostics); var validLockFile = true; string lockFileValidationMessage = null; @@ -192,8 +195,9 @@ namespace Microsoft.DotNet.ProjectModel target = SelectTarget(LockFile); if (target != null) { - var packageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver); - ScanLibraries(target, lockFileLookup, libraries, packageResolver, projectResolver); + var nugetPackageResolver = new PackageDependencyProvider(PackagesDirectory, frameworkReferenceResolver); + var msbuildProjectResolver = new MSBuildDependencyProvider(Project, ProjectResolver); + ScanLibraries(target, lockFileLookup, libraries, msbuildProjectResolver, nugetPackageResolver, projectResolver); } } @@ -203,8 +207,6 @@ namespace Microsoft.DotNet.ProjectModel // Resolve the dependencies ResolveDependencies(libraries, referenceAssemblyDependencyResolver, out requiresFrameworkAssemblies); - var diagnostics = new List(); - // REVIEW: Should this be in NuGet (possibly stored in the lock file?) if (LockFile == null) { @@ -269,6 +271,51 @@ namespace Microsoft.DotNet.ProjectModel LockFile); } + private void ReadLockFile(ICollection diagnostics) + { + try + { + LockFile = LockFile ?? LockFileResolver(ProjectDirectory); + } + catch (FileFormatException e) + { + var lockFilePath = ""; + if (LockFile != null) + { + lockFilePath = LockFile.LockFilePath; + } + else if (Project != null) + { + lockFilePath = Path.Combine(Project.ProjectDirectory, LockFile.FileName); + } + + diagnostics.Add(new DiagnosticMessage( + ErrorCodes.DOTNET1014, + ComposeMessageFromInnerExceptions(e), + lockFilePath, + DiagnosticMessageSeverity.Error)); + } + } + + private static string ComposeMessageFromInnerExceptions(Exception exception) + { + var sb = new StringBuilder(); + var messages = new HashSet(); + + while (exception != null) + { + messages.Add(exception.Message); + exception = exception.InnerException; + } + + foreach (var message in messages) + { + sb.AppendLine(message); + } + + return sb.ToString(); + } + private void ResolveDependencies(Dictionary libraries, ReferenceAssemblyDependencyResolver referenceAssemblyDependencyResolver, out bool requiresFrameworkAssemblies) @@ -342,7 +389,7 @@ namespace Microsoft.DotNet.ProjectModel } } - private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectDependencyProvider) + private void ScanLibraries(LockFileTarget target, LockFileLookup lockFileLookup, Dictionary libraries, MSBuildDependencyProvider msbuildResolver, PackageDependencyProvider packageResolver, ProjectDependencyProvider projectResolver) { foreach (var library in target.Libraries) { @@ -355,11 +402,18 @@ namespace Microsoft.DotNet.ProjectModel if (projectLibrary != null) { - var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path)); - description = projectDependencyProvider.GetDescription(library.Name, path, library, ProjectResolver); + if (MSBuildDependencyProvider.IsMSBuildProjectLibrary(projectLibrary)) + { + description = msbuildResolver.GetDescription(TargetFramework, projectLibrary, library); + type = LibraryType.MSBuildProject; + } + else + { + var path = Path.GetFullPath(Path.Combine(ProjectDirectory, projectLibrary.Path)); + description = projectResolver.GetDescription(library.Name, path, library, ProjectResolver); + type = LibraryType.Project; + } } - - type = LibraryType.Project; } else { diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs new file mode 100644 index 000000000..ea9bda755 --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/MSBuildDependencyProvider.cs @@ -0,0 +1,106 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.DotNet.ProjectModel.Graph; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.ProjectModel.Resolution +{ + public class MSBuildDependencyProvider + { + private readonly Project _rootProject; + private readonly Func _projectResolver; + + public MSBuildDependencyProvider(Project rootProject, Func projectResolver) + { + _rootProject = rootProject; + _projectResolver = projectResolver; + } + + public MSBuildProjectDescription GetDescription(NuGetFramework targetFramework, LockFileProjectLibrary projectLibrary, LockFileTargetLibrary targetLibrary) + { + var compatible = targetLibrary.FrameworkAssemblies.Any() || + targetLibrary.CompileTimeAssemblies.Any() || + targetLibrary.RuntimeAssemblies.Any(); + + var dependencies = new List(targetLibrary.Dependencies.Count + targetLibrary.FrameworkAssemblies.Count); + PopulateDependencies(dependencies, targetLibrary, targetFramework); + + var msbuildProjectFilePath = GetMSBuildProjectFilePath(projectLibrary); + var msbuildProjectDirectoryPath = Path.GetDirectoryName(msbuildProjectFilePath); + + var exists = Directory.Exists(msbuildProjectDirectoryPath); + + var projectFile = projectLibrary.Path == null ? null : _projectResolver(projectLibrary.Path); + + var msbuildPackageDescription = new MSBuildProjectDescription( + msbuildProjectDirectoryPath, + msbuildProjectFilePath, + projectLibrary, + targetLibrary, + projectFile, + dependencies, + compatible, + resolved: compatible && exists); + + return msbuildPackageDescription; + } + + private string GetMSBuildProjectFilePath(LockFileProjectLibrary projectLibrary) + { + if (_rootProject == null) + { + throw new InvalidOperationException("Root xproj project does not exist. Cannot compute the path of its referenced csproj projects."); + } + + var rootProjectPath = Path.GetDirectoryName(_rootProject.ProjectFilePath); + var msbuildProjectFilePath = Path.Combine(rootProjectPath, projectLibrary.MSBuildProject); + + return Path.GetFullPath(msbuildProjectFilePath); + } + + private void PopulateDependencies( + List dependencies, + LockFileTargetLibrary targetLibrary, + NuGetFramework targetFramework) + { + foreach (var dependency in targetLibrary.Dependencies) + { + dependencies.Add(new LibraryRange( + dependency.Id, + dependency.VersionRange, + LibraryType.Unspecified, + LibraryDependencyType.Default)); + } + + if (!targetFramework.IsPackageBased) + { + // Only add framework assemblies for non-package based frameworks. + foreach (var frameworkAssembly in targetLibrary.FrameworkAssemblies) + { + dependencies.Add(new LibraryRange( + frameworkAssembly, + LibraryType.ReferenceAssembly, + LibraryDependencyType.Default)); + } + } + } + + public static bool IsMSBuildProjectLibrary(LockFileProjectLibrary projectLibrary) + { + var msbuildProjectPath = projectLibrary.MSBuildProject; + if (msbuildProjectPath == null) + { + return false; + } + + var extension = Path.GetExtension(msbuildProjectPath); + + return !string.Equals(extension, ".xproj", StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs b/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs new file mode 100644 index 000000000..31a8b48da --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/TargetLibraryWithAssets.cs @@ -0,0 +1,47 @@ +// 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.Collections.Generic; +using Microsoft.DotNet.ProjectModel.Graph; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.ProjectModel +{ + public abstract class TargetLibraryWithAssets : LibraryDescription + { + public TargetLibraryWithAssets( + LibraryIdentity libraryIdentity, + string sha512, + string path, + LockFileTargetLibrary lockFileLibrary, + IEnumerable dependencies, + bool compatible, + bool resolved, + NuGetFramework framework = null) + : base( + libraryIdentity, + sha512, + path, + dependencies: dependencies, + framework: null, + resolved: resolved, + compatible: compatible) + { + TargetLibrary = lockFileLibrary; + } + + private LockFileTargetLibrary TargetLibrary { get; } + + public virtual IEnumerable RuntimeAssemblies => TargetLibrary.RuntimeAssemblies; + + public virtual IEnumerable CompileTimeAssemblies => TargetLibrary.CompileTimeAssemblies; + + public virtual IEnumerable ResourceAssemblies => TargetLibrary.ResourceAssemblies; + + public virtual IEnumerable NativeLibraries => TargetLibrary.NativeLibraries; + + public virtual IEnumerable ContentFiles => TargetLibrary.ContentFiles; + + public virtual IEnumerable RuntimeTargets => TargetLibrary.RuntimeTargets; + } +} diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index db5b0429a..15c1e5dec 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -603,6 +603,11 @@ namespace Microsoft.DotNet.Tools.Build } compilerIO.Inputs.Add(project.LockFile.LockFilePath); + + if (project.LockFile.ExportFile != null) + { + compilerIO.Inputs.Add(project.LockFile.ExportFile.ExportFilePath); + } } private static void AddDependencies(ProjectDependenciesFacade dependencies, CompilerIO compilerIO) diff --git a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs index 684d2e403..01cb47e25 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/InternalModels/ProjectContextSnapshot.cs @@ -4,7 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; -using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.DotNet.ProjectModel.Server.Helpers; using Microsoft.DotNet.ProjectModel.Server.Models; using Microsoft.DotNet.Cli.Compiler.Common; @@ -51,15 +51,13 @@ namespace Microsoft.DotNet.ProjectModel.Server var description = DependencyDescription.Create(export.Library, diagnostics, allExports); allDependencies[description.Name] = description; - var projectDescription = export.Library as ProjectDescription; - if (projectDescription != null) + var projectReferene = ProjectReferenceDescription.Create(export.Library); + if (projectReferene != null && export.Library.Identity.Name != context.ProjectFile.Name) { - if (projectDescription.Identity.Name != context.ProjectFile.Name) - { - allProjectReferences.Add(ProjectReferenceDescription.Create(projectDescription)); - } + allProjectReferences.Add(projectReferene); } - else + + if (export.Library.Identity.Type != LibraryType.Project) { allFileReferences.AddRange(export.CompilationAssemblies.Select(asset => asset.ResolvedPath)); } diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs index c30be87d9..07aa58a64 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Models/DependencyDescription.cs @@ -5,7 +5,6 @@ using System.Collections.Generic; using System.Linq; using Microsoft.DotNet.ProjectModel.Compilation; using Microsoft.DotNet.ProjectModel.Graph; -using Microsoft.DotNet.ProjectModel.Server.Helpers; namespace Microsoft.DotNet.ProjectModel.Server.Models { @@ -24,7 +23,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models public string Type { get; private set; } public bool Resolved { get; private set; } - + public IEnumerable Dependencies { get; private set; } public IEnumerable Errors { get; private set; } @@ -57,7 +56,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models List diagnostics, IDictionary exportsLookup) { - return new DependencyDescription + var result = new DependencyDescription { Name = library.Identity.Name, DisplayName = library.Identity.Name, @@ -71,6 +70,14 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models Warnings = diagnostics.Where(d => d.Severity == DiagnosticMessageSeverity.Warning) .Select(d => new DiagnosticMessageView(d)) }; + + var msbuildLibrary = library as MSBuildProjectDescription; + if (msbuildLibrary != null) + { + result.Path = msbuildLibrary.MSBuildProjectPath; + } + + return result; } private static DependencyItem GetDependencyItem(LibraryRange dependency, diff --git a/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs b/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs index b0cb6ffc0..224837488 100644 --- a/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs +++ b/src/dotnet/commands/dotnet-projectmodel-server/Models/ProjectReferenceDescription.cs @@ -1,8 +1,6 @@ // 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 NuGet.Frameworks; - namespace Microsoft.DotNet.ProjectModel.Server.Models { internal class ProjectReferenceDescription @@ -12,44 +10,48 @@ namespace Microsoft.DotNet.ProjectModel.Server.Models public FrameworkData Framework { get; set; } public string Name { get; set; } public string Path { get; set; } - public string WrappedProjectPath { get; set; } public override bool Equals(object obj) { var other = obj as ProjectReferenceDescription; return other != null && string.Equals(Name, other.Name) && - string.Equals(Path, other.Path) && - string.Equals(WrappedProjectPath, other.WrappedProjectPath); + string.Equals(Path, other.Path); } public override int GetHashCode() { return base.GetHashCode(); } - - public static ProjectReferenceDescription Create(ProjectDescription description) + + /// + /// Create a ProjectReferenceDescription from given LibraryDescription. If the library doesn't + /// represent a project reference returns null. + /// + public static ProjectReferenceDescription Create(LibraryDescription library) { - var targetFrameworkInformation = description.TargetFrameworkInfo; - - string wrappedProjectPath = null; - if (!string.IsNullOrEmpty(targetFrameworkInformation?.WrappedProject) && - description.Project != null) + if (library is ProjectDescription) { - wrappedProjectPath = System.IO.Path.Combine( - description.Project.ProjectDirectory, - targetFrameworkInformation.WrappedProject); - - wrappedProjectPath = System.IO.Path.GetFullPath(wrappedProjectPath); + return new ProjectReferenceDescription + { + Framework = library.Framework.ToPayload(), + Name = library.Identity.Name, + Path = library.Path + }; } - - return new ProjectReferenceDescription + else if (library is MSBuildProjectDescription) { - Framework = description.Framework.ToPayload(), - Name = description.Identity.Name, - Path = description.Path, - WrappedProjectPath = wrappedProjectPath, - }; + return new ProjectReferenceDescription + { + Framework = library.Framework.ToPayload(), + Name = library.Identity.Name, + Path = ((MSBuildProjectDescription)library).MSBuildProjectPath, + }; + } + else + { + return null; + } } } } diff --git a/src/dotnet/commands/dotnet-publish/Program.cs b/src/dotnet/commands/dotnet-publish/Program.cs index e06e484a9..849fec5fd 100644 --- a/src/dotnet/commands/dotnet-publish/Program.cs +++ b/src/dotnet/commands/dotnet-publish/Program.cs @@ -28,6 +28,7 @@ namespace Microsoft.DotNet.Tools.Publish var configuration = app.Option("-c|--configuration ", "Configuration under which to build", CommandOptionType.SingleValue); var projectPath = app.Argument("", "The project to publish, defaults to the current directory. Can be a path to a project.json or a project directory"); var nativeSubdirectories = app.Option("--native-subdirectory", "Temporary mechanism to include subdirectories from native assets of dependency packages in output", CommandOptionType.NoValue); + var noBuild = app.Option("--no-build", "Do not build projects before publishing", CommandOptionType.NoValue); app.OnExecute(() => { @@ -41,6 +42,7 @@ namespace Microsoft.DotNet.Tools.Publish publish.NativeSubdirectories = nativeSubdirectories.HasValue(); publish.ProjectPath = projectPath.Value; publish.VersionSuffix = versionSuffix.Value(); + publish.ShouldBuild = !noBuild.HasValue(); if (string.IsNullOrEmpty(publish.ProjectPath)) { diff --git a/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index 9fb175ed7..abe835442 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -35,6 +35,7 @@ namespace Microsoft.DotNet.Tools.Publish public string VersionSuffix { get; set; } public int NumberOfProjects { get; private set; } public int NumberOfPublishedProjects { get; private set; } + public bool ShouldBuild { get; set; } public bool TryPrepareForPublish() { @@ -119,34 +120,7 @@ namespace Microsoft.DotNet.Tools.Publish } // Compile the project (and transitively, all it's dependencies) - var args = new List() { - "--framework", - $"{context.TargetFramework.DotNetFrameworkName}", - "--configuration", - configuration, - context.ProjectFile.ProjectDirectory - }; - - if (!string.IsNullOrEmpty(context.RuntimeIdentifier)) - { - args.Insert(0, context.RuntimeIdentifier); - args.Insert(0, "--runtime"); - } - - if (!string.IsNullOrEmpty(VersionSuffix)) - { - args.Add("--version-suffix"); - args.Add(VersionSuffix); - } - - if (!string.IsNullOrEmpty(buildBasePath)) - { - args.Add("--build-base-path"); - args.Add(buildBasePath); - } - - var result = Build.BuildCommand.Run(args.ToArray()); - if (result != 0) + if (ShouldBuild && !InvokeBuildOnProject(context, buildBasePath, configuration)) { return false; } @@ -206,6 +180,40 @@ namespace Microsoft.DotNet.Tools.Publish return true; } + private bool InvokeBuildOnProject(ProjectContext context, string buildBasePath, string configuration) + { + var args = new List() + { + "--framework", + $"{context.TargetFramework.DotNetFrameworkName}", + "--configuration", + configuration, + context.ProjectFile.ProjectDirectory + }; + + if (!string.IsNullOrEmpty(context.RuntimeIdentifier)) + { + args.Insert(0, context.RuntimeIdentifier); + args.Insert(0, "--runtime"); + } + + if (!string.IsNullOrEmpty(VersionSuffix)) + { + args.Add("--version-suffix"); + args.Add(VersionSuffix); + } + + if (!string.IsNullOrEmpty(buildBasePath)) + { + args.Add("--build-base-path"); + args.Add(buildBasePath); + } + + var result = Build.BuildCommand.Run(args.ToArray()); + + return result == 0; + } + private HashSet GetExclusionList(ProjectContext context, Dictionary exports) { var exclusionList = new HashSet(); diff --git a/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs b/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs new file mode 100644 index 000000000..2688643ee --- /dev/null +++ b/test/Microsoft.DotNet.ProjectModel.Tests/LockFilePatchingTests.cs @@ -0,0 +1,127 @@ +// 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.IO; +using System.Linq; +using FluentAssertions; +using Xunit; +using Microsoft.DotNet.ProjectModel.Graph; +using Microsoft.DotNet.Tools.Test.Utilities; +using NuGet.ProjectModel; + +namespace Microsoft.DotNet.ProjectModel.Tests +{ + public class LockFilePatchingTests : TestBase + { + + private static string ExportFilesRoot=> Path.Combine(RepoRoot, "TestAssets", "LockFiles", "ExportFiles"); + + [Fact] + public void TestExportFileIsParsed() + { + var lockFilePath = GetLockFilePath("valid"); + var lockFile = LockFileReader.Read(lockFilePath); + + var exportFile = lockFile.ExportFile; + + exportFile.Should().NotBeNull(); + exportFile.Exports.Count.Should().Be(3); + exportFile.Exports.Should().OnlyHaveUniqueItems(); + + // check export structure + foreach (var export in exportFile.Exports) + { + export.TargetFramework.Should().NotBeNull(); + AssertTargetLibrary(export); + } + } + + [Fact] + public void TestLockFileIsPatchedWithExportData() + { + var lockFilePath = GetLockFilePath("valid"); + var lockFile = LockFileReader.Read(lockFilePath); + + // check lock file structure is similar to export structure + foreach (var target in lockFile.Targets) + { + target.Libraries.Count.Should().Be(3); + + foreach (var library in target.Libraries) + { + AssertTargetLibrary(library); + } + } + } + + [Fact] + public void TestFragmentExistsButNoHolesInLockFile() + { + var lockFilePath = GetLockFilePath("valid_staleFragment"); + var lockFile = LockFileReader.Read(lockFilePath); + + var exportFile = lockFile.ExportFile; + + exportFile.Should().BeNull(); + + lockFile.Targets.Count.Should().Be(1); + + lockFile.Targets[0].Libraries.Count.Should().Be(0); + } + + [Fact] + public void TestMissingExportFileThrows() + { + var lockFilePath = GetLockFilePath("invalid_nofragment"); + + Assert.Throws(() => LockFileReader.Read(lockFilePath)); + } + + [Fact] + public void TestMissingExportsThrow() + { + var lockFilePath = GetLockFilePath("invalid_missing-exports"); + + Assert.Throws(() => LockFileReader.Read(lockFilePath)); + } + + [Fact] + public void TestMissmatchingFileVersionsThrows() + { + var lockFilePath = GetLockFilePath("invalid_missmatching-versions"); + + Assert.Throws(() => LockFileReader.Read(lockFilePath)); + } + + private static int LibraryNumberFromName(Microsoft.DotNet.ProjectModel.Graph.LockFileTargetLibrary library) + { + var libraryName = library.Name; + return (int)char.GetNumericValue(libraryName[libraryName.Length - 1]); + } + + private static void AssertTargetLibrary(Microsoft.DotNet.ProjectModel.Graph.LockFileTargetLibrary library) + { + var libraryNumber = LibraryNumberFromName(library); + + library.Type.Should().Be("project"); + + library.Name.Should().Be("ClassLibrary" + libraryNumber); + library.Version.ToNormalizedString().Should().Be("1.0.0"); + + var dll = $"bin/Debug/ClassLibrary{libraryNumber}.dll"; + dll = dll.Replace('/', Path.DirectorySeparatorChar); + + library.CompileTimeAssemblies.Count.Should().Be(1); + library.CompileTimeAssemblies.ElementAt(0).Path.Should().Be(dll); + + library.RuntimeAssemblies.Count.Should().Be(1); + library.RuntimeAssemblies.ElementAt(0).Path.Should().Be(dll); + } + + private static string GetLockFilePath(string exportSample) + { + return Path.Combine(ExportFilesRoot, exportSample, "project.lock.json"); + } + } +} diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs index 284d5be39..509530b9b 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/PublishCommand.cs @@ -19,9 +19,10 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private readonly string _framework; private readonly string _runtime; private readonly string _config; + private readonly bool _noBuild; private readonly string _output; - public PublishCommand(string projectPath, string framework = "", string runtime = "", string output = "", string config = "", bool forcePortable = false) + public PublishCommand(string projectPath, string framework = "", string runtime = "", string output = "", string config = "", bool forcePortable = false, bool noBuild = false) : base("dotnet") { _path = projectPath; @@ -30,6 +31,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities _runtime = runtime; _output = output; _config = config; + _noBuild = noBuild; } public override CommandResult Execute(string args = "") @@ -91,12 +93,13 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private string BuildArgs() { - return $"{_path} {FrameworkOption} {RuntimeOption} {OutputOption} {ConfigOption}"; + return $"{_path} {FrameworkOption} {RuntimeOption} {OutputOption} {ConfigOption} {NoBuildFlag}"; } private string FrameworkOption => string.IsNullOrEmpty(_framework) ? "" : $"-f {_framework}"; private string RuntimeOption => string.IsNullOrEmpty(_runtime) ? "" : $"-r {_runtime}"; private string OutputOption => string.IsNullOrEmpty(_output) ? "" : $"-o \"{_output}\""; private string ConfigOption => string.IsNullOrEmpty(_config) ? "" : $"-c {_output}"; + private string NoBuildFlag => _noBuild ? "--no-build" :""; } } diff --git a/test/dotnet-projectmodel-server.Tests/DthTests.cs b/test/dotnet-projectmodel-server.Tests/DthTests.cs index 1d10084ab..92df20c70 100644 --- a/test/dotnet-projectmodel-server.Tests/DthTests.cs +++ b/test/dotnet-projectmodel-server.Tests/DthTests.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; @@ -148,8 +149,7 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests .AssertJArrayCount(1) .RetrieveArraryElementAs(0) .AssertProperty("Name", expectedUnresolvedDependency) - .AssertProperty("Path", expectedUnresolvedProjectPath) - .AssertProperty("WrappedProjectPath", prop => !prop.HasValues); + .AssertProperty("Path", expectedUnresolvedProjectPath); } else if (referenceType == "Package") { @@ -412,5 +412,64 @@ namespace Microsoft.DotNet.ProjectModel.Server.Tests } } } + + [Fact] + public void MSBuildReferenceTest() + { + var testProject = Path.Combine(RepoRoot, "TestAssets", + "ProjectModelServer", + "MSBuildReferencesProjects", + "ValidCase01", + "src", + "MainApp"); + + using (var server = new DthTestServer(_loggerFactory)) + using (var client = new DthTestClient(server, _loggerFactory)) + { + client.Initialize(testProject); + var messages = client.DrainAllMessages(); + + var classLibraries = new HashSet(new string[] { "ClassLibrary1", "ClassLibrary2", "ClassLibrary3" }); + var dependencies = messages.RetrieveSingleMessage(MessageTypes.Dependencies); + var testProjectRoot = Path.Combine(RepoRoot, "TestAssets", "ProjectModelServer", "MSBuildReferencesProjects", "ValidCase01"); + foreach (var classLibrary in classLibraries) + { + dependencies.RetrieveDependency(classLibrary) + .AssertProperty("Type", LibraryType.MSBuildProject.ToString()) + .AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, classLibrary, $"{classLibrary}.csproj"))) + .AssertProperty("Resolved", true) + .AssertProperty("Name", classLibrary) + .AssertProperty("Errors", array => array.Count == 0) + .AssertProperty("Warnings", array => array.Count == 0); + } + + var references = messages.RetrieveSingleMessage(MessageTypes.References) + .RetrievePayloadAs(); + + var projectReferences = references.RetrievePropertyAs("ProjectReferences"); + Assert.Equal(3, projectReferences.Count); + for (int i = 0; i < 3; ++i) + { + var projectRef = projectReferences.RetrieveArraryElementAs(i); + var name = projectRef["Name"].Value(); + + Assert.True(classLibraries.Contains(name)); + projectRef.AssertProperty("Path", NormalizePathString(Path.Combine(testProjectRoot, name, $"{name}.csproj"))); + } + + var fileReferences = references.RetrievePropertyAs("FileReferences") + .Select(each => each.Value()) + .ToArray(); + foreach (var each in classLibraries) + { + fileReferences.Contains(Path.Combine("ValidCase01", "ClassLibrary1", "bin", "Debug", $"{each}.dll")); + } + } + } + + private static string NormalizePathString(string original) + { + return original.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); + } } } diff --git a/test/dotnet-publish.Tests/PublishTests.cs b/test/dotnet-publish.Tests/PublishTests.cs index 7aa760807..99a282b7f 100644 --- a/test/dotnet-publish.Tests/PublishTests.cs +++ b/test/dotnet-publish.Tests/PublishTests.cs @@ -176,6 +176,31 @@ namespace Microsoft.DotNet.Tools.Publish.Tests publishCommand.Execute().Should().Fail(); } + [Fact] + public void PublishFailsWhenProjectNotBuiltAndNoBuildFlagSet() + { + TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppCompilationContext") + .WithLockFiles(); + + var testProject = _getProjectJson(instance.TestRoot, "TestApp"); + var publishCommand = new PublishCommand(testProject, noBuild: true); + + publishCommand.Execute().Should().Fail(); + } + + [Fact] + public void PublishSucceedsWhenProjectPreviouslyCompiledAndNoBuildFlagSet() + { + TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppCompilationContext") + .WithLockFiles() + .WithBuildArtifacts(); + + var testProject = _getProjectJson(instance.TestRoot, "TestApp"); + var publishCommand = new PublishCommand(testProject, noBuild: true); + + publishCommand.Execute().Should().Pass(); + } + [Fact] public void PublishScriptsRun() { diff --git a/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs b/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs index f1c0629c1..81d9da1c1 100644 --- a/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs +++ b/tools/RuntimeGraphGenerator/RuntimeGraphManager.cs @@ -21,7 +21,7 @@ namespace Microsoft.DotNet.ProjectModel { if (export.Library.Identity.Type == LibraryType.Package) { - var runtimeJson = ((PackageDescription) export.Library).Library.Files.FirstOrDefault(f => f == RuntimeJsonFileName); + var runtimeJson = ((PackageDescription) export.Library).PackageLibrary.Files.FirstOrDefault(f => f == RuntimeJsonFileName); if (runtimeJson != null) { var runtimeJsonFullName = Path.Combine(export.Library.Path, runtimeJson);