diff --git a/.gitignore b/.gitignore index b620a468b..3f156e9b9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ ### Repo-specific things ### +# Test results +*-testResults.xml + # NuGet keeps dropping Library/ diff --git a/Microsoft.DotNet.Cli.sln b/Microsoft.DotNet.Cli.sln index be6d49846..ce13bb1b6 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 @@ -58,14 +50,23 @@ EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-projectmodel-server.Tests", "test\dotnet-projectmodel-server.Tests\dotnet-projectmodel-server.Tests.xproj", "{11C77123-E4DA-499F-8900-80C88C2C69F2}" EndProject Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Microsoft.DotNet.Files", "src\Microsoft.DotNet.Files\Microsoft.DotNet.Files.xproj", "{D521DD9F-0614-4929-93B4-D8FA5682C174}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{88278B81-7649-45DC-8A6A-D3A645C5AFC3}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestAssets", "TestAssets", "{82BD2E61-326D-4EA4-A1C1-93A565573C81}" +Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-cli-build", "scripts\dotnet-cli-build\dotnet-cli-build.xproj", "{D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}" 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}") = "Microsoft.DotNet.Cli.Build.Framework", "scripts\Microsoft.DotNet.Cli.Build.Framework\Microsoft.DotNet.Cli.Build.Framework.xproj", "{49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}" 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}") = "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.TestFramework", "src\Microsoft.DotNet.TestFramework\Microsoft.DotNet.TestFramework.xproj", "{0724ED7C-56E3-4604-9970-25E600611383}" +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}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -255,86 +256,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 @@ -431,6 +352,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 + {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 {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 @@ -463,22 +480,38 @@ Global {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 - {0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Debug|x64.ActiveCfg = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Debug|x64.Build.0 = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.MinSizeRel|x64.Build.0 = Debug|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Release|Any CPU.Build.0 = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Release|x64.ActiveCfg = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.Release|x64.Build.0 = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU - {0724ED7C-56E3-4604-9970-25E600611383}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Debug|x64.ActiveCfg = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Debug|x64.Build.0 = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Release|Any CPU.Build.0 = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Release|x64.ActiveCfg = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.Release|x64.Build.0 = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5}.RelWithDebInfo|x64.Build.0 = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Debug|x64.ActiveCfg = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Debug|x64.Build.0 = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.MinSizeRel|x64.Build.0 = Debug|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Release|Any CPU.Build.0 = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Release|x64.ActiveCfg = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.Release|x64.Build.0 = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D}.RelWithDebInfo|x64.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -495,19 +528,22 @@ 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} + {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} {09C52F96-EFDD-4448-95EC-6D362DD60BAA} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} {44E7D1AC-DCF1-4A18-9C22-F09E6BB302B5} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7} - {0724ED7C-56E3-4604-9970-25E600611383} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F} + {D7B9695D-23EB-4EA8-B8AB-707A0092E1D5} = {88278B81-7649-45DC-8A6A-D3A645C5AFC3} + {49BEB486-AB5A-4416-91EA-8CD34ABB0C9D} = {88278B81-7649-45DC-8A6A-D3A645C5AFC3} EndGlobalSection EndGlobal diff --git a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json index 6b317abf2..dcc22edfe 100644 --- a/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppCompilationContext/TestApp/project.json @@ -13,10 +13,5 @@ "frameworks": { "dnxcore50": { } - }, - - "scripts": { - "prepublish" : ["echo prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"], - "postpublish" : ["echo postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"] } } diff --git a/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json b/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json index 51b830d57..64ba761af 100644 --- a/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json +++ b/TestAssets/TestProjects/TestAppWithLibrary/TestApp/project.json @@ -13,10 +13,5 @@ "frameworks": { "dnxcore50": { } - }, - - "scripts": { - "prepublish" : ["echo prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"], - "postpublish" : ["echo postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:Framework%? ?%publish:Runtime%?"] } } diff --git a/TestAssets/TestProjects/TestAppWithScripts/Program.cs b/TestAssets/TestProjects/TestAppWithScripts/Program.cs new file mode 100644 index 000000000..7bcd4fbd3 --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithScripts/Program.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; + +namespace TestApp +{ + public class Program + { + public static int Main(string[] args) + { + Console.WriteLine("Hello World"); + return 0; + } + } +} diff --git a/TestAssets/TestProjects/TestAppWithScripts/TestApp.xproj b/TestAssets/TestProjects/TestAppWithScripts/TestApp.xproj new file mode 100644 index 000000000..4cef17daa --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithScripts/TestApp.xproj @@ -0,0 +1,20 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + + 58808bbc-371e-47d6-a3d0-4902145eda4e + TestApp + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + diff --git a/TestAssets/TestProjects/TestAppWithScripts/echoscript.cmd b/TestAssets/TestProjects/TestAppWithScripts/echoscript.cmd new file mode 100644 index 000000000..a996a370f --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithScripts/echoscript.cmd @@ -0,0 +1,2 @@ +@echo off +echo %* \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithScripts/echoscript.sh b/TestAssets/TestProjects/TestAppWithScripts/echoscript.sh new file mode 100755 index 000000000..778a035de --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithScripts/echoscript.sh @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +echo $@ \ No newline at end of file diff --git a/TestAssets/TestProjects/TestAppWithScripts/project.json b/TestAssets/TestProjects/TestAppWithScripts/project.json new file mode 100644 index 000000000..8df726e4d --- /dev/null +++ b/TestAssets/TestProjects/TestAppWithScripts/project.json @@ -0,0 +1,22 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811" + }, + + "frameworks": { + "dnxcore50": { } + }, + + "scripts": { + "prepublish" : ["echoscript prepublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:TargetFramework%? ?%publish:Runtime%?"], + "postpublish" : ["echoscript postpublish_output ?%publish:ProjectPath%? ?%publish:Configuration%? ?%publish:OutputPath%? ?%publish:TargetFramework%? ?%publish:Runtime%?"], + + "precompile" : ["echoscript precompile_output ?%compile:ProjectPath%? ?%compile:Configuration%? ?%compile:OutputPath%? ?%compile:TargetFramework%? ?%compile:Runtime%?"], + "postcompile" : ["echoscript postcompile_output ?%compile:ProjectPath%? ?%compile:Configuration%? ?%compile:OutputPath%? ?%compile:TargetFramework%? ?%compile:Runtime%?"] + } +} diff --git a/branchinfo.txt b/branchinfo.txt new file mode 100644 index 000000000..7ac005498 --- /dev/null +++ b/branchinfo.txt @@ -0,0 +1,7 @@ +# This is a file containing environment variables specific to this branch +# Any line that is not blank and does not start with '#' is interpreted as a variable to set +# Each line is expected to be in the format "[Name]=[Value]". +MAJOR_VERSION=1 +MINOR_VERSION=0 +PATCH_VERSION=0 +RELEASE_SUFFIX=beta diff --git a/build.cmd b/build.cmd index 9b72ee74b..615538658 100644 --- a/build.cmd +++ b/build.cmd @@ -6,4 +6,4 @@ REM Licensed under the MIT license. See LICENSE file in the project root for ful REM Crossgen Workaround set ComPlus_ReadyToRun=0 -powershell -NoProfile -NoLogo -Command "%~dp0scripts\build\build.ps1 %*; exit $LastExitCode;" +powershell -NoProfile -NoLogo -Command "%~dp0scripts\run-build.ps1 %*; exit $LastExitCode;" diff --git a/build.sh b/build.sh index 36895885b..fb885b57b 100755 --- a/build.sh +++ b/build.sh @@ -16,26 +16,9 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -source "$DIR/scripts/common/_common.sh" -source "$REPOROOT/scripts/build/process-args.sh" - -# splitting build from package is required to work around dotnet/coreclr#2215 -# once that is fixed, we should remove the NOPACKAGE flag and do the full build either in -# or out of docker. +# Check if we need to build in docker if [ ! -z "$BUILD_IN_DOCKER" ]; then - export BUILD_COMMAND=". /opt/code/scripts/build/process-args.sh $@ ; . /opt/code/scripts/build/build.sh" - $REPOROOT/scripts/docker/dockerbuild.sh + $DIR/scripts/dockerbuild.sh "$@" else - $REPOROOT/scripts/build/build.sh -fi - -if [ ! -z "$NOPACKAGE" ]; then - header "Skipping packaging" -else - if [ ! -z "$PACKAGE_IN_DOCKER" ]; then - export BUILD_COMMAND="/opt/code/scripts/package/package.sh" - $REPOROOT/scripts/docker/dockerbuild.sh - else - $REPOROOT/scripts/package/package.sh - fi + $DIR/scripts/run-build.sh "$@" fi diff --git a/netci.groovy b/netci.groovy index a617fa11d..49d474f8a 100644 --- a/netci.groovy +++ b/netci.groovy @@ -6,19 +6,14 @@ import jobs.generation.Utilities; def project = GithubProject +def branch = GithubBranchName def osList = ['Ubuntu', 'OSX', 'Windows_NT', 'CentOS7.1'] -def machineLabelMap = ['Ubuntu':'ubuntu-doc', - 'OSX':'mac', - 'Windows_NT':'windows', - 'CentOS7.1' : 'centos-71'] - def static getBuildJobName(def configuration, def os) { return configuration.toLowerCase() + '_' + os.toLowerCase() } - [true, false].each { isPR -> ['Debug', 'Release'].each { configuration -> osList.each { os -> @@ -28,7 +23,6 @@ def static getBuildJobName(def configuration, def os) { // Calculate job name def jobName = getBuildJobName(configuration, os) def buildCommand = ''; - def postBuildCommand = ''; // Calculate the build command if (os == 'Windows_NT') { @@ -40,7 +34,6 @@ def static getBuildJobName(def configuration, def os) { def newJob = job(Utilities.getFullJobName(project, jobName, isPR)) { // Set the label. - label(machineLabelMap[os]) steps { if (os == 'Windows_NT') { // Batch @@ -49,26 +42,15 @@ def static getBuildJobName(def configuration, def os) { else { // Shell shell(buildCommand) - - // Post Build Cleanup - publishers { - postBuildScripts { - steps { - shell(postBuildCommand) - } - onlyIfBuildSucceeds(false) - } - } - } } } - - Utilities.standardJobSetup(newJob, project, isPR) + Utilities.setMachineAffinity(newJob, os, 'latest-or-auto') + Utilities.standardJobSetup(newJob, project, isPR, "*/${branch}") Utilities.addXUnitDotNETResults(newJob, '**/*-testResults.xml') if (isPR) { - Utilities.addGithubPRTrigger(newJob, "${os} ${configuration} Build") + Utilities.addGithubPRTriggerForBranch(newJob, branch, "${os} ${configuration} Build") } else { Utilities.addGithubPushTrigger(newJob) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiColorExtensions.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiColorExtensions.cs new file mode 100644 index 000000000..874fc7608 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiColorExtensions.cs @@ -0,0 +1,52 @@ +// 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. + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class AnsiColorExtensions + { + public static string Black(this string text) + { + return "\x1B[30m" + text + "\x1B[39m"; + } + + public static string Red(this string text) + { + return "\x1B[31m" + text + "\x1B[39m"; + } + public static string Green(this string text) + { + return "\x1B[32m" + text + "\x1B[39m"; + } + + public static string Yellow(this string text) + { + return "\x1B[33m" + text + "\x1B[39m"; + } + + public static string Blue(this string text) + { + return "\x1B[34m" + text + "\x1B[39m"; + } + + public static string Magenta(this string text) + { + return "\x1B[35m" + text + "\x1B[39m"; + } + + public static string Cyan(this string text) + { + return "\x1B[36m" + text + "\x1B[39m"; + } + + public static string White(this string text) + { + return "\x1B[37m" + text + "\x1B[39m"; + } + + public static string Bold(this string text) + { + return "\x1B[1m" + text + "\x1B[22m"; + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs new file mode 100644 index 000000000..8458eb629 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/AnsiConsole.cs @@ -0,0 +1,143 @@ +// 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.Build.Framework +{ + public class AnsiConsole + { + private AnsiConsole(TextWriter writer, bool useConsoleColor) + { + Writer = writer; + + _useConsoleColor = useConsoleColor; + if (_useConsoleColor) + { + OriginalForegroundColor = Console.ForegroundColor; + } + } + + private int _boldRecursion; + private bool _useConsoleColor; + + public static AnsiConsole GetOutput(bool useConsoleColor) + { + return new AnsiConsole(Console.Out, useConsoleColor); + } + + public static AnsiConsole GetError(bool useConsoleColor) + { + return new AnsiConsole(Console.Error, useConsoleColor); + } + + public TextWriter Writer { get; } + + public ConsoleColor OriginalForegroundColor { get; } + + private void SetColor(ConsoleColor color) + { + Console.ForegroundColor = (ConsoleColor)(((int)Console.ForegroundColor & 0x08) | ((int)color & 0x07)); + } + + private void SetBold(bool bold) + { + _boldRecursion += bold ? 1 : -1; + if (_boldRecursion > 1 || (_boldRecursion == 1 && !bold)) + { + return; + } + + Console.ForegroundColor = (ConsoleColor)((int)Console.ForegroundColor ^ 0x08); + } + + public void WriteLine(string message) + { + if (!_useConsoleColor) + { + Writer.WriteLine(message); + return; + } + + var escapeScan = 0; + for (;;) + { + var escapeIndex = message.IndexOf("\x1b[", escapeScan); + if (escapeIndex == -1) + { + var text = message.Substring(escapeScan); + Writer.Write(text); + break; + } + else + { + var startIndex = escapeIndex + 2; + var endIndex = startIndex; + while (endIndex != message.Length && + message[endIndex] >= 0x20 && + message[endIndex] <= 0x3f) + { + endIndex += 1; + } + + var text = message.Substring(escapeScan, escapeIndex - escapeScan); + Writer.Write(text); + if (endIndex == message.Length) + { + break; + } + + switch (message[endIndex]) + { + case 'm': + int value; + if (int.TryParse(message.Substring(startIndex, endIndex - startIndex), out value)) + { + switch (value) + { + case 1: + SetBold(true); + break; + case 22: + SetBold(false); + break; + case 30: + SetColor(ConsoleColor.Black); + break; + case 31: + SetColor(ConsoleColor.Red); + break; + case 32: + SetColor(ConsoleColor.Green); + break; + case 33: + SetColor(ConsoleColor.Yellow); + break; + case 34: + SetColor(ConsoleColor.Blue); + break; + case 35: + SetColor(ConsoleColor.Magenta); + break; + case 36: + SetColor(ConsoleColor.Cyan); + break; + case 37: + SetColor(ConsoleColor.Gray); + break; + case 39: + SetColor(OriginalForegroundColor); + break; + } + } + break; + } + + escapeScan = endIndex + 1; + } + } + Writer.WriteLine(); + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/ArgumentEscaper.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/ArgumentEscaper.cs new file mode 100644 index 000000000..7b1958057 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/ArgumentEscaper.cs @@ -0,0 +1,206 @@ +// 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 System.Text; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class ArgumentEscaper + { + /// + /// Undo the processing which took place to create string[] args in Main, + /// so that the next process will receive the same string[] args + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + public static string EscapeAndConcatenateArgArrayForProcessStart(IEnumerable args) + { + return string.Join(" ", EscapeArgArray(args)); + } + + /// + /// Undo the processing which took place to create string[] args in Main, + /// so that the next process will receive the same string[] args + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + public static string EscapeAndConcatenateArgArrayForCmdProcessStart(IEnumerable args) + { + return string.Join(" ", EscapeArgArrayForCmd(args)); + } + + /// + /// Undo the processing which took place to create string[] args in Main, + /// so that the next process will receive the same string[] args + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + private static IEnumerable EscapeArgArray(IEnumerable args) + { + var escapedArgs = new List(); + + foreach (var arg in args) + { + escapedArgs.Add(EscapeArg(arg)); + } + + return escapedArgs; + } + + /// + /// This prefixes every character with the '^' character to force cmd to + /// interpret the argument string literally. An alternative option would + /// be to do this only for cmd metacharacters. + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + private static IEnumerable EscapeArgArrayForCmd(IEnumerable arguments) + { + var escapedArgs = new List(); + + foreach (var arg in arguments) + { + escapedArgs.Add(EscapeArgForCmd(arg)); + } + + return escapedArgs; + } + + private static string EscapeArg(string arg) + { + var sb = new StringBuilder(); + + var quoted = ShouldSurroundWithQuotes(arg); + if (quoted) sb.Append("\""); + + for (int i = 0; i < arg.Length; ++i) + { + var backslashCount = 0; + + // Consume All Backslashes + while (i < arg.Length && arg[i] == '\\') + { + backslashCount++; + i++; + } + + // Escape any backslashes at the end of the arg + // This ensures the outside quote is interpreted as + // an argument delimiter + if (i == arg.Length) + { + sb.Append('\\', 2 * backslashCount); + } + + // Escape any preceding backslashes and the quote + else if (arg[i] == '"') + { + sb.Append('\\', (2 * backslashCount) + 1); + sb.Append('"'); + } + + // Output any consumed backslashes and the character + else + { + sb.Append('\\', backslashCount); + sb.Append(arg[i]); + } + } + + if (quoted) sb.Append("\""); + + return sb.ToString(); + } + + /// + /// Prepare as single argument to + /// roundtrip properly through cmd. + /// + /// This prefixes every character with the '^' character to force cmd to + /// interpret the argument string literally. An alternative option would + /// be to do this only for cmd metacharacters. + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + private static string EscapeArgForCmd(string argument) + { + var sb = new StringBuilder(); + + var quoted = ShouldSurroundWithQuotes(argument); + + if (quoted) sb.Append("^\""); + + foreach (var character in argument) + { + + if (character == '"') + { + + sb.Append('^'); + sb.Append('"'); + sb.Append('^'); + sb.Append(character); + } + else + { + sb.Append("^"); + sb.Append(character); + } + } + + if (quoted) sb.Append("^\""); + + return sb.ToString(); + } + + /// + /// Prepare as single argument to + /// roundtrip properly through cmd. + /// + /// This prefixes every character with the '^' character to force cmd to + /// interpret the argument string literally. An alternative option would + /// be to do this only for cmd metacharacters. + /// + /// See here for more info: + /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx + /// + /// + /// + internal static bool ShouldSurroundWithQuotes(string argument) + { + // Don't quote already quoted strings + if (argument.StartsWith("\"", StringComparison.Ordinal) && + argument.EndsWith("\"", StringComparison.Ordinal)) + { + return false; + } + + // Only quote if whitespace exists in the string + if (argument.Contains(" ") || argument.Contains("\t") || argument.Contains("\n")) + { + return true; + } + + return true; + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs new file mode 100644 index 000000000..312fdd6ce --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildContext.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildContext + { + private IDictionary _completedTargets = new Dictionary(StringComparer.OrdinalIgnoreCase); + + public static readonly string DefaultTarget = "Default"; + + private int _maxTargetLen; + private Stack _targetStack = new Stack(); + + public IDictionary Targets { get; } + + public IDictionary Properties = new Dictionary(); + + public string BuildDirectory { get; } + + public object this[string name] + { + get { return Properties.ContainsKey(name) ? Properties[name] : null; } + set { Properties[name] = value; } + } + + public BuildContext(IDictionary targets, string buildDirectory) + { + Targets = targets; + BuildDirectory = buildDirectory; + _maxTargetLen = targets.Values.Select(t => t.Name.Length).Max(); + } + + public BuildTargetResult RunTarget(string name) => RunTarget(name, force: false); + + public BuildTargetResult RunTarget(string name, bool force) + { + BuildTarget target; + if (!Targets.TryGetValue(name, out target)) + { + Reporter.Verbose.WriteLine($"Skipping undefined target: {name}"); + } + + // Check if it's been completed + BuildTargetResult result; + if (!force && _completedTargets.TryGetValue(name, out result)) + { + Reporter.Verbose.WriteLine($"Skipping completed target: {target.Name}"); + return result; + } + + + // It hasn't, or we're forcing, so run it + result = ExecTarget(target); + _completedTargets[target.Name] = result; + return result; + } + + public void Verbose(string message) + { + Reporter.Output.WriteLine("trace".White() + $": {message}"); + } + + public void Info(string message) + { + Reporter.Output.WriteLine("info ".Green() + $": {message}"); + } + + public void Warn(string message) + { + Reporter.Output.WriteLine("warn ".Yellow() + $": {message}"); + } + + public void Error(string message) + { + Reporter.Error.WriteLine("error".Red().Bold() + $": {message}"); + } + + private BuildTargetResult ExecTarget(BuildTarget target) + { + var sectionName = $"{target.Name.PadRight(_maxTargetLen + 2).Yellow()} ({target.Source.White()})"; + BuildReporter.BeginSection("TARGET", sectionName); + + BuildTargetResult result; + + // Run the dependencies + var dependencyResults = new Dictionary(); + var failedDependencyResult = RunDependencies(target, dependencyResults); + if (failedDependencyResult != null) + { + result = failedDependencyResult; + } + else if (target.Body != null) + { + try + { + result = target.Body(new BuildTargetContext(this, target, dependencyResults)); + } + catch (Exception ex) + { + result = new BuildTargetResult(target, success: false, exception: ex); + } + } + else + { + result = new BuildTargetResult(target, success: true); + } + BuildReporter.EndSection("TARGET", sectionName, result.Success); + + return result; + } + + private BuildTargetResult RunDependencies(BuildTarget target, Dictionary dependencyResults) + { + BuildTargetResult result = null; + foreach (var dependency in target.Dependencies) + { + result = RunTarget(dependency); + dependencyResults[dependency] = result; + + if (!result.Success) + { + return result; + } + } + + return null; + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildFailureException.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildFailureException.cs new file mode 100644 index 000000000..665c0243a --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildFailureException.cs @@ -0,0 +1,42 @@ +using System; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildFailureException : Exception + { + public BuildTarget Target { get; } + + public BuildFailureException() + { + } + + public BuildFailureException(BuildTarget target) : base($"The '{target.Name}' target failed") + { + Target = target; + } + + public BuildFailureException(BuildTarget target, Exception innerException) : base($"The '{target.Name}' target failed", innerException) + { + Target = target; + } + + public BuildFailureException(string message) : base(message) + { + } + + public BuildFailureException(string message, BuildTarget target) : base(message) + { + Target = target; + } + + public BuildFailureException(string message, Exception innerException) : base(message, innerException) + { + } + + public BuildFailureException(string message, Exception innerException, BuildTarget target) : base(message, innerException) + { + Target = target; + } + + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildHelpers.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildHelpers.cs new file mode 100644 index 000000000..cb7aa8ede --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildHelpers.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class BuildHelpers + { + public static int ExecInSilent(string workingDirectory, string command, params string[] args) => ExecInSilent(workingDirectory, command, (IEnumerable)args); + public static int ExecInSilent(string workingDirectory, string command, IEnumerable args) => ExecCore(command, args, workingDirectory, silent: true); + + public static int ExecIn(string workingDirectory, string command, params string[] args) => ExecIn(workingDirectory, command, (IEnumerable)args); + public static int ExecIn(string workingDirectory, string command, IEnumerable args) => ExecCore(command, args, workingDirectory, silent: false); + + public static int ExecSilent(string command, params string[] args) => ExecSilent(command, (IEnumerable)args); + public static int ExecSilent(string command, IEnumerable args) => ExecCore(command, args, workingDirectory: null, silent: true); + + public static int Exec(string command, params string[] args) => Exec(command, (IEnumerable)args); + public static int Exec(string command, IEnumerable args) => ExecCore(command, args, workingDirectory: null, silent: false); + + public static Command Cmd(string command, params string[] args) => Cmd(command, (IEnumerable)args); + public static Command Cmd(string command, IEnumerable args) + { + return Command.Create(command, args); + } + + internal static int ExecCore(string command, IEnumerable args, string workingDirectory, bool silent) + { + var cmd = Cmd(command, args); + if(!string.IsNullOrEmpty(workingDirectory)) + { + cmd.WorkingDirectory(workingDirectory); + } + if(silent) + { + cmd.CaptureStdErr().CaptureStdOut(); + } + var result = cmd.Execute(); + + result.EnsureSuccessful(); + return result.ExitCode; + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildReporter.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildReporter.cs new file mode 100644 index 000000000..bbefb7cf6 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildReporter.cs @@ -0,0 +1,27 @@ +using System; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class BuildReporter + { + public static void BeginSection(string type, string name) + { + Reporter.Output.WriteLine($"[{type.PadRight(10)} >]".Green() + $" [....] [{DateTime.Now:O}]".Blue() + $" {name}"); + } + + public static void EndSection(string type, string name, bool success) + { + var header = $"[{type.PadRight(10)} <]"; + if(success) + { + header = header.Green(); + } + else + { + header = header.Red(); + } + var successString = success ? " OK " : "FAIL"; + Reporter.Output.WriteLine(header + $" [{successString}] [{DateTime.Now:O}]".Blue() + $" {name}"); + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs new file mode 100644 index 000000000..34eb86afa --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildSetup.cs @@ -0,0 +1,148 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildSetup + { + private Dictionary _targets = new Dictionary(); + + public IList _overrides = new List(); + + public string ProductName { get; } + + public BuildSetup(string productName) + { + ProductName = productName; + } + + public static BuildSetup Create(string productName) + { + return new BuildSetup(productName); + } + + public BuildSetup UseTargets(IEnumerable targets) + { + foreach (var target in targets) + { + BuildTarget previousTarget; + if (_targets.TryGetValue(target.Name, out previousTarget)) + { + _overrides.Add(new TargetOverride(target.Name, previousTarget.Source, target.Source)); + } + _targets[target.Name] = target; + } + return this; + } + + public BuildSetup UseAllTargetsFromAssembly() + { + var asm = typeof(T).GetTypeInfo().Assembly; + return UseTargets(asm.GetExportedTypes().SelectMany(t => CollectTargets(t))); + } + + public BuildSetup UseTargetsFrom() + { + return UseTargets(CollectTargets(typeof(T))); + } + + public int Run(string[] args) + { + DebugHelper.HandleDebugSwitch(ref args); + + var targets = new[] { BuildContext.DefaultTarget }; + if(args.Length > 0) + { + targets = args; + } + + Reporter.Output.WriteBanner($"Building {ProductName}"); + + if (_overrides.Any()) + { + foreach (var targetOverride in _overrides) + { + Reporter.Verbose.WriteLine($"Target {targetOverride.Name} from {targetOverride.OriginalSource} was overridden in {targetOverride.OverrideSource}".Black()); + } + } + + var context = new BuildContext(_targets, Directory.GetCurrentDirectory()); + BuildTargetResult result = null; + try + { + foreach (var target in targets) + { + result = context.RunTarget(target); + if(!result.Success) + { + break; + } + } + } + catch (Exception ex) + { + Reporter.Error.WriteLine(ex.ToString().Red()); + return 1; + } + + if(result != null && !result.Success) + { + Reporter.Error.WriteLine($"Build failed: {result.ErrorMessage}".Red()); + return 1; + } + else + { + Reporter.Output.WriteLine("Build succeeded".Green()); + return 0; + } + } + + private static IEnumerable CollectTargets(Type typ) + { + return from m in typ.GetMethods() + let attr = m.GetCustomAttribute() + where attr != null + select CreateTarget(m, attr); + } + + private static BuildTarget CreateTarget(MethodInfo m, TargetAttribute attr) + { + return new BuildTarget( + attr.Name ?? m.Name, + $"{m.DeclaringType.FullName}.{m.Name}", + attr.Dependencies, + (Func)m.CreateDelegate(typeof(Func))); + } + + private string GenerateSourceString(string file, int? line, string member) + { + if (!string.IsNullOrEmpty(file) && line != null) + { + return $"{file}:{line}"; + } + else if (!string.IsNullOrEmpty(member)) + { + return member; + } + return string.Empty; + } + + public class TargetOverride + { + public string Name { get; } + public string OriginalSource { get; } + public string OverrideSource { get; } + + public TargetOverride(string name, string originalSource, string overrideSource) + { + Name = name; + OriginalSource = originalSource; + OverrideSource = overrideSource; + } + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs new file mode 100644 index 000000000..303e0ae66 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTarget.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildTarget + { + public string Name { get; } + public string Source { get; } + public IEnumerable Dependencies { get; } + public Func Body { get; } + + public BuildTarget(string name, string source) : this(name, source, Enumerable.Empty(), null) { } + public BuildTarget(string name, string source, IEnumerable dependencies) : this(name, source, dependencies, null) { } + public BuildTarget(string name, string source, IEnumerable dependencies, Func body) + { + Name = name; + Source = source; + Dependencies = dependencies; + Body = body; + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetContext.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetContext.cs new file mode 100644 index 000000000..376234dc2 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetContext.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildTargetContext + { + private IDictionary _dependencyResults; + + public BuildContext BuildContext { get; } + public BuildTarget Target { get; } + + public BuildTargetContext(BuildContext buildContext, BuildTarget target, IDictionary dependencyResults) + { + BuildContext = buildContext; + Target = target; + _dependencyResults = dependencyResults; + } + + public BuildTargetResult Success() + { + return new BuildTargetResult(Target, success: true); + } + + public BuildTargetResult Failed() => Failed(errorMessage: string.Empty); + + public BuildTargetResult Failed(string errorMessage) + { + return new BuildTargetResult(Target, success: false, errorMessage: errorMessage); + } + + public void Info(string message) => BuildContext.Info(message); + public void Warn(string message) => BuildContext.Warn(message); + public void Error(string message) => BuildContext.Error(message); + public void Verbose(string message) => BuildContext.Verbose(message); + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetResult.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetResult.cs new file mode 100644 index 000000000..cadf74a03 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/BuildTargetResult.cs @@ -0,0 +1,41 @@ +using System; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class BuildTargetResult + { + public BuildTarget Target { get; } + public bool Success { get; } + public string ErrorMessage { get; } + public Exception Exception { get; } + + public BuildTargetResult(BuildTarget target, bool success) : this(target, success, errorMessage: string.Empty) { } + + public BuildTargetResult(BuildTarget target, bool success, Exception exception) : this(target, success, exception.ToString()) + { + Exception = exception; + } + + public BuildTargetResult(BuildTarget target, bool success, string errorMessage) + { + Target = target; + Success = success; + ErrorMessage = errorMessage; + } + + public void EnsureSuccessful() + { + if(!Success) + { + if(string.IsNullOrEmpty(ErrorMessage)) + { + throw new BuildFailureException(Target, Exception); + } + else + { + throw new BuildFailureException(ErrorMessage, Exception, Target); + } + } + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs new file mode 100644 index 000000000..625b3f776 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Command.cs @@ -0,0 +1,327 @@ +// 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 System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public class Command + { + private Process _process; + + private StringWriter _stdOutCapture; + private StringWriter _stdErrCapture; + + private Action _stdOutForward; + private Action _stdErrForward; + + private Action _stdOutHandler; + private Action _stdErrHandler; + + private bool _running = false; + + private Command(string executable, string args) + { + // Set the things we need + var psi = new ProcessStartInfo() + { + FileName = executable, + Arguments = args + }; + + _process = new Process() + { + StartInfo = psi + }; + } + + public static Command Create(string executable, params string[] args) + { + return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args)); + } + + public static Command Create(string executable, IEnumerable args) + { + return Create(executable, ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args)); + } + + public static Command Create(string executable, string args) + { + ResolveExecutablePath(ref executable, ref args); + + return new Command(executable, args); + } + + private static void ResolveExecutablePath(ref string executable, ref string args) + { + foreach (string suffix in Constants.RunnableSuffixes) + { + var fullExecutable = Path.GetFullPath(Path.Combine( + AppContext.BaseDirectory, executable + suffix)); + + if (File.Exists(fullExecutable)) + { + executable = fullExecutable; + + // In priority order we've found the best runnable extension, so break. + break; + } + } + + // On Windows, we want to avoid using "cmd" if possible (it mangles the colors, and a bunch of other things) + // So, do a quick path search to see if we can just directly invoke it + var useCmd = ShouldUseCmd(executable); + + if (useCmd) + { + var comSpec = System.Environment.GetEnvironmentVariable("ComSpec"); + + // cmd doesn't like "foo.exe ", so we need to ensure that if + // args is empty, we just run "foo.exe" + if (!string.IsNullOrEmpty(args)) + { + executable = (executable + " " + args).Replace("\"", "\\\""); + } + args = $"/C \"{executable}\""; + executable = comSpec; + } + } + + private static bool ShouldUseCmd(string executable) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var extension = Path.GetExtension(executable); + if (!string.IsNullOrEmpty(extension)) + { + return !string.Equals(extension, ".exe", StringComparison.Ordinal); + } + else if (executable.Contains(Path.DirectorySeparatorChar)) + { + // It's a relative path without an extension + if (File.Exists(executable + ".exe")) + { + // It refers to an exe! + return false; + } + } + else + { + // Search the path to see if we can find it + foreach (var path in System.Environment.GetEnvironmentVariable("PATH").Split(Path.PathSeparator)) + { + var candidate = Path.Combine(path, executable + ".exe"); + if (File.Exists(candidate)) + { + // We found an exe! + return false; + } + } + } + + // It's a non-exe :( + return true; + } + + // Non-windows never uses cmd + return false; + } + + public Command Environment(IDictionary env) + { + foreach(var item in env) + { + _process.StartInfo.Environment[item.Key] = item.Value; + } + return this; + } + + public CommandResult Execute() + { + ThrowIfRunning(); + _running = true; + + if (_process.StartInfo.RedirectStandardOutput) + { + _process.OutputDataReceived += (sender, args) => + { + ProcessData(args.Data, _stdOutCapture, _stdOutForward, _stdOutHandler); + }; + } + + if (_process.StartInfo.RedirectStandardError) + { + _process.ErrorDataReceived += (sender, args) => + { + ProcessData(args.Data, _stdErrCapture, _stdErrForward, _stdErrHandler); + }; + } + + _process.EnableRaisingEvents = true; + + var sw = Stopwatch.StartNew(); + BuildReporter.BeginSection("EXEC", FormatProcessInfo(_process.StartInfo)); + + _process.Start(); + + if (_process.StartInfo.RedirectStandardOutput) + { + _process.BeginOutputReadLine(); + } + + if (_process.StartInfo.RedirectStandardError) + { + _process.BeginErrorReadLine(); + } + + _process.WaitForExit(); + + var exitCode = _process.ExitCode; + + var message = $"{FormatProcessInfo(_process.StartInfo)} exited with {exitCode}"; + if (exitCode == 0) + { + BuildReporter.EndSection("EXEC", message.Green(), success: true); + } + else + { + BuildReporter.EndSection("EXEC", message.Red().Bold(), success: false); + } + + return new CommandResult( + _process.StartInfo, + exitCode, + _stdOutCapture?.GetStringBuilder()?.ToString(), + _stdErrCapture?.GetStringBuilder()?.ToString()); + } + + public Command WorkingDirectory(string projectDirectory) + { + _process.StartInfo.WorkingDirectory = projectDirectory; + return this; + } + + public Command EnvironmentVariable(string name, string value) + { + _process.StartInfo.Environment[name] = value; + return this; + } + + public Command CaptureStdOut() + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardOutput = true; + _stdOutCapture = new StringWriter(); + return this; + } + + public Command CaptureStdErr() + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardError = true; + _stdErrCapture = new StringWriter(); + return this; + } + + public Command ForwardStdOut(TextWriter to = null) + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardOutput = true; + if (to == null) + { + _stdOutForward = Reporter.Output.WriteLine; + } + else + { + _stdOutForward = to.WriteLine; + } + return this; + } + + public Command ForwardStdErr(TextWriter to = null) + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardError = true; + if (to == null) + { + _stdErrForward = Reporter.Error.WriteLine; + } + else + { + _stdErrForward = to.WriteLine; + } + return this; + } + + public Command OnOutputLine(Action handler) + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardOutput = true; + if (_stdOutHandler != null) + { + throw new InvalidOperationException("Already handling stdout!"); + } + _stdOutHandler = handler; + return this; + } + + public Command OnErrorLine(Action handler) + { + ThrowIfRunning(); + _process.StartInfo.RedirectStandardError = true; + if (_stdErrHandler != null) + { + throw new InvalidOperationException("Already handling stderr!"); + } + _stdErrHandler = handler; + return this; + } + + private string FormatProcessInfo(ProcessStartInfo info) + { + if (string.IsNullOrWhiteSpace(info.Arguments)) + { + return info.FileName; + } + + return info.FileName + " " + info.Arguments; + } + + private void ThrowIfRunning([CallerMemberName] string memberName = null) + { + if (_running) + { + throw new InvalidOperationException($"Unable to invoke {memberName} after the command has been run"); + } + } + + private void ProcessData(string data, StringWriter capture, Action forward, Action handler) + { + if (data == null) + { + return; + } + + if (capture != null) + { + capture.WriteLine(data); + } + + if (forward != null) + { + forward(data); + } + + if (handler != null) + { + handler(data); + } + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/CommandResult.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/CommandResult.cs new file mode 100644 index 000000000..6630a857b --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/CommandResult.cs @@ -0,0 +1,34 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public struct CommandResult + { + public static readonly CommandResult Empty = new CommandResult(); + + public ProcessStartInfo StartInfo { get; } + public int ExitCode { get; } + public string StdOut { get; } + public string StdErr { get; } + + public CommandResult(ProcessStartInfo startInfo, int exitCode, string stdOut, string stdErr) + { + StartInfo = startInfo; + ExitCode = exitCode; + StdOut = stdOut; + StdErr = stdErr; + } + + public void EnsureSuccessful() + { + if(ExitCode != 0) + { + throw new BuildFailureException($"Command failed with exit code {ExitCode}: {StartInfo.FileName} {StartInfo.Arguments}"); + } + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Constants.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Constants.cs new file mode 100644 index 000000000..66bbb9000 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Constants.cs @@ -0,0 +1,23 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class Constants + { + //public static readonly string ProjectFileName = "project.json"; + public static readonly string ExeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty; + + // Priority order of runnable suffixes to look for and run + public static readonly string[] RunnableSuffixes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? new string[] { ".exe", ".cmd", ".bat" } + : new string[] { string.Empty }; + + public static readonly string DynamicLibPrefix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "" : "lib"; + + public static readonly string DynamicLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" : ".so"; + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/DebugHelper.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/DebugHelper.cs new file mode 100644 index 000000000..988e15f8d --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/DebugHelper.cs @@ -0,0 +1,29 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class DebugHelper + { + [Conditional("DEBUG")] + public static void HandleDebugSwitch(ref string[] args) + { + if (args.Length > 0 && string.Equals("--debug", args[0], StringComparison.OrdinalIgnoreCase)) + { + args = args.Skip(1).ToArray(); + WaitForDebugger(); + } + } + + private static void WaitForDebugger() + { + Console.WriteLine("Waiting for debugger to attach. Press ENTER to continue"); + Console.WriteLine($"Process ID: {Process.GetCurrentProcess().Id}"); + Console.ReadLine(); + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj b/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj new file mode 100644 index 000000000..26f7e55e4 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Microsoft.DotNet.Cli.Build.Framework.xproj @@ -0,0 +1,19 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 49beb486-ab5a-4416-91ea-8cd34abb0c9d + Microsoft.DotNet.Cli.Build.Framework + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs new file mode 100644 index 000000000..766ddf764 --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/Reporter.cs @@ -0,0 +1,65 @@ +// 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.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + // Stupid-simple console manager + internal class Reporter + { + private static readonly Reporter Null = new Reporter(console: null); + private static object _lock = new object(); + + private readonly AnsiConsole _console; + + private Reporter(AnsiConsole console) + { + _console = console; + } + + public static Reporter Output { get; } = Create(AnsiConsole.GetOutput); + public static Reporter Error { get; } = Create(AnsiConsole.GetOutput); + public static Reporter Verbose { get; } = Create(AnsiConsole.GetOutput); + + public static Reporter Create(Func getter) + { + var stripColors = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) || + string.Equals(Environment.GetEnvironmentVariable("NO_COLOR"), "1"); + return new Reporter(getter(stripColors)); + } + + public void WriteLine(string message) + { + lock (_lock) + { + _console?.WriteLine(message); + } + } + + public void WriteLine() + { + lock (_lock) + { + _console?.Writer?.WriteLine(); + } + } + + public void Write(string message) + { + lock (_lock) + { + _console?.Writer?.Write(message); + } + } + + public void WriteBanner(string content) + { + string border = new string('*', content.Length + 6); + WriteLine($@"{border} +* {content} * +{border}".Green()); + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs new file mode 100644 index 000000000..c22ac967a --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/StandardGoals.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + public static class StandardGoals + { + public static BuildSetup UseStandardGoals(this BuildSetup self) + { + return self.UseTargets(new[] + { + new BuildTarget("Default", "Standard Goals", new [] { "Prepare", "Compile", "Test", "Publish" }), + new BuildTarget("Prepare", "Standard Goals"), + new BuildTarget("Compile", "Standard Goals"), + new BuildTarget("Test", "Standard Goals"), + new BuildTarget("Publish", "Standard Goals") + }); + } + } +} diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs new file mode 100644 index 000000000..6cc6771fc --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetAttribute.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Microsoft.DotNet.Cli.Build.Framework +{ + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] + public class TargetAttribute : Attribute + { + public string Name { get; set; } + public IEnumerable Dependencies { get; } + + public TargetAttribute() + { + Dependencies = Enumerable.Empty(); + } + + // Attributes can only use constants, so a comma-separated string is better :) + public TargetAttribute(params string[] dependencies) + { + Dependencies = dependencies; + } + } +} \ No newline at end of file diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json new file mode 100644 index 000000000..dd887545d --- /dev/null +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/project.json @@ -0,0 +1,12 @@ +{ + "version": "1.0.0-*", + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "System.Diagnostics.Process": "4.1.0-rc2-23811" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/scripts/build/build.ps1 b/scripts/build/build.ps1 deleted file mode 100644 index c302e0378..000000000 --- a/scripts/build/build.ps1 +++ /dev/null @@ -1,56 +0,0 @@ -# -# 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. -# - -param( - [string]$Configuration="Debug", - [switch]$Offline, - [switch]$NoPackage) - -$ErrorActionPreference="Stop" - -. "$PSScriptRoot\..\common\_common.ps1" - -. "$RepoRoot\scripts\build\generate-version.ps1" - -_ "$RepoRoot\scripts\clean\clear-nuget-cache.ps1" - -header "Building dotnet tools version $($env:DOTNET_CLI_VERSION) - $Configuration" -header "Checking Pre-Reqs" - -_ "$RepoRoot\scripts\test\check-prereqs.ps1" - -header "Restoring Tools and Packages" - -if ($Offline){ - info "Skipping Tools and Packages dowlnoad: Offline build" -} -else { - _ "$RepoRoot\scripts\obtain\install-tools.ps1" -} - -header "Cleaning out .ni's from Stage0" -rm "$RepoRoot\.dotnet_stage0\**\*.ni.*" - -_ "$RepoRoot\scripts\build\restore-packages.ps1" - -header "Compiling" -_ "$RepoRoot\scripts\compile\compile.ps1" @("$Configuration") - -header "Setting Stage2 as PATH and DOTNET_TOOLS" -setPathAndHome "$Stage2Dir" - -header "Testing" -_ "$RepoRoot\scripts\test\test.ps1" - -header "Validating Dependencies" -_ "$RepoRoot\scripts\test\validate-dependencies.ps1" - -if ($NoPackage){ - info "Skipping Packaging" - exit 0 -} -else { - _ "$RepoRoot\scripts\package\package.ps1" -} diff --git a/scripts/build/build.sh b/scripts/build/build.sh deleted file mode 100755 index 362f7c531..000000000 --- a/scripts/build/build.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -# Set OFFLINE environment variable to build offline - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -source "$REPOROOT/scripts/build/generate-version.sh" - -"$REPOROOT/scripts/clean/clear-nuget-cache.sh" - -header "Building dotnet tools version $DOTNET_CLI_VERSION - $CONFIGURATION" -header "Checking Pre-Reqs" - -$REPOROOT/scripts/test/check-prereqs.sh - -header "Adjusting file descriptors limit, if necessary" -# Increases the file descriptors limit for this bash. It prevents an issue we were hitting during restore -FILE_DESCRIPTOR_LIMIT=$( ulimit -n ) -if [ $FILE_DESCRIPTOR_LIMIT -lt 1024 ] -then - info "Increasing file description limit to 1024" - ulimit -n 1024 -fi - -header "Restoring Tools and Packages" - -if [ ! -z "$OFFLINE" ]; then - info "Skipping Tools and Package Download: Offline build" -else - $REPOROOT/scripts/obtain/install-tools.sh -fi - -header "Cleaning out .ni's from Stage0" -find ".dotnet_stage0" -name '*.ni.*' -delete - -$REPOROOT/scripts/build/restore-packages.sh - -header "Compiling" -$REPOROOT/scripts/compile/compile.sh - -header "Setting Stage2 as PATH, DOTNET_HOME, and DOTNET_TOOLS" -export DOTNET_HOME=$STAGE2_DIR && export DOTNET_TOOLS=$STAGE2DIR && export PATH=$STAGE2_DIR/bin:$PATH - -header "Testing" -$REPOROOT/scripts/test/test.sh - -header "Validating Dependencies" -$REPOROOT/scripts/test/validate-dependencies.sh diff --git a/scripts/build/build_appdeps.ps1 b/scripts/build/build_appdeps.ps1 deleted file mode 100644 index f2fd8d5bc..000000000 --- a/scripts/build/build_appdeps.ps1 +++ /dev/null @@ -1,19 +0,0 @@ -# -# 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. -# -param( - [Parameter(Mandatory=$true)][string]$RepoRoot, - [Parameter(Mandatory=$true)][string]$OutputDir) - -$appdepBinDir = "$OutputDir\bin\appdepsdk" - -If (Test-Path $appdepBinDir){ - rmdir -Force -Rec $appdepBinDir -} - -mkdir -Force "$appdepBinDir" - -ls "$env:NUGET_PACKAGES\toolchain.win7-x64.Microsoft.DotNet.AppDep\1.0.5-prerelease-00001\*" | foreach { - copy -Rec $_ "$appdepBinDir" -} diff --git a/scripts/build/build_appdeps.sh b/scripts/build/build_appdeps.sh deleted file mode 100755 index 3c47986bb..000000000 --- a/scripts/build/build_appdeps.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -# Always recalculate the RID because the package always uses a specific RID, regardless of OS X version or Linux distro. -if [ "$OSNAME" == "osx" ]; then - RID=osx.10.10-x64 -elif [ "$OSNAME" == "ubuntu" ]; then - RID=ubuntu.14.04-x64 -elif [ "$OSNAME" == "centos" ]; then - RID=centos.7.1-x64 -else - echo "Unknown OS: $OSNAME" 1>&2 - exit 1 -fi - -# Get Absolute Output Dir -pushd $1 -OUTPUT_DIR="$(pwd)" -popd - -## App Deps ## -APPDEP_SDK=$NUGET_PACKAGES/toolchain.$RID.Microsoft.DotNet.AppDep/1.0.5-prerelease-00001/ -mkdir -p $OUTPUT_DIR/appdepsdk -cp -a $APPDEP_SDK/. $OUTPUT_DIR/appdepsdk diff --git a/scripts/build/build_info.sh b/scripts/build/build_info.sh deleted file mode 100755 index 3002f798a..000000000 --- a/scripts/build/build_info.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -UNAME=$(uname) -echo "Platform: $UNAME" - -if [ "$UNAME" = "Linux" ]; then - DISTRO=$(cat /etc/os-release | grep "^ID=" | cut -d = -f 2 | sed s/\"//g) - VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | cut -d = -f 2 | sed s/\"//g) - echo "Distro: $DISTRO" - echo "Version: $VERSION" - echo "RID: $DISTRO.$VERSION-x64" -else - VERSION=$(sw_vers -productVersion) - echo "OS: Mac OS X $VERSION" - echo "RID: osx.$(echo $VERSION | cut -d . -f 1,2)-x64" -fi diff --git a/scripts/build/fix-mode-flags.sh b/scripts/build/fix-mode-flags.sh deleted file mode 100755 index 955d184cd..000000000 --- a/scripts/build/fix-mode-flags.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -# Managed code doesn't need 'x' -find . -type f -name "*.dll" | xargs chmod 644 -find . -type f -name "*.exe" | xargs chmod 644 - -# Generally, dylibs and sos have 'x' (no idea if it's required ;)) -if [ "$(uname)" == "Darwin" ]; then - find . -type f -name "*.dylib" | xargs chmod 755 -else - find . -type f -name "*.so" | xargs chmod 755 -fi - -# Executables (those without dots) are executable :) -find . -type f ! -name "*.*" | xargs chmod 755 diff --git a/scripts/build/generate-version.ps1 b/scripts/build/generate-version.ps1 deleted file mode 100644 index 28e49bec2..000000000 --- a/scripts/build/generate-version.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -# MSI versioning -# Encode the CLI version to fit into the MSI versioning scheme - https://msdn.microsoft.com/en-us/library/windows/desktop/aa370859(v=vs.85).aspx -# MSI versions are 3 part -# major.minor.build -# Size(bits) of each part 8 8 16 -# So we have 32 bits to encode the CLI version -# Starting with most significant bit this how the CLI version is going to be encoded as MSI Version -# CLI major -> 6 bits -# CLI minor -> 6 bits -# CLI patch -> 6 bits -# CLI commitcount -> 14 bits -function GetMSIVersionFromCLIVersion([uint32]$Major, [uint32]$Minor, [uint32]$Patch, [uint32]$CommitCount) -{ - if($Major -ge 0x40) - { - throw [System.NotSupportedException] "Invalid Major version - $Major. Major version must be less than 64." - } - - if($Minor -ge 0x40) - { - throw [System.NotSupportedException] "Invalid Minor version - $Minor. Minor version must be less than 64." - } - - if($Patch -ge 0x40) - { - throw [System.NotSupportedException] "Invalid Patch version - $Patch. Patch version must be less than 64." - } - - if($CommitCount -ge 0x4000) - { - throw [System.NotSupportedException] "Invalid CommitCount version - $CommitCount. CommitCount version must be less than 16384." - } - - $Major = ($Major -shl 26) - $Minor = ($Minor -shl 20) - $Patch = ($Patch -shl 14) - [System.UInt32]$MSIVersionNumber = ($Major -bor $Minor -bor $Patch -bor $CommitCount) - - $MSIMajor = ($MSIVersionNumber -shr 24) -band 0xFF - $MSIMinor = ($MSIVersionNumber -shr 16) -band 0xFF - $MSIBuild = $MSIVersionNumber -band 0xFFFF - $MSIVersion = "$MSIMajor.$MSIMinor.$MSIBuild" - - return $MSIVersion -} - -$env:MajorVersion = 1 -$env:MinorVersion = 0 -$env:PatchVersion = 0 - -$CommitCount = [int32](git rev-list --count HEAD) -$env:CommitCountVersion = ([string]$CommitCount).PadLeft(6, "0") - -# Zero Padded Suffix for use with Nuget -$env:VersionSuffix = "$env:ReleaseSuffix-$env:CommitCountVersion" - -$env:DOTNET_CLI_VERSION = "$env:MajorVersion.$env:MinorVersion.$env:PatchVersion.$env:CommitCountVersion" -$env:DOTNET_MSI_VERSION = GetMSIVersionFromCLIVersion $env:MajorVersion $env:MinorVersion $env:PatchVersion $CommitCount diff --git a/scripts/build/generate-version.sh b/scripts/build/generate-version.sh deleted file mode 100755 index 8d541bc4f..000000000 --- a/scripts/build/generate-version.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -export MAJOR_VERSION=1 -export MINOR_VERSION=0 -export PATCH_VERSION=0 - -export COMMIT_COUNT_VERSION=$(printf "%06d" $(git rev-list --count HEAD)) - -export DOTNET_CLI_VERSION=$MAJOR_VERSION.$MINOR_VERSION.$PATCH_VERSION.$COMMIT_COUNT_VERSION diff --git a/scripts/build/place-binary.cmd b/scripts/build/place-binary.cmd deleted file mode 100644 index 143d4a9eb..000000000 --- a/scripts/build/place-binary.cmd +++ /dev/null @@ -1,24 +0,0 @@ -@echo off - -REM Copyright (c) .NET Foundation and contributors. All rights reserved. -REM Licensed under the MIT license. See LICENSE file in the project root for full license information. - -set SRC=%1 - -set SRC=%SRC:/=\% - -pushd %~dp0..\.. -set DST=%CD%\artifacts\win7-x64\stage2\bin -popd - -if not exist "%SRC%" goto end -if not exist "%DST%" goto skip - -xcopy /F /Y /I "%SRC%" "%DST%" - -goto end - -:skip -echo The destination "%DST%" does not exist. This script is only designed to update a previous full build! - -:end diff --git a/scripts/build/place-binary.sh b/scripts/build/place-binary.sh deleted file mode 100755 index 533ff2b56..000000000 --- a/scripts/build/place-binary.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -echo "Copy From: $1" -echo " To: $STAGE2_DIR/bin/" - -src=${1//\\//} -dst=$STAGE2_DIR/bin/ - -if [ ! -d "$dst" ]; then - mkdir -p $dst -fi - -# Copy the files, if they exist -if ls $src 1> /dev/null 2>&1; then - cp $src $dst - rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi -fi diff --git a/scripts/build/process-args.sh b/scripts/build/process-args.sh deleted file mode 100755 index 53178bd0d..000000000 --- a/scripts/build/process-args.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -params=("$@") - -for i in "${!params[@]}" -do - lowerI="$(echo ${params[$i]} | awk '{print tolower($0)}')" - case $lowerI in - "release" | "--release") - export CONFIGURATION=Release - ;; - "debug" | "--debug") - export CONFIGURATION=Debug - ;; - "offline" | "--offline") - export OFFLINE=true - ;; - "nopackage" | "--nopackage") - export NOPACKAGE=true - ;; - "--buildindocker-ubuntu") - export BUILD_IN_DOCKER=true - export DOCKER_OS=ubuntu - ;; - "--buildindocker-centos") - export BUILD_IN_DOCKER=true - export DOCKER_OS=centos - ;; - *) - esac -done diff --git a/scripts/build/restore-packages.ps1 b/scripts/build/restore-packages.ps1 deleted file mode 100644 index 9ba972481..000000000 --- a/scripts/build/restore-packages.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -# Restore packages -# NOTE(anurse): I had to remove --quiet, because NuGet3 is too quiet when that's provided :( -header "Restoring packages" - -$StartPath = $env:PATH -$env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$StartPath" - -& dotnet restore "$RepoRoot\src" --runtime "$Rid" -& dotnet restore "$RepoRoot\tools" --runtime "$Rid" - -$env:PATH=$StartPath diff --git a/scripts/build/restore-packages.sh b/scripts/build/restore-packages.sh deleted file mode 100755 index 935bca61a..000000000 --- a/scripts/build/restore-packages.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -export StartPath=$PATH -export PATH=$DOTNET_INSTALL_DIR/bin:$PATH - -header "Restoring packages" - -dotnet restore "$REPOROOT/src" --runtime "$RID" $DISABLE_PARALLEL -dotnet restore "$REPOROOT/tools" --runtime "$RID" $DISABLE_PARALLEL - -export PATH=$StartPath diff --git a/scripts/ci_build.cmd b/scripts/ci_build.cmd index 54f5f51e3..e30184df7 100644 --- a/scripts/ci_build.cmd +++ b/scripts/ci_build.cmd @@ -4,7 +4,9 @@ REM Copyright (c) .NET Foundation and contributors. All rights reserved. REM Licensed under the MIT license. See LICENSE file in the project root for full license information. set CI_BUILD=1 +set CONFIGURATION=%1 +set VERBOSE=1 -CALL %~dp0..\build.cmd %* +CALL %~dp0..\build.cmd %2 exit /b %errorlevel% diff --git a/scripts/ci_build.sh b/scripts/ci_build.sh index 488e3192a..29e9664e1 100755 --- a/scripts/ci_build.sh +++ b/scripts/ci_build.sh @@ -7,6 +7,7 @@ set -e export CI_BUILD=1 +export NO_COLOR=1 SOURCE="${BASH_SOURCE[0]}" while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink @@ -16,7 +17,36 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done SCRIPT_DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -source "$SCRIPT_DIR/common/_common.sh" +while [[ $# > 0 ]]; do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in + "release" | "--release") + export CONFIGURATION=Release + ;; + "debug" | "--debug") + export CONFIGURATION=Debug + ;; + "offline" | "--offline") + export OFFLINE=true + ;; + "nopackage" | "--nopackage") + export NOPACKAGE=true + ;; + "--buildindocker-ubuntu") + export BUILD_IN_DOCKER=1 + export DOCKER_IMAGENAME=ubuntu + ;; + "--buildindocker-centos") + export BUILD_IN_DOCKER=1 + export DOCKER_IMAGENAME=centos + ;; + *) + break + ;; + esac + + shift +done # Tell install scripts to skip pre-req check since the CI has the pre-reqs but not ldconfig it seems # Also, install to a directory under the repo root since we don't have permission to work elsewhere @@ -35,17 +65,15 @@ container_name="" #Jenkins [ ! -z "$BUILD_TAG" ] && container_name="$BUILD_TAG" + #VSO [ ! -z "$BUILD_BUILDID" ] && container_name="$BUILD_BUILDID" export DOTNET_BUILD_CONTAINER_NAME="$container_name" +## CentOS-based CI machines don't have docker, ditto OSX. So only build in docker if we're on Ubuntu +#if [ "$(cat /etc/*-release | grep -cim1 ubuntu)" -eq 1 ]; then + #export BUILD_IN_DOCKER=1 +#fi -if [[ "$OSNAME" == "ubuntu" ]]; then - export PACKAGE_IN_DOCKER="true" - unset BUILD_IN_DOCKER - - $SCRIPT_DIR/../build.sh $@ -else - $SCRIPT_DIR/../build.sh $@ -fi +VERBOSE=1 $SCRIPT_DIR/../build.sh "$@" diff --git a/scripts/common/_clang.sh b/scripts/common/_clang.sh deleted file mode 100644 index f4e442d23..000000000 --- a/scripts/common/_clang.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -# Set up the environment to be used for building with clang. -if which "clang-3.5" > /dev/null 2>&1; then - export CC="$(which clang-3.5)" - export CXX="$(which clang++-3.5)" -elif which "clang-3.6" > /dev/null 2>&1; then - export CC="$(which clang-3.6)" - export CXX="$(which clang++-3.6)" -elif which clang > /dev/null 2>&1; then - export CC="$(which clang)" - export CXX="$(which clang++)" -else - error "Unable to find Clang Compiler" - error "Install clang-3.5 or clang3.6" - exit 1 -fi diff --git a/scripts/common/_common.ps1 b/scripts/common/_common.ps1 index 85621ab53..dbc1101ce 100644 --- a/scripts/common/_common.ps1 +++ b/scripts/common/_common.ps1 @@ -5,33 +5,26 @@ . $PSScriptRoot\_utility.ps1 -$Skip_Crossgen = $false -$Rid = "win7-x64" -$Tfm = "dnxcore50" -$RepoRoot = Resolve-Path "$PSScriptRoot\..\.." -$OutputDir = "$RepoRoot\artifacts\$Rid" -$Stage1Dir = "$OutputDir\stage1" -$Stage1CompilationDir = "$OutputDir\stage1compilation" -$Stage2Dir = "$OutputDir\stage2" -$Stage2CompilationDir = "$OutputDir\stage2compilation" -$HostDir = "$OutputDir\corehost" -$PackageDir = "$RepoRoot\artifacts\packages\dnvm" -$TestBinRoot = "$RepoRoot\artifacts\tests" -$TestPackageDir = "$TestBinRoot\packages" +# Copy things from environment variables that were sent by the build scripts +$Rid = $env:Rid +$Tfm = $env:Tfm +$OutputDir = $env:OutputDir +$Stage1Dir = $env:Stage1Dir +$Stage1CompilationDir = $env:Stage1CompilationDir +$Stage2Dir = $env:Stage2Dir +$Stage2CompilationDir = $env:Stage2CompilationDir +$HostDir = $env:HostDir +$PackageDir = $env:PackageDir +$TestBinRoot = $env:TestBinRoot +$TestPackageDir = $env:TestPackageDir -$env:TEST_ROOT = "$OutputDir\tests" -$env:TEST_ARTIFACTS = "$env:TEST_ROOT\artifacts" +$env:TEST_ROOT = "$OutputDir\tests" +$env:TEST_ARTIFACTS = "$env:TEST_ROOT\artifacts" -$env:ReleaseSuffix = "beta" -$env:Channel = "$env:ReleaseSuffix" +$env:Channel = "$env:RELEASE_SUFFIX" # Set reasonable defaults for unset variables setEnvIfDefault "DOTNET_INSTALL_DIR" "$RepoRoot\.dotnet_stage0\win7-x64" setEnvIfDefault "DOTNET_CLI_VERSION" "0.1.0.0" -setEnvIfDefault "SKIP_CROSSGEN" "$Skip_Crossgen" setPathAndHomeIfDefault "$Stage2Dir" setVarIfDefault "Configuration" "Debug" - -# Common Files which depend on above properties -. $PSScriptRoot\_nuget.ps1 -. $PSScriptRoot\_configuration.ps1 \ No newline at end of file diff --git a/scripts/common/_common.sh b/scripts/common/_common.sh index 163bbf797..5f0477930 100644 --- a/scripts/common/_common.sh +++ b/scripts/common/_common.sh @@ -12,23 +12,11 @@ done COMMONDIR="$( cd -P "$( dirname "$COMMONSOURCE" )" && pwd )" source "$COMMONDIR/_prettyprint.sh" -source "$COMMONDIR/_rid.sh" - -# TODO: Replace this with a dotnet generation -export SKIP_CROSSGEN=false -export TFM=dnxcore50 -export REPOROOT=$(cd $COMMONDIR/../.. && pwd) -export OUTPUT_ROOT=$REPOROOT/artifacts/$RID -export STAGE1_DIR=$OUTPUT_ROOT/stage1 -export STAGE2_DIR=$OUTPUT_ROOT/stage2 -export HOST_DIR=$OUTPUT_ROOT/corehost -export TEST_BIN_ROOT="$REPOROOT/artifacts/tests" -export TEST_PACKAGE_DIR="$TEST_BIN_ROOT/packages" +# Other variables are set by the outer build script export TEST_ROOT="$OUTPUT_ROOT/tests" export TEST_ARTIFACTS="$TEST_ROOT/artifacts" -export RELEASE_SUFFIX=beta export CHANNEL=$RELEASE_SUFFIX [ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$REPOROOT/.dotnet_stage0/$RID @@ -36,10 +24,6 @@ export CHANNEL=$RELEASE_SUFFIX [ -z "$DOTNET_HOME" ] && export DOTNET_HOME=$STAGE2_DIR && export PATH=$STAGE2_DIR/bin:$PATH [ -z "$CONFIGURATION" ] && export CONFIGURATION=Debug -# Common Files which depend on above properties -source "$COMMONDIR/_nuget.sh" -source "$COMMONDIR/_configuration.sh" - #TODO this is a workaround for a nuget bug on ubuntu. Remove export DISABLE_PARALLEL="" [[ "$RID" =~ "ubuntu" ]] && export DISABLE_PARALLEL="--disable-parallel" diff --git a/scripts/common/_configuration.ps1 b/scripts/common/_configuration.ps1 deleted file mode 100644 index e019a55c8..000000000 --- a/scripts/common/_configuration.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -# -# 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. -# - -function loadTestProjectList() -{ - return Import-CSV "$RepoRoot\scripts\configuration\testProjects.csv" -Header "ProjectName" -} - -function loadTestScriptList() -{ - return Import-CSV "$RepoRoot\scripts\configuration\testScripts.csv" -Header "ProjectName" -} - -function loadTestPackageList() -{ - return Import-CSV "$RepoRoot\scripts\configuration\testPackageProjects.csv" -Header "ProjectName" -} - -function loadBuildProjectList() -{ - return Import-CSV "$RepoRoot\scripts\configuration\buildProjects.csv" -Header "ProjectName" -} \ No newline at end of file diff --git a/scripts/common/_configuration.sh b/scripts/common/_configuration.sh deleted file mode 100644 index 45d2502a7..000000000 --- a/scripts/common/_configuration.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -loadTestProjectList() -{ - echo $(cat "$REPOROOT/scripts/configuration/testProjects.csv") -} - -loadTestScriptList() -{ - echo $(cat "$REPOROOT/scripts/configuration/testScripts.csv") -} - -loadTestPackageList() -{ - echo $(cat "$REPOROOT/scripts/configuration/testPackageProjects.csv") -} - -loadBuildProjectList() -{ - echo $(cat "$REPOROOT/scripts/configuration/buildProjects.csv") -} \ No newline at end of file diff --git a/scripts/common/_nuget.ps1 b/scripts/common/_nuget.ps1 deleted file mode 100644 index df3428d69..000000000 --- a/scripts/common/_nuget.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -# -# 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. -# - -$env:NUGET_PACKAGES = (Join-Path $env:USERPROFILE ".nuget\packages") -$env:DOTNET_PACKAGES = $env:NUGET_PACKAGES -$env:DNX_PACKAGES = $env:NUGET_PACKAGES -if(!(Test-Path $env:NUGET_PACKAGES)) { - mkdir $env:NUGET_PACKAGES | Out-Null -} - -# default the package cache expiration to 1 week, in hours -setEnvIfDefault "NUGET_PACKAGES_CACHE_TIME_LIMIT" (7 * 24) diff --git a/scripts/common/_nuget.sh b/scripts/common/_nuget.sh deleted file mode 100644 index 81bb9fac5..000000000 --- a/scripts/common/_nuget.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -if [ ! -z "$CI_BUILD" ]; then - # On CI, $HOME is redirected under the repo, which gets deleted after every build. - # So make $NUGET_PACKAGES outside of the repo. - NUGET_PACKAGES=$REPOROOT/../.nuget/packages -else - NUGET_PACKAGES=~/.nuget/packages -fi - -export NUGET_PACKAGES -export DOTNET_PACKAGES=$NUGET_PACKAGES -export DNX_PACKAGES=$NUGET_PACKAGES - -if [ ! -d $NUGET_PACKAGES ]; then - mkdir -p $NUGET_PACKAGES -fi - -if [ -z "$NUGET_PACKAGES_CACHE_TIME_LIMIT" ]; then - # default the package cache expiration to 1 week, in hours - export NUGET_PACKAGES_CACHE_TIME_LIMIT=$(( 7 * 24 )) -fi diff --git a/scripts/common/_rid.sh b/scripts/common/_rid.sh deleted file mode 100644 index 37f3c459e..000000000 --- a/scripts/common/_rid.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -export UNAME=$(uname) - -if [ -z "$RID" ]; then - if [ "$UNAME" == "Darwin" ]; then - export OSNAME=osx - if [ -n "$(sw_vers -productVersion | grep 10.10)" ]; then - export RID=osx.10.10-x64 - elif [ -n "$(sw_vers -productVersion | grep 10.11)" ]; then - export RID=osx.10.11-x64 - else - error "unknown OS X: $(sw_vers -productVersion)" 1>&2 - fi - elif [ "$UNAME" == "Linux" ]; then - # Detect Distro - if [ "$(cat /etc/*-release | grep -cim1 ubuntu)" -eq 1 ]; then - export OSNAME=ubuntu - export RID=ubuntu.14.04-x64 - elif [ "$(cat /etc/*-release | grep -cim1 centos)" -eq 1 ]; then - export OSNAME=centos - export RID=centos.7-x64 - else - error "unknown Linux Distro" 1>&2 - fi - else - error "unknown OS: $UNAME" 1>&2 - fi -fi - -if [ -z "$RID" ]; then - exit 1 -fi diff --git a/scripts/common/_utility.ps1 b/scripts/common/_utility.ps1 index e331c776a..2e5d68a62 100644 --- a/scripts/common/_utility.ps1 +++ b/scripts/common/_utility.ps1 @@ -73,4 +73,4 @@ function _cmd([string]$command) error "Command Failed: 'cmd /c $command'" Exit 1 } -} \ No newline at end of file +} diff --git a/scripts/compile/compile-corehost.ps1 b/scripts/compile/compile-corehost.ps1 deleted file mode 100644 index ec2f88234..000000000 --- a/scripts/compile/compile-corehost.ps1 +++ /dev/null @@ -1,46 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -header "Building corehost" -pushd "$RepoRoot\src\corehost" -try { - if (!(Test-Path "cmake\$Rid")) { - mkdir "cmake\$Rid" | Out-Null - } - cd "cmake\$Rid" - cmake ..\.. -G "Visual Studio 14 2015 Win64" - $pf = $env:ProgramFiles - if (Test-Path "env:\ProgramFiles(x86)") { - $pf = (cat "env:\ProgramFiles(x86)") - } - $BuildConfiguration = $Configuration - if ($Configuration -eq "Release") { - $BuildConfiguration = "RelWithDebInfo" - } - & "$pf\MSBuild\14.0\Bin\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration="$BuildConfiguration" - if (!$?) { - Write-Host "Command failed: $pf\MSBuild\14.0\Bin\MSBuild.exe" ALL_BUILD.vcxproj /p:Configuration="$BuildConfiguration" - Exit 1 - } - - if (!(Test-Path $HostDir)) { - mkdir $HostDir | Out-Null - } - cp "$RepoRoot\src\corehost\cmake\$Rid\cli\$BuildConfiguration\corehost.exe" $HostDir - cp "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$BuildConfiguration\hostpolicy.dll" $HostDir - - if (Test-Path "$RepoRoot\src\corehost\cmake\$Rid\cli\$BuildConfiguration\corehost.pdb") - { - cp "$RepoRoot\src\corehost\cmake\$Rid\cli\$BuildConfiguration\corehost.pdb" $HostDir - } - if (Test-Path "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$BuildConfiguration\hostpolicy.pdb") - { - cp "$RepoRoot\src\corehost\cmake\$Rid\cli\dll\$BuildConfiguration\hostpolicy.pdb" $HostDir - } -} finally { - popd -} diff --git a/scripts/compile/compile-corehost.sh b/scripts/compile/compile-corehost.sh deleted file mode 100755 index 109e5a655..000000000 --- a/scripts/compile/compile-corehost.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" -source "$DIR/../common/_clang.sh" - -header "Building corehost" - -pushd "$REPOROOT/src/corehost" 2>&1 >/dev/null -[ -d "cmake/$RID" ] || mkdir -p "cmake/$RID" -cd "cmake/$RID" -cmake ../.. -G "Unix Makefiles" -DCMAKE_BUILD_TYPE:STRING=$CONFIGURATION -make - -# Publish to artifacts -[ -d "$HOST_DIR" ] || mkdir -p $HOST_DIR -if [[ "$OSNAME" == "osx" ]]; then - COREHOST_LIBNAME=libhostpolicy.dylib -else - COREHOST_LIBNAME=libhostpolicy.so -fi -cp "$REPOROOT/src/corehost/cmake/$RID/cli/corehost" $HOST_DIR -cp "$REPOROOT/src/corehost/cmake/$RID/cli/dll/${COREHOST_LIBNAME}" $HOST_DIR -popd 2>&1 >/dev/null diff --git a/scripts/compile/compile-stage-1.ps1 b/scripts/compile/compile-stage-1.ps1 deleted file mode 100644 index d682a75a9..000000000 --- a/scripts/compile/compile-stage-1.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -header "Compiling stage1 dotnet using downloaded stage0 ..." -$StartPath = $env:PATH -$env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$StartPath" - -_ "$RepoRoot\scripts\compile\compile-stage.ps1" @("$Tfm","$Rid","$Configuration","$Stage1Dir","$RepoRoot","$HostDir", "$Stage1CompilationDir") - -$env:PATH=$StartPath \ No newline at end of file diff --git a/scripts/compile/compile-stage-1.sh b/scripts/compile/compile-stage-1.sh deleted file mode 100755 index ce11e4690..000000000 --- a/scripts/compile/compile-stage-1.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -export StartPath=$PATH -export PATH=$DOTNET_INSTALL_DIR/bin:$PATH - -# Build Stage 1 -header "Building stage1 dotnet using downloaded stage0 ..." -OUTPUT_DIR=$STAGE1_DIR $REPOROOT/scripts/compile/compile-stage.sh - -export PATH=$StartPath \ No newline at end of file diff --git a/scripts/compile/compile-stage-2.ps1 b/scripts/compile/compile-stage-2.ps1 deleted file mode 100644 index 874438d4a..000000000 --- a/scripts/compile/compile-stage-2.ps1 +++ /dev/null @@ -1,27 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -header "Compiling stage2 dotnet using stage1 ..." -$StartPath = $env:PATH -$env:PATH = "$Stage1Dir\bin;$env:PATH" - -# Compile -_ "$RepoRoot\scripts\compile\compile-stage.ps1" @("$Tfm","$Rid","$Configuration","$Stage2Dir","$RepoRoot","$HostDir", "$Stage2CompilationDir") - - -# Build the projects that we are going to ship as nuget packages -. $REPOROOT\scripts\package\projectsToPack.ps1 - -$ProjectsToPack | ForEach-Object { - dotnet build --build-base-path "$Stage2CompilationDir\forPackaging" --configuration "$Configuration" "$RepoRoot\src\$_" - if (!$?) { - Write-Host Command failed: dotnet build --native-subdirectory --build-base-path "$Stage2CompilationDir\forPackaging" --configuration "$Configuration" "$RepoRoot\src\$_" - exit 1 - } -} - -$env:PATH=$StartPath \ No newline at end of file diff --git a/scripts/compile/compile-stage-2.sh b/scripts/compile/compile-stage-2.sh deleted file mode 100755 index 521d1ae22..000000000 --- a/scripts/compile/compile-stage-2.sh +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -# Use stage1 tools -export StartPath=$PATH -export DOTNET_TOOLS=$STAGE1_DIR -export PATH=$STAGE1_DIR/bin:$PATH - -# Compile Stage 2 -header "Compiling stage2 dotnet using just-built stage1 ..." -OUTPUT_DIR=$STAGE2_DIR $REPOROOT/scripts/compile/compile-stage.sh - -export DOTNET_HOME=$STAGE2_DIR -export DOTNET_TOOLS=$STAGE2_DIR \ No newline at end of file diff --git a/scripts/compile/compile-stage.ps1 b/scripts/compile/compile-stage.ps1 deleted file mode 100644 index a2de5c30d..000000000 --- a/scripts/compile/compile-stage.ps1 +++ /dev/null @@ -1,84 +0,0 @@ -# -# 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. -# - -param( - [Parameter(Mandatory=$true)][string]$Tfm, - [Parameter(Mandatory=$true)][string]$Rid, - [Parameter(Mandatory=$true)][string]$Configuration, - [Parameter(Mandatory=$true)][string]$StageOutputDir, - [Parameter(Mandatory=$true)][string]$RepoRoot, - [Parameter(Mandatory=$true)][string]$HostDir, - [Parameter(Mandatory=$true)][string]$CompilationOutputDir) - -$Projects = loadBuildProjectList - -$BinariesForCoreHost = @( - "csi" - "csc" - "vbc" -) - -$FilesToClean = @( - "README.md" - "Microsoft.DotNet.Runtime.exe" - "Microsoft.DotNet.Runtime.dll" - "Microsoft.DotNet.Runtime.deps" - "Microsoft.DotNet.Runtime.pdb" -) - -$RuntimeOutputDir = "$StageOutputDir\runtime\coreclr" - -# Publish each project -$Projects | ForEach-Object { - dotnet publish --native-subdirectory --framework "$Tfm" --runtime "$Rid" --output "$StageOutputDir\bin" --configuration "$Configuration" "$RepoRoot\src\$($_.ProjectName)" - if (!$?) { - Write-Host Command failed: dotnet publish --native-subdirectory --framework "$Tfm" --runtime "$Rid" --output "$StageOutputDir\bin" --configuration "$Configuration" "$RepoRoot\src\$($_.ProjectName)" - exit 1 - } -} - -# Publish the runtime -dotnet publish --framework "$Tfm" --runtime "$Rid" --output "$RuntimeOutputDir" --configuration "$Configuration" "$RepoRoot\src\Microsoft.DotNet.Runtime" -if (!$?) { - Write-Host Command failed: dotnet publish --framework "$Tfm" --runtime "$Rid" --output "$RuntimeOutputDir" --configuration "$Configuration" "$RepoRoot\src\Microsoft.DotNet.Runtime" - Exit 1 -} - -# Clean up bogus additional files -$FilesToClean | ForEach-Object { - $path = Join-Path $RuntimeOutputDir $_ - if (Test-Path $path) { - del -for $path - } -} - -# Copy the runtime app-local for the tools -cp -rec "$RuntimeOutputDir\*" "$StageOutputDir\bin" -ErrorVariable capturedErrors -ErrorAction SilentlyContinue -$capturedErrors | foreach-object { - if ($_ -notmatch "already exists") { - write-error $_ - Exit 1 - } -} - -# Deploy the CLR host to the output -cp "$HostDir\corehost.exe" "$StageOutputDir\bin" -cp "$HostDir\hostpolicy.dll" "$StageOutputDir\bin" - -# corehostify externally-provided binaries (csc, vbc, etc.) -$BinariesForCoreHost | ForEach-Object { - mv $StageOutputDir\bin\$_.exe $StageOutputDir\bin\$_.dll -Force - cp $StageOutputDir\bin\corehost.exe $StageOutputDir\bin\$_.exe -Force -} - -# Crossgen Roslyn -if (-not (Test-Path "$StageOutputDir\bin\csc.ni.exe")) { - _cmd "$RepoRoot\scripts\crossgen\crossgen_roslyn.cmd ""$StageOutputDir""" -} - -# Copy in AppDeps -header "Acquiring Native App Dependencies" -_ "$RepoRoot\scripts\build\build_appdeps.ps1" @("$RepoRoot", "$StageOutputDir") - diff --git a/scripts/compile/compile-stage.sh b/scripts/compile/compile-stage.sh deleted file mode 100755 index 2f4b8ef9d..000000000 --- a/scripts/compile/compile-stage.sh +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -[ ! -z "$TFM" ] || die "Missing required environment variable TFM" -[ ! -z "$RID" ] || die "Missing required environment variable RID" -[ ! -z "$CONFIGURATION" ] || die "Missing required environment variable CONFIGURATION" -[ ! -z "$OUTPUT_DIR" ] || die "Missing required environment variable OUTPUT_DIR" -[ ! -z "$HOST_DIR" ] || die "Missing required environment variable HOST_DIR" - -PROJECTS=$(loadBuildProjectList) - -BINARIES_FOR_COREHOST=( \ - csi \ - csc \ - vbc \ -) - -FILES_TO_CLEAN=( \ - README.md \ - Microsoft.DotNet.Runtime \ - Microsoft.DotNet.Runtime.dll \ - Microsoft.DotNet.Runtime.deps \ - Microsoft.DotNet.Runtime.pdb \ -) - -RUNTIME_OUTPUT_DIR="$OUTPUT_DIR/runtime/coreclr" - -for project in $PROJECTS -do - echo dotnet publish --native-subdirectory --framework "$TFM" --output "$OUTPUT_DIR/bin" --configuration "$CONFIGURATION" "$REPOROOT/src/$project" - dotnet publish --native-subdirectory --framework "$TFM" --output "$OUTPUT_DIR/bin" --configuration "$CONFIGURATION" "$REPOROOT/src/$project" -done - -# Bring in the runtime -dotnet publish --output "$RUNTIME_OUTPUT_DIR" --configuration "$CONFIGURATION" "$REPOROOT/src/Microsoft.DotNet.Runtime" - -# Clean up bogus additional files -for file in ${FILES_TO_CLEAN[@]} -do - [ -e "$RUNTIME_OUTPUT_DIR/$file" ] && rm "$RUNTIME_OUTPUT_DIR/$file" -done - -# Copy the runtime app-local for the tools -cp -R $RUNTIME_OUTPUT_DIR/* $OUTPUT_DIR/bin - -# Deploy CLR host to the output -if [[ "$OSNAME" == "osx" ]]; then - COREHOST_LIBNAME=libhostpolicy.dylib -else - COREHOST_LIBNAME=libhostpolicy.so -fi -cp "$HOST_DIR/corehost" "$OUTPUT_DIR/bin" -cp "$HOST_DIR/${COREHOST_LIBNAME}" "$OUTPUT_DIR/bin" - -# corehostify externally-provided binaries (csc, vbc, etc.) -for binary in ${BINARIES_FOR_COREHOST[@]} -do - cp $OUTPUT_DIR/bin/corehost $OUTPUT_DIR/bin/$binary - mv $OUTPUT_DIR/bin/${binary}.exe $OUTPUT_DIR/bin/${binary}.dll -done - -cd $OUTPUT_DIR - -# Fix up permissions. Sometimes they get dropped with the wrong info -find . -type f | xargs chmod 644 -$REPOROOT/scripts/build/fix-mode-flags.sh - -if [ ! -f "$OUTPUT_DIR/bin/csc.ni.exe" ]; then - $REPOROOT/scripts/crossgen/crossgen_roslyn.sh "$OUTPUT_DIR/bin" -fi - -# Make OUTPUT_DIR Folder Accessible -chmod -R a+r $OUTPUT_DIR - -# No compile native support in centos yet -# https://github.com/dotnet/cli/issues/453 -if [ "$OSNAME" != "centos" ]; then - # Copy in AppDeps - if [ ! -d "$OUTPUT_DIR/bin/appdepsdk" ]; then - header "Acquiring Native App Dependencies" - DOTNET_HOME=$OUTPUT_DIR DOTNET_TOOLS=$OUTPUT_DIR $REPOROOT/scripts/build/build_appdeps.sh "$OUTPUT_DIR/bin" - fi -fi - -# Stamp the output with the commit metadata -COMMIT=$(git rev-parse HEAD) -echo $COMMIT > $OUTPUT_DIR/.version -echo $DOTNET_CLI_VERSION >> $OUTPUT_DIR/.version diff --git a/scripts/compile/compile.ps1 b/scripts/compile/compile.ps1 deleted file mode 100644 index b562c4fab..000000000 --- a/scripts/compile/compile.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -# -# 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. -# - -param([string]$Configuration = "Debug") - -$ErrorActionPreference="Stop" - -. $PSScriptRoot\..\common\_common.ps1 - -# Capture PATH for later -$StartPath = $env:PATH -$StartDotNetHome = $env:DOTNET_HOME - -try { - _ "$RepoRoot\scripts\compile\compile-corehost.ps1" - - _ "$RepoRoot\scripts\compile\compile-stage-1.ps1" - - # Issue https://github.com/dotnet/cli/issues/1294 - _ "$RepoRoot\scripts\build\restore-packages.ps1" - - _ "$RepoRoot\scripts\compile\compile-stage-2.ps1" -} finally { - $env:PATH = $StartPath - $env:DOTNET_HOME = $StartDotNetHome -} diff --git a/scripts/compile/compile.sh b/scripts/compile/compile.sh deleted file mode 100755 index 3a1416a30..000000000 --- a/scripts/compile/compile.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -$REPOROOT/scripts/compile/compile-corehost.sh - -$REPOROOT/scripts/compile/compile-stage-1.sh - -# Issue https://github.com/dotnet/cli/issues/1294 -$REPOROOT/scripts/build/restore-packages.sh - -$REPOROOT/scripts/compile/compile-stage-2.sh diff --git a/scripts/configuration/buildProjects.csv b/scripts/configuration/buildProjects.csv deleted file mode 100644 index 3d25d1bdf..000000000 --- a/scripts/configuration/buildProjects.csv +++ /dev/null @@ -1 +0,0 @@ -dotnet diff --git a/scripts/configuration/testPackageProjects.csv b/scripts/configuration/testPackageProjects.csv deleted file mode 100644 index 90069c976..000000000 --- a/scripts/configuration/testPackageProjects.csv +++ /dev/null @@ -1,2 +0,0 @@ -dotnet-hello/v1/dotnet-hello -dotnet-hello/v2/dotnet-hello \ No newline at end of file diff --git a/scripts/configuration/testProjects.csv b/scripts/configuration/testProjects.csv deleted file mode 100644 index bc53a303d..000000000 --- a/scripts/configuration/testProjects.csv +++ /dev/null @@ -1,6 +0,0 @@ -EndToEnd -dotnet-publish.Tests -dotnet-compile.Tests -dotnet-build.Tests -Microsoft.DotNet.Cli.Utils.Tests -Microsoft.DotNet.Compiler.Common.Tests diff --git a/scripts/configuration/testScripts.csv b/scripts/configuration/testScripts.csv deleted file mode 100644 index 6ce784583..000000000 --- a/scripts/configuration/testScripts.csv +++ /dev/null @@ -1,2 +0,0 @@ -argument-forwarding-tests -package-command-test \ No newline at end of file diff --git a/scripts/crossgen/crossgen_roslyn.cmd b/scripts/crossgen/crossgen_roslyn.cmd deleted file mode 100644 index f27515cbd..000000000 --- a/scripts/crossgen/crossgen_roslyn.cmd +++ /dev/null @@ -1,68 +0,0 @@ -REM Turn echo off off so we can echo with echo and the echoing -REM (But seriously, this script has weird hangs and crashes sometimes so we want to know exactly which commands are failing) -REM @echo off - -REM Copyright (c) .NET Foundation and contributors. All rights reserved. -REM Licensed under the MIT license. See LICENSE file in the project root for full license information. - -if %SKIP_CROSSGEN% EQU 0 goto skip - -echo Crossgenning Roslyn compiler ... - -REM Get absolute path -pushd %1 -set BIN_DIR=%CD%\bin -popd - -REM Replace with a robust method for finding the right crossgen.exe -set CROSSGEN_UTIL=%NUGET_PACKAGES%\runtime.win7-x64.Microsoft.NETCore.Runtime.CoreCLR\1.0.1-rc2-23811\tools\crossgen.exe - -REM Crossgen currently requires itself to be next to mscorlib -copy %CROSSGEN_UTIL% /Y %BIN_DIR% > nul - -pushd %BIN_DIR% - -REM It must also be called mscorlib, not mscorlib.ni -if exist mscorlib.ni.dll ( - copy /Y mscorlib.ni.dll mscorlib.dll > nul -) - -set READYTORUN= - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% System.Collections.Immutable.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% System.Reflection.Metadata.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% Microsoft.CodeAnalysis.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% Microsoft.CodeAnalysis.CSharp.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% Microsoft.CodeAnalysis.VisualBasic.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% csc.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -crossgen /nologo %READYTORUN% /Platform_Assemblies_Paths %BIN_DIR% vbc.dll >nul 2>nul -if not %errorlevel% EQU 0 goto fail - -popd - -echo CrossGen Roslyn Finished - -goto end - -:fail -popd -echo Crossgen failed... -exit /B 1 - -:skip -echo Skipping Crossgen -goto end - -:end diff --git a/scripts/crossgen/crossgen_roslyn.sh b/scripts/crossgen/crossgen_roslyn.sh deleted file mode 100755 index d50bb8814..000000000 --- a/scripts/crossgen/crossgen_roslyn.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -if $SKIP_CROSSGEN ; then - echo "Skipping Crossgen" - exit 0 -fi - - -info "Crossgenning Roslyn compiler ..." - -set -e - -BIN_DIR="$( cd $1 && pwd )" - -UNAME=`uname` - -# Always recalculate the RID because the package always uses a specific RID, regardless of OS X version or Linux distro. -if [ "$OSNAME" == "osx" ]; then - RID=osx.10.10-x64 -elif [ "$OSNAME" == "ubuntu" ]; then - RID=ubuntu.14.04-x64 -elif [ "$OSNAME" == "centos" ]; then - RID=rhel.7-x64 -else - echo "Unknown OS: $OSNAME" 1>&2 - exit 1 -fi - -READYTORUN="" - -# Replace with a robust method for finding the right crossgen.exe -CROSSGEN_UTIL=$NUGET_PACKAGES/runtime.$RID.Microsoft.NETCore.Runtime.CoreCLR/1.0.1-rc2-23811/tools/crossgen - -cd $BIN_DIR - -# Crossgen currently requires itself to be next to mscorlib -cp $CROSSGEN_UTIL $BIN_DIR -chmod +x crossgen - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR mscorlib.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR System.Collections.Immutable.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR System.Reflection.Metadata.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR Microsoft.CodeAnalysis.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR Microsoft.CodeAnalysis.CSharp.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR Microsoft.CodeAnalysis.VisualBasic.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR csc.dll -[ -e csc.ni.exe ] && [ ! -e csc.ni.dll ] && mv csc.ni.exe csc.ni.dll - -./crossgen -nologo $READYTORUN -platform_assemblies_paths $BIN_DIR vbc.dll -[ -e vbc.ni.exe ] && [ ! -e vbc.ni.dll ] && mv vbc.ni.exe vbc.ni.dll - -info "CrossGen Roslyn Finished" diff --git a/scripts/docker/dockerbuild.sh b/scripts/docker/dockerbuild.sh deleted file mode 100755 index 6ec676a4b..000000000 --- a/scripts/docker/dockerbuild.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -cd $REPOROOT - -[ -z "$DOTNET_BUILD_CONTAINER_TAG" ] && DOTNET_BUILD_CONTAINER_TAG="dotnetcli-build" -[ -z "$DOTNET_BUILD_CONTAINER_NAME" ] && DOTNET_BUILD_CONTAINER_NAME="dotnetcli-build-container" -[ -z "$DOCKER_HOST_SHARE_DIR" ] && DOCKER_HOST_SHARE_DIR=$(pwd) -[ -z "$DOCKER_OS" ] && DOCKER_OS=$OSNAME -[ -z "$BUILD_COMMAND" ] && BUILD_COMMAND="/opt/code/scripts/build/build.sh" - -# Build the docker container (will be fast if it is already built) -header "Building Docker Container" -docker build --build-arg USER_ID=$(id -u) -t $DOTNET_BUILD_CONTAINER_TAG scripts/docker/$DOCKER_OS - -# Run the build in the container -header "Launching build in Docker Container" -info "Using code from: $DOCKER_HOST_SHARE_DIR" -docker run -t --rm --sig-proxy=true \ - --name $DOTNET_BUILD_CONTAINER_NAME \ - -v $DOCKER_HOST_SHARE_DIR:/opt/code \ - -e DOTNET_CLI_VERSION \ - -e SASTOKEN \ - -e STORAGE_ACCOUNT \ - -e STORAGE_CONTAINER \ - -e CHANNEL \ - -e CONNECTION_STRING \ - -e REPO_ID \ - -e REPO_USER \ - -e REPO_PASS \ - -e REPO_SERVER \ - $DOTNET_BUILD_CONTAINER_TAG \ - bash -c "${BUILD_COMMAND}" diff --git a/scripts/docker/dockerrun.sh b/scripts/docker/dockerrun.sh deleted file mode 100755 index d388d0b1b..000000000 --- a/scripts/docker/dockerrun.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../_common.sh" - -cd $REPOROOT - -[ -z "$DOTNET_BUILD_CONTAINER_TAG" ] && DOTNET_BUILD_CONTAINER_TAG="dotnetcli-build" -[ -z "$DOTNET_BUILD_CONTAINER_NAME" ] && DOTNET_BUILD_CONTAINER_NAME="dotnetcli-build-container" -[ -z "$DOCKER_HOST_SHARE_DIR" ] && DOCKER_HOST_SHARE_DIR=$(pwd) - -# Enter the container -docker run -it --rm --sig-proxy=true \ - -v $DOCKER_HOST_SHARE_DIR:/opt/code \ - $DOTNET_BUILD_CONTAINER_TAG diff --git a/scripts/docker/windows_dockerbuild.sh b/scripts/docker/windows_dockerbuild.sh deleted file mode 100755 index 960740dbc..000000000 --- a/scripts/docker/windows_dockerbuild.sh +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -# Prerequisites: -# Git Bash (http://www.git-scm.com/downloads) -# Docker Toolbox (https://www.docker.com/docker-toolbox) -# Ensure Hyper-V is disabled! - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -# This function is necessary to bypass POSIX Path Conversion in Git Bash -# http://www.mingw.org/wiki/Posix_path_conversion -_convert_path(){ - local path=$1 - path=$( echo "$path" | sed -r 's/[\/]+/\\/g') - path=${path#\\} - path=//$path - - echo $path -} - -# Bypass Msys path conversion -REPO_ROOT=$(readlink -f $DIR/../..) -REPO_ROOT=$(_convert_path $REPO_ROOT) - -VM_NAME="dotnet" -VM_CODE_DIR="/home/docker/code" - -RESULTS_DIR="$REPO_ROOT/artifacts" - -execute(){ - check_prereqs - - echo "Setting up VM..." - create_or_start_vm - - echo "Copying code from Host to VM" - eval $(docker-machine env --shell bash $VM_NAME) - copy_code_to_vm - - echo "Running Build in Docker Container" - run_build - - echo "Copying Results from VM to Hosts..." - copy_results_from_vm -} - -check_prereqs(){ - if ! which docker; then - echo "Error: Install docker toolbox (https://www.docker.com/docker-toolbox)" - exit 1 - fi - - if ! which docker-machine; then - echo "Error: Install docker toolbox (https://www.docker.com/docker-toolbox)" - exit 1 - fi - -} - -create_or_start_vm(){ - - if [[ $(docker-machine ls | grep $VM_NAME) == "" ]]; then - docker-machine create -d virtualbox $VM_NAME - else - # This fails sometimes - if ! docker-machine start $VM_NAME; then - docker-machine rm -f $VM_NAME - docker-machine create -d virtualbox $VM_NAME - fi - fi - -} - -copy_code_to_vm(){ - docker-machine ssh $VM_NAME "sudo rm -rf $VM_CODE_DIR" - docker-machine scp -r $REPO_ROOT $VM_NAME:$VM_CODE_DIR >> /dev/null 2>&1 -} - - -run_build(){ - # These are env variables for dockerbuild.sh - export DOCKER_HOST_SHARE_DIR="$(_convert_path $VM_CODE_DIR)" - export BUILD_COMMAND="//opt\\code\\build.sh" - - $DIR/../dockerbuild.sh debian -} - -# This will duplicate the entire repo + any side effects from -# the operations in the docker container -copy_results_from_vm(){ - T_RESULTS_DIR=$( echo "$RESULTS_DIR" | sed -r 's/[\\]+/\//g') - T_RESULTS_DIR=${T_RESULTS_DIR#/} - - mkdir $T_RESULTS_DIR - docker-machine ssh $VM_NAME "sudo chmod -R a+rx $VM_CODE_DIR" - docker-machine scp -r $VM_NAME:$VM_CODE_DIR/artifacts $REPO_ROOT >> /dev/null 2>&1 -} - -execute - diff --git a/scripts/test/setup/restore-test-prerequisites.sh b/scripts/dockerbuild.sh similarity index 51% rename from scripts/test/setup/restore-test-prerequisites.sh rename to scripts/dockerbuild.sh index 1ade59817..34351f8b0 100755 --- a/scripts/test/setup/restore-test-prerequisites.sh +++ b/scripts/dockerbuild.sh @@ -1,8 +1,4 @@ #!/usr/bin/env bash -# -# 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. -# set -e @@ -14,11 +10,4 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -source "$DIR/../../common/_common.sh" - -header "Restoring TestAssets" -dotnet restore "$REPOROOT/TestAssets" --runtime $RID --quiet $DISABLE_PARALLEL - -set +e -dotnet restore "$REPOROOT/testapp" --runtime $RID $DISABLE_PARALLEL >/dev/null 2>&1 -set -e \ No newline at end of file +BUILD_COMMAND=/opt/code/scripts/run-build.sh $DIR/dockerrun.sh --non-interactive "$@" diff --git a/scripts/dockerrun.sh b/scripts/dockerrun.sh new file mode 100755 index 000000000..f56f04d24 --- /dev/null +++ b/scripts/dockerrun.sh @@ -0,0 +1,102 @@ +#!/usr/bin/env bash +# +# 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. +# + +set -e + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +cd "$DIR/.." + +INTERACTIVE="-i" + +while [[ $# > 0 ]]; do + key=$1 + + case $key in + --non-interactive) + INTERACTIVE= + ;; + -i|--image) + DOCKER_IMAGENAME=$2 + shift + ;; + -d|--dockerfile) + DOCKERFILE=$2 + shift + ;; + -h|-?|--help) + echo "Usage: $0 [-d|--dockerfile ] [-i|--image ] " + echo "" + echo "Options:" + echo " The path to the Dockerfile to use to create the build container" + echo " The name of an existing Dockerfile folder under scripts/docker to use as the Dockerfile" + echo " The command to run once inside the container (/opt/code is mapped to the repo root; defaults to nothing, which runs the default shell)" + exit 0 + ;; + *) + break # the first non-switch we get ends parsing + ;; + esac + + shift +done + +if [ -z "$DOCKERFILE" ]; then + if [ -z "$DOCKER_IMAGENAME" ]; then + if [ "$(uname)" == "Darwin" ]; then + echo "Defaulting to 'ubuntu' image for Darwin" + export DOCKERFILE=scripts/docker/ubuntu + elif [ "$(cat /etc/*-release | grep -cim1 ubuntu)" -eq 1 ]; then + echo "Detected current OS as Ubuntu, using 'ubuntu' image" + export DOCKERFILE=scripts/docker/ubuntu + elif [ "$(cat /etc/*-release | grep -cim1 centos)" -eq 1 ]; then + echo "Detected current OS as CentOS, using 'centos' image" + export DOCKERFILE=scripts/docker/centos + else + echo "Unknown Linux Distro. Using 'ubuntu' image" + export DOCKERFILE=scripts/docker/ubuntu + fi + else + echo "Using requested image: $DOCKER_IMAGENAME" + export DOCKERFILE="scripts/docker/$DOCKER_IMAGENAME" + fi +fi + +[ -z "$DOTNET_BUILD_CONTAINER_TAG" ] && DOTNET_BUILD_CONTAINER_TAG="dotnetcli-build" +[ -z "$DOTNET_BUILD_CONTAINER_NAME" ] && DOTNET_BUILD_CONTAINER_NAME="dotnetcli-build-container" +[ -z "$DOCKER_HOST_SHARE_DIR" ] && DOCKER_HOST_SHARE_DIR=$(pwd) + +# Build the docker container (will be fast if it is already built) +echo "Building Docker Container using Dockerfile: $DOCKERFILE" +docker build --build-arg USER_ID=$(id -u) -t $DOTNET_BUILD_CONTAINER_TAG $DOCKERFILE + +# Run the build in the container +echo "Launching build in Docker Container" +echo "Running command: $BUILD_COMMAND" +echo "Using code from: $DOCKER_HOST_SHARE_DIR" +[ -z "$INTERACTIVE" ] || echo "Running Interactive" + +docker run $INTERACTIVE -t --rm --sig-proxy=true \ + --name $DOTNET_BUILD_CONTAINER_NAME \ + -v $DOCKER_HOST_SHARE_DIR:/opt/code \ + -e SASTOKEN \ + -e STORAGE_ACCOUNT \ + -e STORAGE_CONTAINER \ + -e CHANNEL \ + -e CONNECTION_STRING \ + -e REPO_ID \ + -e REPO_USER \ + -e REPO_PASS \ + -e REPO_SERVER \ + -e DOTNET_BUILD_SKIP_CROSSGEN \ + $DOTNET_BUILD_CONTAINER_TAG \ + $BUILD_COMMAND "$@" diff --git a/scripts/dotnet-cli-build/CompileTargets.cs b/scripts/dotnet-cli-build/CompileTargets.cs new file mode 100644 index 000000000..5185fa361 --- /dev/null +++ b/scripts/dotnet-cli-build/CompileTargets.cs @@ -0,0 +1,401 @@ +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +using static Microsoft.DotNet.Cli.Build.FS; +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public class CompileTargets + { + public static readonly string CoreCLRVersion = "1.0.1-rc2-23811"; + public static readonly string AppDepSdkVersion = "1.0.5-prerelease-00001"; + + public static readonly List AssembliesToCrossGen = GetAssembliesToCrossGen(); + + public static readonly string[] BinariesForCoreHost = new[] + { + "csi", + "csc", + "vbc" + }; + + public static readonly string[] ProjectsToPublish = new[] + { + "dotnet" + }; + + public static readonly string[] FilesToClean = new[] + { + "README.md", + "Microsoft.DotNet.Runtime.exe", + "Microsoft.DotNet.Runtime.dll", + "Microsoft.DotNet.Runtime.deps", + "Microsoft.DotNet.Runtime.pdb" + }; + + public static readonly string[] ProjectsToPack = new[] + { + "Microsoft.DotNet.Cli.Utils", + "Microsoft.DotNet.ProjectModel", + "Microsoft.DotNet.ProjectModel.Loader", + "Microsoft.DotNet.ProjectModel.Workspaces", + "Microsoft.Extensions.DependencyModel", + "Microsoft.Extensions.Testing.Abstractions" + }; + + [Target(nameof(PrepareTargets.Init), nameof(CompileCoreHost), nameof(CompileStage1), nameof(CompileStage2))] + public static BuildTargetResult Compile(BuildTargetContext c) + { + return c.Success(); + } + + [Target] + public static BuildTargetResult CompileCoreHost(BuildTargetContext c) + { + // Generate build files + var cmakeOut = Path.Combine(Dirs.Corehost, "cmake"); + + Rmdir(cmakeOut); + Mkdirp(cmakeOut); + + var configuration = (string)c.BuildContext["Configuration"]; + + // Run the build + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Why does Windows directly call cmake but Linux/Mac calls "build.sh" in the corehost dir? + // See the comment in "src/corehost/build.sh" for details. It doesn't work for some reason. + ExecIn(cmakeOut, "cmake", + Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost"), + "-G", + "Visual Studio 14 2015 Win64"); + + var pf32 = RuntimeInformation.OSArchitecture == Architecture.X64 ? + Environment.GetEnvironmentVariable("ProgramFiles(x86)") : + Environment.GetEnvironmentVariable("ProgramFiles"); + + if (configuration.Equals("Release")) + { + // Cmake calls it "RelWithDebInfo" in the generated MSBuild + configuration = "RelWithDebInfo"; + } + + Exec(Path.Combine(pf32, "MSBuild", "14.0", "Bin", "MSBuild.exe"), + Path.Combine(cmakeOut, "ALL_BUILD.vcxproj"), + $"/p:Configuration={configuration}"); + + // Copy the output out + File.Copy(Path.Combine(cmakeOut, "cli", "Debug", "corehost.exe"), Path.Combine(Dirs.Corehost, "corehost.exe"), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "Debug", "corehost.pdb"), Path.Combine(Dirs.Corehost, "corehost.pdb"), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "dll", "Debug", "hostpolicy.dll"), Path.Combine(Dirs.Corehost, "hostpolicy.dll"), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "dll", "Debug", "hostpolicy.pdb"), Path.Combine(Dirs.Corehost, "hostpolicy.pdb"), overwrite: true); + } + else + { + ExecIn(cmakeOut, Path.Combine(c.BuildContext.BuildDirectory, "src", "corehost", "build.sh")); + + // Copy the output out + File.Copy(Path.Combine(cmakeOut, "cli", "corehost"), Path.Combine(Dirs.Corehost, "corehost"), overwrite: true); + File.Copy(Path.Combine(cmakeOut, "cli", "dll", $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true); + } + + return c.Success(); + } + + [Target] + public static BuildTargetResult CompileStage1(BuildTargetContext c) + { + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); + return CompileStage(c, + dotnet: DotNetCli.Stage0, + outputDir: Dirs.Stage1); + } + + [Target] + public static BuildTargetResult CompileStage2(BuildTargetContext c) + { + var configuration = (string)c.BuildContext["Configuration"]; + + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); + var result = CompileStage(c, + dotnet: DotNetCli.Stage1, + outputDir: Dirs.Stage2); + if (!result.Success) + { + return result; + } + + // Build projects that are packed in NuGet packages, but only on Windows + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var packagingOutputDir = Path.Combine(Dirs.Stage2Compilation, "forPackaging"); + Mkdirp(packagingOutputDir); + foreach(var project in ProjectsToPack) + { + // Just build them, we'll pack later + DotNetCli.Stage1.Build( + "--build-base-path", + packagingOutputDir, + "--configuration", + configuration, + Path.Combine(c.BuildContext.BuildDirectory, "src", project)) + .Execute() + .EnsureSuccessful(); + } + } + + return c.Success(); + } + + private static BuildTargetResult CompileStage(BuildTargetContext c, DotNetCli dotnet, string outputDir) + { + Rmdir(outputDir); + + dotnet.SetDotNetHome(); + + var configuration = (string)c.BuildContext["Configuration"]; + var binDir = Path.Combine(outputDir, "bin"); + var runtimeOutputDir = Path.Combine(outputDir, "runtime", "coreclr"); + + Mkdirp(binDir); + Mkdirp(runtimeOutputDir); + + foreach (var project in ProjectsToPublish) + { + dotnet.Publish( + "--native-subdirectory", + "--output", + binDir, + "--configuration", + configuration, + Path.Combine(c.BuildContext.BuildDirectory, "src", project)) + .Execute() + .EnsureSuccessful(); + } + + // Publish the runtime + dotnet.Publish( + "--output", + runtimeOutputDir, + "--configuration", + configuration, + Path.Combine(c.BuildContext.BuildDirectory, "src", "Microsoft.DotNet.Runtime")) + .Execute() + .EnsureSuccessful(); + + // Clean bogus files + foreach (var fileToClean in FilesToClean) + { + var pathToClean = Path.Combine(runtimeOutputDir, fileToClean); + if (File.Exists(pathToClean)) + { + File.Delete(pathToClean); + } + } + + FixModeFlags(outputDir); + + // Copy the whole runtime local to the tools + CopyRecursive(runtimeOutputDir, binDir); + + // Copy corehost + File.Copy(Path.Combine(Dirs.Corehost, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), overwrite: true); + File.Copy(Path.Combine(Dirs.Corehost, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), Path.Combine(binDir, $"{Constants.DynamicLibPrefix}hostpolicy{Constants.DynamicLibSuffix}"), overwrite: true); + + // Corehostify binaries + foreach(var binaryToCorehostify in BinariesForCoreHost) + { + try + { + // Yes, it is .exe even on Linux. This is the managed exe we're working with + File.Copy(Path.Combine(binDir, $"{binaryToCorehostify}.exe"), Path.Combine(binDir, $"{binaryToCorehostify}.dll")); + File.Delete(Path.Combine(binDir, $"{binaryToCorehostify}.exe")); + File.Copy(Path.Combine(binDir, $"corehost{Constants.ExeSuffix}"), Path.Combine(binDir, binaryToCorehostify + Constants.ExeSuffix)); + } + catch(Exception ex) + { + return c.Failed($"Failed to corehostify '{binaryToCorehostify}': {ex.ToString()}"); + } + } + + // Crossgen Roslyn + var result = Crossgen(c, binDir); + if (!result.Success) + { + return result; + } + + // Copy AppDeps + result = CopyAppDeps(c, binDir); + if(!result.Success) + { + return result; + } + + // Generate .version file + var version = ((BuildVersion)c.BuildContext["BuildVersion"]).SimpleVersion; + var content = $@"{version}{Environment.NewLine}{c.BuildContext["CommitHash"]}{Environment.NewLine}"; + File.WriteAllText(Path.Combine(outputDir, ".version"), content); + + return c.Success(); + } + + private static BuildTargetResult CopyAppDeps(BuildTargetContext c, string outputDir) + { + var appDepOutputDir = Path.Combine(outputDir, "appdepsdk"); + Rmdir(appDepOutputDir); + Mkdirp(appDepOutputDir); + + // Find toolchain package + string packageId; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + packageId = "toolchain.win7-x64.Microsoft.DotNet.AppDep"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + if (string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase)) + { + packageId = "toolchain.ubuntu.14.04-x64.Microsoft.DotNet.AppDep"; + } + else if (string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase)) + { + c.Warn("Native compilation is not yet working on CentOS"); + return c.Success(); + } + else + { + return c.Failed($"Unknown Linux Distro: {osname}"); + } + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + packageId = "toolchain.osx.10.10-x64.Microsoft.DotNet.AppDep"; + } + else + { + return c.Failed("Unsupported OS Platform"); + } + + var appDepPath = Path.Combine( + Dirs.NuGetPackages, + packageId, + AppDepSdkVersion); + CopyRecursive(appDepPath, appDepOutputDir, overwrite: true); + + return c.Success(); + } + + private static BuildTargetResult Crossgen(BuildTargetContext c, string outputDir) + { + // Check if we need to skip crossgen + if (string.Equals(Environment.GetEnvironmentVariable("DOTNET_BUILD_SKIP_CROSSGEN"), "1")) + { + c.Warn("Skipping crossgen because DOTNET_BUILD_SKIP_CROSSGEN is set"); + return c.Success(); + } + + // Find crossgen + string packageId; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + packageId = "runtime.win7-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + var osname = PlatformServices.Default.Runtime.OperatingSystem; + if (string.Equals(osname, "ubuntu", StringComparison.OrdinalIgnoreCase)) + { + packageId = "runtime.ubuntu.14.04-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } + else if (string.Equals(osname, "centos", StringComparison.OrdinalIgnoreCase)) + { + // CentOS runtime is in the runtime.rhel.7-x64... package. + packageId = "runtime.rhel.7-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } + else + { + return c.Failed($"Unknown Linux Distro: {osname}"); + } + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + packageId = "runtime.osx.10.10-x64.Microsoft.NETCore.Runtime.CoreCLR"; + } + else + { + return c.Failed("Unsupported OS Platform"); + } + + var crossGenExePath = Path.Combine( + Dirs.NuGetPackages, + packageId, + CoreCLRVersion, + "tools", + $"crossgen{Constants.ExeSuffix}"); + + // We have to copy crossgen next to mscorlib + var crossgen = Path.Combine(outputDir, $"crossgen{Constants.ExeSuffix}"); + File.Copy(crossGenExePath, crossgen, overwrite: true); + Chmod(crossgen, "a+x"); + + // And if we have mscorlib.ni.dll, we need to rename it to mscorlib.dll + if (File.Exists(Path.Combine(outputDir, "mscorlib.ni.dll"))) + { + File.Copy(Path.Combine(outputDir, "mscorlib.ni.dll"), Path.Combine(outputDir, "mscorlib.dll"), overwrite: true); + } + + foreach (var assemblyToCrossgen in AssembliesToCrossGen) + { + c.Info($"Crossgenning {assemblyToCrossgen}"); + ExecIn(outputDir, crossgen, "-nologo", "-platform_assemblies_paths", outputDir, assemblyToCrossgen); + } + + c.Info("Crossgen complete"); + + // Check if csc/vbc.ni.exe exists, and overwrite the dll with it just in case + if (File.Exists(Path.Combine(outputDir, "csc.ni.exe")) && !File.Exists(Path.Combine(outputDir, "csc.ni.dll"))) + { + File.Move(Path.Combine(outputDir, "csc.ni.exe"), Path.Combine(outputDir, "csc.ni.dll")); + } + + if (File.Exists(Path.Combine(outputDir, "vbc.ni.exe")) && !File.Exists(Path.Combine(outputDir, "vbc.ni.dll"))) + { + File.Move(Path.Combine(outputDir, "vbc.ni.exe"), Path.Combine(outputDir, "vbc.ni.dll")); + } + + return c.Success(); + } + + private static List GetAssembliesToCrossGen() + { + var list = new List + { + "System.Collections.Immutable.dll", + "System.Reflection.Metadata.dll", + "Microsoft.CodeAnalysis.dll", + "Microsoft.CodeAnalysis.CSharp.dll", + "Microsoft.CodeAnalysis.VisualBasic.dll", + "csc.dll", + "vbc.dll" + }; + + // mscorlib is already crossgenned on Windows + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // mscorlib has to be crossgenned first + list.Insert(0, "mscorlib.dll"); + } + + return list; + } + } +} diff --git a/scripts/dotnet-cli-build/PrepareTargets.cs b/scripts/dotnet-cli-build/PrepareTargets.cs new file mode 100644 index 000000000..abd94ba68 --- /dev/null +++ b/scripts/dotnet-cli-build/PrepareTargets.cs @@ -0,0 +1,219 @@ +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; + +using static Microsoft.DotNet.Cli.Build.FS; +using static Microsoft.DotNet.Cli.Build.Utils; +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public class PrepareTargets + { + [Target(nameof(Init), nameof(RestorePackages))] + public static BuildTargetResult Prepare(BuildTargetContext c) => c.Success(); + + // All major targets will depend on this in order to ensure variables are set up right if they are run independently + [Target(nameof(GenerateVersions), nameof(CheckPrereqs), nameof(LocateStage0))] + public static BuildTargetResult Init(BuildTargetContext c) + { + var runtimeInfo = PlatformServices.Default.Runtime; + + var configEnv = Environment.GetEnvironmentVariable("CONFIGURATION"); + + if(string.IsNullOrEmpty(configEnv)) + { + configEnv = "Debug"; + } + c.BuildContext["Configuration"] = configEnv; + + c.Info($"Building {c.BuildContext["Configuration"]} to: {Dirs.Output}"); + c.Info("Build Environment:"); + c.Info($" Operating System: {runtimeInfo.OperatingSystem} {runtimeInfo.OperatingSystemVersion}"); + c.Info($" Platform: {runtimeInfo.OperatingSystemPlatform}"); + + return c.Success(); + } + + [Target] + public static BuildTargetResult GenerateVersions(BuildTargetContext c) + { + var gitResult = Cmd("git", "rev-list", "--count", "HEAD") + .CaptureStdOut() + .Execute(); + gitResult.EnsureSuccessful(); + var commitCount = int.Parse(gitResult.StdOut); + + gitResult = Cmd("git", "rev-parse", "HEAD") + .CaptureStdOut() + .Execute(); + gitResult.EnsureSuccessful(); + var commitHash = gitResult.StdOut.Trim(); + + var branchInfo = ReadBranchInfo(c, Path.Combine(c.BuildContext.BuildDirectory, "branchinfo.txt")); + var buildVersion = new BuildVersion() + { + Major = int.Parse(branchInfo["MAJOR_VERSION"]), + Minor = int.Parse(branchInfo["MINOR_VERSION"]), + Patch = int.Parse(branchInfo["PATCH_VERSION"]), + ReleaseSuffix = branchInfo["RELEASE_SUFFIX"], + CommitCount = commitCount + }; + c.BuildContext["BuildVersion"] = buildVersion; + c.BuildContext["CommitHash"] = commitHash; + + c.Info($"Building Version: {buildVersion.SimpleVersion} (NuGet Packages: {buildVersion.NuGetVersion})"); + c.Info($"From Commit: {commitHash}"); + + return c.Success(); + } + + [Target] + public static BuildTargetResult LocateStage0(BuildTargetContext c) + { + // We should have been run in the repo root, so locate the stage 0 relative to current directory + var stage0 = DotNetCli.Stage0.BinPath; + + if (!Directory.Exists(stage0)) + { + return c.Failed($"Stage 0 directory does not exist: {stage0}"); + } + + // Identify the version + var version = File.ReadAllLines(Path.Combine(stage0, "..", ".version")); + c.Info($"Using Stage 0 Version: {version[1]}"); + + return c.Success(); + } + + [Target] + public static BuildTargetResult CheckPrereqs(BuildTargetContext c) + { + try + { + Command.Create("cmake", "--version") + .CaptureStdOut() + .CaptureStdErr() + .Execute(); + } + catch (Exception ex) + { + string message = $@"Error running cmake: {ex.Message} +cmake is required to build the native host 'corehost'"; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + message += Environment.NewLine + "Download it from https://www.cmake.org"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + message += Environment.NewLine + "Ubuntu: 'sudo apt-get install cmake'"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + message += Environment.NewLine + "OS X w/Homebrew: 'brew install cmake'"; + } + return c.Failed(message); + } + + return c.Success(); + } + + [Target] + public static BuildTargetResult CheckPackageCache(BuildTargetContext c) + { + var ciBuild = string.Equals(Environment.GetEnvironmentVariable("CI_BUILD"), "1", StringComparison.Ordinal); + + if (ciBuild) + { + // On CI, HOME is redirected under the repo, which gets deleted after every build. + // So make NUGET_PACKAGES outside of the repo. + var nugetPackages = Path.GetFullPath(Path.Combine(c.BuildContext.BuildDirectory, "..", ".nuget", "packages")); + Environment.SetEnvironmentVariable("NUGET_PACKAGES", nugetPackages); + Dirs.NuGetPackages = nugetPackages; + } + + // Set the package cache location in NUGET_PACKAGES just to be safe + if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("NUGET_PACKAGES"))) + { + Environment.SetEnvironmentVariable("NUGET_PACKAGES", Dirs.NuGetPackages); + } + + CleanNuGetTempCache(); + + // Determine cache expiration time + var cacheExpiration = 7 * 24; // cache expiration in hours + var cacheExpirationStr = Environment.GetEnvironmentVariable("NUGET_PACKAGES_CACHE_TIME_LIMIT"); + if (!string.IsNullOrEmpty(cacheExpirationStr)) + { + cacheExpiration = int.Parse(cacheExpirationStr); + } + + if (ciBuild) + { + var cacheTimeFile = Path.Combine(Dirs.NuGetPackages, "packageCacheTime.txt"); + + DateTime? cacheTime = null; + try + { + // Read the cache file + if(File.Exists(cacheTimeFile)) + { + var content = File.ReadAllText(cacheTimeFile); + if(!string.IsNullOrEmpty(content)) + { + cacheTime = DateTime.ParseExact("O", content, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + } + } + } + catch(Exception ex) + { + c.Warn($"Error reading NuGet cache time file, leaving the cache alone"); + c.Warn($"Error Detail: {ex.ToString()}"); + } + + if(cacheTime == null || (cacheTime.Value.AddHours(cacheExpiration) < DateTime.UtcNow)) + { + // Cache has expired or the status is unknown, clear it and write the file + c.Info("Clearing NuGet cache"); + Rmdir(Dirs.NuGetPackages); + Mkdirp(Dirs.NuGetPackages); + File.WriteAllText(cacheTimeFile, DateTime.UtcNow.ToString("O")); + } + } + + return c.Success(); + } + + [Target(nameof(CheckPackageCache))] + public static BuildTargetResult RestorePackages(BuildTargetContext c) + { + var dotnet = DotNetCli.Stage0; + + dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "src")).Execute().EnsureSuccessful(); + dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "tools")).Execute().EnsureSuccessful(); + + return c.Success(); + } + + private static IDictionary ReadBranchInfo(BuildTargetContext c, string path) + { + var lines = File.ReadAllLines(path); + var dict = new Dictionary(); + c.Verbose("Branch Info:"); + foreach(var line in lines) + { + if(!line.Trim().StartsWith("#") && !string.IsNullOrWhiteSpace(line)) + { + var splat = line.Split(new[] { '=' }, 2); + dict[splat[0]] = splat[1]; + c.Verbose($" {splat[0]} = {splat[1]}"); + } + } + return dict; + } + } +} diff --git a/scripts/dotnet-cli-build/Program.cs b/scripts/dotnet-cli-build/Program.cs new file mode 100755 index 000000000..bc2661b2c --- /dev/null +++ b/scripts/dotnet-cli-build/Program.cs @@ -0,0 +1,12 @@ +using Microsoft.DotNet.Cli.Build.Framework; + +namespace Microsoft.DotNet.Cli.Build +{ + public class Program + { + public static int Main(string[] args) => BuildSetup.Create(".NET Core CLI") + .UseStandardGoals() + .UseAllTargetsFromAssembly() + .Run(args); + } +} diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs new file mode 100644 index 000000000..e7dbe752b --- /dev/null +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -0,0 +1,71 @@ +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public static class PublishTargets + { + [Target(nameof(PrepareTargets.Init))] + public static BuildTargetResult Publish(BuildTargetContext c) + { + // NOTE(anurse): Currently, this just invokes the remaining build scripts as-is. We should port those to C# as well, but + // I want to get the merged in. + + // Set up the environment variables previously defined by common.sh/ps1 + // This is overkill, but I want to cover all the variables used in all OSes (including where some have the same names) + var buildVersion = (BuildVersion)c.BuildContext["BuildVersion"]; + var env = new Dictionary() + { + { "RID", PlatformServices.Default.Runtime.GetRuntimeIdentifier() }, + { "OSNAME", PlatformServices.Default.Runtime.OperatingSystem }, + { "TFM", "dnxcore50" }, + { "OutputDir", Dirs.Output }, + { "Stage1Dir", Dirs.Stage1 }, + { "Stage1CompilationDir", Dirs.Stage1Compilation }, + { "Stage2Dir", Dirs.Stage2 }, + { "STAGE2_DIR", Dirs.Stage2 }, + { "Stage2CompilationDir", Dirs.Stage2Compilation }, + { "HostDir", Dirs.Corehost }, + { "PackageDir", Path.Combine(Dirs.Packages, "dnvm") }, // Legacy name + { "TestBinRoot", Dirs.TestOutput }, + { "TestPackageDir", Dirs.TestPackages }, + { "MajorVersion", buildVersion.Major.ToString() }, + { "MinorVersion", buildVersion.Minor.ToString() }, + { "PatchVersion", buildVersion.Patch.ToString() }, + { "CommitCountVersion", buildVersion.CommitCountString }, + { "COMMIT_COUNT_VERSION", buildVersion.CommitCountString }, + { "DOTNET_CLI_VERSION", buildVersion.SimpleVersion }, + { "DOTNET_MSI_VERSION", buildVersion.GenerateMsiVersion() }, + { "VersionSuffix", buildVersion.VersionSuffix } + }; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + env["OSNAME"] = "osx"; + } + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Cmd("powershell", "-NoProfile", "-NoLogo", Path.Combine(c.BuildContext.BuildDirectory, "scripts", "package", "package.ps1")) + .Environment(env) + .Execute() + .EnsureSuccessful(); + } + else + { + // Can directly execute scripts on Unix :). Thank you shebangs! + Cmd(Path.Combine(c.BuildContext.BuildDirectory, "scripts", "package", "package.sh")) + .Environment(env) + .Execute() + .EnsureSuccessful(); + } + return c.Success(); + } + } +} diff --git a/scripts/dotnet-cli-build/TestTargets.cs b/scripts/dotnet-cli-build/TestTargets.cs new file mode 100644 index 000000000..6937781f8 --- /dev/null +++ b/scripts/dotnet-cli-build/TestTargets.cs @@ -0,0 +1,241 @@ +using Microsoft.DotNet.Cli.Build.Framework; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +using static Microsoft.DotNet.Cli.Build.FS; +using static Microsoft.DotNet.Cli.Build.Utils; +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public class TestTargets + { + public static readonly string[] TestPackageProjects = new[] + { + "dotnet-hello/v1/dotnet-hello", + "dotnet-hello/v2/dotnet-hello" + }; + + public static readonly string[] TestProjects = new[] + { + "EndToEnd", + "dotnet-publish.Tests", + "dotnet-compile.Tests", + "dotnet-compile.UnitTests", + "dotnet-build.Tests", + "Microsoft.DotNet.Cli.Utils.Tests", + "Microsoft.DotNet.Compiler.Common.Tests", + "ArgumentForwardingTests" + }; + + [Target(nameof(PrepareTargets.Init), nameof(SetupTests), nameof(RestoreTests), nameof(BuildTests), nameof(RunTests), nameof(ValidateDependencies))] + public static BuildTargetResult Test(BuildTargetContext c) => c.Success(); + + [Target(nameof(RestoreTestPrerequisites), nameof(BuildTestPrerequisites))] + public static BuildTargetResult SetupTests(BuildTargetContext c) => c.Success(); + + [Target] + public static BuildTargetResult RestoreTestPrerequisites(BuildTargetContext c) + { + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); + + CleanNuGetTempCache(); + + var dotnet = DotNetCli.Stage2; + dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets")).Execute().EnsureSuccessful(); + + // The 'testapp' directory contains intentionally-unresolved dependencies, so don't check for success. Also, suppress the output + dotnet.Restore().WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "testapp")).CaptureStdErr().CaptureStdOut().Execute(); + + return c.Success(); + } + + [Target] + public static BuildTargetResult BuildTestPrerequisites(BuildTargetContext c) + { + var dotnet = DotNetCli.Stage2; + + Rmdir(Dirs.TestPackages); + Mkdirp(Dirs.TestPackages); + + foreach (var relativePath in TestPackageProjects) + { + var fullPath = Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestPackages", relativePath.Replace('/', Path.DirectorySeparatorChar)); + c.Info("Packing: {fullPath}"); + dotnet.Pack("--output", Dirs.TestPackages) + .WorkingDirectory(fullPath) + .Execute() + .EnsureSuccessful(); + } + + return c.Success(); + } + + [Target] + public static BuildTargetResult RestoreTests(BuildTargetContext c) + { + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "src")); + CleanBinObj(c, Path.Combine(c.BuildContext.BuildDirectory, "test")); + + CleanNuGetTempCache(); + DotNetCli.Stage2.Restore("--fallbacksource", Dirs.TestPackages) + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "test")) + .Execute() + .EnsureSuccessful(); + return c.Success(); + } + + [Target] + public static BuildTargetResult BuildTests(BuildTargetContext c) + { + var dotnet = DotNetCli.Stage2; + foreach (var testProject in TestProjects) + { + c.Info("Building tests: {project}"); + dotnet.Build() + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "test", testProject)) + .Execute() + .EnsureSuccessful(); + } + return c.Success(); + } + + [Target(nameof(RunXUnitTests), nameof(RunPackageCommandTests))] + public static BuildTargetResult RunTests(BuildTargetContext c) => c.Success(); + + [Target] + public static BuildTargetResult RunXUnitTests(BuildTargetContext c) + { + // Need to load up the VS Vars + var dotnet = DotNetCli.Stage2; + var vsvars = LoadVsVars(); + + // Copy the test projects + var testProjectsDir = Path.Combine(Dirs.TestOutput, "TestProjects"); + Rmdir(testProjectsDir); + Mkdirp(testProjectsDir); + CopyRecursive(Path.Combine(c.BuildContext.BuildDirectory, "TestAssets", "TestProjects"), testProjectsDir); + + // Run the tests and set the VS vars in the environment when running them + var failingTests = new List(); + foreach (var project in TestProjects) + { + c.Info("Running tests in: {project}"); + var result = dotnet.Test("-xml", $"{project}-testResults.xml", "-notrait", "category=failing") + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "test", project)) + .Environment(vsvars) + .EnvironmentVariable("PATH", $"{DotNetCli.Stage2.BinPath}{Path.PathSeparator}{Environment.GetEnvironmentVariable("PATH")}") + .Execute(); + if (result.ExitCode != 0) + { + failingTests.Add(project); + } + } + + if (failingTests.Any()) + { + foreach (var project in failingTests) + { + c.Error($"{project} failed"); + } + return c.Failed("Tests failed!"); + } + + return c.Success(); + } + + [Target] + public static BuildTargetResult RunPackageCommandTests(BuildTargetContext c) + { + var dotnet = DotNetCli.Stage2; + var consumers = Path.Combine(c.BuildContext.BuildDirectory, "test", "PackagedCommands", "Consumers"); + + // Compile the consumer apps + foreach(var dir in Directory.EnumerateDirectories(consumers)) + { + dotnet.Build().WorkingDirectory(dir).Execute().EnsureSuccessful(); + } + + // Test the apps + foreach(var dir in Directory.EnumerateDirectories(consumers)) + { + var result = dotnet.Exec("hello").WorkingDirectory(dir).CaptureStdOut().CaptureStdErr().Execute(); + result.EnsureSuccessful(); + if(!string.Equals("Hello", result.StdOut.Trim(), StringComparison.Ordinal)) + { + var testName = Path.GetFileName(dir); + c.Error($"Packaged Commands Test '{testName}' failed"); + c.Error($" Expected 'Hello', but got: '{result.StdOut.Trim()}'"); + return c.Failed($"Packaged Commands Test failed '{testName}'"); + } + } + + return c.Success(); + } + + [Target] + public static BuildTargetResult ValidateDependencies(BuildTargetContext c) + { + var configuration = (string)c.BuildContext["Configuration"]; + var dotnet = DotNetCli.Stage2; + + c.Info("Publishing MultiProjectValidator"); + dotnet.Publish("--output", Path.Combine(Dirs.Output, "tools"), "--configuration", configuration) + .WorkingDirectory(Path.Combine(c.BuildContext.BuildDirectory, "tools", "MultiProjectValidator")) + .Execute() + .EnsureSuccessful(); + + var validator = Path.Combine(Dirs.Output, "tools", $"pjvalidate{Constants.ExeSuffix}"); + + Cmd(validator, Path.Combine(c.BuildContext.BuildDirectory, "src")) + .Execute(); + + return c.Success(); + } + + private static Dictionary LoadVsVars() + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return new Dictionary(); + } + + var vsvarsPath = Path.GetFullPath(Path.Combine(Environment.GetEnvironmentVariable("VS140COMNTOOLS"), "..", "..", "VC")); + + // Write a temp batch file because that seems to be the easiest way to do this (argument parsing is hard) + var temp = Path.Combine(Path.GetTempPath(), $"{Path.GetRandomFileName()}.cmd"); + File.WriteAllText(temp, $@"@echo off +cd {vsvarsPath} +call vcvarsall.bat x64 +set"); + + CommandResult result; + try + { + result = Cmd(Environment.GetEnvironmentVariable("COMSPEC"), "/c", temp) + .WorkingDirectory(vsvarsPath) + .CaptureStdOut() + .Execute(); + } + finally + { + if (File.Exists(temp)) + { + File.Delete(temp); + } + } + result.EnsureSuccessful(); + var vars = new Dictionary(); + foreach (var line in result.StdOut.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries)) + { + var splat = line.Split(new[] { '=' }, 2); + vars[splat[0]] = splat[1]; + } + return vars; + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/BuildVersion.cs b/scripts/dotnet-cli-build/Utils/BuildVersion.cs new file mode 100644 index 000000000..c03b48bd3 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/BuildVersion.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build +{ + public class BuildVersion + { + public int Major { get; set; } + public int Minor { get; set; } + public int Patch { get; set; } + public int CommitCount { get; set; } + public string CommitCountString => CommitCount.ToString("000000"); + public string ReleaseSuffix { get; set; } + + public string SimpleVersion => $"{Major}.{Minor}.{Patch}.{CommitCount}"; + public string VersionSuffix => $"{ReleaseSuffix}-{CommitCount}"; + public string NuGetVersion => $"{Major}.{Minor}.{Patch}-{VersionSuffix}"; + + public string GenerateMsiVersion() + { + // MSI versioning + // Encode the CLI version to fit into the MSI versioning scheme - https://msdn.microsoft.com/en-us/library/windows/desktop/aa370859(v=vs.85).aspx + // MSI versions are 3 part + // major.minor.build + // Size(bits) of each part 8 8 16 + // So we have 32 bits to encode the CLI version + // Starting with most significant bit this how the CLI version is going to be encoded as MSI Version + // CLI major -> 6 bits + // CLI minor -> 6 bits + // CLI patch -> 6 bits + // CLI commitcount -> 14 bits + + var major = Major << 26; + var minor = Minor << 20; + var patch = Patch << 14; + var msiVersionNumber = major | minor | patch | CommitCount; + + var msiMajor = (msiVersionNumber >> 24) & 0xFF; + var msiMinor = (msiVersionNumber >> 16) & 0xFF; + var msiBuild = msiVersionNumber & 0xFFFF; + + return $"{msiMajor}.{msiMinor}.{msiBuild}"; + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/Dirs.cs b/scripts/dotnet-cli-build/Utils/Dirs.cs new file mode 100644 index 000000000..c90b63406 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/Dirs.cs @@ -0,0 +1,38 @@ +using Microsoft.Extensions.PlatformAbstractions; +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build +{ + public static class Dirs + { + public static readonly string Output = Path.Combine( + Directory.GetCurrentDirectory(), + "artifacts", + PlatformServices.Default.Runtime.GetRuntimeIdentifier()); + public static readonly string Packages = Path.Combine(Output, "packages"); + public static readonly string Stage1 = Path.Combine(Output, "stage1"); + public static readonly string Stage1Compilation = Path.Combine(Output, "stage1compilation"); + public static readonly string Stage2 = Path.Combine(Output, "stage2"); + public static readonly string Stage2Compilation = Path.Combine(Output, "stage2compilation"); + public static readonly string Corehost = Path.Combine(Output, "corehost"); + public static readonly string TestOutput = Path.Combine(Output, "tests"); + public static readonly string TestPackages = Path.Combine(TestOutput, "packages"); + + public static readonly string OSXReferenceAssembliesPath = "/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks"; + public static readonly string UsrLocalReferenceAssembliesPath = "/usr/local/lib/mono/xbuild-frameworks"; + public static readonly string UsrReferenceAssembliesPath = "/usr/lib/mono/xbuild-frameworks"; + + public static string NuGetPackages = Environment.GetEnvironmentVariable("NUGET_PACKAGES") ?? GetNuGetPackagesDir(); + + private static string GetNuGetPackagesDir() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), ".nuget", "packages"); + } + return Path.Combine(Environment.GetEnvironmentVariable("HOME"), ".nuget", "packages"); + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/DotNetCli.cs b/scripts/dotnet-cli-build/Utils/DotNetCli.cs new file mode 100644 index 000000000..51e194504 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/DotNetCli.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Linq; +using System; +using System.Runtime.InteropServices; +using Microsoft.DotNet.Cli.Build.Framework; +using Microsoft.Extensions.PlatformAbstractions; + +namespace Microsoft.DotNet.Cli.Build +{ + internal class DotNetCli + { + public static readonly DotNetCli Stage0 = new DotNetCli(GetStage0Path()); + public static readonly DotNetCli Stage1 = new DotNetCli(Path.Combine(Dirs.Stage1, "bin")); + public static readonly DotNetCli Stage2 = new DotNetCli(Path.Combine(Dirs.Stage2, "bin")); + + public string BinPath { get; } + + public DotNetCli(string binPath) + { + BinPath = binPath; + } + + public void SetDotNetHome() + { + Environment.SetEnvironmentVariable("DOTNET_HOME", Path.GetDirectoryName(BinPath)); + } + + public Command Exec(string command, params string[] args) + { + return Command.Create(Path.Combine(BinPath, $"dotnet{Constants.ExeSuffix}"), Enumerable.Concat(new[] { command }, args)); + } + + public Command Restore(params string[] args) => Exec("restore", args); + public Command Build(params string[] args) => Exec("build", args); + public Command Pack(params string[] args) => Exec("pack", args); + public Command Test(params string[] args) => Exec("test", args); + public Command Publish(params string[] args) => Exec("publish", args); + + private static string GetStage0Path() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0", PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(), "cli", "bin"); + } + else + { + return Path.Combine(Directory.GetCurrentDirectory(), ".dotnet_stage0", PlatformServices.Default.Runtime.OperatingSystemPlatform.ToString(), "share", "dotnet", "cli", "bin"); + } + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/FS.cs b/scripts/dotnet-cli-build/Utils/FS.cs new file mode 100644 index 000000000..b336d46f2 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/FS.cs @@ -0,0 +1,114 @@ +using System.IO; +using System.Runtime.InteropServices; +using System; + +using Microsoft.DotNet.Cli.Build.Framework; + +using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; + +namespace Microsoft.DotNet.Cli.Build +{ + public static class FS + { + public static void Mkdirp(string dir) + { + if (!Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + } + + public static void Rm(string file) + { + if(File.Exists(file)) + { + File.Delete(file); + } + } + + public static void Rmdir(string dir) + { + if(Directory.Exists(dir)) + { + Directory.Delete(dir, recursive: true); + } + } + + public static void Chmod(string file, string mode, bool recursive = false) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (recursive) + { + Command.Create("chmod", "-R", mode, file).Execute().EnsureSuccessful(); + } + else + { + Command.Create("chmod", mode, file).Execute().EnsureSuccessful(); + } + } + } + + public static void ChmodAll(string searchDir, string pattern, string mode) + { + Exec("find", searchDir, "-type", "f", "-name", pattern, "-exec", "chmod", mode, "{}", ";"); + } + + public static void FixModeFlags(string dir) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Managed code doesn't need 'x' + ChmodAll(dir, "*.dll", "644"); + ChmodAll(dir, "*.exe", "644"); + + // Generally, dylibs and sos have 'x' (no idea if it's required ;)) + // (No need to condition this on OS since there shouldn't be any dylibs on Linux, + // but even if they are we may as well set their mode flags :)) + ChmodAll(dir, "*.dylib", "755"); + ChmodAll(dir, "*.so", "755"); + + // Executables (those without dots) are executable :) + Exec("find", dir, "-type", "f", "!", "-name", "*.*", "-exec", "chmod", "755", "{}", ";"); + } + } + + public static void CopyRecursive(string sourceDirectory, string destinationDirectory, bool overwrite = false) + { + Mkdirp(destinationDirectory); + + foreach(var dir in Directory.EnumerateDirectories(sourceDirectory)) + { + CopyRecursive(dir, Path.Combine(destinationDirectory, Path.GetFileName(dir)), overwrite); + } + + foreach(var file in Directory.EnumerateFiles(sourceDirectory)) + { + var dest = Path.Combine(destinationDirectory, Path.GetFileName(file)); + if (!File.Exists(dest) || overwrite) + { + // We say overwrite true, because we only get here if the file didn't exist (thus it doesn't matter) or we + // wanted to overwrite :) + File.Copy(file, dest, overwrite: true); + } + } + } + + public static void CleanBinObj(BuildTargetContext c, string dir) + { + dir = dir ?? c.BuildContext.BuildDirectory; + foreach(var candidate in Directory.EnumerateDirectories(dir)) + { + if (string.Equals(Path.GetFileName(candidate), "bin") || + string.Equals(Path.GetFileName(candidate), "obj")) + { + Directory.Delete(candidate, recursive: true); + } + else + { + CleanBinObj(c, candidate); + } + } + } + } +} diff --git a/scripts/dotnet-cli-build/Utils/Utils.cs b/scripts/dotnet-cli-build/Utils/Utils.cs new file mode 100644 index 000000000..edbee23d1 --- /dev/null +++ b/scripts/dotnet-cli-build/Utils/Utils.cs @@ -0,0 +1,38 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.DotNet.Cli.Build +{ + public static class Utils + { + public static void CleanNuGetTempCache() + { + // Clean NuGet Temp Cache on Linux (seeing some issues on Linux) + if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && Directory.Exists("/tmp/NuGet")) + { + Directory.Delete("/tmp/NuGet", recursive: true); + } + } + + public static string GetOSName() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return "win"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + return "osx"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + throw new NotImplementedException(); + } + else + { + throw new PlatformNotSupportedException(); + } + } + } +} diff --git a/scripts/dotnet-cli-build/dotnet-cli-build.xproj b/scripts/dotnet-cli-build/dotnet-cli-build.xproj new file mode 100644 index 000000000..fadd44933 --- /dev/null +++ b/scripts/dotnet-cli-build/dotnet-cli-build.xproj @@ -0,0 +1,18 @@ + + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + d7b9695d-23eb-4ea8-b8ab-707a0092e1d5 + Microsoft.DotNet.Cli.Build + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + 2.0 + + + \ No newline at end of file diff --git a/scripts/dotnet-cli-build/project.json b/scripts/dotnet-cli-build/project.json new file mode 100755 index 000000000..326ce33b3 --- /dev/null +++ b/scripts/dotnet-cli-build/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0-*", + "description": "Build scripts for dotnet-cli", + "compilationOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "System.IO.Compression.ZipFile": "4.0.1-rc2-23811", + "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537", + "Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*" + }, + + "frameworks": { + "dnxcore50": { } + } +} diff --git a/scripts/global.json b/scripts/global.json new file mode 100644 index 000000000..22936715c --- /dev/null +++ b/scripts/global.json @@ -0,0 +1,3 @@ +{ + "projects": [ "." ] +} diff --git a/scripts/obtain/install-tools.ps1 b/scripts/obtain/install-tools.ps1 deleted file mode 100644 index 89ae69dfe..000000000 --- a/scripts/obtain/install-tools.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot -if (!(Test-Path $env:DOTNET_INSTALL_DIR)) -{ - mkdir $env:DOTNET_INSTALL_DIR | Out-Null -} - -# Install a stage 0 -header "Installing dotnet stage 0" -_ "$RepoRoot\scripts\obtain\install.ps1" @("$env:Channel") diff --git a/scripts/obtain/install-tools.sh b/scripts/obtain/install-tools.sh deleted file mode 100755 index f4a99f26c..000000000 --- a/scripts/obtain/install-tools.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot -[ -d $DOTNET_INSTALL_DIR ] || mkdir -p $DOTNET_INSTALL_DIR - -# Ensure the latest stage0 is installed -header "Installing dotnet stage 0" -$REPOROOT/scripts/obtain/install.sh - -# Now patch the runtime in stage 0 -# HACK(anurse): BIG HACK. This is just to dodge the current broken Linux stage0. We'll remove it as soon as we've got a new stage 0 -( - export PATH="$DOTNET_INSTALL_DIR/bin:$PATH" - cd $REPOROOT/src/Microsoft.DotNet.Runtime - dotnet restore - dotnet publish -o "$DOTNET_INSTALL_DIR/share/dotnet/cli/runtime/coreclr" - cp $DOTNET_INSTALL_DIR/share/dotnet/cli/runtime/coreclr/* $DOTNET_INSTALL_DIR/share/dotnet/cli/bin -) diff --git a/scripts/package/package-dnvm.sh b/scripts/package/package-dnvm.sh index 412161753..47d8fe396 100755 --- a/scripts/package/package-dnvm.sh +++ b/scripts/package/package-dnvm.sh @@ -33,6 +33,6 @@ header "Packaging $PACKAGE_SHORT_NAME" # We need both "*" and ".version" to ensure we pick up that file tar -czf $PACKAGE_NAME * .version -info "Packaged stage2 to $PACKAGE_NAME" +info "Packaged stage2 from '$STAGE2_DIR' to '$PACKAGE_NAME'" $REPOROOT/scripts/publish/publish.sh $PACKAGE_NAME diff --git a/scripts/package/package.ps1 b/scripts/package/package.ps1 index 577a17380..cfb3c13d8 100644 --- a/scripts/package/package.ps1 +++ b/scripts/package/package.ps1 @@ -4,7 +4,8 @@ # . "$PSScriptRoot\..\common\_common.ps1" -. "$RepoRoot\scripts\build\generate-version.ps1" + +$RepoRoot = Convert-Path "$PSScriptRoot\..\.." header "Generating zip package" _ "$RepoRoot\scripts\package\package-zip.ps1" diff --git a/scripts/package/package.sh b/scripts/package/package.sh index dea779842..a412a04f7 100755 --- a/scripts/package/package.sh +++ b/scripts/package/package.sh @@ -12,8 +12,9 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" +export REPOROOT="$(cd -P "$DIR/../.." && pwd)" + source "$DIR/../common/_common.sh" -source "$REPOROOT/scripts/build/generate-version.sh" if [ -z "$DOTNET_CLI_VERSION" ]; then TIMESTAMP=$(date "+%Y%m%d%H%M%S") @@ -33,5 +34,5 @@ header "Generating version badge" sed "s/ver_number/$DOTNET_CLI_VERSION/g" $VERSION_BADGE > $BADGE_DESTINATION header "Publishing version badge" -$REPOROOT/scripts/publish/publish.sh $BADGE_DESTINATION +$DIR/../publish/publish.sh $BADGE_DESTINATION diff --git a/scripts/run-build.ps1 b/scripts/run-build.ps1 new file mode 100644 index 000000000..9b9453722 --- /dev/null +++ b/scripts/run-build.ps1 @@ -0,0 +1,55 @@ +# +# 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. +# + +param( + [string]$Configuration="Debug") + +$env:CONFIGURATION = $Configuration; + +# Load Branch Info +cat "$PSScriptRoot\..\branchinfo.txt" | ForEach-Object { + if(!$_.StartsWith("#") -and ![String]::IsNullOrWhiteSpace($_)) { + $splat = $_.Split([char[]]@("="), 2) + Set-Content "env:\$($splat[0])" -Value $splat[1] + } +} + +$env:CHANNEL=$env:RELEASE_SUFFIX + +# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot +if (!$env:DOTNET_INSTALL_DIR) +{ + $env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows" +} + +if (!(Test-Path $env:DOTNET_INSTALL_DIR)) +{ + mkdir $env:DOTNET_INSTALL_DIR | Out-Null +} + +# Install a stage 0 +Write-Host "Installing .NET Core CLI Stage 0 from beta channel" +& "$PSScriptRoot\obtain\install.ps1" -Channel $env:CHANNEL + +# Put the stage0 on the path +$env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$env:PATH" + +# Restore the build scripts +Write-Host "Restoring Build Script projects..." +pushd $PSScriptRoot +dotnet restore +if($LASTEXITCODE -ne 0) { throw "Failed to restore" } +popd + +# Publish the builder +Write-Host "Compiling Build Scripts..." +dotnet publish "$PSScriptRoot\dotnet-cli-build" -o "$PSScriptRoot/dotnet-cli-build/bin" --framework dnxcore50 +if($LASTEXITCODE -ne 0) { throw "Failed to compile build scripts" } + +# Run the builder +Write-Host "Invoking Build Scripts..." +$env:DOTNET_HOME="$env:DOTNET_INSTALL_DIR\cli" +& "$PSScriptRoot\dotnet-cli-build\bin\dotnet-cli-build.exe" @args +if($LASTEXITCODE -ne 0) { throw "Build failed" } diff --git a/scripts/run-build.sh b/scripts/run-build.sh new file mode 100755 index 000000000..c5a7f3542 --- /dev/null +++ b/scripts/run-build.sh @@ -0,0 +1,80 @@ +#!/usr/bin/env bash +# +# 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. +# + +set -e + +SOURCE="${BASH_SOURCE[0]}" +while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink + DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + SOURCE="$(readlink "$SOURCE")" + [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located +done +DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" + +# Set up the environment to be used for building with clang. +if which "clang-3.5" > /dev/null 2>&1; then + export CC="$(which clang-3.5)" + export CXX="$(which clang++-3.5)" +elif which "clang-3.6" > /dev/null 2>&1; then + export CC="$(which clang-3.6)" + export CXX="$(which clang++-3.6)" +elif which clang > /dev/null 2>&1; then + export CC="$(which clang)" + export CXX="$(which clang++)" +else + error "Unable to find Clang Compiler" + error "Install clang-3.5 or clang3.6" + exit 1 +fi + +# Load Branch Info +while read line; do + if [[ $line != \#* ]]; then + IFS='=' read -ra splat <<< "$line" + export ${splat[0]}="${splat[1]}" + fi +done < "$DIR/../branchinfo.txt" + +# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot +[ -z "$DOTNET_INSTALL_DIR" ] && export DOTNET_INSTALL_DIR=$DIR/../.dotnet_stage0/$(uname) +[ -d $DOTNET_INSTALL_DIR ] || mkdir -p $DOTNET_INSTALL_DIR + +# Ensure the latest stage0 is installed +$DIR/obtain/install.sh --channel $RELEASE_SUFFIX + +# Put stage 0 on the PATH (for this shell only) +PATH="$DOTNET_INSTALL_DIR/bin:$PATH" + +# Increases the file descriptors limit for this bash. It prevents an issue we were hitting during restore +FILE_DESCRIPTOR_LIMIT=$( ulimit -n ) +if [ $FILE_DESCRIPTOR_LIMIT -lt 1024 ] +then + echo "Increasing file description limit to 1024" + ulimit -n 1024 +fi + +# Restore the build scripts +echo "Restoring Build Script projects..." +( + cd $DIR + dotnet restore +) + +# Build the builder +echo "Compiling Build Scripts..." +dotnet publish "$DIR/dotnet-cli-build" -o "$DIR/dotnet-cli-build/bin" --framework dnxcore50 + +# Run the builder +echo "Invoking Build Scripts..." + +if [ -f "$DIR/dotnet-cli-build/bin/dotnet-cli-build" ]; then + DOTNET_HOME="$DOTNET_INSTALL_DIR/share/dotnet/cli" $DIR/dotnet-cli-build/bin/dotnet-cli-build "$@" + exit $? +else + # We're on an older CLI. This is temporary while Ubuntu and CentOS VSO builds are stalled. + DOTNET_HOME="$DOTNET_INSTALL_DIR/share/dotnet/cli" $DIR/dotnet-cli-build/bin/Debug/dnxcore50/dotnet-cli-build "$@" + exit $? +fi diff --git a/scripts/test/argument-forwarding-tests.ps1 b/scripts/test/argument-forwarding-tests.ps1 deleted file mode 100644 index 8461f2ac8..000000000 --- a/scripts/test/argument-forwarding-tests.ps1 +++ /dev/null @@ -1,35 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -$ArgTestRoot = "$RepoRoot\test\ArgumentForwardingTests" -$ArgTestOutputRoot = "$RepoRoot\artifacts\tests\arg-forwarding" - -dotnet publish --framework "dnxcore50" --runtime "$Rid" --output "$ArgTestOutputRoot" --configuration "$Configuration" "$ArgTestRoot\Reflector" -if (!$?) { - Write-Host Command failed: dotnet publish --framework "dnxcore50" --runtime "$Rid" --output "$ArgTestOutputRoot" --configuration "$Configuration" "$ArgTestRoot\Reflector" - Exit 1 -} - -dotnet publish --framework "dnxcore50" --runtime "$Rid" --output "$ArgTestOutputRoot" --configuration "$Configuration" "$ArgTestRoot\ArgumentForwardingTests" -if (!$?) { - Write-Host Command failed: dotnet publish --framework "dnxcore50" --runtime "$Rid" --output "$ArgTestOutputRoot" --configuration "$Configuration" "$ArgTestRoot\ArgumentForwardingTests" - Exit 1 -} - -cp "$ArgTestRoot\Reflector\reflector_cmd.cmd" "$ArgTestOutputRoot" - -pushd "$ArgTestOutputRoot" - -& ".\corerun" "xunit.console.netcore.exe" "ArgumentForwardingTests.dll" -xml "$_-testResults.xml" -notrait category=failing -$exitCode = $LastExitCode - -popd - -# No need to output here, we'll get test results -if ($exitCode -ne 0) { - Exit 1 -} \ No newline at end of file diff --git a/scripts/test/argument-forwarding-tests.sh b/scripts/test/argument-forwarding-tests.sh deleted file mode 100755 index 069683a35..000000000 --- a/scripts/test/argument-forwarding-tests.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -ArgTestRoot="$REPOROOT/test/ArgumentForwardingTests" -ArgTestOutputRoot="$REPOROOT/artifacts/tests/arg-forwarding" - -dotnet publish --framework "dnxcore50" --output "$ArgTestOutputRoot" --configuration "$CONFIGURATION" "$ArgTestRoot/Reflector" -dotnet publish --framework "dnxcore50" --output "$ArgTestOutputRoot" --configuration "$CONFIGURATION" "$ArgTestRoot/ArgumentForwardingTests" - - - -pushd "$ArgTestOutputRoot" - ./corerun "xunit.console.netcore.exe" "ArgumentForwardingTests.dll" -xml "ArgumentForwardingTests-testResults.xml" -notrait category=failing -popd diff --git a/scripts/test/build-tests.ps1 b/scripts/test/build-tests.ps1 deleted file mode 100644 index 140e75ab6..000000000 --- a/scripts/test/build-tests.ps1 +++ /dev/null @@ -1,17 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -# Publish each test project -loadTestProjectList | foreach { - #we should use publish to an output path, we will once issue #1183 has been fixed and we can point dotnet test do a dll. - #we need to add back tfm, rid and configuration, but dotnet test need to be made aware of those as well. Tracked at issue #1237. - dotnet build "$RepoRoot\test\$($_.ProjectName)" - if (!$?) { - Write-Host Command failed: dotnet build "$RepoRoot\test\$($_.ProjectName)" - exit 1 - } -} diff --git a/scripts/test/build-tests.sh b/scripts/test/build-tests.sh deleted file mode 100755 index d12d6d4c9..000000000 --- a/scripts/test/build-tests.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -PROJECTS=$(loadTestProjectList) - -for project in $PROJECTS -do - #we should use publish to an output path, we will once issue #1183 has been fixed and we can point dotnet test do a dll. - dotnet build "$REPOROOT/test/$project" -done - diff --git a/scripts/test/check-prereqs.ps1 b/scripts/test/check-prereqs.ps1 deleted file mode 100644 index 21a65b988..000000000 --- a/scripts/test/check-prereqs.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -# -# 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. -# - -if (!(Get-Command -ErrorAction SilentlyContinue cmake)) { - throw @" -cmake is required to build the native host 'corehost' -Download it from https://www.cmake.org -"@ -} \ No newline at end of file diff --git a/scripts/test/check-prereqs.sh b/scripts/test/check-prereqs.sh deleted file mode 100755 index 8640ffb03..000000000 --- a/scripts/test/check-prereqs.sh +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -if ! type -p cmake >/dev/null; then - error "cmake is required to build the native host 'corehost'" - error "OS X w/Homebrew: 'brew install cmake'" - error "Ubuntu: 'sudo apt-get install cmake'" - exit 1 -fi diff --git a/scripts/test/package-command-test.ps1 b/scripts/test/package-command-test.ps1 deleted file mode 100644 index 476a171c9..000000000 --- a/scripts/test/package-command-test.ps1 +++ /dev/null @@ -1,34 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -#compile apps -dir "$RepoRoot\test\PackagedCommands\Consumers" | where {$_.PsIsContainer} | where {$_.Name.Contains("Direct")} | -foreach { - pushd "$RepoRoot\test\PackagedCommands\Consumers\$_" - dotnet build - popd -} - -#run test -dir "$RepoRoot\test\PackagedCommands\Consumers" | where {$_.PsIsContainer} | where {$_.Name.Contains("AppWith")} | -foreach { - $testName = "test\PackagedCommands\Consumers\$_" - pushd "$RepoRoot\$testName" - $outputArray = dotnet hello | Out-String - $output = [string]::Join('\n', $outputArray).Trim("`r", "`n") - - if ($output -ne "hello") { - error "Test Failed: $testName\dotnet hello" - error " printed $output" - Exit 1 - } - - info "Test passed: $testName" - popd -} - -Exit 0 diff --git a/scripts/test/package-command-test.sh b/scripts/test/package-command-test.sh deleted file mode 100755 index 6baf6eb59..000000000 --- a/scripts/test/package-command-test.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -#compile tests with direct dependencies -for test in $(ls -l "$REPOROOT/test/PackagedCommands/Consumers" | grep ^d | awk '{print $9}' | grep "Direct") -do - pushd "$REPOROOT/test/PackagedCommands/Consumers/$test" - dotnet build - popd -done - -#run test -for test in $(ls -l "$REPOROOT/test/PackagedCommands/Consumers" | grep ^d | awk '{print $9}' | grep "AppWith") -do - testName="test/PackagedCommands/Consumers/$test" - - pushd "$REPOROOT/$testName" - - output=$(dotnet hello) - - - if [ "$output" == "Hello" ] ; - then - echo "Test Passed: $testName" - else - error "Test Failed: $testName/dotnet hello" - error " printed $output" - exit 1 - fi - - popd -done diff --git a/scripts/test/restore-tests.ps1 b/scripts/test/restore-tests.ps1 deleted file mode 100644 index 48d1dd5e7..000000000 --- a/scripts/test/restore-tests.ps1 +++ /dev/null @@ -1,11 +0,0 @@ -# -# 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. -# - -. $PSScriptRoot\..\common\_common.ps1 - -info "Restoring Test Projects" - -# Restore packages -& dotnet restore "$RepoRoot\test" -f "$TestPackageDir" diff --git a/scripts/test/run-tests.ps1 b/scripts/test/run-tests.ps1 deleted file mode 100644 index 31dcc70cb..000000000 --- a/scripts/test/run-tests.ps1 +++ /dev/null @@ -1,67 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -$TestBinRoot = "$RepoRoot\artifacts\tests" - -$TestProjects = loadTestProjectList -$TestScripts = loadTestScriptList - -$failCount = 0 -$failingTests = @() - -## Temporary Workaround for Native Compilation -## Need x64 Native Tools Dev Prompt Env Vars -## Tracked Here: https://github.com/dotnet/cli/issues/301 -pushd "$env:VS140COMNTOOLS\..\..\VC" -cmd /c "vcvarsall.bat x64&set" | -foreach { - if ($_ -match "=") { - $v = $_.split("=", 2); set-item -force -literalpath "ENV:\$($v[0])" -value "$($v[1])" - } -} -popd - -# copy TestProjects to $TestBinRoot -mkdir -Force "$TestBinRoot\TestProjects" -cp -rec -Force "$RepoRoot\TestAssets\TestProjects\*" "$TestBinRoot\TestProjects" - -# Run each test project -$TestProjects | foreach { - # This is a workaroudn for issue #1184, where dotnet test needs to be executed from the folder containing the project.json. - pushd "$RepoRoot\test\$($_.ProjectName)" - dotnet test -xml "$TestBinRoot\$($_.ProjectName)-testResults.xml" -notrait category=failing - popd - - $exitCode = $LastExitCode - if ($exitCode -ne 0) { - $failingTests += "$($_.ProjectName)" - } - - $failCount += $exitCode -} - -$TestScripts | foreach { - $scriptName = "$($_.ProjectName).ps1" - - & "$RepoRoot\scripts\test\$scriptName" - $exitCode = $LastExitCode - if ($exitCode -ne 0) { - $failingTests += "$scriptName" - $failCount += 1 - } -} - -if ($failCount -ne 0) { - Write-Host -ForegroundColor Red "The following tests failed." - $failingTests | foreach { - Write-Host -ForegroundColor Red "$_.dll failed. Logs in '$TestBinRoot\$_-testResults.xml'" - } -} else { - Write-Host -ForegroundColor Green "All the tests passed!" -} - -Exit $failCount diff --git a/scripts/test/run-tests.sh b/scripts/test/run-tests.sh deleted file mode 100755 index fdf089426..000000000 --- a/scripts/test/run-tests.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -TestProjects=$(loadTestProjectList) -TestScripts=$(loadTestScriptList) - -failedTests=() -failCount=0 - -# Copy TestProjects to $TEST_BIN_ROOT -mkdir -p "$TEST_BIN_ROOT/TestProjects" -cp -a $REPOROOT/TestAssets/TestProjects/* $TEST_BIN_ROOT/TestProjects - -pushd "$TEST_BIN_ROOT" -set +e - -for project in $TestProjects -do - # This is a workaroudn for issue #1184, where dotnet test needs to be executed from the folder containing the project.json. - pushd "$REPOROOT/test/$project" - dotnet test -xml "$TEST_BIN_ROOT/${project}-testResults.xml" -notrait category=failing - popd - - exitCode=$? - failCount+=$exitCode - if [ $exitCode -ne 0 ]; then - failedTests+=("${project}.dll") - fi -done - -popd - -for script in $TestScripts -do - scriptName=${script}.sh - - "$REPOROOT/scripts/test/${scriptName}" - exitCode=$? - if [ $exitCode -ne 0 ]; then - failedTests+=("$scriptName") - failCount+=1 - fi -done - -for test in ${failedTests[@]} -do - error "$test failed. Logs in '$TEST_BIN_ROOT/${test}-testResults.xml'" -done - -set -e - -exit $failCount diff --git a/scripts/test/setup/build-test-prerequisites.sh b/scripts/test/setup/build-test-prerequisites.sh deleted file mode 100755 index 7ce6c6c1f..000000000 --- a/scripts/test/setup/build-test-prerequisites.sh +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../../common/_common.sh" - -buildTestPackages() { - mkdir -p "$TEST_PACKAGE_DIR" - - PROJECTS=$(loadTestPackageList) - - for project in $PROJECTS - do - dotnet pack "$REPOROOT/TestAssets/TestPackages/$project" --output "$TEST_PACKAGE_DIR" - done -} - -buildTestProjects() { - testProjectsRoot="$REPOROOT/TestAssets/TestProjects" - exclusionList=( "$testProjectsRoot/CompileFail/project.json" ) - testProjectsList=( $(find $testProjectsRoot -name "project.json") ) - - for project in "${testProjectsList[@]}" - do - if [[ "${exclusionList[@]}" != "${project}" ]]; then - dotnet build "$project" --framework dnxcore50 - fi - done -} - -buildTestPackages -buildTestProjects diff --git a/scripts/test/setup/restore-test-prerequisites.ps1 b/scripts/test/setup/restore-test-prerequisites.ps1 deleted file mode 100644 index 6bfb8242f..000000000 --- a/scripts/test/setup/restore-test-prerequisites.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -# -# 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. -# - -". $PSScriptRoot\..\..\common\_common.ps1" - -header "Restoring TestAssets" -& dotnet restore "$RepoRoot\TestAssets" --quiet --runtime "$Rid" - -$oldErrorAction=$ErrorActionPreference -$ErrorActionPreference="SilentlyContinue" -& dotnet restore "$RepoRoot\testapp" "$Rid" 2>&1 | Out-Null -$ErrorActionPreference=$oldErrorAction diff --git a/scripts/test/setup/setup-tests.ps1 b/scripts/test/setup/setup-tests.ps1 deleted file mode 100644 index 816c3950c..000000000 --- a/scripts/test/setup/setup-tests.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\..\common\_common.ps1" - -header "Test Setup: Restoring Prerequisites" -_ "$RepoRoot\scripts\test\setup\restore-test-prerequisites.ps1" - -header "Test Setup: Building Prerequisites" -_ "$RepoRoot\scripts\test\setup\build-test-prerequisites.ps1" \ No newline at end of file diff --git a/scripts/test/setup/setup-tests.sh b/scripts/test/setup/setup-tests.sh deleted file mode 100755 index d8ad16d6d..000000000 --- a/scripts/test/setup/setup-tests.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../../common/_common.sh" - -header "Test Setup: Restoring Prerequisites" -"$REPOROOT/scripts/test/setup/restore-test-prerequisites.sh" - -header "Test Setup: Building Prerequisites" -"$REPOROOT/scripts/test/setup/build-test-prerequisites.sh" \ No newline at end of file diff --git a/scripts/test/test.ps1 b/scripts/test/test.ps1 deleted file mode 100644 index d586fb74e..000000000 --- a/scripts/test/test.ps1 +++ /dev/null @@ -1,18 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -header "Setting up Tests" -_ "$RepoRoot\scripts\test\setup\setup-tests.ps1" - -header "Restoring test projects" -_ "$RepoRoot\scripts\test\restore-tests.ps1" - -header "Building test projects" -_ "$RepoRoot\scripts\test\build-tests.ps1" - -header "Running Tests" -_ "$RepoRoot\scripts\test\run-tests.ps1" \ No newline at end of file diff --git a/scripts/test/test.sh b/scripts/test/test.sh deleted file mode 100755 index f05fe115a..000000000 --- a/scripts/test/test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done - -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -source "$DIR/../common/_common.sh" - -header "Setting up Tests" -"$REPOROOT/scripts/test/setup/setup-tests.sh" - -header "Restoring test projects" -"$REPOROOT/scripts/test/restore-tests.sh" - -header "Building test projects" -"$REPOROOT/scripts/test/build-tests.sh" - -header "Running Tests" -"$REPOROOT/scripts/test/run-tests.sh" \ No newline at end of file diff --git a/scripts/test/validate-dependencies.ps1 b/scripts/test/validate-dependencies.ps1 deleted file mode 100644 index e47e55c1a..000000000 --- a/scripts/test/validate-dependencies.ps1 +++ /dev/null @@ -1,21 +0,0 @@ -# -# 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. -# - -. "$PSScriptRoot\..\common\_common.ps1" - -# Run Validation for Project.json dependencies -dotnet publish $RepoRoot\tools\MultiProjectValidator -o $Stage2Dir\..\tools -c "$Configuration" - -$pjvalidatePath = "$Stage2Dir\..\tools\$Configuration\$Tfm" -if (! (Test-Path $pjvalidatePath)) { - $pjvalidatePath = "$Stage2Dir\..\tools" -} - -& "$pjvalidatePath\pjvalidate" "$RepoRoot\src" -# TODO For release builds, this should be uncommented and fail. -# if (!$?) { -# Write-Host "Project Validation Failed" -# Exit 1 -# } \ No newline at end of file diff --git a/scripts/test/validate-dependencies.sh b/scripts/test/validate-dependencies.sh deleted file mode 100755 index a9e476097..000000000 --- a/scripts/test/validate-dependencies.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash -# -# 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. -# - -set -e - -SOURCE="${BASH_SOURCE[0]}" -while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink - DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - SOURCE="$(readlink "$SOURCE")" - [[ "$SOURCE" != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located -done -DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" - -. "$DIR/../common/_common.sh" - -# Run Validation for Project.json dependencies -dotnet publish "$REPOROOT/tools/MultiProjectValidator" -o "$STAGE2_DIR/../tools" -c "$CONFIGURATION" -#TODO for release builds this should fail -set +e -PJ_VALIDATE_PATH="$STAGE2_DIR/../tools/$CONFIGURATION/$TFM" -if [ ! -d "$PJ_VALIDATE_PATH" ] -then - PJ_VALIDATE_PATH="$STAGE2_DIR/../tools" -fi - -"$PJ_VALIDATE_PATH/pjvalidate" "$REPOROOT/src" -set -e diff --git a/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs b/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs index 30835d159..4a5d0f4fe 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ArgumentEscaper.cs @@ -86,8 +86,10 @@ namespace Microsoft.DotNet.Cli.Utils { var sb = new StringBuilder(); - var quoted = ShouldSurroundWithQuotes(arg); - if (quoted) sb.Append("\""); + var needsQuotes = ShouldSurroundWithQuotes(arg); + var isQuoted = needsQuotes || IsSurroundedWithQuotes(arg); + + if (needsQuotes) sb.Append("\""); for (int i = 0; i < arg.Length; ++i) { @@ -101,13 +103,21 @@ namespace Microsoft.DotNet.Cli.Utils } // Escape any backslashes at the end of the arg + // when the argument is also quoted. // This ensures the outside quote is interpreted as // an argument delimiter - if (i == arg.Length) + if (i == arg.Length && isQuoted) { sb.Append('\\', 2 * backslashCount); } + // At then end of the arg, which isn't quoted, + // just add the backslashes, no need to escape + else if (i == arg.Length) + { + sb.Append('\\', backslashCount); + } + // Escape any preceding backslashes and the quote else if (arg[i] == '"') { @@ -123,7 +133,7 @@ namespace Microsoft.DotNet.Cli.Utils } } - if (quoted) sb.Append("\""); + if (needsQuotes) sb.Append("\""); return sb.ToString(); } @@ -149,22 +159,14 @@ namespace Microsoft.DotNet.Cli.Utils if (quoted) sb.Append("^\""); + // Prepend every character with ^ + // This is harmless when passing through cmd + // and ensures cmd metacharacters are not interpreted + // as such foreach (var character in argument) { - - if (character == '"') - { - - sb.Append('^'); - sb.Append('"'); - sb.Append('^'); - sb.Append(character); - } - else - { - sb.Append("^"); - sb.Append(character); - } + sb.Append("^"); + sb.Append(character); } if (quoted) sb.Append("^\""); @@ -172,35 +174,27 @@ namespace Microsoft.DotNet.Cli.Utils return sb.ToString(); } - /// - /// Prepare as single argument to - /// roundtrip properly through cmd. - /// - /// This prefixes every character with the '^' character to force cmd to - /// interpret the argument string literally. An alternative option would - /// be to do this only for cmd metacharacters. - /// - /// See here for more info: - /// http://blogs.msdn.com/b/twistylittlepassagesallalike/archive/2011/04/23/everyone-quotes-arguments-the-wrong-way.aspx - /// - /// - /// internal static bool ShouldSurroundWithQuotes(string argument) { // Don't quote already quoted strings - if (argument.StartsWith("\"", StringComparison.Ordinal) && - argument.EndsWith("\"", StringComparison.Ordinal)) + if (IsSurroundedWithQuotes(argument)) { return false; } // Only quote if whitespace exists in the string - if (argument.Contains(" ") || argument.Contains("\t") || argument.Contains("\n")) - { - return true; - } + return ArgumentContainsWhitespace(argument); + } - return true; + internal static bool IsSurroundedWithQuotes(string argument) + { + return argument.StartsWith("\"", StringComparison.Ordinal) && + argument.EndsWith("\"", StringComparison.Ordinal); + } + + internal static bool ArgumentContainsWhitespace(string argument) + { + return argument.Contains(" ") || argument.Contains("\t") || argument.Contains("\n"); } } } diff --git a/src/Microsoft.DotNet.Cli.Utils/Command.cs b/src/Microsoft.DotNet.Cli.Utils/Command.cs index 6118deaa1..1480c2c7f 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Command.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Command.cs @@ -8,10 +8,11 @@ using System.IO; using System.Linq; using System.Runtime.CompilerServices; using NuGet.Frameworks; +using Microsoft.DotNet.ProjectModel; namespace Microsoft.DotNet.Cli.Utils { - public class Command + public class Command : ICommand { private readonly Process _process; private readonly StreamForwarder _stdOut; @@ -31,7 +32,7 @@ namespace Microsoft.DotNet.Cli.Utils _stdOut = new StreamForwarder(); _stdErr = new StreamForwarder(); - + _process = new Process { StartInfo = psi @@ -40,9 +41,9 @@ namespace Microsoft.DotNet.Cli.Utils ResolutionStrategy = commandSpec.ResolutionStrategy; } - public static Command CreateDotNet(string commandName, IEnumerable args, NuGetFramework framework = null, bool useComSpec = false) + public static Command CreateDotNet(string commandName, IEnumerable args, NuGetFramework framework = null) { - return Create("dotnet", new[] { commandName }.Concat(args), framework, useComSpec); + return Create("dotnet", new[] { commandName }.Concat(args), framework); } /// @@ -55,9 +56,9 @@ namespace Microsoft.DotNet.Cli.Utils /// /// /// - public static Command Create(string commandName, IEnumerable args, NuGetFramework framework = null, bool useComSpec = false) + public static Command Create(string commandName, IEnumerable args, NuGetFramework framework = null) { - var commandSpec = CommandResolver.TryResolveCommandSpec(commandName, args, framework, useComSpec); + var commandSpec = CommandResolver.TryResolveCommandSpec(commandName, args, framework); if (commandSpec == null) { @@ -69,6 +70,20 @@ namespace Microsoft.DotNet.Cli.Utils return command; } + public static Command CreateForScript(string commandName, IEnumerable args, Project project, string[] inferredExtensionList) + { + var commandSpec = CommandResolver.TryResolveScriptCommandSpec(commandName, args, project, inferredExtensionList); + + if (commandSpec == null) + { + throw new CommandUnknownException(commandName); + } + + var command = new Command(commandSpec); + + return command; + } + public CommandResult Execute() { @@ -115,33 +130,37 @@ 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) { +#if NET451 + _process.StartInfo.EnvironmentVariables[name] = value; +#else _process.StartInfo.Environment[name] = value; +#endif 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 +177,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 +194,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); @@ -193,6 +212,8 @@ namespace Microsoft.DotNet.Cli.Utils public string CommandName => _process.StartInfo.FileName; + public string CommandArgs => _process.StartInfo.Arguments; + private string FormatProcessInfo(ProcessStartInfo info) { if (string.IsNullOrWhiteSpace(info.Arguments)) diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs index aecec2211..83589d989 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolutionStrategy.cs @@ -8,6 +8,9 @@ //command loaded from the same directory as the executing assembly BaseDirectory, + //command loaded from the same directory as a project.json file + ProjectLocal, + //command loaded from path Path, diff --git a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs index d4b3ec243..f62486969 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CommandResolver.cs @@ -1,64 +1,72 @@ using System; using System.Collections.Generic; using System.IO; -using NuGet.Frameworks; using System.Linq; using System.Runtime.InteropServices; using Microsoft.DotNet.ProjectModel; using Microsoft.DotNet.ProjectModel.Graph; using Microsoft.Extensions.PlatformAbstractions; +using NuGet.Frameworks; using NuGet.Packaging; namespace Microsoft.DotNet.Cli.Utils { internal static class CommandResolver { - public static CommandSpec TryResolveCommandSpec(string commandName, IEnumerable args, NuGetFramework framework = null, bool useComSpec = false) + public static CommandSpec TryResolveCommandSpec(string commandName, IEnumerable args, NuGetFramework framework = null) { - return ResolveFromRootedCommand(commandName, args, useComSpec) ?? - ResolveFromProjectDependencies(commandName, args, framework, useComSpec) ?? - ResolveFromProjectTools(commandName, args, useComSpec) ?? - ResolveFromAppBase(commandName, args, useComSpec) ?? - ResolveFromPath(commandName, args, useComSpec); + return ResolveFromRootedCommand(commandName, args) ?? + ResolveFromProjectDependencies(commandName, args, framework) ?? + ResolveFromProjectTools(commandName, args) ?? + ResolveFromAppBase(commandName, args) ?? + ResolveFromPath(commandName, args); + } + + public static CommandSpec TryResolveScriptCommandSpec(string commandName, IEnumerable args, Project project, string[] inferredExtensionList) + { + return ResolveFromRootedCommand(commandName, args) ?? + ResolveFromProjectPath(commandName, args, project, inferredExtensionList) ?? + ResolveFromAppBase(commandName, args) ?? + ResolveFromPath(commandName, args); } - private static CommandSpec ResolveFromPath(string commandName, IEnumerable args, bool useComSpec = false) + private static CommandSpec ResolveFromPath(string commandName, IEnumerable args) { var commandPath = Env.GetCommandPath(commandName); return commandPath == null ? null - : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.Path, useComSpec); + : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.Path); } - private static CommandSpec ResolveFromAppBase(string commandName, IEnumerable args, bool useComSpec = false) + private static CommandSpec ResolveFromAppBase(string commandName, IEnumerable args) { - var commandPath = Env.GetCommandPathFromAppBase(AppContext.BaseDirectory, commandName); + var commandPath = Env.GetCommandPathFromRootPath(PlatformServices.Default.Application.ApplicationBasePath, commandName); return commandPath == null ? null - : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.BaseDirectory, useComSpec); + : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.BaseDirectory); + } + + private static CommandSpec ResolveFromProjectPath(string commandName, IEnumerable args, Project project, string[] inferredExtensionList) + { + var commandPath = Env.GetCommandPathFromRootPath(project.ProjectDirectory, commandName, inferredExtensionList); + return commandPath == null + ? null + : CreateCommandSpecPreferringExe(commandName, args, commandPath, CommandResolutionStrategy.ProjectLocal); } - private static CommandSpec ResolveFromRootedCommand(string commandName, IEnumerable args, bool useComSpec = false) + private static CommandSpec ResolveFromRootedCommand(string commandName, IEnumerable args) { if (Path.IsPathRooted(commandName)) { - if (useComSpec) - { - return CreateComSpecCommandSpec(commandName, args, CommandResolutionStrategy.Path); - } - else - { - var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); - return new CommandSpec(commandName, escapedArgs, CommandResolutionStrategy.Path); - } - + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); + return new CommandSpec(commandName, escapedArgs, CommandResolutionStrategy.Path); } return null; } public static CommandSpec ResolveFromProjectDependencies(string commandName, IEnumerable args, - NuGetFramework framework, bool useComSpec = false) + NuGetFramework framework) { if (framework == null) return null; @@ -72,7 +80,7 @@ namespace Microsoft.DotNet.Cli.Utils var depsPath = projectContext.GetOutputPaths(Constants.DefaultConfiguration).RuntimeFiles.Deps; - return ConfigureCommandFromPackage(commandName, args, commandPackage, projectContext, depsPath, useComSpec); + return ConfigureCommandFromPackage(commandName, args, commandPackage, projectContext, depsPath); } private static ProjectContext GetProjectContext(NuGetFramework framework) @@ -101,7 +109,7 @@ namespace Microsoft.DotNet.Cli.Utils e == FileNameSuffixes.DotNet.DynamicLib)); } - public static CommandSpec ResolveFromProjectTools(string commandName, IEnumerable args, bool useComSpec = false) + public static CommandSpec ResolveFromProjectTools(string commandName, IEnumerable args) { var context = GetProjectContext(FrameworkConstants.CommonFrameworks.DnxCore50); @@ -147,7 +155,7 @@ namespace Microsoft.DotNet.Cli.Utils } private static CommandSpec ConfigureCommandFromPackage(string commandName, IEnumerable args, - PackageDescription commandPackage, ProjectContext projectContext, string depsPath = null, bool useComSpec = false) + PackageDescription commandPackage, ProjectContext projectContext, string depsPath = null) { var files = commandPackage.Library.Files; @@ -157,11 +165,11 @@ namespace Microsoft.DotNet.Cli.Utils var packageDir = Path.Combine(packageRoot, packagePath); - return ConfigureCommandFromPackage(commandName, args, files, packageDir, depsPath, useComSpec); + return ConfigureCommandFromPackage(commandName, args, files, packageDir, depsPath); } private static CommandSpec ConfigureCommandFromPackage(string commandName, IEnumerable args, - IEnumerable files, string packageDir, string depsPath = null, bool useComSpec = false) + IEnumerable files, string packageDir, string depsPath = null) { var fileName = string.Empty; @@ -192,25 +200,19 @@ namespace Microsoft.DotNet.Cli.Utils fileName = Path.Combine(packageDir, commandPath); } - if (useComSpec) - { - return CreateComSpecCommandSpec(fileName, args, CommandResolutionStrategy.NugetPackage); - } - else - { - var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); - return new CommandSpec(fileName, escapedArgs, CommandResolutionStrategy.NugetPackage); - } + var escapedArgs = ArgumentEscaper.EscapeAndConcatenateArgArrayForProcessStart(args); + return new CommandSpec(fileName, escapedArgs, CommandResolutionStrategy.NugetPackage); } private static CommandSpec CreateCommandSpecPreferringExe( string commandName, IEnumerable args, string commandPath, - CommandResolutionStrategy resolutionStrategy, - bool useComSpec = false) + CommandResolutionStrategy resolutionStrategy) { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + var useComSpec = false; + + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows && Path.GetExtension(commandPath).Equals(".cmd", StringComparison.OrdinalIgnoreCase)) { var preferredCommandPath = Env.GetCommandPath(commandName, ".exe"); @@ -228,7 +230,7 @@ namespace Microsoft.DotNet.Cli.Utils if (useComSpec) { - return CreateComSpecCommandSpec(commandPath, args, resolutionStrategy); + return CreateCmdCommandSpec(commandPath, args, resolutionStrategy); } else { @@ -237,14 +239,14 @@ namespace Microsoft.DotNet.Cli.Utils } } - private static CommandSpec CreateComSpecCommandSpec( + private static CommandSpec CreateCmdCommandSpec( string command, IEnumerable args, CommandResolutionStrategy resolutionStrategy) { - // To prevent Command Not Found, comspec gets passed in as - // the command already in some cases var comSpec = Environment.GetEnvironmentVariable("ComSpec"); + + // Handle the case where ComSpec is already the command if (command.Equals(comSpec, StringComparison.OrdinalIgnoreCase)) { command = args.FirstOrDefault(); diff --git a/src/Microsoft.DotNet.Cli.Utils/Constants.cs b/src/Microsoft.DotNet.Cli.Utils/Constants.cs index 943fdb7c4..2a58ba8b6 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Constants.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Constants.cs @@ -1,17 +1,19 @@ // 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.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Cli.Utils { public static class Constants { + private static Platform CurrentPlatform => PlatformServices.Default.Runtime.OperatingSystemPlatform; + public static readonly string ProjectFileName = "project.json"; - public static readonly string ExeSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".exe" : string.Empty; + public static readonly string ExeSuffix = CurrentPlatform == Platform.Windows ? ".exe" : string.Empty; // Priority order of runnable suffixes to look for and run - public static readonly string[] RunnableSuffixes = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + public static readonly string[] RunnableSuffixes = CurrentPlatform == Platform.Windows ? new string[] { ".exe", ".cmd", ".bat" } : new string[] { string.Empty }; @@ -19,22 +21,23 @@ namespace Microsoft.DotNet.Cli.Utils public static readonly string BinDirectoryName = "bin"; public static readonly string ObjDirectoryName = "obj"; - public static readonly string DynamicLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".dll" : - RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? ".dylib" : ".so"; + public static readonly string DynamicLibSuffix = CurrentPlatform == Platform.Windows ? ".dll" : + CurrentPlatform == Platform.Darwin ? ".dylib" : ".so"; - public static readonly string LibCoreClrName = (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "coreclr" : "libcoreclr") + DynamicLibSuffix; + public static readonly string LibCoreClrName = (CurrentPlatform == Platform.Windows ? "coreclr" : "libcoreclr") + DynamicLibSuffix; - public static readonly string RuntimeIdentifier = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win7-x64" : - RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx.10.10-x64" : "ubuntu.14.04-x64"; + public static readonly string RuntimeIdentifier = CurrentPlatform == Platform.Windows ? "win7-x64" : + CurrentPlatform == Platform.Darwin ? "osx.10.10-x64" : "ubuntu.14.04-x64"; - public static readonly string StaticLibSuffix = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ".lib" : ".a" ; + public static readonly string StaticLibSuffix = CurrentPlatform == Platform.Windows ? ".lib" : ".a"; public static readonly string ResponseFileSuffix = ".rsp"; public static readonly string HostExecutableName = "corehost" + ExeSuffix; public static readonly string[] HostBinaryNames = new string[] { HostExecutableName, - (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "hostpolicy" : "libhostpolicy") + DynamicLibSuffix + (CurrentPlatform == Platform.Windows ? "hostpolicy" : "libhostpolicy") + DynamicLibSuffix }; + } } diff --git a/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs b/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs index 0ab2d2c6f..7775800ec 100644 --- a/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs +++ b/src/Microsoft.DotNet.Cli.Utils/CoreHost.cs @@ -1,6 +1,5 @@ -using System; using System.IO; -using Microsoft.DotNet.ProjectModel; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Cli.Utils { @@ -12,7 +11,7 @@ namespace Microsoft.DotNet.Cli.Utils /// /// Gets the path to the version of corehost that was shipped with this command /// - public static string LocalHostExePath => Path.Combine(AppContext.BaseDirectory, Constants.HostExecutableName); + public static string LocalHostExePath => Path.Combine(PlatformServices.Default.Application.ApplicationBasePath, Constants.HostExecutableName); public static string HostExePath { @@ -33,7 +32,7 @@ namespace Microsoft.DotNet.Cli.Utils if (_hostDir == null) { _hostDir = Path.GetDirectoryName(Env.GetCommandPath( - Constants.HostExecutableName, new[] {string.Empty})); + Constants.HostExecutableName, new[] { string.Empty })); } return _hostDir; diff --git a/src/Microsoft.DotNet.Cli.Utils/DotNetCommandFactory.cs b/src/Microsoft.DotNet.Cli.Utils/DotNetCommandFactory.cs new file mode 100644 index 000000000..4f8f01935 --- /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) + { + return Command.CreateDotNet(commandName, args, framework); + } + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/Env.cs b/src/Microsoft.DotNet.Cli.Utils/Env.cs index fcd47711c..6fdac60f1 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Env.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Env.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Cli.Utils { @@ -18,7 +19,7 @@ namespace Microsoft.DotNet.Cli.Utils if (_executableExtensions == null) { - _executableExtensions = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + _executableExtensions = PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows ? Environment.GetEnvironmentVariable("PATHEXT") .Split(';') .Select(e => e.ToLower().Trim('"')) @@ -35,7 +36,7 @@ namespace Microsoft.DotNet.Cli.Utils { if (_searchPaths == null) { - var searchPaths = new List {AppContext.BaseDirectory}; + var searchPaths = new List { PlatformServices.Default.Application.ApplicationBasePath }; searchPaths.AddRange(Environment .GetEnvironmentVariable("PATH") @@ -65,14 +66,14 @@ namespace Microsoft.DotNet.Cli.Utils return commandPath; } - public static string GetCommandPathFromAppBase(string appBase, string commandName, params string[] extensions) + public static string GetCommandPathFromRootPath(string rootPath, string commandName, params string[] extensions) { if (!extensions.Any()) { extensions = Env.ExecutableExtensions.ToArray(); } - var commandPath = extensions.Select(e => Path.Combine(appBase, commandName + e)) + var commandPath = extensions.Select(e => Path.Combine(rootPath, commandName + e)) .FirstOrDefault(File.Exists); return commandPath; diff --git a/src/Microsoft.DotNet.Cli.Utils/ICommand.cs b/src/Microsoft.DotNet.Cli.Utils/ICommand.cs new file mode 100644 index 000000000..1b7cde7b6 --- /dev/null +++ b/src/Microsoft.DotNet.Cli.Utils/ICommand.cs @@ -0,0 +1,35 @@ +// 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; } + + string CommandArgs { 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..8fcda8c53 --- /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); + } +} diff --git a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs index d2fe50f2a..691c4f560 100644 --- a/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs +++ b/src/Microsoft.DotNet.Cli.Utils/PathUtility.cs @@ -3,7 +3,7 @@ using System; using System.IO; -using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Tools.Common { @@ -98,7 +98,7 @@ namespace Microsoft.DotNet.Tools.Common } StringComparison compare; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) { compare = StringComparison.OrdinalIgnoreCase; // check if paths are on the same volume @@ -154,7 +154,7 @@ namespace Microsoft.DotNet.Tools.Common path += ".." + separator; } } - + for (var i = index; len2 - 1 > i; ++i) { path += path2Segments[i] + separator; @@ -216,7 +216,7 @@ namespace Microsoft.DotNet.Tools.Common { var comparison = StringComparison.Ordinal; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) { comparison = StringComparison.OrdinalIgnoreCase; } diff --git a/src/Microsoft.DotNet.Cli.Utils/Reporter.cs b/src/Microsoft.DotNet.Cli.Utils/Reporter.cs index e60ac3c50..c27314fc5 100644 --- a/src/Microsoft.DotNet.Cli.Utils/Reporter.cs +++ b/src/Microsoft.DotNet.Cli.Utils/Reporter.cs @@ -2,7 +2,7 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.Cli.Utils { @@ -25,7 +25,7 @@ namespace Microsoft.DotNet.Cli.Utils public static Reporter Create(Func getter) { - return new Reporter(getter(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))); + return new Reporter(getter(PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows)); } public void WriteLine(string message) diff --git a/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs b/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs index 59ef038f9..8f8f91b73 100644 --- a/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs +++ b/src/Microsoft.DotNet.Cli.Utils/ScriptExecutor.cs @@ -2,97 +2,62 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using Microsoft.DotNet.Cli.Utils.CommandParsing; using Microsoft.DotNet.ProjectModel; +using Microsoft.Extensions.PlatformAbstractions; 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) + { + var scriptArguments = ParseScriptArguments(project, scriptCommandLine, getVariable); + if (scriptArguments == null) + { + throw new Exception($"ScriptExecutor: failed to parse script \"{scriptCommandLine}\""); + } + + var inferredExtensions = DetermineInferredScriptExtensions(); + + return Command + .CreateForScript(scriptArguments.First(), scriptArguments.Skip(1), project, inferredExtensions) + .WorkingDirectory(project.ProjectDirectory); + } + + private static IEnumerable ParseScriptArguments(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. var scriptArguments = CommandGrammar.Process( scriptCommandLine, GetScriptVariable(project, getVariable), - preserveSurroundingQuotes: true); + preserveSurroundingQuotes: false); - // Ensure the array won't be empty and the elements won't be null or empty strings. scriptArguments = scriptArguments.Where(argument => !string.IsNullOrEmpty(argument)).ToArray(); if (scriptArguments.Length == 0) { return null; } - var useComSpec = false; + return scriptArguments; + } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + private static string[] DetermineInferredScriptExtensions() + { + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) { - // Only forward slashes are used in script blocks. Replace with backslashes to correctly - // locate the script. The directory separator is platform-specific. - scriptArguments[0] = scriptArguments[0].Replace( - Path.AltDirectorySeparatorChar, - Path.DirectorySeparatorChar); - - // Command-lines on Windows are executed via "cmd /S /C" in order to support batch files, &&, - // built-in commands like echo, et cetera. /S allows quoting the command as well as the arguments. - // ComSpec is Windows-specific, and contains the full path to cmd.exe - var comSpec = Environment.GetEnvironmentVariable("ComSpec"); - if (!string.IsNullOrEmpty(comSpec)) - { - useComSpec=true; - - scriptArguments = new string[] { comSpec } - .Concat(scriptArguments) - .ToArray(); - } + return new string[] { "", ".cmd" }; } else { - // Special-case a script name that, perhaps with added .sh, matches an existing file. - var surroundWithQuotes = false; - var scriptCandidate = scriptArguments[0]; - if (scriptCandidate.StartsWith("\"", StringComparison.Ordinal) && - scriptCandidate.EndsWith("\"", StringComparison.Ordinal)) - { - // Strip surrounding quotes; they were required in project.json to keep the script name - // together but confuse File.Exists() e.g. "My Script", lacking ./ prefix and .sh suffix. - surroundWithQuotes = true; - scriptCandidate = scriptCandidate.Substring(1, scriptCandidate.Length - 2); - } - - if (!scriptCandidate.EndsWith(".sh", StringComparison.Ordinal)) - { - scriptCandidate = scriptCandidate + ".sh"; - } - - if (File.Exists(Path.Combine(project.ProjectDirectory, scriptCandidate))) - { - // scriptCandidate may be a path relative to the project root. If so, likely will not be found - // in the $PATH; add ./ to let bash know where to look. - var prefix = Path.IsPathRooted(scriptCandidate) ? string.Empty : "./"; - var quote = surroundWithQuotes ? "\"" : string.Empty; - scriptArguments[0] = $"{ quote }{ prefix }{ scriptCandidate }{ quote }"; - } - - // Always use /usr/bin/env bash -c in order to support redirection and so on; similar to Windows case. - // Unlike Windows, must escape quotation marks within the newly-quoted string. - scriptArguments = new[] { "/usr/bin/env", "bash", "-c", "\"" } - .Concat(scriptArguments.Select(argument => argument.Replace("\"", "\\\""))) - .Concat(new[] { "\"" }) - .ToArray(); + return new string[] { "", ".sh" }; } - - return Command.Create(scriptArguments.FirstOrDefault(), scriptArguments.Skip(1), useComSpec: useComSpec) - .WorkingDirectory(project.ProjectDirectory); } + private static Func WrapVariableDictionary(IDictionary contextVariables) { return key => diff --git a/src/Microsoft.DotNet.Cli.Utils/StreamForwarder.cs b/src/Microsoft.DotNet.Cli.Utils/StreamForwarder.cs index 0a4c70518..a2cbc32af 100644 --- a/src/Microsoft.DotNet.Cli.Utils/StreamForwarder.cs +++ b/src/Microsoft.DotNet.Cli.Utils/StreamForwarder.cs @@ -13,7 +13,6 @@ namespace Microsoft.DotNet.Cli.Utils private StringBuilder _builder; private StringWriter _capture; - private Action _write; private Action _writeLine; public string CapturedOutput @@ -130,4 +129,4 @@ namespace Microsoft.DotNet.Cli.Utils } } } -} \ No newline at end of file +} diff --git a/src/Microsoft.DotNet.Cli.Utils/project.json b/src/Microsoft.DotNet.Cli.Utils/project.json index ec5a4c08c..279e70226 100644 --- a/src/Microsoft.DotNet.Cli.Utils/project.json +++ b/src/Microsoft.DotNet.Cli.Utils/project.json @@ -2,20 +2,24 @@ "version": "1.0.0-*", "compilationOptions": { - "keyFile": "../../tools/Key.snk" + "keyFile": "../../tools/Key.snk", + "warningsAsErrors": true }, "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "System.Reflection.Metadata": "1.2.0-rc2-23811", "Microsoft.Extensions.PlatformAbstractions": "1.0.0-rc2-16537" }, "frameworks": { + "net451": { }, "dnxcore50": { - "imports": "portable-net45+win8" + "imports": "portable-net45+win8", + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811" } + } }, "scripts": { diff --git a/src/Microsoft.DotNet.Compiler.Common/project.json b/src/Microsoft.DotNet.Compiler.Common/project.json index 207ea5d19..25dd9fc6d 100644 --- a/src/Microsoft.DotNet.Compiler.Common/project.json +++ b/src/Microsoft.DotNet.Compiler.Common/project.json @@ -7,8 +7,9 @@ "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", + "System.Reflection.Metadata": "1.2.0-rc3-23811", "System.CommandLine": "0.1.0-e160119-1", - "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160108-01", + "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160202-02", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Cli.Utils": "1.0.0-*", "Microsoft.DotNet.Files": {"version": "1.0.0-*", "target": "project"} diff --git a/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json b/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json index 5d60662e8..36e401df5 100644 --- a/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json +++ b/src/Microsoft.DotNet.ProjectModel.Workspaces/project.json @@ -5,9 +5,10 @@ }, "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", + "System.Reflection.Metadata": "1.2.0-rc3-23811", "Microsoft.DotNet.ProjectModel": "1.0.0-*", "Microsoft.DotNet.Compiler.Common": "1.0.0-*", - "Microsoft.CodeAnalysis.CSharp.Workspaces": "1.2.0-beta1-20160108-01" + "Microsoft.CodeAnalysis.CSharp.Workspaces": "1.2.0-beta1-20160202-02" }, "frameworks": { "dnxcore50": { diff --git a/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs b/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs index c7d79b607..3e4e6216e 100644 --- a/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs +++ b/src/Microsoft.DotNet.ProjectModel/CommonCompilerOptions.cs @@ -58,7 +58,7 @@ namespace Microsoft.DotNet.ProjectModel } private static bool EnumerableEquals(IEnumerable left, IEnumerable right) - => Enumerable.SequenceEqual(left ?? Array.Empty(), right ?? Array.Empty()); + => Enumerable.SequenceEqual(left ?? EmptyArray.Value, right ?? EmptyArray.Value); public override int GetHashCode() { @@ -69,7 +69,7 @@ namespace Microsoft.DotNet.ProjectModel { if (@new != null) { - old = old ?? Array.Empty(); + old = old ?? EmptyArray.Value; return old.Concat(@new).Distinct().ToArray(); } return old; diff --git a/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs b/src/Microsoft.DotNet.ProjectModel/Compilation/LibraryExporter.cs index 91469b7d9..333812b92 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) @@ -162,7 +162,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation var analyzers = GetAnalyzerReferences(package); return new LibraryExport(package, compileAssemblies, - sourceReferences, runtimeAssemblies, Array.Empty(), nativeLibraries, analyzers); + sourceReferences, runtimeAssemblies, EmptyArray.Value, nativeLibraries, analyzers); } private LibraryExport ExportProject(ProjectDescription project) @@ -175,8 +175,8 @@ namespace Microsoft.DotNet.ProjectModel.Compilation sourceReferences: Enumerable.Empty(), nativeLibraries: Enumerable.Empty(), runtimeAssets: Enumerable.Empty(), - runtimeAssemblies: Array.Empty(), - analyzers: Array.Empty()); + runtimeAssemblies: EmptyArray.Value, + analyzers: EmptyArray.Value); } var compileAssemblies = new List(); @@ -226,7 +226,7 @@ namespace Microsoft.DotNet.ProjectModel.Compilation // just the same as compileAssemblies and nativeLibraries are empty // Also no support for analyzer projects return new LibraryExport(project, compileAssemblies, sourceReferences, - compileAssemblies, runtimeAssets, Array.Empty(), Array.Empty()); + compileAssemblies, runtimeAssets, EmptyArray.Value, EmptyArray.Value); } private static string ResolvePath(Project project, string configuration, string path) @@ -250,13 +250,13 @@ namespace Microsoft.DotNet.ProjectModel.Compilation return new LibraryExport( library, string.IsNullOrEmpty(library.Path) ? - Array.Empty() : + EmptyArray.Value : new[] { new LibraryAsset(library.Identity.Name, library.Path, library.Path) }, - Array.Empty(), - Array.Empty(), - Array.Empty(), - Array.Empty(), - Array.Empty()); + EmptyArray.Value, + EmptyArray.Value, + EmptyArray.Value, + EmptyArray.Value, + EmptyArray.Value); } private IEnumerable GetSharedSources(PackageDescription package) diff --git a/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs b/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs index c1015240f..c09f5bf07 100644 --- a/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs +++ b/src/Microsoft.DotNet.ProjectModel/FileNameSuffixes.cs @@ -1,5 +1,5 @@ using System; -using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.ProjectModel { @@ -11,11 +11,17 @@ namespace Microsoft.DotNet.ProjectModel { get { - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return Windows; } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return Linux; } - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { return OSX; } - - throw new InvalidOperationException("Unknown Platform"); + switch (PlatformServices.Default.Runtime.OperatingSystemPlatform) + { + case Platform.Windows: + return Windows; + case Platform.Darwin: + return OSX; + case Platform.Linux: + return Linux; + default: + throw new InvalidOperationException("Unknown Platform"); + } } } diff --git a/src/Microsoft.DotNet.ProjectModel/Internal/EmptyArray.cs b/src/Microsoft.DotNet.ProjectModel/Internal/EmptyArray.cs new file mode 100644 index 000000000..d55b1456b --- /dev/null +++ b/src/Microsoft.DotNet.ProjectModel/Internal/EmptyArray.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. + +namespace Microsoft.DotNet.ProjectModel +{ + internal static class EmptyArray + { +#if NET451 + public static readonly T[] Value = new T[0]; +#else + public static readonly T[] Value = System.Array.Empty(); +#endif + } +} diff --git a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs index 5ebbbeb4a..744023c1a 100644 --- a/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs +++ b/src/Microsoft.DotNet.ProjectModel/ProjectReader.cs @@ -144,9 +144,9 @@ namespace Microsoft.DotNet.ProjectModel project.CompilerName = rawProject.ValueAsString("compilerName"); project.TestRunner = rawProject.ValueAsString("testRunner"); - project.Authors = rawProject.ValueAsStringArray("authors") ?? Array.Empty(); - project.Owners = rawProject.ValueAsStringArray("owners") ?? Array.Empty(); - project.Tags = rawProject.ValueAsStringArray("tags") ?? Array.Empty(); + project.Authors = rawProject.ValueAsStringArray("authors") ?? EmptyArray.Value; + project.Owners = rawProject.ValueAsStringArray("owners") ?? EmptyArray.Value; + project.Tags = rawProject.ValueAsStringArray("tags") ?? EmptyArray.Value; project.Language = rawProject.ValueAsString("language"); project.ReleaseNotes = rawProject.ValueAsString("releaseNotes"); diff --git a/src/Microsoft.DotNet.ProjectModel/Resolution/FrameworkReferenceResolver.cs b/src/Microsoft.DotNet.ProjectModel/Resolution/FrameworkReferenceResolver.cs index f63462629..17458d0eb 100644 --- a/src/Microsoft.DotNet.ProjectModel/Resolution/FrameworkReferenceResolver.cs +++ b/src/Microsoft.DotNet.ProjectModel/Resolution/FrameworkReferenceResolver.cs @@ -5,10 +5,10 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Xml.Linq; using Microsoft.DotNet.ProjectModel.Utilities; +using Microsoft.Extensions.PlatformAbstractions; using NuGet.Frameworks; namespace Microsoft.DotNet.ProjectModel.Resolution @@ -60,7 +60,7 @@ namespace Microsoft.DotNet.ProjectModel.Resolution return referenceAssembliesPath; } - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform != Platform.Windows) { // There is no reference assemblies path outside of windows // The environment variable can be used to specify one diff --git a/src/Microsoft.DotNet.ProjectModel/Utilities/PathUtility.cs b/src/Microsoft.DotNet.ProjectModel/Utilities/PathUtility.cs index 6185a7313..2381ea32b 100644 --- a/src/Microsoft.DotNet.ProjectModel/Utilities/PathUtility.cs +++ b/src/Microsoft.DotNet.ProjectModel/Utilities/PathUtility.cs @@ -3,7 +3,7 @@ using System; using System.IO; -using System.Runtime.InteropServices; +using Microsoft.Extensions.PlatformAbstractions; namespace Microsoft.DotNet.ProjectModel.Utilities { @@ -84,7 +84,7 @@ namespace Microsoft.DotNet.ProjectModel.Utilities } StringComparison compare; - if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + if (PlatformServices.Default.Runtime.OperatingSystemPlatform == Platform.Windows) { compare = StringComparison.OrdinalIgnoreCase; // check if paths are on the same volume diff --git a/src/Microsoft.DotNet.ProjectModel/Utilities/VersionUtility.cs b/src/Microsoft.DotNet.ProjectModel/Utilities/VersionUtility.cs index 4755457af..81c421bf3 100644 --- a/src/Microsoft.DotNet.ProjectModel/Utilities/VersionUtility.cs +++ b/src/Microsoft.DotNet.ProjectModel/Utilities/VersionUtility.cs @@ -1,7 +1,10 @@ // 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. +#if !NET451 using System.Runtime.Loader; +#endif +using System.Reflection; using System.Text; using NuGet.Versioning; @@ -16,7 +19,11 @@ namespace Microsoft.DotNet.ProjectModel.Utilities internal static NuGetVersion GetAssemblyVersion(string path) { +#if NET451 + return new NuGetVersion(AssemblyName.GetAssemblyName(path).Version); +#else return new NuGetVersion(AssemblyLoadContext.GetAssemblyName(path).Version); +#endif } public static string RenderVersion(VersionRange range) diff --git a/src/Microsoft.DotNet.ProjectModel/project.json b/src/Microsoft.DotNet.ProjectModel/project.json index 6b56073f6..f9c7dddf4 100644 --- a/src/Microsoft.DotNet.ProjectModel/project.json +++ b/src/Microsoft.DotNet.ProjectModel/project.json @@ -5,15 +5,9 @@ }, "description": "Types to model a .NET Project", "dependencies": { - "NETStandard.Library": "1.0.0-rc2-23811", - "System.Reflection.Metadata": "1.2.0-rc2-23811", - "System.Runtime.Loader": "4.0.0-rc2-23811", - "System.Dynamic.Runtime": "4.0.11-rc2-23811", - "System.Security.Cryptography.Algorithms": "4.0.0-rc2-23811", - "Microsoft.CSharp": "4.0.1-rc2-23811", - "System.Xml.XDocument": "4.0.11-rc2-23811", - "NuGet.Packaging": "3.4.0-beta-583", + "System.Reflection.Metadata": "1.2.0-rc2-23811", + "NuGet.Packaging": "3.4.0-beta-583", "Microsoft.Extensions.FileSystemGlobbing": "1.0.0-rc2-15996", "Microsoft.Extensions.JsonParser.Sources": { "type": "build", @@ -28,11 +22,23 @@ "version": "1.0.0-*" } }, - "frameworks": { + "net451": { + "frameworkAssemblies": { + "System.IO": "" + } + }, "dnxcore50": { - "imports": "portable-net45+win8" + "imports": "portable-net45+win8", + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23811", + "System.Dynamic.Runtime": "4.0.11-rc2-23811", + "System.Runtime.Loader": "4.0.0-rc2-23811", + "System.Security.Cryptography.Algorithms": "4.0.0-rc2-23811", + "Microsoft.CSharp": "4.0.1-rc2-23811", + "System.Xml.XDocument": "4.0.11-rc2-23811" } + } }, "scripts": { } diff --git a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs index a00bcdb6d..6acd61e16 100644 --- a/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs +++ b/src/Microsoft.Extensions.DependencyModel/CompilationLibrary.cs @@ -25,7 +25,7 @@ namespace Microsoft.Extensions.DependencyModel string basePath; - var appBase = Path.GetDirectoryName(entryAssembly.Location); + var appBase = PlatformServices.Default.Application.ApplicationBasePath; var refsDir = Path.Combine(appBase, "refs"); var hasRefs = Directory.Exists(refsDir); var isProject = string.Equals(LibraryType, "project", StringComparison.OrdinalIgnoreCase); diff --git a/src/Microsoft.Extensions.Testing.Abstractions/project.json b/src/Microsoft.Extensions.Testing.Abstractions/project.json index d22bed163..889044a2f 100644 --- a/src/Microsoft.Extensions.Testing.Abstractions/project.json +++ b/src/Microsoft.Extensions.Testing.Abstractions/project.json @@ -1,27 +1,29 @@ { - "description": "Abstractions for test runners to communicate to a tool, such as Visual Studio.", - "version": "1.0.0-*", - "repository": { - "type": "git", - "url": "git://github.com/dotnet/cli" - }, - "compilationOptions": { - "warningsAsErrors": true, - "keyFile": "../../tools/Key.snk" - }, - "dependencies": { - "Newtonsoft.Json": "7.0.1", - "Microsoft.DotNet.ProjectModel": "1.0.0-*", - "Microsoft.Extensions.Logging.Abstractions": "1.0.0-rc2-16040", + "description": "Abstractions for test runners to communicate to a tool, such as Visual Studio.", + "version": "1.0.0-*", + "repository": { + "type": "git", + "url": "git://github.com/dotnet/cli" + }, + "compilationOptions": { + "warningsAsErrors": true, + "keyFile": "../../tools/Key.snk" + }, + "dependencies": { + "Newtonsoft.Json": "7.0.1", + "Microsoft.DotNet.ProjectModel": "1.0.0-*", + "Microsoft.Extensions.Logging.Abstractions": "1.0.0-rc2-16040" + }, + "frameworks": { + "net451": { }, + "dnxcore50": { + "imports": "portable-net45+win8", + "dependencies": { "NETStandard.Library": "1.0.0-rc2-23811", "System.Resources.ResourceManager": "4.0.1-rc2-23811", "System.Runtime.Serialization.Primitives": "4.1.0-rc2-23811" - }, - "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" - } - }, - "scripts": { + } } -} + }, + "scripts": { } +} \ No newline at end of file diff --git a/scripts/test/restore-tests.sh b/src/corehost/build.sh similarity index 56% rename from scripts/test/restore-tests.sh rename to src/corehost/build.sh index a39c795fd..339838348 100755 --- a/scripts/test/restore-tests.sh +++ b/src/corehost/build.sh @@ -1,8 +1,8 @@ #!/usr/bin/env bash -# -# 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. -# + +# Why is this a separate script? Why not just invoke 'cmake' and 'make' in the C# build scripts themselves? +# I really don't know, but it doesn't work when I do that. Something about SIGCHLD not getting from clang to cmake or something. +# -anurse set -e @@ -14,8 +14,6 @@ while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symli done DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )" -source "$DIR/../common/_common.sh" - -header "Restoring Test Packages" - -dotnet restore "$REPOROOT/test" --runtime $RID -f "$TEST_PACKAGE_DIR" $DISABLE_PARALLEL +echo "Building Corehost from $DIR to $(pwd)" +cmake "$DIR" -G "Unix Makefiles" +make diff --git a/src/corehost/cli/hostpolicy.cpp b/src/corehost/cli/hostpolicy.cpp index efe4259b2..ead5f5da0 100644 --- a/src/corehost/cli/hostpolicy.cpp +++ b/src/corehost/cli/hostpolicy.cpp @@ -117,7 +117,7 @@ int run(const arguments_t& args, const pal::string_t& clr_path) // Workaround for dotnet/cli Issue #488 and #652 pal::string_t server_gc; - std::string server_gc_cstr = (pal::getenv(_X("COREHOST_SERVER_GC"), &server_gc) && !server_gc.empty()) ? pal::to_stdstring(server_gc) : "1"; + std::string server_gc_cstr = (pal::getenv(_X("COREHOST_SERVER_GC"), &server_gc) && !server_gc.empty()) ? pal::to_stdstring(server_gc) : "0"; const char* property_values[] = { // TRUSTED_PLATFORM_ASSEMBLIES diff --git a/src/dotnet/commands/dotnet-build/BuilderCommandApp.cs b/src/dotnet/commands/dotnet-build/BuilderCommandApp.cs index e9d3affa2..6f0348404 100644 --- a/src/dotnet/commands/dotnet-build/BuilderCommandApp.cs +++ b/src/dotnet/commands/dotnet-build/BuilderCommandApp.cs @@ -8,15 +8,18 @@ namespace Microsoft.DotNet.Tools.Build internal class BuilderCommandApp : CompilerCommandApp { public const string BuildProfileFlag = "--build-profile"; - public const string ForceUnsafeFlag = "--no-incremental"; + public const string NoIncrementalFlag = "--no-incremental"; + public const string NoDependenciesFlag = "--no-dependencies"; - public bool BuildProfileValue => OptionHasValue(BuildProfileFlag); - public bool ForceUnsafeValue => OptionHasValue(ForceUnsafeFlag); + public bool ShouldPrintIncrementalPreconditions => OptionHasValue(BuildProfileFlag); + public bool ShouldNotUseIncrementality => OptionHasValue(NoIncrementalFlag); + public bool ShouldSkipDependencies => OptionHasValue(NoDependenciesFlag); public BuilderCommandApp(string name, string fullName, string description) : base(name, fullName, description) { AddNoValueOption(BuildProfileFlag, "Set this flag to print the incremental safety checks that prevent incremental compilation"); - AddNoValueOption(ForceUnsafeFlag, "Set this flag to turn off incremental build"); + AddNoValueOption(NoIncrementalFlag, "Set this flag to turn off incremental build"); + AddNoValueOption(NoDependenciesFlag, "Set this flag to ignore project to project references and only build the root project"); } } } \ No newline at end of file diff --git a/src/dotnet/commands/dotnet-build/CompileContext.cs b/src/dotnet/commands/dotnet-build/CompileContext.cs index 0cae3a45b..6c2906386 100644 --- a/src/dotnet/commands/dotnet-build/CompileContext.cs +++ b/src/dotnet/commands/dotnet-build/CompileContext.cs @@ -23,9 +23,9 @@ namespace Microsoft.DotNet.Tools.Build public static readonly string[] KnownCompilers = { "csc", "vbc", "fsc" }; private readonly ProjectContext _rootProject; + private readonly ProjectDependenciesFacade _rootProjectDependencies; private readonly BuilderCommandApp _args; private readonly IncrementalPreconditions _preconditions; - private readonly ProjectDependenciesFacade _dependencies; public bool IsSafeForIncrementalCompilation => !_preconditions.PreconditionsDetected(); @@ -36,12 +36,9 @@ namespace Microsoft.DotNet.Tools.Build // Cleaner to clone the args and mutate the clone than have separate CompileContext fields for mutated args // and then reasoning which ones to get from args and which ones from fields. _args = (BuilderCommandApp)args.ShallowCopy(); - - _args.OutputValue = _args.OutputValue; - _args.BuildBasePathValue = _args.BuildBasePathValue; // Set up dependencies - _dependencies = new ProjectDependenciesFacade(_rootProject, _args.ConfigValue); + _rootProjectDependencies = new ProjectDependenciesFacade(_rootProject, _args.ConfigValue); // gather preconditions _preconditions = GatherIncrementalPreconditions(); @@ -51,17 +48,36 @@ namespace Microsoft.DotNet.Tools.Build { CreateOutputDirectories(); - // compile dependencies - foreach (var dependency in Sort(_dependencies.ProjectDependenciesWithSources)) - { - if (incremental) - { - var dependencyProjectContext = ProjectContext.Create(dependency.Path, dependency.Framework, new[] { _rootProject.RuntimeIdentifier }); + return CompileDendencies(incremental) && CompileRootProject(incremental); + } - if (!NeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue))) - { - continue; - } + private bool CompileRootProject(bool incremental) + { + if (incremental && !NeedsRebuilding(_rootProject, _rootProjectDependencies)) + { + // todo: what if the previous build had errors / warnings and nothing changed? Need to propagate them in case of incremental + return true; + } + + var success = InvokeCompileOnRootProject(); + + PrintSummary(success); + + return success; + } + + private bool CompileDendencies(bool incremental) + { + if (_args.ShouldSkipDependencies) + { + return true; + } + + foreach (var dependency in Sort(_rootProjectDependencies.ProjectDependenciesWithSources)) + { + if (incremental && !DependencyNeedsRebuilding(dependency)) + { + continue; } if (!InvokeCompileOnDependency(dependency)) @@ -70,28 +86,18 @@ namespace Microsoft.DotNet.Tools.Build } } - if (incremental && !NeedsRebuilding(_rootProject, _dependencies)) - { - // todo: what if the previous build had errors / warnings and nothing changed? Need to propagate them in case of incremental - return true; - } + return true; + } - // compile project - var success = InvokeCompileOnRootProject(); - - PrintSummary(success); - - return success; + private bool DependencyNeedsRebuilding(ProjectDescription dependency) + { + var dependencyProjectContext = ProjectContext.Create(dependency.Path, dependency.Framework, new[] { _rootProject.RuntimeIdentifier }); + return NeedsRebuilding(dependencyProjectContext, new ProjectDependenciesFacade(dependencyProjectContext, _args.ConfigValue)); } private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies) { - return NeedsRebuilding(project, dependencies, _args.BuildBasePathValue); - } - - private bool NeedsRebuilding(ProjectContext project, ProjectDependenciesFacade dependencies, string baseBuildPath) - { - var compilerIO = GetCompileIO(project, _args.ConfigValue, baseBuildPath, _args.OutputValue, dependencies, project == _rootProject); + var compilerIO = GetCompileIO(project, _args.ConfigValue, _args.BuildBasePathValue, _args.OutputValue, dependencies, project == _rootProject); // rebuild if empty inputs / outputs if (!(compilerIO.Outputs.Any() && compilerIO.Inputs.Any())) @@ -195,9 +201,9 @@ namespace Microsoft.DotNet.Tools.Build private IncrementalPreconditions GatherIncrementalPreconditions() { - var preconditions = new IncrementalPreconditions(_args.BuildProfileValue); + var preconditions = new IncrementalPreconditions(_args.ShouldPrintIncrementalPreconditions); - if (_args.ForceUnsafeValue) + if (_args.ShouldNotUseIncrementality) { preconditions.AddForceUnsafePrecondition(); } @@ -217,11 +223,16 @@ namespace Microsoft.DotNet.Tools.Build // check the entire project tree that needs to be compiled, duplicated for each framework private List GetProjectsToCheck() { + if (_args.ShouldSkipDependencies) + { + return new List(1) { _rootProject }; + } + // include initial root project - var contextsToCheck = new List(1 + _dependencies.ProjectDependenciesWithSources.Count) { _rootProject }; + var contextsToCheck = new List(1 + _rootProjectDependencies.ProjectDependenciesWithSources.Count) { _rootProject }; // convert ProjectDescription to ProjectContext - var dependencyContexts = _dependencies.ProjectDependenciesWithSources.Select + var dependencyContexts = _rootProjectDependencies.ProjectDependenciesWithSources.Select (keyValuePair => ProjectContext.Create(keyValuePair.Value.Path, keyValuePair.Value.Framework)); contextsToCheck.AddRange(dependencyContexts); diff --git a/src/dotnet/commands/dotnet-build/IncrementalPreconditions.cs b/src/dotnet/commands/dotnet-build/IncrementalPreconditions.cs index bba3f4084..fbcd4435a 100644 --- a/src/dotnet/commands/dotnet-build/IncrementalPreconditions.cs +++ b/src/dotnet/commands/dotnet-build/IncrementalPreconditions.cs @@ -36,7 +36,7 @@ namespace Microsoft.DotNet.Tools.Build public void AddForceUnsafePrecondition() { - _preconditions.Add($"[Forced Unsafe] The build was marked as unsafe. Remove the {BuilderCommandApp.ForceUnsafeFlag} flag to enable incremental compilation"); + _preconditions.Add($"[Forced Unsafe] The build was marked as unsafe. Remove the {BuilderCommandApp.NoIncrementalFlag} flag to enable incremental compilation"); } public bool PreconditionsDetected() diff --git a/src/dotnet/commands/dotnet-build/README.md b/src/dotnet/commands/dotnet-build/README.md index 4e7eac3f1..d958d923b 100644 --- a/src/dotnet/commands/dotnet-build/README.md +++ b/src/dotnet/commands/dotnet-build/README.md @@ -33,3 +33,6 @@ Prints out the incremental safety checks that users need to address in order for --no-incremental Marks the build as unsafe for incrementality. This turns off incremental compilation and forces a clean rebuild of the project dependency graph. + +--no-dependencies +Ignore project to project references and only build the root project specified to build. diff --git a/src/dotnet/commands/dotnet-compile-fsc/Program.cs b/src/dotnet/commands/dotnet-compile-fsc/Program.cs index e22954eba..3dfff1547 100644 --- a/src/dotnet/commands/dotnet-compile-fsc/Program.cs +++ b/src/dotnet/commands/dotnet-compile-fsc/Program.cs @@ -12,6 +12,7 @@ using System.Text; using Microsoft.DotNet.Cli.Compiler.Common; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.ProjectModel; +using NuGet.Frameworks; namespace Microsoft.DotNet.Tools.Compiler.Fsc { @@ -79,6 +80,9 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc return returnCode; } + outputName = outputName.Trim('"'); + tempOutDir = tempOutDir.Trim('"'); + var translated = TranslateCommonOptions(commonOptions, outputName); var allArgs = new List(translated); @@ -89,8 +93,10 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc File.WriteAllText(assemblyInfo, AssemblyInfoFileGenerator.GenerateFSharp(assemblyInfoOptions)); allArgs.Add($"{assemblyInfo}"); + bool targetNetCore = commonOptions.Defines.Contains("DNXCORE50"); + //HACK fsc raise error FS0208 if target exe doesnt have extension .exe - bool hackFS0208 = commonOptions.EmitEntryPoint == true; + bool hackFS0208 = targetNetCore && commonOptions.EmitEntryPoint == true; string originalOutputName = outputName; if (outputName != null) @@ -100,26 +106,18 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc outputName = Path.ChangeExtension(outputName, ".exe"); } - allArgs.Add($"--out:"); - allArgs.Add($"{outputName}"); + allArgs.Add($"--out:{outputName}"); } - foreach (var reference in references) + //set target framework + if (targetNetCore) { - allArgs.Add("-r"); - allArgs.Add($"{reference}"); + allArgs.Add("--targetprofile:netcore"); } - foreach (var resource in resources) - { - allArgs.Add("--resource"); - allArgs.Add($"{resource}"); - } - - foreach (var source in sources) - { - allArgs.Add($"{source}"); - } + allArgs.AddRange(references.Select(r => $"-r:{r.Trim('"')}")); + allArgs.AddRange(resources.Select(resource => $"--resource:{resource.Trim('"')}")); + allArgs.AddRange(sources.Select(s => $"{s.Trim('"')}")); var rsp = Path.Combine(tempOutDir, "dotnet-compile-fsc.rsp"); File.WriteAllLines(rsp, allArgs, Encoding.UTF8); @@ -130,6 +128,8 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc .ForwardStdOut() .Execute(); + bool successFsc = result.ExitCode == 0; + if (hackFS0208 && File.Exists(outputName)) { if (File.Exists(originalOutputName)) @@ -137,6 +137,13 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc File.Move(outputName, originalOutputName); } + //HACK dotnet build require a pdb (crash without), fsc atm cant generate a portable pdb, so an empty pdb is created + string pdbPath = Path.ChangeExtension(outputName, ".pdb"); + if (successFsc && !File.Exists(pdbPath)) + { + File.WriteAllBytes(pdbPath, Array.Empty()); + } + return result.ExitCode; } @@ -167,11 +174,29 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc commonArgs.AddRange(options.Defines.Select(def => $"-d:{def}")); } + if (options.SuppressWarnings != null) + { + } + + // Additional arguments are added verbatim + if (options.AdditionalArguments != null) + { + commonArgs.AddRange(options.AdditionalArguments); + } + + if (options.LanguageVersion != null) + { + } + if (options.Platform != null) { commonArgs.Add($"--platform:{options.Platform}"); } + if (options.AllowUnsafe == true) + { + } + if (options.WarningsAsErrors == true) { commonArgs.Add("--warnaserror"); @@ -182,7 +207,19 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc commonArgs.Add("--optimize"); } - if(options.GenerateXmlDocumentation == true) + if (options.KeyFile != null) + { + } + + if (options.DelaySign == true) + { + } + + if (options.PublicSign == true) + { + } + + if (options.GenerateXmlDocumentation == true) { commonArgs.Add($"--doc:{Path.ChangeExtension(outputName, "xml")}"); } @@ -199,7 +236,7 @@ namespace Microsoft.DotNet.Tools.Compiler.Fsc if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { var win32manifestPath = Path.Combine(AppContext.BaseDirectory, "default.win32manifest"); - commonArgs.Add($"--win32manifest:\"{win32manifestPath}\""); + commonArgs.Add($"--win32manifest:{win32manifestPath}"); } } 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..d1d284f2e --- /dev/null +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -0,0 +1,200 @@ +// 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.GetShortFolderName() }, + { "compile:FullTargetFramework", 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/src/dotnet/commands/dotnet-publish/PublishCommand.cs b/src/dotnet/commands/dotnet-publish/PublishCommand.cs index 112712794..ce3acfc60 100644 --- a/src/dotnet/commands/dotnet-publish/PublishCommand.cs +++ b/src/dotnet/commands/dotnet-publish/PublishCommand.cs @@ -96,7 +96,8 @@ namespace Microsoft.DotNet.Tools.Publish { "publish:ProjectPath", context.ProjectDirectory }, { "publish:Configuration", configuration }, { "publish:OutputPath", outputPath }, - { "publish:Framework", context.TargetFramework.Framework }, + { "publish:TargetFramework", context.TargetFramework.GetShortFolderName() }, + { "publish:FullTargetFramework", context.TargetFramework.DotNetFrameworkName }, { "publish:Runtime", context.RuntimeIdentifier }, }; diff --git a/src/dotnet/commands/dotnet-restore/NuGet3.cs b/src/dotnet/commands/dotnet-restore/NuGet3.cs index 1458040e3..58f74a6b8 100644 --- a/src/dotnet/commands/dotnet-restore/NuGet3.cs +++ b/src/dotnet/commands/dotnet-restore/NuGet3.cs @@ -21,8 +21,8 @@ namespace Microsoft.DotNet.Tools.Restore var result = Run(Enumerable.Concat( prefixArgs, args)) - .ForwardStdErr() .ForwardStdOut() + .ForwardStdErr() .Execute(); return result.ExitCode; diff --git a/src/dotnet/project.json b/src/dotnet/project.json index bf5ea8b6e..6ffe6144f 100644 --- a/src/dotnet/project.json +++ b/src/dotnet/project.json @@ -18,10 +18,12 @@ "dependencies": { "Newtonsoft.Json": "7.0.1", - "Microsoft.Net.Compilers.netcore": "1.2.0-beta1-20160108-01", + "Microsoft.Net.Compilers.netcore": "1.2.0-beta1-20160202-02", "Microsoft.FSharp.Compiler.netcore": "1.0.0-alpha-151218", - "Microsoft.Net.CSharp.Interactive.netcore": "1.2.0-beta1-20160108-01", - "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160108-01", + "Microsoft.Net.CSharp.Interactive.netcore": "1.2.0-beta1-20160202-02", + "Microsoft.CodeAnalysis.CSharp": "1.2.0-beta1-20160202-02", + "Microsoft.DiaSymReader.Native": "1.3.3", + "NuGet.CommandLine.XPlat": "3.4.0-beta-583", "System.CommandLine": "0.1.0-e160119-1", @@ -52,6 +54,7 @@ "Microsoft.NETCore.ConsoleHost": "1.0.0-rc2-23811", "Microsoft.NETCore.TestHost": "1.0.0-rc2-23811", "NETStandard.Library": "1.0.0-rc2-23811", + "System.Reflection.Metadata": "1.2.0-rc3-23811", "System.Diagnostics.TextWriterTraceListener": "4.0.0-rc2-23811", "System.Diagnostics.TraceSource": "4.0.0-rc2-23811", "System.Linq.Expressions": "4.0.11-rc2-23811", diff --git a/test/ArgumentForwardingTests/ArgumentForwardingTests/ArgumentForwardingTests.cs b/test/ArgumentForwardingTests/ArgumentForwardingTests.cs similarity index 90% rename from test/ArgumentForwardingTests/ArgumentForwardingTests/ArgumentForwardingTests.cs rename to test/ArgumentForwardingTests/ArgumentForwardingTests.cs index adde47bf9..8834625af 100644 --- a/test/ArgumentForwardingTests/ArgumentForwardingTests/ArgumentForwardingTests.cs +++ b/test/ArgumentForwardingTests/ArgumentForwardingTests.cs @@ -18,7 +18,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding { public class ArgumentForwardingTests : TestBase { - private static readonly string s_reflectorExeName = "Reflector" + Constants.ExeSuffix; + private static readonly string s_reflectorExeName = "ArgumentsReflector" + Constants.ExeSuffix; private static readonly string s_reflectorCmdName = "reflector_cmd"; private string ReflectorPath { get; set; } @@ -28,7 +28,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding { Console.WriteLine("Dummy Entrypoint."); } - + public ArgumentForwardingTests() { // This test has a dependency on an argument reflector @@ -94,16 +94,12 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding [InlineData("\"abc\"\t\td\te")] [InlineData(@"a\\b d""e f""g h")] [InlineData(@"\ \\ \\\")] - [InlineData(@"a\""b c d")] [InlineData(@"a\\""b c d")] - [InlineData(@"a\\\""b c d")] [InlineData(@"a\\\\""b c d")] [InlineData(@"a\\\\""b c d")] [InlineData(@"a\\\\""b c"" d e")] [InlineData(@"a""b c""d e""f g""h i""j k""l")] [InlineData(@"a b c""def")] - [InlineData(@"""\a\"" \\""\\\ b c")] - [InlineData(@"a\""b \\ cd ""\e f\"" \\""\\\")] public void TestArgumentForwardingCmd(string testUserArgument) { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -139,7 +135,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding { var rawArg = rawEvaluatedArgument[i]; var escapedArg = escapedEvaluatedRawArgument[i]; - + try { rawArg.Should().Be(escapedArg); @@ -153,10 +149,33 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding } } + [Theory] + [InlineData(@"a\""b c d")] + [InlineData(@"a\\\""b c d")] + [InlineData(@"""\a\"" \\""\\\ b c")] + [InlineData(@"a\""b \\ cd ""\e f\"" \\""\\\")] + public void TestArgumentForwardingCmdFailsWithUnbalancedQuote(string testArgString) + { + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + // Get Baseline Argument Evaluation via Reflector + // This does not need to be different for cmd because + // it only establishes what the string[] args should be + var rawEvaluatedArgument = RawEvaluateArgumentString(testArgString); + + // Escape and Re-Evaluate the rawEvaluatedArgument + var escapedEvaluatedRawArgument = EscapeAndEvaluateArgumentStringCmd(rawEvaluatedArgument); + + rawEvaluatedArgument.Length.Should().NotBe(escapedEvaluatedRawArgument.Length); + } + /// /// EscapeAndEvaluateArgumentString returns a representation of string[] args /// when rawEvaluatedArgument is passed as an argument to a process using - /// Command.Create(). Ideally this should escape the argument such that + /// Command.Create(). Ideally this should escape the argument such that /// the output is == rawEvaluatedArgument. /// /// A string[] representing string[] args as already evaluated by a process @@ -176,7 +195,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding /// /// EscapeAndEvaluateArgumentString returns a representation of string[] args /// when rawEvaluatedArgument is passed as an argument to a process using - /// Command.Create(). Ideally this should escape the argument such that + /// Command.Create(). Ideally this should escape the argument such that /// the output is == rawEvaluatedArgument. /// /// A string[] representing string[] args as already evaluated by a process @@ -199,7 +218,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding /// /// Parse the output of the reflector into a string array. - /// Reflector output is simply string[] args written to + /// Reflector output is simply string[] args written to /// one string separated by commas. /// /// @@ -211,7 +230,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding /// /// Parse the output of the reflector into a string array. - /// Reflector output is simply string[] args written to + /// Reflector output is simply string[] args written to /// one string separated by commas. /// /// @@ -243,7 +262,7 @@ namespace Microsoft.DotNet.Tests.ArgumentForwarding { StartInfo = new ProcessStartInfo { - FileName = s_reflectorExeName, + FileName = ReflectorPath, Arguments = testUserArgument, UseShellExecute = false, RedirectStandardOutput = true, diff --git a/test/ArgumentForwardingTests/ArgumentForwardingTests/ArgumentForwardingTests.xproj b/test/ArgumentForwardingTests/ArgumentForwardingTests.xproj similarity index 100% rename from test/ArgumentForwardingTests/ArgumentForwardingTests/ArgumentForwardingTests.xproj rename to test/ArgumentForwardingTests/ArgumentForwardingTests.xproj diff --git a/test/ArgumentForwardingTests/ArgumentForwardingTests/project.json b/test/ArgumentForwardingTests/ArgumentForwardingTests/project.json deleted file mode 100644 index e895933c4..000000000 --- a/test/ArgumentForwardingTests/ArgumentForwardingTests/project.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "version": "1.0.0-*", - "compilationOptions": { - "emitEntryPoint": true - }, - - "dependencies": { - "NETStandard.Library" : "1.0.0-rc2-23811", - "Microsoft.NETCore.TestHost": "1.0.0-rc2-23811", - - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.netcore.extensions": "1.0.0-prerelease-00153", - "xunit.runner.utility": "2.1.0", - - "Microsoft.DotNet.ProjectModel": { "target": "project" }, - "Microsoft.DotNet.Cli.Utils": { "target": "project" }, - "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" } - }, - - "frameworks": { - "dnxcore50": { - "imports": "portable-net45+win8" - } - } -} diff --git a/test/ArgumentForwardingTests/Reflector/project.json b/test/ArgumentForwardingTests/project.json similarity index 67% rename from test/ArgumentForwardingTests/Reflector/project.json rename to test/ArgumentForwardingTests/project.json index e895933c4..19d7b3954 100644 --- a/test/ArgumentForwardingTests/Reflector/project.json +++ b/test/ArgumentForwardingTests/project.json @@ -6,21 +6,22 @@ "dependencies": { "NETStandard.Library" : "1.0.0-rc2-23811", - "Microsoft.NETCore.TestHost": "1.0.0-rc2-23811", - - "xunit": "2.1.0", - "xunit.console.netcore": "1.0.2-prerelease-00101", - "xunit.netcore.extensions": "1.0.0-prerelease-00153", - "xunit.runner.utility": "2.1.0", "Microsoft.DotNet.ProjectModel": { "target": "project" }, "Microsoft.DotNet.Cli.Utils": { "target": "project" }, - "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" } + "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, + + "xunit": "2.1.0", + "dotnet-test-xunit": "1.0.0-dev-48273-16" }, "frameworks": { "dnxcore50": { "imports": "portable-net45+win8" } - } + }, + + "testRunner": "xunit", + + "scripts": { "precompile": "dotnet build ../ArgumentsReflector/project.json --framework dnxcore50 --output %compile:RuntimeOutputDir%" } } diff --git a/test/ArgumentForwardingTests/Reflector/Reflector.cs b/test/ArgumentsReflector/Reflector.cs similarity index 66% rename from test/ArgumentForwardingTests/Reflector/Reflector.cs rename to test/ArgumentsReflector/Reflector.cs index 1af26f716..4176ebb0d 100644 --- a/test/ArgumentForwardingTests/Reflector/Reflector.cs +++ b/test/ArgumentsReflector/Reflector.cs @@ -2,17 +2,6 @@ // 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.Runtime.InteropServices; -using System.Text; -using Xunit; -using Microsoft.DotNet.Cli.Utils; -using Microsoft.DotNet.ProjectModel; -using Microsoft.DotNet.Tools.Test.Utilities; -using Microsoft.Extensions.PlatformAbstractions; -using System.Diagnostics; -using FluentAssertions; namespace Microsoft.DotNet.Tests.ArgumentForwarding { diff --git a/test/ArgumentForwardingTests/Reflector/Reflector.xproj b/test/ArgumentsReflector/Reflector.xproj similarity index 100% rename from test/ArgumentForwardingTests/Reflector/Reflector.xproj rename to test/ArgumentsReflector/Reflector.xproj diff --git a/test/ArgumentsReflector/project.json b/test/ArgumentsReflector/project.json new file mode 100644 index 000000000..e2dc63e05 --- /dev/null +++ b/test/ArgumentsReflector/project.json @@ -0,0 +1,18 @@ +{ + "version": "1.0.0-*", + "compilationOptions": { + "emitEntryPoint": true + }, + + "dependencies": { + "NETStandard.Library" : "1.0.0-rc2-23811" + }, + + "frameworks": { + "dnxcore50": { + "imports": "portable-net45+win8" + } + }, + + "content": ["reflector_cmd.cmd"] +} diff --git a/test/ArgumentForwardingTests/Reflector/reflector_cmd.cmd b/test/ArgumentsReflector/reflector_cmd.cmd similarity index 100% rename from test/ArgumentForwardingTests/Reflector/reflector_cmd.cmd rename to test/ArgumentsReflector/reflector_cmd.cmd diff --git a/test/EndToEnd/EndToEndTest.cs b/test/EndToEnd/EndToEndTest.cs index 25450216a..bd93d730c 100644 --- a/test/EndToEnd/EndToEndTest.cs +++ b/test/EndToEnd/EndToEndTest.cs @@ -16,7 +16,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd private static readonly string s_expectedOutput = "Hello World!" + Environment.NewLine; private static readonly string s_testdirName = "e2etestroot"; private static readonly string s_outputdirName = "test space/bin"; - + private static string RestoredTestProjectDirectory { get; set; } private string Rid { get; set; } @@ -33,7 +33,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd { Console.WriteLine("Dummy Entrypoint."); } - + public EndToEndTest() { TestInstanceSetup(); @@ -192,7 +192,7 @@ namespace Microsoft.DotNet.Tests.EndToEnd { Directory.Delete(RestoredTestProjectDirectory, true); } - catch(Exception e) {} + catch(Exception) {} Directory.CreateDirectory(RestoredTestProjectDirectory); @@ -231,4 +231,4 @@ namespace Microsoft.DotNet.Tests.EndToEnd File.SetLastWriteTimeUtc(csFile, DateTime.UtcNow); } } -} \ No newline at end of file +} diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs index 4c1b4f2d6..6b6534feb 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/BuildCommand.cs @@ -26,6 +26,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private string _cppCompilerFlags; private bool _buildProfile; private bool _noIncremental; + private bool _noDependencies; private string OutputOption { @@ -166,6 +167,16 @@ namespace Microsoft.DotNet.Tools.Test.Utilities } } + private string NoDependencies + { + get + { + return _noDependencies ? + "--no-dependencies" : + ""; + } + } + public BuildCommand( string projectPath, string output="", @@ -181,11 +192,11 @@ namespace Microsoft.DotNet.Tools.Test.Utilities bool nativeCppMode=false, string cppCompilerFlags="", bool buildProfile=true, - bool noIncremental=false + bool noIncremental=false, + bool noDependencies=false ) : base("dotnet") { - _projectPath = projectPath; _project = ProjectReader.GetProject(projectPath); @@ -203,6 +214,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities _cppCompilerFlags = cppCompilerFlags; _buildProfile = buildProfile; _noIncremental = noIncremental; + _noDependencies = noDependencies; } public override CommandResult Execute(string args = "") @@ -226,7 +238,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities private string BuildArgs() { - return $"{BuildProfile} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}"; + return $"{BuildProfile} {NoDependencies} {NoIncremental} \"{_projectPath}\" {OutputOption} {BuildBasePathOption} {ConfigurationOption} {FrameworkOption} {NoHostOption} {NativeOption} {ArchitectureOption} {IlcArgsOption} {IlcPathOption} {AppDepSDKPathOption} {NativeCppModeOption} {CppCompilerFlagsOption}"; } } } diff --git a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs index f1672a62a..ef78f1018 100644 --- a/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs +++ b/test/Microsoft.DotNet.Tools.Tests.Utilities/Commands/TestCommand.cs @@ -24,7 +24,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities if (!Path.IsPathRooted(_command)) { _command = Env.GetCommandPath(_command) ?? - Env.GetCommandPathFromAppBase(AppContext.BaseDirectory, _command); + Env.GetCommandPathFromRootPath(AppContext.BaseDirectory, _command); } Console.WriteLine($"Executing - {_command} {args}"); @@ -43,7 +43,7 @@ namespace Microsoft.DotNet.Tools.Test.Utilities Console.WriteLine($"Executing (Captured Output) - {_command} {args}"); var commandPath = Env.GetCommandPath(_command, ".exe", ".cmd", "") ?? - Env.GetCommandPathFromAppBase(AppContext.BaseDirectory, _command, ".exe", ".cmd", ""); + Env.GetCommandPathFromRootPath(AppContext.BaseDirectory, _command, ".exe", ".cmd", ""); var stdOut = new StreamForwarder(); var stdErr = new StreamForwarder(); diff --git a/test/ScriptExecutorTests/ScriptExecutorTests.cs b/test/ScriptExecutorTests/ScriptExecutorTests.cs new file mode 100644 index 000000000..b1e156cac --- /dev/null +++ b/test/ScriptExecutorTests/ScriptExecutorTests.cs @@ -0,0 +1,155 @@ +using System; +using System.IO; +using System.Collections.Generic; +using Microsoft.DotNet.Cli.Utils; +using Microsoft.DotNet.ProjectModel; +using Microsoft.DotNet.Tools.Test.Utilities; +using System.Runtime.InteropServices; +using Xunit; +using FluentAssertions; +using NuGet.Frameworks; + +namespace Microsoft.DotNet.Cli.Utils.ScriptExecutorTests +{ + public class ScriptExecutorTests : TestBase + { + private static readonly string s_testProjectRoot = Path.Combine(AppContext.BaseDirectory, "TestAssets/TestProjects"); + + private TempDirectory _root; + private string binTestProjectPath; + private Project project; + + public ScriptExecutorTests() + { + _root = Temp.CreateDirectory(); + + var sourceTestProjectPath = Path.Combine(s_testProjectRoot, "TestApp"); + binTestProjectPath = _root.CopyDirectory(sourceTestProjectPath).Path; + project = ProjectContext.Create(binTestProjectPath, NuGetFramework.Parse("dnxcore50")).ProjectFile; + } + + [Fact] + public void Test_Project_Local_Script_is_Resolved() + { + CreateTestFile("some.script", binTestProjectPath); + var scriptCommandLine = "some.script"; + + var command = ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + + command.Should().NotBeNull(); + command.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + } + + [Fact] + public void Test_Nonexistent_Project_Local_Script_throws_CommandUnknownException() + { + var scriptCommandLine = "nonexistent.script"; + + Action action = () => ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + action.ShouldThrow(); + } + + [Fact] + public void Test_Extension_sh_is_Inferred_over_cmd_in_Project_Local_Scripts_on_Unix() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var extensionList = new string[] { ".cmd", ".sh" }; + + var expectedExtension = ".sh"; + + foreach (var extension in extensionList) + { + CreateTestFile("uniquescriptname" + extension, binTestProjectPath); + } + + // Don't include extension + var scriptCommandLine = "uniquescriptname"; + + var command = ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + + command.Should().NotBeNull(); + command.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + command.CommandArgs.Should().Contain(scriptCommandLine + expectedExtension); + } + + [Fact] + public void Test_Extension_cmd_is_Inferred_over_sh_in_Project_Local_Scripts_on_Windows() + { + if (! RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + var extensionList = new string[] { ".cmd", ".sh" }; + + var expectedExtension = ".cmd"; + + foreach (var extension in extensionList) + { + CreateTestFile("uniquescriptname" + extension, binTestProjectPath); + } + + // Don't include extension + var scriptCommandLine = "uniquescriptname"; + + var command = ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + + command.Should().NotBeNull(); + command.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + command.CommandArgs.Should().Contain(scriptCommandLine + expectedExtension); + } + + [Fact] + public void Test_Script_Exe_Files_Dont_Use_Cmd_or_Sh() + { + CreateTestFile("some.exe", binTestProjectPath); + var scriptCommandLine = "some.exe"; + + var command = ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + + command.Should().NotBeNull(); + command.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + + Path.GetFileName(command.CommandName).Should().NotBe("cmd.exe"); + Path.GetFileName(command.CommandName).Should().NotBe("sh"); + } + + [Fact] + public void Test_Script_Cmd_Files_Use_CmdExe() + { + if (! RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + return; + } + + CreateTestFile("some.cmd", binTestProjectPath); + var scriptCommandLine = "some.cmd"; + + var command = ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + + command.Should().NotBeNull(); + command.ResolutionStrategy.Should().Be(CommandResolutionStrategy.ProjectLocal); + + Path.GetFileName(command.CommandName).Should().Be("cmd.exe"); + } + + [Fact] + public void Test_Script_Builtins_throws_CommandUnknownException() + { + var scriptCommandLine = "echo"; + + Action action = () => ScriptExecutor.CreateCommandForScript(project, scriptCommandLine, new Dictionary()); + action.ShouldThrow(); + } + + private void CreateTestFile(string filename, string directory) + { + string path = Path.Combine(directory, filename); + File.WriteAllText(path, "echo hello"); + } + } +} diff --git a/test/ScriptExecutorTests/ScriptExecutorTests.xproj b/test/ScriptExecutorTests/ScriptExecutorTests.xproj new file mode 100644 index 000000000..8b66a40d6 --- /dev/null +++ b/test/ScriptExecutorTests/ScriptExecutorTests.xproj @@ -0,0 +1,19 @@ + + + + 14.0.23107 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + + 833ffee1-7eed-4f51-8dfd-946d48833333 + Microsoft.DotNet.Cli.Utils.ScriptExecutorTests + ..\..\artifacts\obj\$(MSBuildProjectName) + ..\..\artifacts\bin\$(MSBuildProjectName)\ + + + + 2.0 + + + \ No newline at end of file diff --git a/test/ScriptExecutorTests/project.json b/test/ScriptExecutorTests/project.json new file mode 100644 index 000000000..22bda6b8e --- /dev/null +++ b/test/ScriptExecutorTests/project.json @@ -0,0 +1,26 @@ +{ + "version": "1.0.0-*", + + "dependencies": { + "NETStandard.Library": "1.0.0-rc2-23805", + + "Microsoft.DotNet.ProjectModel": { "target": "project" }, + "Microsoft.DotNet.Cli.Utils": { "target": "project" }, + "Microsoft.DotNet.Tools.Tests.Utilities": { "target": "project" }, + + "xunit": "2.1.0", + "dotnet-test-xunit": "1.0.0-dev-48273-16" + }, + + "frameworks": { + "dnxcore50": { + "imports": "portable-net45+win8" + } + }, + + "content": [ + "../../TestAssets/TestProjects/TestApp/**/*" + ], + + "testRunner": "xunit" +} diff --git a/test/dotnet-build.Tests/BuildProjectToProjectTests.cs b/test/dotnet-build.Tests/BuildProjectToProjectTests.cs index 662b1e773..dacc29a28 100644 --- a/test/dotnet-build.Tests/BuildProjectToProjectTests.cs +++ b/test/dotnet-build.Tests/BuildProjectToProjectTests.cs @@ -5,6 +5,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using FluentAssertions; using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Tools.Test.Utilities; using Xunit; @@ -14,7 +15,7 @@ namespace Microsoft.DotNet.Tools.Builder.Tests { public class ProjectToProjectDependenciesIncrementalTest : IncrementalTestBase { - private string[] _projects = new[] { "L0", "L11", "L12", "L21", "L22" }; + private readonly string[] _projects = new[] { "L0", "L11", "L12", "L21", "L22" }; private string MainProjectExe { @@ -58,6 +59,38 @@ namespace Microsoft.DotNet.Tools.Builder.Tests AssertRebuilt(result3, expectedRebuiltProjects); } + [Fact] + public void TestNoDependencyFlag() + { + var dependencies = new[] { "L11", "L12", "L21", "L22" }; + + // first clean build; all projects required compilation + var result1 = BuildProject(); + AssertRebuilt(result1, _projects); + + // modify the source code of a leaf dependency + TouchSourcesOfProject("L22"); + + // second build with no dependencies and no incremental; only the root rebuilds + var result2 = BuildProject(noDependencies: true, noIncremental: true); + result2.Should().StdOutMatchPattern("Compiling.*L0.*"); + + AssertResultDoesNotContainStrings(result2, dependencies); + + // third build with no dependencies but incremental; nothing rebuilds + var result3 = BuildProject(noDependencies: true); + result3.Should().HaveSkippedProjectCompilation("L0"); + AssertResultDoesNotContainStrings(result3, dependencies); + } + + private static void AssertResultDoesNotContainStrings(CommandResult commandResult, string[] strings) + { + foreach (var s in strings) + { + commandResult.StdOut.Should().NotContain(s); + } + } + // compute A - B private T[] SetDifference(T[] A, T[] B) { diff --git a/test/dotnet-build.Tests/IncrementalTestBase.cs b/test/dotnet-build.Tests/IncrementalTestBase.cs index b4fce519a..ca202766e 100644 --- a/test/dotnet-build.Tests/IncrementalTestBase.cs +++ b/test/dotnet-build.Tests/IncrementalTestBase.cs @@ -58,15 +58,15 @@ namespace Microsoft.DotNet.Tools.Builder.Tests File.SetLastWriteTimeUtc(file, DateTime.UtcNow); } - protected CommandResult BuildProject(bool noIncremental = false, bool expectBuildFailure = false) + protected CommandResult BuildProject(bool noDependencies = false, bool noIncremental = false, bool expectBuildFailure = false) { var mainProjectFile = GetProjectFile(MainProject); return BuildProject(mainProjectFile, noIncremental, expectBuildFailure); } - protected CommandResult BuildProject(string projectFile, bool noIncremental = false, bool expectBuildFailure = false) + protected CommandResult BuildProject(string projectFile, bool noDependencies = false, bool noIncremental = false, bool expectBuildFailure = false) { - var buildCommand = new BuildCommand(projectFile, output: GetOutputDir(), framework: "dnxcore50", noIncremental: noIncremental); + var buildCommand = new BuildCommand(projectFile, output: GetOutputDir(), framework: "dnxcore50", noIncremental: noIncremental, noDependencies : noDependencies); var result = buildCommand.ExecuteWithCapturedOutput(); if (!expectBuildFailure) diff --git a/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs b/test/dotnet-compile.UnitTests/GivenACompilationDriver.cs new file mode 100644 index 000000000..b0724bd99 --- /dev/null +++ b/test/dotnet-compile.UnitTests/GivenACompilationDriver.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..bfb98b0b7 --- /dev/null +++ b/test/dotnet-compile.UnitTests/GivenThatICareAboutScriptVariablesFromAManagedCompiler.cs @@ -0,0 +1,242 @@ +// 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_FullTargetFramework_variable_to_the_pre_compile_scripts() + { + _fixture.PreCompileScriptVariables.Should().ContainKey("compile:FullTargetFramework"); + _fixture.PreCompileScriptVariables["compile:FullTargetFramework"].Should().Be("dnxcore,Version=v5.0"); + } + + [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("dnxcore50"); + } + + [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_FullTargetFramework_variable_to_the_post_compile_scripts() + { + _fixture.PostCompileScriptVariables.Should().ContainKey("compile:FullTargetFramework"); + _fixture.PostCompileScriptVariables["compile:FullTargetFramework"].Should().Be("dnxcore,Version=v5.0"); + } + + [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("dnxcore50"); + } + + [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())) + .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" +} diff --git a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs index 7972f7a91..9ab89cc6c 100644 --- a/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs +++ b/test/dotnet-publish.Tests/Microsoft.DotNet.Tools.Publish.Tests.cs @@ -177,14 +177,13 @@ namespace Microsoft.DotNet.Tools.Publish.Tests } [Fact] - [ActiveIssue(982)] public void PublishScriptsRun() { - TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppWithLibrary") + TestInstance instance = TestAssetsManager.CreateTestInstance("TestAppWithScripts") .WithLockFiles() .WithBuildArtifacts(); - var testProject = _getProjectJson(instance.TestRoot, "TestApp"); + var testProject = _getProjectJson(instance.TestRoot, "TestAppWithScripts"); var publishCommand = new PublishCommand(testProject); var result = publishCommand.ExecuteWithCapturedOutput();