Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
experimental .NET Core support for the new VS 2017 csproj files, #300
  • Loading branch information
adamsitnik committed Jan 26, 2017
1 parent f99c827 commit c7aba11
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 8 deletions.
18 changes: 18 additions & 0 deletions src/BenchmarkDotNet.Core/Templates/CsProj.txt
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk" ToolsVersion="15.0">
<PropertyGroup>
<AssemblyTitle>BenchmarkDotNet.Autogenerated</AssemblyTitle>
<TargetFramework>$TFM$</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<PlatformTarget>$PLATFORM$</PlatformTarget>
<AssemblyName>BenchmarkDotNet.Autogenerated</AssemblyName>
<OutputType>Exe</OutputType>
</PropertyGroup>

<ItemGroup>
<Compile Include="$CODEFILENAME$" Exclude="bin\**;obj\**;**\*.xproj;packages\**" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\$EXECUTINGASSEMBLY$\$EXECUTINGASSEMBLY$.csproj" />
</ItemGroup>
</Project>
44 changes: 44 additions & 0 deletions src/BenchmarkDotNet.Core/Toolchains/CsProj/CsProjGenerator.cs
@@ -0,0 +1,44 @@
using System;
using System.IO;
using BenchmarkDotNet.Characteristics;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Helpers;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.DotNetCli;
using System.Reflection;

namespace BenchmarkDotNet.Toolchains.CsProj
{
public class CsProjGenerator : DotNetCliGenerator
{
public CsProjGenerator(string targetFrameworkMoniker, Func<Platform, string> platformProvider)
: base(targetFrameworkMoniker, null, platformProvider, null, null)
{
}

protected override string GetProjectFilePath(string binariesDirectoryPath)
=> Path.Combine(binariesDirectoryPath, "BenchmarkDotNet.Autogenerated.csproj");

protected override void GenerateProject(Benchmark benchmark, ArtifactsPaths artifactsPaths, IResolver resolver)
{
string template = ResourceHelper.LoadTemplate("CsProj.txt");

string content = SetPlatform(template, PlatformProvider(benchmark.Job.ResolveValue(EnvMode.PlatformCharacteristic, resolver)));
content = SetCodeFileName(content, Path.GetFileName(artifactsPaths.ProgramCodePath));
content = SetDependencyToExecutingAssembly(content, benchmark.Target.Type);
content = SetTargetFrameworkMoniker(content, TargetFrameworkMoniker);
//content = SetGcMode(content, benchmark.Job.Env.Gc, resolver); todo: implement

File.WriteAllText(artifactsPaths.ProjectFilePath, content);
}

protected override string SetDependencyToExecutingAssembly(string template, Type benchmarkTarget)
{
var assemblyName = benchmarkTarget.GetTypeInfo().Assembly.GetName();

// todo: support custom path .csprojs, now it's <ProjectReference Include="..\$EXECUTINGASSEMBLY$\$EXECUTINGASSEMBLY$.csproj" />
return template.Replace("$EXECUTINGASSEMBLY$", assemblyName.Name);
}
}
}
39 changes: 39 additions & 0 deletions src/BenchmarkDotNet.Core/Toolchains/CsProj/CsProjToolchain.cs
@@ -0,0 +1,39 @@
using BenchmarkDotNet.Characteristics;
using BenchmarkDotNet.Environments;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.Core;
using BenchmarkDotNet.Toolchains.DotNetCli;

namespace BenchmarkDotNet.Toolchains.CsProj
{
/// <summary>
/// very simple, experimental version
/// limitations:
/// can not set process priority and/or affinity
/// can not break with ctrl+c
/// does not support custom GcMode settings (will change in the future)
/// does not support x86 settings (will change in the future)
/// </summary>
public class CsProjToolchain : Toolchain
{
public static readonly IToolchain NetCoreApp11 = From(NetCoreAppSettings.NetCoreApp11);
public static readonly IToolchain NetCoreApp12 = From(NetCoreAppSettings.NetCoreApp12);
public static readonly IToolchain NetCoreApp20 = From(NetCoreAppSettings.NetCoreApp20);

private CsProjToolchain(string name, IGenerator generator, IBuilder builder, IExecutor executor)
: base(name, generator, builder, executor)
{
}

private static IToolchain From(NetCoreAppSettings settings)
=> new CsProjToolchain("CsProjCore",
new CsProjGenerator(settings.TargetFrameworkMoniker, PlatformProvider),
new DotNetCliBuilder(settings.TargetFrameworkMoniker),
new DotNetRunExecutor());

// dotnet cli supports only x64 compilation now
private static string PlatformProvider(Platform platform) => "x64";
}
}
55 changes: 55 additions & 0 deletions src/BenchmarkDotNet.Core/Toolchains/CsProj/DotnetRunExecutor.cs
@@ -0,0 +1,55 @@
using System.Diagnostics;
using System.IO;
using BenchmarkDotNet.Characteristics;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Loggers;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Toolchains.DotNetCli;
using BenchmarkDotNet.Toolchains.Results;

namespace BenchmarkDotNet.Toolchains.CsProj
{
/// <summary>
/// very simple, experimental version
/// limitations: can not set process priority and/or affinity + can not break with ctrl+c (verify)
/// </summary>
public class DotNetRunExecutor : IExecutor
{
public ExecuteResult Execute(BuildResult buildResult, Benchmark benchmark, ILogger logger, IResolver resolver, IDiagnoser diagnoser = null)
{
return Execute(benchmark, logger, buildResult.ArtifactsPaths.BuildArtifactsDirectoryPath, diagnoser, resolver);
}

private ExecuteResult Execute(Benchmark benchmark, ILogger logger, string workingDirectory, IDiagnoser diagnoser,
IResolver resolver)
{
using (var process = new Process { StartInfo = DotNetCliCommandExecutor.BuildStartInfo(workingDirectory, "run --configuration Release") }) // there is only one framework in the .csproj, no need to specify it
{
var loggerWithDiagnoser = new SynchronousProcessOutputLoggerWithDiagnoser(logger, process, diagnoser, benchmark);

//consoleHandler.SetProcess(process); // todo

process.Start();

//process.EnsureHighPriority(logger); // todo
//if (benchmark.Job.Env.HasValue(EnvMode.AffinityCharacteristic))
//{
// process.EnsureProcessorAffinity(benchmark.Job.Env.Affinity);
//}

loggerWithDiagnoser.ProcessInput();

process.WaitForExit(); // should we add timeout here?

if (process.ExitCode == 0)
{
return new ExecuteResult(true, process.ExitCode, loggerWithDiagnoser.LinesWithResults, loggerWithDiagnoser.LinesWithExtraOutput);
}

return new ExecuteResult(true, process.ExitCode, new string[0], new string[0]);
}
}
}
}
Expand Up @@ -51,7 +51,7 @@ internal static bool ExecuteCommand(string commandWithArguments, string workingD
}
}

private static ProcessStartInfo BuildStartInfo(string workingDirectory, string arguments)
internal static ProcessStartInfo BuildStartInfo(string workingDirectory, string arguments)
{
return new ProcessStartInfo
{
Expand Down
Expand Up @@ -16,11 +16,11 @@ namespace BenchmarkDotNet.Toolchains.DotNetCli
[PublicAPI("Used by some of our Superusers that implement their own Toolchains (e.g. Kestrel team)")]
public class DotNetCliGenerator : GeneratorBase
{
private string TargetFrameworkMoniker { get; }
protected string TargetFrameworkMoniker { get; }

private string ExtraDependencies { get; }
protected Func<Platform, string> PlatformProvider { get; }

private Func<Platform, string> PlatformProvider { get; }
private string ExtraDependencies { get; }

private string Imports { get; }

Expand Down Expand Up @@ -131,11 +131,11 @@ protected override void GenerateBuildScript(Benchmark benchmark, ArtifactsPaths
File.WriteAllText(artifactsPaths.BuildScriptFilePath, content);
}

private static string SetPlatform(string template, string platform) => template.Replace("$PLATFORM$", platform);
protected static string SetPlatform(string template, string platform) => template.Replace("$PLATFORM$", platform);

private static string SetCodeFileName(string template, string codeFileName) => template.Replace("$CODEFILENAME$", codeFileName);
protected static string SetCodeFileName(string template, string codeFileName) => template.Replace("$CODEFILENAME$", codeFileName);

private static string SetDependencyToExecutingAssembly(string template, Type benchmarkTarget)
protected virtual string SetDependencyToExecutingAssembly(string template, Type benchmarkTarget)
{
var assemblyName = benchmarkTarget.GetTypeInfo().Assembly.GetName();
string packageVersion = GetPackageVersion(assemblyName);
Expand All @@ -145,7 +145,7 @@ private static string SetDependencyToExecutingAssembly(string template, Type ben
Replace("$EXECUTINGASSEMBLY$", assemblyName.Name);
}

private static string SetTargetFrameworkMoniker(string content, string targetFrameworkMoniker) => content.Replace("$TFM$", targetFrameworkMoniker);
protected static string SetTargetFrameworkMoniker(string content, string targetFrameworkMoniker) => content.Replace("$TFM$", targetFrameworkMoniker);

private static string SetExtraDependencies(string content, string extraDependencies) => content.Replace("$REQUIREDDEPENDENCY$", extraDependencies);

Expand Down

0 comments on commit c7aba11

Please sign in to comment.