diff --git a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs index 2a5afebc15..0fb8349b1f 100644 --- a/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs +++ b/src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs @@ -35,8 +35,8 @@ protected override string GetBuildArtifactsDirectoryPath(BuildPartition buildPar return Path.Combine(directoryName, programName); } - protected override string GetProjectFilePath(string binariesDirectoryPath) - => Path.Combine(binariesDirectoryPath, "BenchmarkDotNet.Autogenerated.csproj"); + protected override string GetProjectFilePath(string buildArtifactsDirectoryPath) + => Path.Combine(buildArtifactsDirectoryPath, "BenchmarkDotNet.Autogenerated.csproj"); protected override string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration) => Path.Combine(buildArtifactsDirectoryPath, "bin", configuration, TargetFrameworkMoniker); @@ -61,7 +61,11 @@ protected override void GenerateProject(BuildPartition buildPartition, Artifacts File.WriteAllText(artifactsPaths.ProjectFilePath, content); } - protected string GetRuntimeSettings(GcMode gcMode, IResolver resolver) + /// + /// returns an MSBuild string that defines Runtime settings + /// + [PublicAPI] + protected virtual string GetRuntimeSettings(GcMode gcMode, IResolver resolver) { if (!gcMode.HasChanges) return string.Empty; @@ -112,7 +116,11 @@ private string GetSettingsThatNeedsToBeCopied(FileInfo projectFile) return customSettings.ToString(); } - protected static FileInfo GetProjectFilePath(Type benchmarkTarget, ILogger logger) + /// + /// returns a path to the project file which defines the benchmarks + /// + [PublicAPI] + protected virtual FileInfo GetProjectFilePath(Type benchmarkTarget, ILogger logger) { if (!GetSolutionRootDirectory(out var solutionRootDirectory)) { diff --git a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs index d8041859f9..5f009a25c1 100644 --- a/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs +++ b/src/BenchmarkDotNet/Toolchains/DotNetCli/DotNetCliCommandExecutor.cs @@ -10,11 +10,12 @@ namespace BenchmarkDotNet.Toolchains.DotNetCli { - internal static class DotNetCliCommandExecutor + [PublicAPI] + public static class DotNetCliCommandExecutor { - internal struct CommandResult + public struct CommandResult { - public bool IsSuccess { get; } + [PublicAPI] public bool IsSuccess { get; } [PublicAPI] public TimeSpan ExecutionTime { get; } @@ -46,7 +47,8 @@ public static CommandResult Failure(TimeSpan time, string standardError, string => new CommandResult(false, time, standardOutput, standardError); } - internal static CommandResult ExecuteCommand( + [PublicAPI] + public static CommandResult ExecuteCommand( string customDotNetCliPath, string commandWithArguments, string workingDirectory, ILogger logger, IReadOnlyList environmentVariables = null, bool useSharedCompilation = false) { diff --git a/src/BenchmarkDotNet/Toolchains/GeneratorBase.cs b/src/BenchmarkDotNet/Toolchains/GeneratorBase.cs index 9b9693fe09..7cc1b9ea76 100644 --- a/src/BenchmarkDotNet/Toolchains/GeneratorBase.cs +++ b/src/BenchmarkDotNet/Toolchains/GeneratorBase.cs @@ -6,10 +6,12 @@ using BenchmarkDotNet.Portability; using BenchmarkDotNet.Running; using BenchmarkDotNet.Toolchains.Results; +using JetBrains.Annotations; using StreamWriter = System.IO.StreamWriter; namespace BenchmarkDotNet.Toolchains { + [PublicAPI] public abstract class GeneratorBase : IGenerator { public GenerateResult GenerateProject(BuildPartition buildPartition, ILogger logger, string rootArtifactsFolderPath) @@ -35,25 +37,80 @@ public GenerateResult GenerateProject(BuildPartition buildPartition, ILogger log } } - protected abstract string GetBuildArtifactsDirectoryPath(BuildPartition assemblyLocation, string programName); - - protected virtual string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration) => buildArtifactsDirectoryPath; - - protected virtual string GetExecutableExtension() => RuntimeInformation.ExecutableExtension; - - protected virtual string GetProjectFilePath(string binariesDirectoryPath) => string.Empty; - - protected abstract string[] GetArtifactsToCleanup(ArtifactsPaths artifactsPaths); - - protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths) { } - - protected virtual void GenerateNuGetConfig(ArtifactsPaths artifactsPaths) { } - - protected virtual void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) { } + /// + /// returns a path to the folder where auto-generated project and code are going to be placed + /// + [PublicAPI] protected abstract string GetBuildArtifactsDirectoryPath(BuildPartition assemblyLocation, string programName); + + /// + /// returns a path where executable should be found after the build + /// + [PublicAPI] protected virtual string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration) + => buildArtifactsDirectoryPath; + + /// + /// returns OS-specific executable extension + /// + [PublicAPI] protected virtual string GetExecutableExtension() + => RuntimeInformation.ExecutableExtension; + + /// + /// returns a path to the auto-generated .csproj file + /// + [PublicAPI] protected virtual string GetProjectFilePath(string buildArtifactsDirectoryPath) + => string.Empty; + + /// + /// returns a list of artifacts that should be removed after running the benchmarks + /// + [PublicAPI] protected abstract string[] GetArtifactsToCleanup(ArtifactsPaths artifactsPaths); + + /// + /// if you need to copy some extra files to make the benchmarks work you should override this method + /// + [PublicAPI] protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths) { } + + /// + /// generates Nuget.Config file to make sure that BDN is using the right NuGet feeds + /// + [PublicAPI] protected virtual void GenerateNuGetConfig(ArtifactsPaths artifactsPaths) { } + + /// + /// generates .csproj file with a reference to the project with benchmarks + /// + [PublicAPI] protected virtual void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) { } + + /// + /// generates a script can be used when dubugging compilation issues + /// + [PublicAPI] protected abstract void GenerateBuildScript(BuildPartition buildPartition, ArtifactsPaths artifactsPaths); + + /// + /// returns a path to the folder where NuGet packages should be restored + /// + [PublicAPI] protected virtual string GetPackagesDirectoryPath(string buildArtifactsDirectoryPath) + => Path.Combine(buildArtifactsDirectoryPath, "packages"); + + /// + /// genrates an app.config file next to the executable with benchmarks + /// + [PublicAPI] protected virtual void GenerateAppConfig(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) + { + string sourcePath = buildPartition.AssemblyLocation + ".config"; - protected abstract void GenerateBuildScript(BuildPartition buildPartition, ArtifactsPaths artifactsPaths); + using (var source = File.Exists(sourcePath) ? new StreamReader(File.OpenRead(sourcePath)) : TextReader.Null) + using (var destination = new StreamWriter(File.Create(artifactsPaths.AppConfigPath), Encoding.UTF8)) + { + AppConfigGenerator.Generate(buildPartition.RepresentativeBenchmarkCase.Job, source, destination, buildPartition.Resolver); + } + } - protected virtual string GetPackagesDirectoryPath(string buildArtifactsDirectoryPath) => Path.Combine(buildArtifactsDirectoryPath, "packages"); + /// + /// generates the C# source code with all required boilerplate. + /// You most probably do NOT need to override this method!! + /// + [PublicAPI] protected virtual void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) + => File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition)); private ArtifactsPaths GetArtifactsPaths(BuildPartition buildPartition, string rootArtifactsFolderPath) { @@ -78,19 +135,5 @@ private ArtifactsPaths GetArtifactsPaths(BuildPartition buildPartition, string r programName: programName, packagesDirectoryName: GetPackagesDirectoryPath(buildArtifactsDirectoryPath)); } - - private static void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) - => File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition)); - - private static void GenerateAppConfig(BuildPartition buildPartition, ArtifactsPaths artifactsPaths) - { - string sourcePath = buildPartition.AssemblyLocation + ".config"; - - using (var source = File.Exists(sourcePath) ? new StreamReader(File.OpenRead(sourcePath)) : TextReader.Null) - using (var destination = new StreamWriter(File.Create(artifactsPaths.AppConfigPath), Encoding.UTF8)) - { - AppConfigGenerator.Generate(buildPartition.RepresentativeBenchmarkCase.Job, source, destination, buildPartition.Resolver); - } - } } } \ No newline at end of file diff --git a/src/BenchmarkDotNet/Toolchains/Results/BuildResult.cs b/src/BenchmarkDotNet/Toolchains/Results/BuildResult.cs index a1c0137520..91e03cfca3 100644 --- a/src/BenchmarkDotNet/Toolchains/Results/BuildResult.cs +++ b/src/BenchmarkDotNet/Toolchains/Results/BuildResult.cs @@ -1,7 +1,9 @@ using System; +using JetBrains.Annotations; namespace BenchmarkDotNet.Toolchains.Results { + [PublicAPI] public class BuildResult : GenerateResult { public bool IsBuildSuccess { get; } @@ -16,9 +18,9 @@ private BuildResult(GenerateResult generateResult, bool isBuildSuccess, Exceptio public bool FailedToAccess => IsGenerateSuccess && !IsBuildSuccess && BuildException.Message.Contains("cannot access"); - public static BuildResult Success(GenerateResult generateResult) => new BuildResult(generateResult, true, null); + [PublicAPI] public static BuildResult Success(GenerateResult generateResult) => new BuildResult(generateResult, true, null); - public static BuildResult Failure(GenerateResult generateResult, Exception exception = null) => new BuildResult(generateResult, false, exception); + [PublicAPI] public static BuildResult Failure(GenerateResult generateResult, Exception exception = null) => new BuildResult(generateResult, false, exception); public override string ToString() => "BuildResult: " + (IsBuildSuccess ? "Success" : "Failure"); }