Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
added xml docs, made some methods virtual/public to make it easier to…
… write your own toolchain
  • Loading branch information
adamsitnik committed Oct 3, 2018
1 parent 9ff7725 commit 41d6b82
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 41 deletions.
16 changes: 12 additions & 4 deletions src/BenchmarkDotNet/Toolchains/CsProj/CsProjGenerator.cs
Expand Up @@ -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);
Expand All @@ -61,7 +61,11 @@ protected override void GenerateProject(BuildPartition buildPartition, Artifacts
File.WriteAllText(artifactsPaths.ProjectFilePath, content);
}

protected string GetRuntimeSettings(GcMode gcMode, IResolver resolver)
/// <summary>
/// returns an MSBuild string that defines Runtime settings
/// </summary>
[PublicAPI]
protected virtual string GetRuntimeSettings(GcMode gcMode, IResolver resolver)
{
if (!gcMode.HasChanges)
return string.Empty;
Expand Down Expand Up @@ -112,7 +116,11 @@ private string GetSettingsThatNeedsToBeCopied(FileInfo projectFile)
return customSettings.ToString();
}

protected static FileInfo GetProjectFilePath(Type benchmarkTarget, ILogger logger)
/// <summary>
/// returns a path to the project file which defines the benchmarks
/// </summary>
[PublicAPI]
protected virtual FileInfo GetProjectFilePath(Type benchmarkTarget, ILogger logger)
{
if (!GetSolutionRootDirectory(out var solutionRootDirectory))
{
Expand Down
Expand Up @@ -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; }

Expand Down Expand Up @@ -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<EnvironmentVariable> environmentVariables = null, bool useSharedCompilation = false)
{
Expand Down
105 changes: 74 additions & 31 deletions src/BenchmarkDotNet/Toolchains/GeneratorBase.cs
Expand Up @@ -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)
Expand All @@ -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) { }
/// <summary>
/// returns a path to the folder where auto-generated project and code are going to be placed
/// </summary>
[PublicAPI] protected abstract string GetBuildArtifactsDirectoryPath(BuildPartition assemblyLocation, string programName);

/// <summary>
/// returns a path where executable should be found after the build
/// </summary>
[PublicAPI] protected virtual string GetBinariesDirectoryPath(string buildArtifactsDirectoryPath, string configuration)
=> buildArtifactsDirectoryPath;

/// <summary>
/// returns OS-specific executable extension
/// </summary>
[PublicAPI] protected virtual string GetExecutableExtension()
=> RuntimeInformation.ExecutableExtension;

/// <summary>
/// returns a path to the auto-generated .csproj file
/// </summary>
[PublicAPI] protected virtual string GetProjectFilePath(string buildArtifactsDirectoryPath)
=> string.Empty;

/// <summary>
/// returns a list of artifacts that should be removed after running the benchmarks
/// </summary>
[PublicAPI] protected abstract string[] GetArtifactsToCleanup(ArtifactsPaths artifactsPaths);

/// <summary>
/// if you need to copy some extra files to make the benchmarks work you should override this method
/// </summary>
[PublicAPI] protected virtual void CopyAllRequiredFiles(ArtifactsPaths artifactsPaths) { }

/// <summary>
/// generates Nuget.Config file to make sure that BDN is using the right NuGet feeds
/// </summary>
[PublicAPI] protected virtual void GenerateNuGetConfig(ArtifactsPaths artifactsPaths) { }

/// <summary>
/// generates .csproj file with a reference to the project with benchmarks
/// </summary>
[PublicAPI] protected virtual void GenerateProject(BuildPartition buildPartition, ArtifactsPaths artifactsPaths, ILogger logger) { }

/// <summary>
/// generates a script can be used when dubugging compilation issues
/// </summary>
[PublicAPI] protected abstract void GenerateBuildScript(BuildPartition buildPartition, ArtifactsPaths artifactsPaths);

/// <summary>
/// returns a path to the folder where NuGet packages should be restored
/// </summary>
[PublicAPI] protected virtual string GetPackagesDirectoryPath(string buildArtifactsDirectoryPath)
=> Path.Combine(buildArtifactsDirectoryPath, "packages");

/// <summary>
/// genrates an app.config file next to the executable with benchmarks
/// </summary>
[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");
/// <summary>
/// generates the C# source code with all required boilerplate.
/// <remarks>You most probably do NOT need to override this method!!</remarks>
/// </summary>
[PublicAPI] protected virtual void GenerateCode(BuildPartition buildPartition, ArtifactsPaths artifactsPaths)
=> File.WriteAllText(artifactsPaths.ProgramCodePath, CodeGenerator.Generate(buildPartition));

private ArtifactsPaths GetArtifactsPaths(BuildPartition buildPartition, string rootArtifactsFolderPath)
{
Expand All @@ -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);
}
}
}
}
6 changes: 4 additions & 2 deletions 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; }
Expand All @@ -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");
}
Expand Down

0 comments on commit 41d6b82

Please sign in to comment.