diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index bd7e28c5a..41f709b3b 100644 --- a/Microsoft.DotNet.Cli.sln +++ b/Microsoft.DotNet.Cli.sln @@ -37,15 +37,7 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "EndToEnd", "test\EndToEnd\E EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Tools.Test.Utilities", "test\Microsoft.DotNet.Tools.Tests.Utilities\Microsoft.DotNet.Tools.Test.Utilities.xproj", "{E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestApp", "TestAssets\TestProjects\TestApp\TestApp.xproj", "{58808BBC-371E-47D6-A3D0-4902145EDA4E}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithArgs", "TestAssets\TestProjects\TestAppWithArgs\TestAppWithArgs.xproj", "{DA8E0E9E-A6D6-4583-864C-8F40465E3A48}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithContents", "TestAssets\TestProjects\TestAppWithContents\TestAppWithContents.xproj", "{0138CB8F-4AA9-4029-A21E-C07C30F425BA}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestLibrary", "TestAssets\TestProjects\TestLibrary\TestLibrary.xproj", "{947DD232-8D9B-4B78-9C6A-94F807D2DD58}" -EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestProjectToProjectDependencies", "TestAssets\TestProjects\TestProjectToProjectDependencies\TestProjectToProjectDependencies.xproj", "{947DD232-8D9B-4B78-9C6A-94F807D22222}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestProjects", "TestProjects", "{713CBFBB-5392-438D-B766-A9A585EF1BB8}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet", "src\dotnet\dotnet.xproj", "{60CF7E6C-D6C8-439D-B7B7-D8A27E29BE2C}" EndProject @@ -59,11 +51,17 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-projectmodel-server. EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Files", "src\Microsoft.DotNet.Files\Microsoft.DotNet.Files.xproj", "{D521DD9F-0614-4929-93B4-D8FA5682C174}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{82BD2E61-326D-4EA4-A1C1-93A565573C81}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-compile.UnitTests", "test\dotnet-compile.UnitTests\dotnet-compile.UnitTests.xproj", "{920B71D8-62DA-4F5E-8A26-926C113F1D97}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Cli.Utils.Tests", "test\Microsoft.DotNet.Cli.Utils.Tests\Microsoft.DotNet.Cli.Utils.Tests.xproj", "{09C52F96-EFDD-4448-95EC-6D362DD60BAA}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestApp", "TestAssets\TestProjects\TestApp\TestApp.xproj", "{58808BBC-371E-47D6-A3D0-4902145EDA4E}" EndProject -Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Compiler.Common.Tests", "test\Microsoft.DotNet.Compiler.Common.Tests\Microsoft.DotNet.Compiler.Common.Tests.xproj", "{44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithArgs", "TestAssets\TestProjects\TestAppWithArgs\TestAppWithArgs.xproj", "{DA8E0E9E-A6D6-4583-864C-8F40465E3A48}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestAppWithContents", "TestAssets\TestProjects\TestAppWithContents\TestAppWithContents.xproj", "{0138CB8F-4AA9-4029-A21E-C07C30F425BA}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestLibrary", "TestAssets\TestProjects\TestLibrary\TestLibrary.xproj", "{947DD232-8D9B-4B78-9C6A-94F807D2DD58}" +EndProject +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "TestProjectToProjectDependencies", "TestAssets\TestProjects\TestProjectToProjectDependencies\TestProjectToProjectDependencies.xproj", "{947DD232-8D9B-4B78-9C6A-94F807D22222}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -253,86 +251,6 @@ Global {E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|x64.ActiveCfg = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|x64.Build.0 = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|Any CPU.Build.0 = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|x64.ActiveCfg = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|x64.Build.0 = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|x64.ActiveCfg = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|x64.Build.0 = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|Any CPU.Build.0 = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|x64.ActiveCfg = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|x64.Build.0 = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|x64.ActiveCfg = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|x64.Build.0 = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|x64.ActiveCfg = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|x64.Build.0 = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.Build.0 = Release|Any CPU {60CF7E6C-D6C8-439D-B7B7-D8A27E29BE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {60CF7E6C-D6C8-439D-B7B7-D8A27E29BE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU {60CF7E6C-D6C8-439D-B7B7-D8A27E29BE2C}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -429,38 +347,102 @@ Global {D521DD9F-0614-4929-93B4-D8FA5682C174}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU {D521DD9F-0614-4929-93B4-D8FA5682C174}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU {D521DD9F-0614-4929-93B4-D8FA5682C174}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Debug|x64.ActiveCfg = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Debug|x64.Build.0 = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Release|Any CPU.Build.0 = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Release|x64.ActiveCfg = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.Release|x64.Build.0 = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {09C52F96-EFDD-4448-95EC-6D362DD60BAA}.RelWithDebInfo|x64.Build.0 = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Debug|x64.ActiveCfg = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Debug|x64.Build.0 = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Release|Any CPU.Build.0 = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Release|x64.ActiveCfg = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.Release|x64.Build.0 = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Debug|Any CPU.Build.0 = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Debug|x64.ActiveCfg = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Debug|x64.Build.0 = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Release|Any CPU.ActiveCfg = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Release|Any CPU.Build.0 = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Release|x64.ActiveCfg = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.Release|x64.Build.0 = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {920B71D8-62DA-4F5E-8A26-926C113F1D97}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|x64.ActiveCfg = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Debug|x64.Build.0 = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|Any CPU.Build.0 = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|x64.ActiveCfg = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.Release|x64.Build.0 = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {58808BBC-371E-47D6-A3D0-4902145EDA4E}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|x64.ActiveCfg = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Debug|x64.Build.0 = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|Any CPU.Build.0 = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|x64.ActiveCfg = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.Release|x64.Build.0 = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|x64.ActiveCfg = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Debug|x64.Build.0 = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|Any CPU.Build.0 = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|x64.ActiveCfg = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.Release|x64.Build.0 = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {0138CB8F-4AA9-4029-A21E-C07C30F425BA}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|Any CPU.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|x64.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Debug|x64.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|Any CPU.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|Any CPU.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|x64.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.Release|x64.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D2DD58}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|Any CPU.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Debug|x64.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|Any CPU.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.Release|x64.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {947DD232-8D9B-4B78-9C6A-94F807D22222}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -477,18 +459,18 @@ Global {688870C8-9843-4F9E-8576-D39290AD0F25} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {65741CB1-8AEE-4C66-8198-10A7EA0E4258} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {E4F46EAB-B5A5-4E60-9B9D-40A1FADBF45C} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} - {58808BBC-371E-47D6-A3D0-4902145EDA4E} = {82BD2E61-326D-4EA4-A1C1-93A565573C81} - {DA8E0E9E-A6D6-4583-864C-8F40465E3A48} = {82BD2E61-326D-4EA4-A1C1-93A565573C81} - {0138CB8F-4AA9-4029-A21E-C07C30F425BA} = {82BD2E61-326D-4EA4-A1C1-93A565573C81} - {947DD232-8D9B-4B78-9C6A-94F807D2DD58} = {82BD2E61-326D-4EA4-A1C1-93A565573C81} - {947DD232-8D9B-4B78-9C6A-94F807D22222} = {82BD2E61-326D-4EA4-A1C1-93A565573C81} + {713CBFBB-5392-438D-B766-A9A585EF1BB8} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {60CF7E6C-D6C8-439D-B7B7-D8A27E29BE2C} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} {833FFEE1-7EED-4F51-8DFD-946D48833333} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {833FFEE1-7EED-4F51-8DFD-946D48893D6E} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {386D412C-003C-47B1-8258-0E35865CB7C4} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {11C77123-E4DA-499F-8900-80C88C2C69F2} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {D521DD9F-0614-4929-93B4-D8FA5682C174} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} - {09C52F96-EFDD-4448-95EC-6D362DD60BAA} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} - {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} + {920B71D8-62DA-4F5E-8A26-926C113F1D97} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} + {58808BBC-371E-47D6-A3D0-4902145EDA4E} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} + {DA8E0E9E-A6D6-4583-864C-8F40465E3A48} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} + {0138CB8F-4AA9-4029-A21E-C07C30F425BA} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} + {947DD232-8D9B-4B78-9C6A-94F807D2DD58} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} + {947DD232-8D9B-4B78-9C6A-94F807D22222} = {713CBFBB-5392-438D-B766-A9A585EF1BB8} EndGlobalSection EndGlobal diff --git a/scripts/configuration/testProjects.csv b/scripts/configuration/testProjects.csv index bc53a303d..74fafd179 100644 --- a/scripts/configuration/testProjects.csv +++ b/scripts/configuration/testProjects.csv @@ -1,6 +1,7 @@ EndToEnd dotnet-publish.Tests dotnet-compile.Tests +dotnet-compile.UnitTests dotnet-build.Tests Microsoft.DotNet.Cli.Utils.Tests Microsoft.DotNet.Compiler.Common.Tests diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index 6118deaa1..9c451c32d 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -11,7 +11,7 @@ using NuGet.Frameworks; namespace Microsoft.DotNet.Cli.Utils { - public class Command + public class Command : ICommand { private readonly Process _process; private readonly StreamForwarder _stdOut; @@ -31,7 +31,7 @@ namespace Microsoft.DotNet.Cli.Utils _stdOut = new StreamForwarder(); _stdErr = new StreamForwarder(); - + _process = new Process { StartInfo = psi @@ -68,7 +68,7 @@ namespace Microsoft.DotNet.Cli.Utils return command; } - + public CommandResult Execute() { @@ -115,33 +115,33 @@ namespace Microsoft.DotNet.Cli.Utils _stdErr.CapturedOutput); } - public Command WorkingDirectory(string projectDirectory) + public ICommand WorkingDirectory(string projectDirectory) { _process.StartInfo.WorkingDirectory = projectDirectory; return this; } - public Command EnvironmentVariable(string name, string value) + public ICommand EnvironmentVariable(string name, string value) { _process.StartInfo.Environment[name] = value; return this; } - public Command CaptureStdOut() + public ICommand CaptureStdOut() { ThrowIfRunning(); _stdOut.Capture(); return this; } - public Command CaptureStdErr() + public ICommand CaptureStdErr() { ThrowIfRunning(); _stdErr.Capture(); return this; } - public Command ForwardStdOut(TextWriter to = null, bool onlyIfVerbose = false) + public ICommand ForwardStdOut(TextWriter to = null, bool onlyIfVerbose = false) { ThrowIfRunning(); if (!onlyIfVerbose || CommandContext.IsVerbose()) @@ -158,7 +158,7 @@ namespace Microsoft.DotNet.Cli.Utils return this; } - public Command ForwardStdErr(TextWriter to = null, bool onlyIfVerbose = false) + public ICommand ForwardStdErr(TextWriter to = null, bool onlyIfVerbose = false) { ThrowIfRunning(); if (!onlyIfVerbose || CommandContext.IsVerbose()) @@ -175,14 +175,14 @@ namespace Microsoft.DotNet.Cli.Utils return this; } - public Command OnOutputLine(Action handler) + public ICommand OnOutputLine(Action handler) { ThrowIfRunning(); _stdOut.ForwardTo(writeLine: handler); return this; } - public Command OnErrorLine(Action handler) + public ICommand OnErrorLine(Action handler) { ThrowIfRunning(); _stdErr.ForwardTo(writeLine: handler); diff --git a/src/Microsoft.DotNet.Cli.Utils/DotNetCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/DotNetCommandFactory.cs new file mode 100644 index 000000000..ba48a29d9 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/DotNetCommandFactory.cs @@ -0,0 +1,16 @@ +// 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 NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public class DotNetCommandFactory : ICommandFactory + { + public ICommand Create(string commandName, IEnumerable args, NuGetFramework framework = null, bool useComSpec = false) + { + return Command.CreateDotNet(commandName, args, framework, useComSpec); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/ICommand.cs b/src/Microsoft.DotNet.Cli.Utils/ICommand.cs new file mode 100644 index 000000000..226736310 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/ICommand.cs @@ -0,0 +1,33 @@ +// 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; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface ICommand + { + CommandResult Execute(); + + ICommand WorkingDirectory(string projectDirectory); + + ICommand EnvironmentVariable(string name, string value); + + ICommand CaptureStdOut(); + + ICommand CaptureStdErr(); + + ICommand ForwardStdOut(TextWriter to = null, bool onlyIfVerbose = false); + + ICommand ForwardStdErr(TextWriter to = null, bool onlyIfVerbose = false); + + ICommand OnOutputLine(Action handler); + + ICommand OnErrorLine(Action handler); + + CommandResolutionStrategy ResolutionStrategy { get; } + + string CommandName { get; } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs new file mode 100644 index 000000000..ae6beddee --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/ICommandFactory.cs @@ -0,0 +1,14 @@ +// 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 NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils +{ + public interface ICommandFactory + { + ICommand Create( + string commandName, IEnumerable args, NuGetFramework framework = null, bool useComSpec = false); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs b/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs index 59ef038f9..cba1bd255 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs @@ -10,12 +10,12 @@ namespace Microsoft.DotNet.Cli.Utils { public static class ScriptExecutor { - public static Command CreateCommandForScript(Project project, string scriptCommandLine, IDictionary variables) + public static ICommand CreateCommandForScript(Project project, string scriptCommandLine, IDictionary variables) { return CreateCommandForScript(project, scriptCommandLine, WrapVariableDictionary(variables)); } - public static Command CreateCommandForScript(Project project, string scriptCommandLine, Func getVariable) + public static ICommand CreateCommandForScript(Project project, string scriptCommandLine, Func getVariable) { // Preserve quotation marks around arguments since command is about to be passed to a shell. May need // the quotes to ensure the shell groups arguments correctly. diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index 91469b7d9..7d4093c54 100644 --- a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs +++ b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs @@ -122,8 +122,8 @@ namespace Microsoft.DotNet.ProjectModel.Compilation } /// - /// Create a LibraryExport from LibraryDescription. - /// + /// Create a LibraryExport from LibraryDescription. + /// /// When the library is not resolved the LibraryExport is created nevertheless. /// private LibraryExport GetExport(LibraryDescription library) diff --git a/src/dotnet/commands/dotnet-compile/CompilationDriver.cs b/src/dotnet/commands/dotnet-compile/CompilationDriver.cs new file mode 100644 index 000000000..897c293e3 --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/CompilationDriver.cs @@ -0,0 +1,36 @@ +// 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; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public class CompilationDriver + { + private readonly ICompiler _managedCompiler; + private readonly ICompiler _nativeCompiler; + + public CompilationDriver(ICompiler managedCompiler, ICompiler nativeCompiler) + { + _managedCompiler = managedCompiler; + _nativeCompiler = nativeCompiler; + } + + public bool Compile(IEnumerable contexts, CompilerCommandApp args) + { + var success = true; + + foreach (var context in contexts) + { + success &= _managedCompiler.Compile(context, args); + if (args.IsNativeValue && success) + { + success &= _nativeCompiler.Compile(context, args); + } + } + + return success; + } + } +} diff --git a/src/dotnet/commands/dotnet-compile/Compiler.cs b/src/dotnet/commands/dotnet-compile/Compiler.cs new file mode 100644 index 000000000..6a0f6a75c --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/Compiler.cs @@ -0,0 +1,202 @@ +// 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.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Compilation; +using Microsoft.DotNet.ProjectModel.Resources; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public abstract class Compiler : ICompiler + { + public abstract bool Compile(ProjectContext context, CompilerCommandApp args); + + protected static bool PrintSummary(List diagnostics, Stopwatch sw, bool success = true) + { + PrintDiagnostics(diagnostics); + + Reporter.Output.WriteLine(); + + var errorCount = diagnostics.Count(d => d.Severity == DiagnosticMessageSeverity.Error); + var warningCount = diagnostics.Count(d => d.Severity == DiagnosticMessageSeverity.Warning); + + if (errorCount > 0 || !success) + { + Reporter.Output.WriteLine("Compilation failed.".Red()); + success = false; + } + else + { + Reporter.Output.WriteLine("Compilation succeeded.".Green()); + } + + Reporter.Output.WriteLine($" {warningCount} Warning(s)"); + Reporter.Output.WriteLine($" {errorCount} Error(s)"); + + Reporter.Output.WriteLine(); + + Reporter.Output.WriteLine($"Time elapsed {sw.Elapsed}"); + + return success; + } + + protected static bool AddNonCultureResources(Project project, List compilerArgs, string intermediateOutputPath) + { + var resgenFiles = CompilerUtil.GetNonCultureResources(project, intermediateOutputPath); + + foreach (var resgenFile in resgenFiles) + { + if (ResourceUtility.IsResxFile(resgenFile.InputFile)) + { + var arguments = new[] + { + resgenFile.InputFile, + $"-o:{resgenFile.OutputFile}", + $"-v:{project.Version.Version}" + }; + + var rsp = Path.Combine(intermediateOutputPath, $"dotnet-resgen-resx.rsp"); + File.WriteAllLines(rsp, arguments); + + var result = Resgen.ResgenCommand.Run(new[] { $"@{rsp}" }); + + if (result != 0) + { + return false; + } + + compilerArgs.Add($"--resource:\"{resgenFile.OutputFile},{Path.GetFileName(resgenFile.MetadataName)}\""); + } + else + { + compilerArgs.Add($"--resource:\"{resgenFile.InputFile},{Path.GetFileName(resgenFile.MetadataName)}\""); + } + } + + return true; + } + + protected static bool GenerateCultureResourceAssemblies( + Project project, + List dependencies, + string intermediateOutputPath, + string outputPath) + { + var referencePaths = CompilerUtil.GetReferencePathsForCultureResgen(dependencies); + var resgenReferenceArgs = referencePaths.Select(path => $"-r:{path}").ToList(); + var cultureResgenFiles = CompilerUtil.GetCultureResources(project, outputPath); + + foreach (var resgenFile in cultureResgenFiles) + { + var resourceOutputPath = Path.GetDirectoryName(resgenFile.OutputFile); + + if (!Directory.Exists(resourceOutputPath)) + { + Directory.CreateDirectory(resourceOutputPath); + } + + var arguments = new List(); + + arguments.AddRange(resgenReferenceArgs); + arguments.Add($"-o:{resgenFile.OutputFile}"); + arguments.Add($"-c:{resgenFile.Culture}"); + arguments.Add($"-v:{project.Version.Version}"); + arguments.AddRange(resgenFile.InputFileToMetadata.Select(fileToMetadata => $"{fileToMetadata.Key},{fileToMetadata.Value}")); + var rsp = Path.Combine(intermediateOutputPath, $"dotnet-resgen.rsp"); + File.WriteAllLines(rsp, arguments); + + var result = Resgen.ResgenCommand.Run(new[] { $"@{rsp}" }); + if (result != 0) + { + return false; + } + } + + return true; + } + + protected static DiagnosticMessage ParseDiagnostic(string projectRootPath, string line) + { + var error = CanonicalError.Parse(line); + + if (error != null) + { + var severity = error.category == CanonicalError.Parts.Category.Error ? + DiagnosticMessageSeverity.Error : DiagnosticMessageSeverity.Warning; + + return new DiagnosticMessage( + error.code, + error.text, + Path.IsPathRooted(error.origin) ? line : projectRootPath + Path.DirectorySeparatorChar + line, + Path.Combine(projectRootPath, error.origin), + severity, + error.line, + error.column, + error.endColumn, + error.endLine, + source: null); + } + + return null; + } + + private static void PrintDiagnostics(List diagnostics) + { + foreach (var diag in diagnostics) + { + PrintDiagnostic(diag); + } + } + + private static void PrintDiagnostic(DiagnosticMessage diag) + { + switch (diag.Severity) + { + case DiagnosticMessageSeverity.Info: + Reporter.Error.WriteLine(diag.FormattedMessage); + break; + case DiagnosticMessageSeverity.Warning: + Reporter.Error.WriteLine(diag.FormattedMessage.Yellow().Bold()); + break; + case DiagnosticMessageSeverity.Error: + Reporter.Error.WriteLine(diag.FormattedMessage.Red().Bold()); + break; + } + } + + private static void CopyFiles(IEnumerable files, string outputPath) + { + foreach (var file in files) + { + File.Copy(file.ResolvedPath, Path.Combine(outputPath, Path.GetFileName(file.ResolvedPath)), overwrite: true); + } + } + + private static string EnsureTrailingSlash(string path) + { + return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar); + } + + private static string EnsureTrailingCharacter(string path, char trailingCharacter) + { + if (path == null) + { + throw new ArgumentNullException(nameof(path)); + } + + // if the path is empty, we want to return the original string instead of a single trailing character. + if (path.Length == 0 || path[path.Length - 1] == trailingCharacter) + { + return path; + } + + return path + trailingCharacter; + } + } +} diff --git a/src/dotnet/commands/dotnet-compile/ICompiler.cs b/src/dotnet/commands/dotnet-compile/ICompiler.cs new file mode 100644 index 000000000..aecb49bee --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/ICompiler.cs @@ -0,0 +1,12 @@ +// 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 Microsoft.DotNet.ProjectModel; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public interface ICompiler + { + bool Compile(ProjectContext context, CompilerCommandApp args); + } +} diff --git a/src/dotnet/commands/dotnet-compile/IScriptRunner.cs b/src/dotnet/commands/dotnet-compile/IScriptRunner.cs new file mode 100644 index 000000000..05910cebc --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/IScriptRunner.cs @@ -0,0 +1,13 @@ +// 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; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public interface IScriptRunner + { + void RunScripts(ProjectContext context, string name, Dictionary contextVariables); + } +} diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs new file mode 100644 index 000000000..40280dd62 --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -0,0 +1,199 @@ +// 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.Diagnostics; +using System.IO; +using System.Linq; +using Microsoft.DotNet.Cli.Compiler.Common; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Utilities; +using Microsoft.Extensions.DependencyModel; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public class ManagedCompiler : Compiler + { + private readonly IScriptRunner _scriptRunner; + private readonly ICommandFactory _commandFactory; + + public ManagedCompiler(IScriptRunner scriptRunner, ICommandFactory commandFactory) + { + _scriptRunner = scriptRunner; + _commandFactory = commandFactory; + } + + public override bool Compile(ProjectContext context, CompilerCommandApp args) + { + // Set up Output Paths + var outputPaths = context.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue); + var outputPath = outputPaths.CompilationOutputPath; + var intermediateOutputPath = outputPaths.IntermediateOutputDirectoryPath; + + Directory.CreateDirectory(outputPath); + Directory.CreateDirectory(intermediateOutputPath); + + // Create the library exporter + var exporter = context.CreateExporter(args.ConfigValue, args.BuildBasePathValue); + + // Gather exports for the project + var dependencies = exporter.GetDependencies().ToList(); + + Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}"); + var sw = Stopwatch.StartNew(); + + var diagnostics = new List(); + var missingFrameworkDiagnostics = new List(); + + // Collect dependency diagnostics + foreach (var diag in context.LibraryManager.GetAllDiagnostics()) + { + if (diag.ErrorCode == ErrorCodes.DOTNET1011 || + diag.ErrorCode == ErrorCodes.DOTNET1012) + { + missingFrameworkDiagnostics.Add(diag); + } + + diagnostics.Add(diag); + } + + if (missingFrameworkDiagnostics.Count > 0) + { + // The framework isn't installed so we should short circuit the rest of the compilation + // so we don't get flooded with errors + PrintSummary(missingFrameworkDiagnostics, sw); + return false; + } + + // Get compilation options + var outputName = outputPaths.CompilationFiles.Assembly; + + // Assemble args + var compilerArgs = new List() + { + $"--temp-output:\"{intermediateOutputPath}\"", + $"--out:\"{outputName}\"" + }; + + var compilationOptions = CompilerUtil.ResolveCompilationOptions(context, args.ConfigValue); + var languageId = CompilerUtil.ResolveLanguageId(context); + + var references = new List(); + + // Add compilation options to the args + compilerArgs.AddRange(compilationOptions.SerializeToArgs()); + + // Add metadata options + compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context))); + + foreach (var dependency in dependencies) + { + references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath)); + compilerArgs.AddRange(dependency.SourceReferences.Select(s => $"\"{s}\"")); + + // Add analyzer references + compilerArgs.AddRange(dependency.AnalyzerReferences + .Where(a => a.AnalyzerLanguage == languageId) + .Select(a => $"--analyzer:\"{a.AssemblyPath}\"")); + } + + compilerArgs.AddRange(references.Select(r => $"--reference:\"{r}\"")); + + if (compilationOptions.PreserveCompilationContext == true) + { + var dependencyContext = DependencyContextBuilder.Build(compilationOptions, + exporter, + args.ConfigValue, + context.TargetFramework, + context.RuntimeIdentifier); + + var writer = new DependencyContextWriter(); + var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json"); + using (var fileStream = File.Create(depsJsonFile)) + { + writer.Write(dependencyContext, fileStream); + } + + compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\""); + } + + if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath)) + { + return false; + } + // Add project source files + var sourceFiles = CompilerUtil.GetCompilationSources(context); + compilerArgs.AddRange(sourceFiles); + + var compilerName = CompilerUtil.ResolveCompilerName(context); + + // Write RSP file + var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.rsp"); + File.WriteAllLines(rsp, compilerArgs); + + // Run pre-compile event + var contextVariables = new Dictionary() + { + { "compile:TargetFramework", context.TargetFramework.DotNetFrameworkName }, + { "compile:Configuration", args.ConfigValue }, + { "compile:OutputFile", outputName }, + { "compile:OutputDir", outputPath.TrimEnd('\\', '/') }, + { "compile:ResponseFile", rsp } + }; + + if (!string.IsNullOrEmpty(context.RuntimeIdentifier)) + { + contextVariables.Add( + "compile:RuntimeOutputDir", + outputPaths.RuntimeOutputPath.TrimEnd('\\', '/')); + } + + _scriptRunner.RunScripts(context, ScriptNames.PreCompile, contextVariables); + + var result = _commandFactory.Create($"compile-{compilerName}", new[] { "@" + $"{rsp}" }) + .OnErrorLine(line => + { + var diagnostic = ParseDiagnostic(context.ProjectDirectory, line); + if (diagnostic != null) + { + diagnostics.Add(diagnostic); + } + else + { + Reporter.Error.WriteLine(line); + } + }) + .OnOutputLine(line => + { + var diagnostic = ParseDiagnostic(context.ProjectDirectory, line); + if (diagnostic != null) + { + diagnostics.Add(diagnostic); + } + else + { + Reporter.Output.WriteLine(line); + } + }).Execute(); + + // Run post-compile event + contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString(); + _scriptRunner.RunScripts(context, ScriptNames.PostCompile, contextVariables); + + var success = result.ExitCode == 0; + + if (!success) + { + Reporter.Error.WriteLine($"{result.StartInfo.FileName} {result.StartInfo.Arguments} returned Exit Code {result.ExitCode}"); + } + + if (success) + { + success &= GenerateCultureResourceAssemblies(context.ProjectFile, dependencies, intermediateOutputPath, outputPath); + } + + return PrintSummary(diagnostics, sw, success); + } + } +} diff --git a/src/dotnet/commands/dotnet-compile/NativeCompiler.cs b/src/dotnet/commands/dotnet-compile/NativeCompiler.cs new file mode 100644 index 000000000..e3a5efbda --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/NativeCompiler.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.Collections.Generic; +using System.IO; +using Microsoft.DotNet.ProjectModel; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public class NativeCompiler : Compiler + { + public override bool Compile(ProjectContext context, CompilerCommandApp args) + { + var outputPaths = context.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue); + var outputPath = outputPaths.RuntimeOutputPath; + var nativeOutputPath = Path.Combine(outputPath, "native"); + var intermediateOutputPath = + outputPaths.IntermediateOutputDirectoryPath; + var nativeTempOutput = Path.Combine(intermediateOutputPath, "native"); + Directory.CreateDirectory(nativeOutputPath); + Directory.CreateDirectory(nativeTempOutput); + + var managedOutput = outputPaths.CompilationFiles.Assembly; + + var nativeArgs = new List(); + + // Input Assembly + nativeArgs.Add($"{managedOutput}"); + + // ILC Args + if (!string.IsNullOrWhiteSpace(args.IlcArgsValue)) + { + nativeArgs.Add("--ilcargs"); + nativeArgs.Add($"{args.IlcArgsValue}"); + } + + // ILC Path + if (!string.IsNullOrWhiteSpace(args.IlcPathValue)) + { + nativeArgs.Add("--ilcpath"); + nativeArgs.Add(args.IlcPathValue); + } + + // ILC SDK Path + if (!string.IsNullOrWhiteSpace(args.IlcSdkPathValue)) + { + nativeArgs.Add("--ilcsdkpath"); + nativeArgs.Add(args.IlcSdkPathValue); + } + + // AppDep SDK Path + if (!string.IsNullOrWhiteSpace(args.AppDepSdkPathValue)) + { + nativeArgs.Add("--appdepsdk"); + nativeArgs.Add(args.AppDepSdkPathValue); + } + + // CodeGen Mode + if (args.IsCppModeValue) + { + nativeArgs.Add("--mode"); + nativeArgs.Add("cpp"); + } + + if (!string.IsNullOrWhiteSpace(args.CppCompilerFlagsValue)) + { + nativeArgs.Add("--cppcompilerflags"); + nativeArgs.Add(args.CppCompilerFlagsValue); + } + + // Configuration + if (args.ConfigValue != null) + { + nativeArgs.Add("--configuration"); + nativeArgs.Add(args.ConfigValue); + } + + // Architecture + if (args.ArchValue != null) + { + nativeArgs.Add("--arch"); + nativeArgs.Add(args.ArchValue); + } + + // Intermediate Path + nativeArgs.Add("--temp-output"); + nativeArgs.Add($"{nativeTempOutput}"); + + // Output Path + nativeArgs.Add("--output"); + nativeArgs.Add($"{nativeOutputPath}"); + + // Write Response File + var rsp = Path.Combine(nativeTempOutput, $"dotnet-compile-native.{context.ProjectFile.Name}.rsp"); + File.WriteAllLines(rsp, nativeArgs); + + // TODO Add -r assembly.dll for all Nuget References + // Need CoreRT Framework published to nuget + + // Do Native Compilation + var result = Native.CompileNativeCommand.Run(new string[] { "--rsp", $"{rsp}" }); + + return result == 0; + } + } +} diff --git a/src/dotnet/commands/dotnet-compile/Program.cs b/src/dotnet/commands/dotnet-compile/Program.cs index 8d75e6dc9..40e8d0485 100644 --- a/src/dotnet/commands/dotnet-compile/Program.cs +++ b/src/dotnet/commands/dotnet-compile/Program.cs @@ -2,19 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using Microsoft.Dotnet.Cli.Compiler.Common; -using Microsoft.DotNet.Cli.Compiler.Common; using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.ProjectModel.Compilation; -using Microsoft.DotNet.ProjectModel.Resources; -using Microsoft.DotNet.ProjectModel.Utilities; -using Microsoft.Extensions.DependencyModel; -using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Tools.Compiler { @@ -27,8 +15,15 @@ namespace Microsoft.DotNet.Tools.Compiler try { + var commandFactory = new DotNetCommandFactory(); + var scriptRunner = new ScriptRunner(); + var managedCompiler = new ManagedCompiler(scriptRunner, commandFactory); + var nativeCompiler = new NativeCompiler(); + var compilationDriver = new CompilationDriver(managedCompiler, nativeCompiler); + var compilerCommandArgs = new CompilerCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform"); - return compilerCommandArgs.Execute(OnExecute, args); + + return compilerCommandArgs.Execute(compilationDriver.Compile, args); } catch (Exception ex) { @@ -40,474 +35,5 @@ namespace Microsoft.DotNet.Tools.Compiler return 1; } } - - private static bool OnExecute(List contexts, CompilerCommandApp args) - { - var success = true; - - foreach (var context in contexts) - { - success &= CompileProject(context, args); - if (args.IsNativeValue && success) - { - success &= CompileNative(context, args); - } - } - return success; - } - - private static bool CompileNative( - ProjectContext context, - CompilerCommandApp args) - { - var outputPaths = context.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue, args.OutputValue); - var outputPath = outputPaths.RuntimeOutputPath; - var nativeOutputPath = Path.Combine(outputPath, "native"); - var intermediateOutputPath = - outputPaths.IntermediateOutputDirectoryPath; - var nativeTempOutput = Path.Combine(intermediateOutputPath, "native"); - Directory.CreateDirectory(nativeOutputPath); - Directory.CreateDirectory(nativeTempOutput); - - var managedOutput = outputPaths.CompilationFiles.Assembly; - - var nativeArgs = new List(); - - // Input Assembly - nativeArgs.Add($"{managedOutput}"); - - // ILC Args - if (!string.IsNullOrWhiteSpace(args.IlcArgsValue)) - { - nativeArgs.Add("--ilcargs"); - nativeArgs.Add($"{args.IlcArgsValue}"); - } - - // ILC Path - if (!string.IsNullOrWhiteSpace(args.IlcPathValue)) - { - nativeArgs.Add("--ilcpath"); - nativeArgs.Add(args.IlcPathValue); - } - - // ILC SDK Path - if (!string.IsNullOrWhiteSpace(args.IlcSdkPathValue)) - { - nativeArgs.Add("--ilcsdkpath"); - nativeArgs.Add(args.IlcSdkPathValue); - } - - // AppDep SDK Path - if (!string.IsNullOrWhiteSpace(args.AppDepSdkPathValue)) - { - nativeArgs.Add("--appdepsdk"); - nativeArgs.Add(args.AppDepSdkPathValue); - } - - // CodeGen Mode - if (args.IsCppModeValue) - { - nativeArgs.Add("--mode"); - nativeArgs.Add("cpp"); - } - - if (!string.IsNullOrWhiteSpace(args.CppCompilerFlagsValue)) - { - nativeArgs.Add("--cppcompilerflags"); - nativeArgs.Add(args.CppCompilerFlagsValue); - } - - // Configuration - if (args.ConfigValue != null) - { - nativeArgs.Add("--configuration"); - nativeArgs.Add(args.ConfigValue); - } - - // Architecture - if (args.ArchValue != null) - { - nativeArgs.Add("--arch"); - nativeArgs.Add(args.ArchValue); - } - - // Intermediate Path - nativeArgs.Add("--temp-output"); - nativeArgs.Add($"{nativeTempOutput}"); - - // Output Path - nativeArgs.Add("--output"); - nativeArgs.Add($"{nativeOutputPath}"); - - // Write Response File - var rsp = Path.Combine(nativeTempOutput, $"dotnet-compile-native.{context.ProjectFile.Name}.rsp"); - File.WriteAllLines(rsp, nativeArgs); - - // TODO Add -r assembly.dll for all Nuget References - // Need CoreRT Framework published to nuget - - // Do Native Compilation - var result = Native.CompileNativeCommand.Run(new string[] { "--rsp", $"{rsp}" }); - - return result == 0; - } - - private static bool CompileProject(ProjectContext context, CompilerCommandApp args) - { - // Set up Output Paths - var outputPaths = context.GetOutputPaths(args.ConfigValue, args.BuildBasePathValue); - var outputPath = outputPaths.CompilationOutputPath; - var intermediateOutputPath = - outputPaths.IntermediateOutputDirectoryPath; - - Directory.CreateDirectory(outputPath); - Directory.CreateDirectory(intermediateOutputPath); - - // Create the library exporter - var exporter = context.CreateExporter(args.ConfigValue, args.BuildBasePathValue); - - // Gather exports for the project - var dependencies = exporter.GetDependencies().ToList(); - - Reporter.Output.WriteLine($"Compiling {context.RootProject.Identity.Name.Yellow()} for {context.TargetFramework.DotNetFrameworkName.Yellow()}"); - var sw = Stopwatch.StartNew(); - - var diagnostics = new List(); - var missingFrameworkDiagnostics = new List(); - - // Collect dependency diagnostics - foreach (var diag in context.LibraryManager.GetAllDiagnostics()) - { - if (diag.ErrorCode == ErrorCodes.DOTNET1011 || - diag.ErrorCode == ErrorCodes.DOTNET1012) - { - missingFrameworkDiagnostics.Add(diag); - } - - diagnostics.Add(diag); - } - - if (missingFrameworkDiagnostics.Count > 0) - { - // The framework isn't installed so we should short circuit the rest of the compilation - // so we don't get flooded with errors - PrintSummary(missingFrameworkDiagnostics, sw); - return false; - } - - // Get compilation options - var outputName = outputPaths.CompilationFiles.Assembly; - - // Assemble args - var compilerArgs = new List() - { - $"--temp-output:\"{intermediateOutputPath}\"", - $"--out:\"{outputName}\"" - }; - - var compilationOptions = CompilerUtil.ResolveCompilationOptions(context, args.ConfigValue); - var languageId = CompilerUtil.ResolveLanguageId(context); - - var references = new List(); - - // Add compilation options to the args - compilerArgs.AddRange(compilationOptions.SerializeToArgs()); - - // Add metadata options - compilerArgs.AddRange(AssemblyInfoOptions.SerializeToArgs(AssemblyInfoOptions.CreateForProject(context))); - - foreach (var dependency in dependencies) - { - references.AddRange(dependency.CompilationAssemblies.Select(r => r.ResolvedPath)); - compilerArgs.AddRange(dependency.SourceReferences.Select(s => $"\"{s}\"")); - - // Add analyzer references - compilerArgs.AddRange(dependency.AnalyzerReferences - .Where(a => a.AnalyzerLanguage == languageId) - .Select(a => $"--analyzer:\"{a.AssemblyPath}\"")); - } - - compilerArgs.AddRange(references.Select(r => $"--reference:\"{r}\"")); - - if (compilationOptions.PreserveCompilationContext == true) - { - var dependencyContext = DependencyContextBuilder.Build(compilationOptions, - exporter, - args.ConfigValue, - context.TargetFramework, - context.RuntimeIdentifier); - - var writer = new DependencyContextWriter(); - var depsJsonFile = Path.Combine(intermediateOutputPath, context.ProjectFile.Name + "dotnet-compile.deps.json"); - using (var fileStream = File.Create(depsJsonFile)) - { - writer.Write(dependencyContext, fileStream); - } - - compilerArgs.Add($"--resource:\"{depsJsonFile},{context.ProjectFile.Name}.deps.json\""); - } - - if (!AddNonCultureResources(context.ProjectFile, compilerArgs, intermediateOutputPath)) - { - return false; - } - // Add project source files - var sourceFiles = CompilerUtil.GetCompilationSources(context); - compilerArgs.AddRange(sourceFiles); - - var compilerName = CompilerUtil.ResolveCompilerName(context); - - // Write RSP file - var rsp = Path.Combine(intermediateOutputPath, $"dotnet-compile.rsp"); - File.WriteAllLines(rsp, compilerArgs); - - // Run pre-compile event - var contextVariables = new Dictionary() - { - { "compile:TargetFramework", context.TargetFramework.DotNetFrameworkName }, - { "compile:Configuration", args.ConfigValue }, - { "compile:OutputFile", outputName }, - { "compile:OutputDir", outputPath }, - { "compile:ResponseFile", rsp } - }; - RunScripts(context, ScriptNames.PreCompile, contextVariables); - - var result = Command.CreateDotNet($"compile-{compilerName}", new[] { "@" + $"{rsp}" }) - .OnErrorLine(line => - { - var diagnostic = ParseDiagnostic(context.ProjectDirectory, line); - if (diagnostic != null) - { - diagnostics.Add(diagnostic); - } - else - { - Reporter.Error.WriteLine(line); - } - }) - .OnOutputLine(line => - { - var diagnostic = ParseDiagnostic(context.ProjectDirectory, line); - if (diagnostic != null) - { - diagnostics.Add(diagnostic); - } - else - { - Reporter.Output.WriteLine(line); - } - }).Execute(); - - // Run post-compile event - contextVariables["compile:CompilerExitCode"] = result.ExitCode.ToString(); - RunScripts(context, ScriptNames.PostCompile, contextVariables); - - var success = result.ExitCode == 0; - - if (!success) - { - Reporter.Error.WriteLine($"{result.StartInfo.FileName} {result.StartInfo.Arguments} returned Exit Code {result.ExitCode}"); - } - - if (success) - { - success &= GenerateCultureResourceAssemblies(context.ProjectFile, dependencies, intermediateOutputPath, outputPath); - } - - return PrintSummary(diagnostics, sw, success); - } - - private static void RunScripts(ProjectContext context, string name, Dictionary contextVariables) - { - foreach (var script in context.ProjectFile.Scripts.GetOrEmpty(name)) - { - ScriptExecutor.CreateCommandForScript(context.ProjectFile, script, contextVariables) - .ForwardStdErr() - .ForwardStdOut() - .Execute(); - } - } - - private static bool PrintSummary(List diagnostics, Stopwatch sw, bool success = true) - { - PrintDiagnostics(diagnostics); - - Reporter.Output.WriteLine(); - - var errorCount = diagnostics.Count(d => d.Severity == DiagnosticMessageSeverity.Error); - var warningCount = diagnostics.Count(d => d.Severity == DiagnosticMessageSeverity.Warning); - - if (errorCount > 0 || !success) - { - Reporter.Output.WriteLine("Compilation failed.".Red()); - success = false; - } - else - { - Reporter.Output.WriteLine("Compilation succeeded.".Green()); - } - - Reporter.Output.WriteLine($" {warningCount} Warning(s)"); - Reporter.Output.WriteLine($" {errorCount} Error(s)"); - - Reporter.Output.WriteLine(); - - Reporter.Output.WriteLine($"Time elapsed {sw.Elapsed}"); - - return success; - } - - private static bool AddNonCultureResources(Project project, List compilerArgs, string intermediateOutputPath) - { - var resgenFiles = CompilerUtil.GetNonCultureResources(project, intermediateOutputPath); - - foreach (var resgenFile in resgenFiles) - { - if (ResourceUtility.IsResxFile(resgenFile.InputFile)) - { - var arguments = new[] - { - resgenFile.InputFile, - $"-o:{resgenFile.OutputFile}", - $"-v:{project.Version.Version}" - }; - - var rsp = Path.Combine(intermediateOutputPath, $"dotnet-resgen-resx.rsp"); - File.WriteAllLines(rsp, arguments); - - var result = Resgen.ResgenCommand.Run(new[] { $"@{rsp}" }); - - if (result != 0) - { - return false; - } - - compilerArgs.Add($"--resource:\"{resgenFile.OutputFile},{Path.GetFileName(resgenFile.MetadataName)}\""); - } - else - { - compilerArgs.Add($"--resource:\"{resgenFile.InputFile},{Path.GetFileName(resgenFile.MetadataName)}\""); - } - } - - return true; - } - - private static bool GenerateCultureResourceAssemblies( - Project project, - List dependencies, - string intermediateOutputPath, - string outputPath) - { - var referencePaths = CompilerUtil.GetReferencePathsForCultureResgen(dependencies); - var resgenReferenceArgs = referencePaths.Select(path => $"-r:{path}").ToList(); - var cultureResgenFiles = CompilerUtil.GetCultureResources(project, outputPath); - - foreach (var resgenFile in cultureResgenFiles) - { - var resourceOutputPath = Path.GetDirectoryName(resgenFile.OutputFile); - - if (!Directory.Exists(resourceOutputPath)) - { - Directory.CreateDirectory(resourceOutputPath); - } - - var arguments = new List(); - - arguments.AddRange(resgenReferenceArgs); - arguments.Add($"-o:{resgenFile.OutputFile}"); - arguments.Add($"-c:{resgenFile.Culture}"); - arguments.Add($"-v:{project.Version.Version}"); - arguments.AddRange(resgenFile.InputFileToMetadata.Select(fileToMetadata => $"{fileToMetadata.Key},{fileToMetadata.Value}")); - var rsp = Path.Combine(intermediateOutputPath, $"dotnet-resgen.rsp"); - File.WriteAllLines(rsp, arguments); - - var result = Resgen.ResgenCommand.Run(new[] { $"@{rsp}" }); - if (result != 0) - { - return false; - } - } - - return true; - } - - private static DiagnosticMessage ParseDiagnostic(string projectRootPath, string line) - { - var error = CanonicalError.Parse(line); - - if (error != null) - { - var severity = error.category == CanonicalError.Parts.Category.Error ? - DiagnosticMessageSeverity.Error : DiagnosticMessageSeverity.Warning; - - return new DiagnosticMessage( - error.code, - error.text, - Path.IsPathRooted(error.origin) ? line : projectRootPath + Path.DirectorySeparatorChar + line, - Path.Combine(projectRootPath, error.origin), - severity, - error.line, - error.column, - error.endColumn, - error.endLine, - source: null); - } - - return null; - } - - private static void PrintDiagnostics(List diagnostics) - { - foreach (var diag in diagnostics) - { - PrintDiagnostic(diag); - } - } - - private static void PrintDiagnostic(DiagnosticMessage diag) - { - switch (diag.Severity) - { - case DiagnosticMessageSeverity.Info: - Reporter.Error.WriteLine(diag.FormattedMessage); - break; - case DiagnosticMessageSeverity.Warning: - Reporter.Error.WriteLine(diag.FormattedMessage.Yellow().Bold()); - break; - case DiagnosticMessageSeverity.Error: - Reporter.Error.WriteLine(diag.FormattedMessage.Red().Bold()); - break; - } - } - - private static void CopyFiles(IEnumerable files, string outputPath) - { - foreach (var file in files) - { - File.Copy(file.ResolvedPath, Path.Combine(outputPath, Path.GetFileName(file.ResolvedPath)), overwrite: true); - } - } - - private static string EnsureTrailingSlash(string path) - { - return EnsureTrailingCharacter(path, Path.DirectorySeparatorChar); - } - - private static string EnsureTrailingCharacter(string path, char trailingCharacter) - { - if (path == null) - { - throw new ArgumentNullException(nameof(path)); - } - - // if the path is empty, we want to return the original string instead of a single trailing character. - if (path.Length == 0 || path[path.Length - 1] == trailingCharacter) - { - return path; - } - - return path + trailingCharacter; - } } } diff --git a/src/dotnet/commands/dotnet-compile/ScriptRunner.cs b/src/dotnet/commands/dotnet-compile/ScriptRunner.cs new file mode 100644 index 000000000..72cb47cd6 --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/ScriptRunner.cs @@ -0,0 +1,24 @@ +// 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.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.ProjectModel.Utilities; + +namespace Microsoft.DotNet.Tools.Compiler +{ + public class ScriptRunner : IScriptRunner + { + public void RunScripts(ProjectContext context, string name, Dictionary contextVariables) + { + foreach (var script in context.ProjectFile.Scripts.GetOrEmpty(name)) + { + ScriptExecutor.CreateCommandForScript(context.ProjectFile, script, contextVariables) + .ForwardStdErr() + .ForwardStdOut() + .Execute(); + } + } + } +} \ No newline at end of file diff --git a/test/dotnet-compile.UnitTests/GivenACompilationDriverController.cs b/test/dotnet-compile.UnitTests/GivenACompilationDriverController.cs new file mode 100644 index 000000000..b0724bd99 --- /dev/null +++ b/test/dotnet-compile.UnitTests/GivenACompilationDriverController.cs @@ -0,0 +1,83 @@ +// 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 FluentAssertions; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Compiler; +using Moq; +using NuGet.Frameworks; +using Xunit; + +namespace Microsoft.DotNet.Tools.Compiler.Tests +{ + public class GivenACompilationDriverController + { + private string _projectJson; + private Mock _managedCompilerMock; + private Mock _nativeCompilerMock; + private List _contexts; + private CompilerCommandApp _args; + + public GivenACompilationDriverController() + { + _projectJson = + Path.Combine(AppContext.BaseDirectory, "TestAssets", "TestProjects", "TestApp", "project.json"); + _managedCompilerMock = new Mock(); + _managedCompilerMock.Setup(c => c + .Compile(It.IsAny(), It.IsAny())) + .Returns(true); + _nativeCompilerMock = new Mock(); + _nativeCompilerMock.Setup(c => c + .Compile(It.IsAny(), It.IsAny())) + .Returns(true); + + _contexts = new List + { + ProjectContext.Create(_projectJson, new NuGetFramework(string.Empty)) + }; + + _args = new CompilerCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform"); + } + + [Fact] + public void It_compiles_all_project_contexts() + { + var compiledProjectContexts = new List(); + _managedCompilerMock.Setup(c => c + .Compile(It.IsAny(), It.IsAny())) + .Callback((p, c) => compiledProjectContexts.Add(p)) + .Returns(true); + + var compilerController = new CompilationDriver(_managedCompilerMock.Object, _nativeCompilerMock.Object); + + compilerController.Compile(_contexts, _args); + + compiledProjectContexts.Should().BeEquivalentTo(_contexts); + } + + [Fact] + public void It_does_not_compile_native_when_the_native_parameter_is_not_passed() + { + var compilerController = new CompilationDriver(_managedCompilerMock.Object, _nativeCompilerMock.Object); + + compilerController.Compile(_contexts, _args); + + _nativeCompilerMock.Verify(c => c.Compile(It.IsAny(), It.IsAny()), Times.Never); + } + + [Fact] + public void It_does_compile_native_when_the_native_parameter_is_passed() + { + var compilerController = new CompilationDriver(_managedCompilerMock.Object, _nativeCompilerMock.Object); + + _args.IsNativeValue = true; + + compilerController.Compile(_contexts, _args); + + _nativeCompilerMock.Verify(c => c.Compile(It.IsAny(), It.IsAny()), Times.Once); + } + } +} diff --git a/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs b/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs new file mode 100644 index 000000000..88ef37190 --- /dev/null +++ b/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs @@ -0,0 +1,229 @@ +// 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 Microsoft.DotNet.ProjectModel; +using Moq; +using NuGet.Frameworks; +using Xunit; +using Microsoft.DotNet.Cli.Utils; +using FluentAssertions; +using System.Linq; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Tools.Compiler.Tests +{ + public class GivenThatICareAboutScriptVariablesFromAManagedCompiler : IClassFixture + { + private readonly ScriptVariablesFixture _fixture; + + public GivenThatICareAboutScriptVariablesFromAManagedCompiler(ScriptVariablesFixture fixture) + { + _fixture = fixture; + } + + [Fact] + public void It_passes_a_TargetFramework_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:TargetFramework"); + _fixture.PreCompileScriptVariables["compile:TargetFramework"].Should().Be("dnxcore,Version=v5.0"); + } + + [Fact] + public void It_passes_a_Configuration_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:Configuration"); + _fixture.PreCompileScriptVariables["compile:Configuration"].Should().Be( + ScriptVariablesFixture.ConfigValue); + } + + [Fact] + public void It_passes_a_OutputFile_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:OutputFile"); + _fixture.PreCompileScriptVariables["compile:OutputFile"].Should().Be(ScriptVariablesFixture.OutputFile); + } + + [Fact] + public void It_passes_a_OutputDir_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:OutputDir"); + _fixture.PreCompileScriptVariables["compile:OutputDir"].Should().Be(ScriptVariablesFixture.OutputPath); + } + + [Fact] + public void It_passes_a_ResponseFile_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:ResponseFile"); + _fixture.PreCompileScriptVariables["compile:ResponseFile"].Should().Be(ScriptVariablesFixture.ResponseFile); + } + + [Fact] + public void It_does_not_pass_a_RuntimeOutputDir_variable_to_the_pre_compile_scripts_if_rid_is_not_set_in() + { + _fixture.PreCompileScriptVariables.Should().NotContainKey("compile:RuntimeOutputDir"); + } + + [Fact] + public void It_passes_a_RuntimeOutputDir_variable_to_the_pre_compile_scripts_if_rid_is_set_in_the_ProjectContext() + { + var rid = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(); + var fixture = ScriptVariablesFixture.GetFixtureWithRids(rid); + fixture.PreCompileScriptVariables.Should().ContainKey("compile:RuntimeOutputDir"); + fixture.PreCompileScriptVariables["compile:RuntimeOutputDir"].Should().Be(fixture.RuntimeOutputDir); + } + + [Fact] + public void It_passes_a_TargetFramework_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:TargetFramework"); + _fixture.PostCompileScriptVariables["compile:TargetFramework"].Should().Be("dnxcore,Version=v5.0"); + } + + [Fact] + public void It_passes_a_Configuration_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:Configuration"); + _fixture.PostCompileScriptVariables["compile:Configuration"].Should().Be( + ScriptVariablesFixture.ConfigValue); + } + + [Fact] + public void It_passes_a_OutputFile_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:OutputFile"); + _fixture.PostCompileScriptVariables["compile:OutputFile"].Should().Be(ScriptVariablesFixture.OutputFile); + } + + [Fact] + public void It_passes_a_OutputDir_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:OutputDir"); + _fixture.PostCompileScriptVariables["compile:OutputDir"].Should().Be(ScriptVariablesFixture.OutputPath); + } + + [Fact] + public void It_passes_a_ResponseFile_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:ResponseFile"); + _fixture.PostCompileScriptVariables["compile:ResponseFile"].Should().Be(ScriptVariablesFixture.ResponseFile); + } + + [Fact] + public void It_passes_a_CompilerExitCode_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:CompilerExitCode"); + _fixture.PostCompileScriptVariables["compile:CompilerExitCode"].Should().Be("0"); + } + + [Fact] + public void It_does_not_pass_a_RuntimeOutputDir_variable_to_the_post_compile_scripts_if_rid_is_not_set_in_the_ProjectContext() + { + _fixture.PostCompileScriptVariables.Should().NotContainKey("compile:RuntimeOutputDir"); + } + + [Fact] + public void It_passes_a_RuntimeOutputDir_variable_to_the_post_compile_scripts_if_rid_is_set_in_the_ProjectContext() + { + var rid = PlatformServices.Default.Runtime.GetLegacyRestoreRuntimeIdentifier(); + var fixture = ScriptVariablesFixture.GetFixtureWithRids(rid); + fixture.PostCompileScriptVariables.Should().ContainKey("compile:RuntimeOutputDir"); + fixture.PostCompileScriptVariables["compile:RuntimeOutputDir"].Should().Be(fixture.RuntimeOutputDir); + } + } + + public class ScriptVariablesFixture + { + public const string ConfigValue = "Debug"; + + public static string TestAssetPath = Path.Combine( + AppContext.BaseDirectory, + "TestAssets", + "TestProjects", + "TestApp"); + + public static string OutputPath = Path.Combine( + TestAssetPath, + "bin", + ConfigValue, + "dnxcore50"); + + public string RuntimeOutputDir { get; private set; } + + public static string OutputFile = Path.Combine(OutputPath, "TestApp.dll"); + + public static string ResponseFile = Path.Combine( + TestAssetPath, + "obj", + ConfigValue, + "dnxcore50", + "dotnet-compile.rsp"); + + public Dictionary PreCompileScriptVariables { get; private set; } + public Dictionary PostCompileScriptVariables { get; private set; } + + public ScriptVariablesFixture() : this(string.Empty) + { + } + + private ScriptVariablesFixture(string rid) + { + var projectJson = Path.Combine(TestAssetPath, "project.json"); + var command = new Mock(); + command.Setup(c => c.Execute()).Returns(new CommandResult()); + command.Setup(c => c.OnErrorLine(It.IsAny>())).Returns(() => command.Object); + command.Setup(c => c.OnOutputLine(It.IsAny>())).Returns(() => command.Object); + var commandFactory = new Mock(); + commandFactory.Setup(c => c + .Create( + It.IsAny(), + It.IsAny>(), + It.IsAny(), + It.IsAny())) + .Returns(command.Object); + + var _args = new CompilerCommandApp("dotnet compile", ".NET Compiler", "Compiler for the .NET Platform"); + _args.ConfigValue = ConfigValue; + + PreCompileScriptVariables = new Dictionary(); + PostCompileScriptVariables = new Dictionary(); + + var _scriptRunner = new Mock(); + _scriptRunner.Setup( + s => + s.RunScripts(It.IsAny(), It.IsAny(), It.IsAny>())) + .Callback>((p, n, v) => + { + if (n.Equals(ScriptNames.PreCompile)) + { + PreCompileScriptVariables = v; + } + + if (n.Equals(ScriptNames.PostCompile)) + { + PostCompileScriptVariables = v; + } + }); + + var managedCompiler = new ManagedCompiler(_scriptRunner.Object, commandFactory.Object); + + var rids = new List(); + if (!string.IsNullOrEmpty(rid)) + { + rids.Add(rid); + } + + var context = ProjectContext.Create(projectJson, new NuGetFramework("dnxcore", new Version(5, 0)), rids); + managedCompiler.Compile(context, _args); + + RuntimeOutputDir = Path.Combine(OutputPath, rid); + } + + public static ScriptVariablesFixture GetFixtureWithRids(string rid) + { + return new ScriptVariablesFixture(rid); + } + } +} diff --git a/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj b/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj new file mode 100644 index 000000000..f2b743757 --- /dev/null +++ b/test/dotnet-compile.UnitTests/dotnet-compile.UnitTests.xproj @@ -0,0 +1,19 @@ + + + + 14.0.24720 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 920b71d8-62da-4f5e-8a26-926c113f1d97 + dotnet-compile.UnitTests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/dotnet-compile.UnitTests/project.json b/test/dotnet-compile.UnitTests/project.json new file mode 100644 index 000000000..3ecadbe2d --- /dev/null +++ b/test/dotnet-compile.UnitTests/project.json @@ -0,0 +1,34 @@ +{ + "version": "1.0.0-*", + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + + "Microsoft.DotNet.Cli.Utils": { + "target": "project", + "type": "build" + }, + + "dotnet": { "target": "project" }, + "Microsoft.DotNet.ProjectModel": { "target": "project" }, + + "xunit": "2.1.0", + "dotnet-test-xunit": "1.0.0-dev-48273-16", + "moq.netcore": "4.4.0-beta8", + "FluentAssertions": "4.2.2" + }, + + "frameworks": { + "dnxcore50": { + "imports": "portable-net451+win8" + } + }, + + "content": [ + "../../TestAssets/TestProjects/TestLibrary/*", + "../../TestAssets/TestProjects/TestApp/*", + "../../TestAssets/TestProjects/global.json" + ], + + "testRunner": "xunit" +}