|
14 | 14 | using BenchmarkDotNet.Loggers; |
15 | 15 | using BenchmarkDotNet.Running; |
16 | 16 | using BenchmarkDotNet.Toolchains.DotNetCli; |
| 17 | +using BenchmarkDotNet.Toolchains.Results; |
17 | 18 | using JetBrains.Annotations; |
18 | 19 |
|
19 | 20 | namespace BenchmarkDotNet.Toolchains.CsProj |
@@ -61,58 +62,94 @@ protected override string GetBuildArtifactsDirectoryPath(BuildPartition buildPar |
61 | 62 | protected override string GetProjectFilePath(string buildArtifactsDirectoryPath) |
62 | 63 | => Path.Combine(buildArtifactsDirectoryPath, "BenchmarkDotNet.Autogenerated.csproj"); |
63 | 64 |
|
64 | | - protected override string GetProjectFilePathForReferences(string buildArtifactsDirectoryPath) |
65 | | - => Path.Combine(buildArtifactsDirectoryPath, "BenchmarkDotNet.Autogenerated.ForReferences.csproj"); |
66 | | - |
67 | 65 | protected override string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration) |
68 | 66 | => Path.Combine(buildArtifactsDirectoryPath, "bin", configuration, TargetFrameworkMoniker); |
69 | 67 |
|
70 | | - [SuppressMessage("ReSharper", "StringLiteralTypo")] // R# complains about $variables$ |
71 | | - private string LoadCsProj(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, string projectFile, string customProperties, string sdkName) |
72 | | - => new StringBuilder(ResourceHelper.LoadTemplate("CsProj.txt")) |
73 | | - .Replace("$PLATFORM$", buildPartition.Platform.ToConfig()) |
74 | | - .Replace("$CODEFILENAME$", Path.GetFileName(artifactsPaths.ProgramCodePath)) |
75 | | - .Replace("$CSPROJPATH$", projectFile) |
76 | | - .Replace("$TFM$", TargetFrameworkMoniker) |
77 | | - .Replace("$PROGRAMNAME$", artifactsPaths.ProgramName) |
78 | | - .Replace("$RUNTIMESETTINGS$", GetRuntimeSettings(buildPartition.RepresentativeBenchmarkCase.Job.Environment.Gc, buildPartition.Resolver)) |
79 | | - .Replace("$COPIEDSETTINGS$", customProperties) |
80 | | - .Replace("$SDKNAME$", sdkName) |
| 68 | + protected override void GenerateBuildScript(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) |
| 69 | + { |
| 70 | + string projectFilePath = GetProjectFilePath(buildPartition.RepresentativeBenchmarkCase.Descriptor.Type, NullLogger.Instance).FullName; |
| 71 | + |
| 72 | + var content = new StringBuilder(300) |
| 73 | + .AppendLine($"call {CliPath ?? "dotnet"} {DotNetCliCommand.GetRestoreCommand(artifactsPaths, buildPartition, projectFilePath)}") |
| 74 | + .AppendLine($"call {CliPath ?? "dotnet"} {DotNetCliCommand.GetPublishCommand(artifactsPaths, buildPartition, projectFilePath, TargetFrameworkMoniker)}") |
| 75 | + .AppendLine($"call {CliPath ?? "dotnet"} {DotNetCliCommand.GetRestoreCommand(artifactsPaths, buildPartition, artifactsPaths.ProjectFilePath)}") |
| 76 | + .AppendLine($"call {CliPath ?? "dotnet"} {DotNetCliCommand.GetPublishCommand(artifactsPaths, buildPartition, artifactsPaths.ProjectFilePath, TargetFrameworkMoniker)}") |
81 | 77 | .ToString(); |
82 | 78 |
|
| 79 | + File.WriteAllText(artifactsPaths.BuildScriptFilePath, content); |
| 80 | + } |
| 81 | + |
| 82 | + [SuppressMessage("ReSharper", "StringLiteralTypo")] // R# complains about $variables$ |
83 | 83 | protected override void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) |
84 | 84 | { |
85 | | - var projectFile = GetProjectFilePath(buildPartition.RepresentativeBenchmarkCase.Descriptor.Type, logger); |
| 85 | + var benchmark = buildPartition.RepresentativeBenchmarkCase; |
| 86 | + var projectFile = GetProjectFilePath(benchmark.Descriptor.Type, logger); |
86 | 87 |
|
87 | 88 | var xmlDoc = new XmlDocument(); |
88 | 89 | xmlDoc.Load(projectFile.FullName); |
89 | 90 | var (customProperties, sdkName) = GetSettingsThatNeedToBeCopied(xmlDoc, projectFile); |
90 | 91 |
|
91 | | - GenerateBuildForReferencesProject(buildPartition, artifactsPaths, projectFile.FullName, customProperties, sdkName); |
92 | | - |
93 | | - var content = LoadCsProj(buildPartition, artifactsPaths, projectFile.FullName, customProperties, sdkName); |
| 92 | + var content = new StringBuilder(ResourceHelper.LoadTemplate("CsProj.txt")) |
| 93 | + .Replace("$PLATFORM$", buildPartition.Platform.ToConfig()) |
| 94 | + .Replace("$CODEFILENAME$", Path.GetFileName(artifactsPaths.ProgramCodePath)) |
| 95 | + .Replace("$CSPROJPATH$", projectFile.FullName) |
| 96 | + .Replace("$TFM$", TargetFrameworkMoniker) |
| 97 | + .Replace("$PROGRAMNAME$", artifactsPaths.ProgramName) |
| 98 | + .Replace("$RUNTIMESETTINGS$", GetRuntimeSettings(benchmark.Job.Environment.Gc, buildPartition.Resolver)) |
| 99 | + .Replace("$COPIEDSETTINGS$", customProperties) |
| 100 | + .Replace("$SDKNAME$", sdkName) |
| 101 | + .ToString(); |
94 | 102 |
|
95 | 103 | File.WriteAllText(artifactsPaths.ProjectFilePath, content); |
| 104 | + |
| 105 | + // Integration tests are built without dependencies, so we skip gathering dlls. |
| 106 | + if (!buildPartition.ForcedNoDependenciesForIntegrationTests) |
| 107 | + { |
| 108 | + GatherReferences(projectFile.FullName, buildPartition, artifactsPaths, logger); |
| 109 | + } |
96 | 110 | } |
97 | 111 |
|
98 | | - protected void GenerateBuildForReferencesProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, string projectFile, string customProperties, string sdkName) |
| 112 | + protected void GatherReferences(string projectFilePath, BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) |
99 | 113 | { |
100 | | - var content = LoadCsProj(buildPartition, artifactsPaths, projectFile, customProperties, sdkName); |
| 114 | + // Build the original project then reference all of the built dlls. |
| 115 | + var buildResult = new DotNetCliCommand( |
| 116 | + CliPath, |
| 117 | + projectFilePath, |
| 118 | + TargetFrameworkMoniker, |
| 119 | + null, |
| 120 | + GenerateResult.Success(artifactsPaths, []), |
| 121 | + logger, |
| 122 | + buildPartition, |
| 123 | + [], |
| 124 | + buildPartition.Timeout |
| 125 | + ) |
| 126 | + .RestoreThenBuild(); |
| 127 | + |
| 128 | + if (!buildResult.IsBuildSuccess) |
| 129 | + { |
| 130 | + throw buildResult.TryToExplainFailureReason(out string reason) |
| 131 | + ? new Exception(reason) |
| 132 | + : new Exception(buildResult.ErrorMessage); |
| 133 | + } |
101 | 134 |
|
102 | | - // We don't include the generated .notcs file when building the reference dlls, only in the final build. |
103 | 135 | var xmlDoc = new XmlDocument(); |
104 | | - xmlDoc.Load(new StringReader(content)); |
| 136 | + xmlDoc.Load(artifactsPaths.ProjectFilePath); |
105 | 137 | XmlElement projectElement = xmlDoc.DocumentElement; |
106 | | - projectElement.RemoveChild(projectElement.SelectSingleNode("ItemGroup/Compile").ParentNode); |
107 | | - |
108 | | - var startupObjectElement = projectElement.SelectSingleNode("PropertyGroup/StartupObject"); |
109 | | - startupObjectElement.ParentNode.RemoveChild(startupObjectElement); |
110 | | - |
111 | | - // We need to change the output type to library since we're only compiling for dlls. |
112 | | - var outputTypeElement = projectElement.SelectSingleNode("PropertyGroup/OutputType"); |
113 | | - outputTypeElement.InnerText = "Library"; |
| 138 | + var itemGroup = xmlDoc.CreateElement("ItemGroup"); |
| 139 | + projectElement.AppendChild(itemGroup); |
| 140 | + foreach (var assemblyFile in Directory.GetFiles(artifactsPaths.BinariesDirectoryPath, "*.dll")) |
| 141 | + { |
| 142 | + var referenceElement = xmlDoc.CreateElement("Reference"); |
| 143 | + itemGroup.AppendChild(referenceElement); |
| 144 | + referenceElement.SetAttribute("Include", Path.GetFileNameWithoutExtension(assemblyFile)); |
| 145 | + var hintPath = xmlDoc.CreateElement("HintPath"); |
| 146 | + referenceElement.AppendChild(hintPath); |
| 147 | + var locationNode = xmlDoc.CreateTextNode(assemblyFile); |
| 148 | + hintPath.AppendChild(locationNode); |
| 149 | + // TODO: Add Aliases here for extern alias #2289 |
| 150 | + } |
114 | 151 |
|
115 | | - xmlDoc.Save(artifactsPaths.BuildForReferencesProjectFilePath); |
| 152 | + xmlDoc.Save(artifactsPaths.ProjectFilePath); |
116 | 153 | } |
117 | 154 |
|
118 | 155 | /// <summary> |
|
0 commit comments