Code Monkey home page Code Monkey logo

buildalyzer's Introduction

A utility to perform design-time builds of .NET projects without having to think too hard about it.

Buildalyzer Logo

NuGet

GitHub

Donations

If you found this library useful, consider sponsoring more of it on GitHub. I promise to use it on something totally frivolous and unrelated.

Sponsor

Sponsors

AWS Logo

Amazon Web Services (AWS) generously sponsors this project. Go check out what they have to offer for .NET developers (it's probably more than you think).


What Is It?

Buildalyzer lets you run MSBuild from your own code and returns information about the project. By default, it runs a design-time build which is higher performance than a normal build because it doesn't actually try to compile the project. You can use it to perform analysis of MSBuild projects, get project properties, or create a Roslyn Workspace using Buildalyzer.Workspaces. It runs MSBuild out-of-process and therefore should work anywhere, anytime, and on any platform you can build the project yourself manually on the command line.

AnalyzerManager manager = new AnalyzerManager();
IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
IAnalyzerResults results = analyzer.Build();
string[] sourceFiles = results.First().SourceFiles;

These blog posts might also help explain the motivation behind the project and how it works:

Installation

Buildalyzer is available on NuGet and can be installed via the commands below:

$ Install-Package Buildalyzer

or via the .NET Core CLI:

$ dotnet add package Buildalyzer

Buildalyzer.Workspaces is available on NuGet and can be installed via the commands below:

$ Install-Package Buildalyzer.Workspaces

or via the .NET Core CLI:

$ dotnet add package Buildalyzer.Workspaces

Both packages target .NET Standard 2.0.

Usage

There are two main classes in Buildalyzer: AnalyzerManager and ProjectAnalyzer.

The AnalyzerManager class coordinates loading each individual project and consolidates information from a solution file if provided.

The ProjectAnalyzer class figures out how to configure MSBuild and uses it to load and compile the project in design-time mode. Using a design-time build lets us get information about the project such as resolved references and source files without actually having to call the compiler.

To get a ProjectAnalyzer you first create an AnalyzerManager and then call GetProject():

AnalyzerManager manager = new AnalyzerManager();
IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");

You can add all projects in a solution to the AnalyzerManager by passing the solution path as the first argument of the AnalyzerManager constructor. This will parse the solution file and execute GetProject() for each of the projects that it finds.

Calling GetProject() again for the same project path will return the existing ProjectAnalyzer. You can iterate all the existing project analyzers with the IReadOnlyDictionary<string, ProjectAnalyzer> property AnalyzerManager.Projects.

To build the project, which triggers evaluation of the specified MSBuild tasks and targets but stops short of invoking the compiler by default in Buildalyzer, call Build(). This method has a number of overloads that lets you customize the build process by specifying target frameworks, build targets, and more.

Results

Calling ProjectAnalyzer.Build() (or an overload) will return an AnalyzerResults object, which is a collection of AnalyzerResult objects for each of the target frameworks that were built. It will usually only contain a single AnalyzerResult unless the project is multi-targeted.

AnalyzerResult contains several properties and methods with the results from the build:

AnalyzerResult.TargetFramework - The target framework of this particular result (each result consists of data from a particular target framework build).

AnalyzerResult.SourceFiles - The full path of all resolved source files in the project.

AnalyzerResult.References - The full path of all resolved references in the project.

AnalyzerResult.ProjectReferences - The full path of the project file for all resolved project references in the project.

AnalyzerResult.Properties - A IReadOnlyDictionary<string, string> containing all MSBuild properties from the project.

AnalyzerResult.GetProperty(string) - Gets the value of the specified MSBuild property.

AnalyzerResult.Items - A IReadOnlyDictionary<string, ProjectItem[]> containing all MSBuild items from the project (the ProjectItem class contains the item name/specification as ProjectItem.ItemSpec and all it's metadata in a IReadOnlyDictionary<string, string> as ProjectItem.Metadata).

Adjusting MSBuild Properties

Buildalyzer sets some MSBuild properties to make loading and compilation work the way it needs to (for example, to trigger a design-time build). You can view these properties with the IReadOnlyDictionary<string, string> property ProjectAnalyzer.GlobalProperties.

If you want to change the configured properties before loading or compiling the project, there are two options:

  • AnalyzerManager.SetGlobalProperty(string key, string value) and AnalyzerManager.RemoveGlobalProperty(string key). This will set the global properties for all projects loaded by this AnalyzerManager.

  • ProjectAnalyzer.SetGlobalProperty(string key, string value) and ProjectAnalyzer.RemoveGlobalProperty(string key). This will set the global properties for just this project.

Be careful though, you may break the ability to load, compile, or interpret the project if you change the MSBuild properties.

Binary Log Files

Buildalyzer can also read MSBuild binary log files:

AnalyzerManager manager = new AnalyzerManager();
IAnalyzerResults results = manager.Analyze(@"C:\MyCode\MyProject.binlog");
string[] sourceFiles = results.First().SourceFiles;

This is useful if you already have a binary log file and want to analyze it with Buildalyzer the same way you would build results.

Logging

Buildalyzer uses the Microsoft.Extensions.Logging framework for logging MSBuild output. When you create an AnayzerManager you can specify an ILoggerFactory that Buildalyzer should use to create loggers. By default, the ProjectAnalyzer will log MSBuild output to the provided logger.

You can also log to a StringWriter using AnalyzerManagerOptions:

StringWriter log = new StringWriter();
AnalyzerManagerOptions options = new AnalyzerManagerOptions
{
    LogWriter = log
};
AnalyzerManager manager = new AnalyzerManager(path, options);
// ...
// check log.ToString() after build for any error messages

Roslyn Workspaces

The extension library Buildalyzer.Workspaces adds extension methods to the Buildalyzer ProjectAnalyzer that make it easier to take Buildalyzer output and create a Roslyn AdhocWorkspace from it:

using Buildalyzer.Workspaces;
using Microsoft.CodeAnalysis;
// ...

AnalyzerManager manager = new AnalyzerManager();
IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
AdhocWorkspace workspace = analyzer.GetWorkspace();

You can also create your own workspace and add Buildalyzer projects to it:

using Buildalyzer.Workspaces;
using Microsoft.CodeAnalysis;
// ...

AnalyzerManager manager = new AnalyzerManager();
IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
AdhocWorkspace workspace = new AdhocWorkspace();
Project roslynProject = analyzer.AddToWorkspace(workspace);

In both cases, Buildalyzer will attempt to resolve project references within the Roslyn workspace so the Roslyn projects will correctly reference each other.

buildalyzer's People

Contributors

0xced avatar adaskothebeast avatar azyobuzin avatar bernd5 avatar bjorkstromm avatar colombod avatar corniel avatar cslong avatar daveaglick avatar dfederm avatar dukedagmor avatar echalone avatar farnyser avatar fbd avatar itn3000 avatar jairbubbles avatar jonstelly avatar josephwoodward avatar ltcmelo avatar markrendle avatar mpdreamz avatar pentp avatar phmonte avatar psfinaki avatar reubenbond avatar sapsari avatar siegfriedpammer avatar slang25 avatar svick avatar tjchester avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

buildalyzer's Issues

Outputs get cleaned

It seems to kind of defeat the purpose of a design-time build to do a clean beforehand. If the project were previously built via normal methods, the outputs will disappear after doing a design-time build.

It seems like at the very least this should be a flag,

Can't parse certain project files

Someone using a tool I wrote, which in turn calls into Buildalyzer, reported this exception:

Unhandled Exception: System.Xml.XmlException: System does not support 'Windows-1252' encoding. Line 1, position 31. ---> System.ArgumentException: 'Windows-1252' is not a supported encoding name. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method. Parameter name: name
at System.Globalization.EncodingTable.internalGetCodePageFromName(String name)
at System.Globalization.EncodingTable.GetCodePageFromName(String name)
at System.Text.Encoding.GetEncoding(String name)
at System.Xml.XmlTextReaderImpl.CheckEncoding(String newEncodingName)
--- End of inner exception stack trace ---
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String[] args, Exception innerException)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg, Exception innerException)
at System.Xml.XmlTextReaderImpl.CheckEncoding(String newEncodingName)
at System.Xml.XmlTextReaderImpl.ParseXmlDeclaration(Boolean isTextDecl)
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.Linq.XDocument.Load(XmlReader reader, LoadOptions options)
at System.Xml.Linq.XDocument.Load(String uri, LoadOptions options)
at Buildalyzer.AnalyzerManager.GetProject(String projectFilePath)

Possible problems with latest SDK not including dependencies alongside Microsoft.NET.Build.Tasks

See dotnet/sdk#2108

If there's no easy resolution within MSBuild and the SDK does stop shipping the assemblies alongside, then we could potentially crawl up the SDK folders when assembly resolution fails:

private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    // Crawl up from the _buildEnvironment.ToolsPath (or _buildEnvironment.SDKsPath?) to see if the missing assemblies can be located
}

This would probably need to go in AnalyzerManager so that the hooks only get added once. We'd also want to use a static flag to keep track of whether we've already added the hooks in the case of multiple managers. May need to consider making AnalyzerManager disposable too and unregister the hooks on disposal.

Failure when loading solution containing Xamarin projects

Microsoft.Build.Exceptions.InvalidProjectFileException occurred
  HResult=0x80131500
  Message=The imported project "C:\Program Files\dotnet\sdk\2.0.2\Xamarin\Android\Xamarin.Android.CSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
  Source=<Cannot evaluate the exception source>
  StackTrace:
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpression(String directoryOfImportingFile, ProjectImportElement importElement, String unescapedExpression, Boolean throwOnFileNotExistsError, List`1& imports)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(String directoryOfImportingFile, ProjectImportElement importElement, List`1& projects, Boolean throwOnFileNotExistsError)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(ILoggingService loggingService, BuildEventContext buildEventContext)
   at Microsoft.Build.Evaluation.Project.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
   at Buildalyzer.ProjectAnalyzer.Load()
   at Buildalyzer.ProjectAnalyzer.Compile()
   at Buildalyzer.Workspaces.ProjectAnalyzerExtensions.AddToWorkspace(ProjectAnalyzer analyzer, AdhocWorkspace workspace, Boolean addProjectReferences)
   at Buildalyzer.Workspaces.AnalyzerManagerExtensions.GetWorkspace(AnalyzerManager manager)
   at PCLMock.CodeGeneration.Generator.<GenerateMocksAsync>d__2.MoveNext() in C:\Users\Kent\Repository\PCLMock\Src\PCLMock.CodeGeneration\Generator.cs:line 41

Symbol analysis not working against solution

My code for loading a solution looks like this:

var manager = new AnalyzerManager(initialPath);
var solution = manager.GetWorkspace().CurrentSolution;

Whilst this seems to take a lot longer than it did previously under Roslyn, it does eventually give me what is ostensibly a working Solution.

However, when I try and analyze symbols within the compilation, I see nothing. Specifically, this code (which starts with the global namespace symbol) never finds any other symbol.

Interestingly, if I look at the ProjectReferences, it is empty, even for projects in the solution that definitely reference other projects in the solution. It's not clear to me whether this is the underlying cause.

On a hunch, I tried doing this after creating my AnalyzerManager:

foreach (var p in manager.Projects)
{
    p.Value.Compile();
}

But that did not help.

Unable to get compilation

When calling GetCompilationAsync I am seeing TaskCanceledException for some projects. Digging in, I found that the build itself is failing:

var buildalyzerLogFactory = new BuildalyzerLogFactory(logSink);
var manager = new AnalyzerManager(initialPath, loggerFactory: buildalyzerLogFactory);
var solution = manager.GetWorkspace().CurrentSolution;

In this code, the final line triggers a build of the solution. Here is the full log output of my application run, which includes the Buildalyzer output interspersed with my own library's output.

Notice these points of interest:

  • All references seem to conflict...with themselves
  • The Xamarin.Forms project appears to create problems with respect to Xamarin.Forms.Build.Tasks.FixedCreateCSharpManifestResourceName
  • You can see the TaskCanceledException at the end. I get this when attempting to get the compilation for the Services.Connected project. Other projects (Utility, ViewModels, and Services) do successfully return a compilation (I have no idea if it's usable yet though)

Use the same logger for Restore and other targets

Currently when AddBinaryLogger is used, a binlog is created for the Restore, but then it's plowed over by the build of the remaining targets.

However, the behavior we want is the same as when using msbuild /restore /bl (note the /restore and not /t:Restore) which does a restore in a separate build session as the rest, but still shares the same logger.

Example of what it should look like:
image

MSBUILD_EXE_PATH

This is more of an observation than an issue at this point.

I've been trying to use Buildalyzer (v0.2.3) with .NET Core on macOS. The log from Buildalyzer would show that my projects were failing to compile because it could not find Microsoft.CSharp.targets. The strange thing, though, was that the directory of the path name was my project directory rather than the .NET Sdk directory. Basically, MSBuildToolsPath was wrong.

After poking around the msbuild source code, I found that there is an MSBUILD_EXE_PATH environment variable that can be used to help get the correct MSBuildToolsPath configured. If I set it like this:

export MSBUILD_EXE_PATH=/usr/local/share/dotnet/sdk/2.1.4/MSBuild.dll

... then MSBuild (and therefore Buildalyzer) are happy.

csc.dll is confused for source file under dotnet test

Problem

I use Buildalyzer to populate an AdhocWorkspace, like this:

var workspace = new AdhocWorkspace();
var analyzerManager = new AnalyzerManager();

foreach (var filePath in projectFilePaths)
{
    ProjectAnalyzer analyzer = _analyzerManager.GetProject(filePath);
    analyzer.AddToWorkspace(workspace);
}

then I compile a project like this:

var compilation = workspace.CurrentSolution.Projects.First().GetCompilationAsync().Result;

My integration tests (written with NUnit) successfully pass when run by ReSharper in Visual Studio. When I try to run them in a console with dotnet test, I get a weird behavior: GetCompilationAsync() produces diagnostics where the compiler complains:

C:\Program Files\dotnet\sdk\2.1.302\Roslyn\bincore\csc.dll(1,1): error CS0116: A namespace cannot directly contain members such as fields or methods

and several screens of strings similar to:

\u0013\u0015Microsoft Corporation1&0$\u0006\u0003U\u0004\u0003\u0013\u001dMicrosoft Time-Stamp PCA 2010\u0002\u00133\u0000

Environment

> dotnet --info

.NET Core SDK (reflecting any global.json):
 Version:   2.1.302
 Commit:    9048955601

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.16299
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.302\

Host (useful for support):
  Version: 2.1.2
  Commit:  811c3ce6c0

.NET Core SDKs installed:
  2.1.2 [C:\Program Files\dotnet\sdk]
  2.1.104 [C:\Program Files\dotnet\sdk]
  2.1.201 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.302 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

Some code review suggestions

Investigating the previous issue I opened took me through a small part of the Buildalyzer source, and I saw a couple of things that could potentially be changed/improved:

  • The TemporaryEnvironment class is unnecessary if you call the overloads of Environment.GetEnvironmentVariable/Environment.SetEnvironmentVariable that take an EnvironmentVariableTarget and specify EnvironmentVariableTarget.Process - doing so will cause any modifications to environment variables to be discarded when the current process exits
  • DotnetPathResolver.GetInfo() should probably call process.WaitForExit(4000) instead of using a Stopwatch+while loop

Can't parse dotnet --info when using global.json if version not found

Output looks something like:

A compatible SDK version for global.json version: [1.0.0-preview2-1-003177] from [E:\Code\Buildalyzer\tests\repos\AngleSharp\global.json] was not found

Host (useful for support):
  Version: 2.1.0
  Commit:  caa7b7e2ba

.NET Core SDKs installed:
  2.1.200 [C:\Program Files\dotnet\sdk]
  2.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.7 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Identify SDK projects by import statements

Turns out you can also identify SDK projects via imports and there may not be a root SDK attribute:
dotnet/msbuild#1493

Right now we just look for the SDK attribute on the root element in the project file. Add support for locating SDK import elements if the SDK attribute isn't found.

PackageReference assemblies not returned by GetReferences() for full framework projects

It seems that GetReferences() on ProjectAnalyzer doesn't return assemblies from NuGet packages if PackageReference is being used instead of packages.config. This causes compilation errors in Roslyn workspaces.

Interestingly this only seems to be a problem when the host is .NET Core. It works just fine when the host is .NET Framework. I added some tests in this commit that show this behaviour. I also see errors in the test output which are very similar to #29.

Missing TestInfo class in MSBuild

Adding this for posterity...

Tests were blowing up:

Target ResolvePackageAssets:
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018: The "ResolvePackageAssets" task failed unexpectedly.
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018: System.NullReferenceException: Object reference not set to an instance of an object.
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at NuGet.ProjectModel.LockFileFormat.Read(TextReader reader, ILogger log, String path)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at NuGet.ProjectModel.LockFileFormat.Read(Stream stream, ILogger log, String path)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at NuGet.Common.FileUtility.SafeRead[T](String filePath, Func`3 read)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at NuGet.ProjectModel.LockFileUtilities.GetLockFile(String lockFilePath, ILogger logger)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.LockFileCache.LoadLockFile(String path)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.LockFileCache.GetLockFile(String path)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheWriter..ctor(ResolvePackageAssets task, Stream stream)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader.CreateReaderFromDisk(ResolvePackageAssets task, Byte[] settingsHash)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolvePackageAssets.CacheReader..ctor(ResolvePackageAssets task)
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ReadItemGroups()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.ResolvePackageAssets.ExecuteCore()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.NET.Build.Tasks.TaskBase.Execute()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
Done building target "ResolvePackageAssets" in project "SdkFrameworkProject.csproj" -- FAILED.

Traced it back to this block in BuildEnvironmentHelper (which is used from NuGet.MSBuildSdkResolver):

    private static bool CheckIfRunningTests()
    {
      if (BuildEnvironmentHelper._runningTests.HasValue)
        return BuildEnvironmentHelper._runningTests.Value;
      lock (BuildEnvironmentHelper._runningTestsLock)
      {
        if (BuildEnvironmentHelper._runningTests.HasValue)
          return BuildEnvironmentHelper._runningTests.Value;
        BuildEnvironmentHelper._runningTests = new bool?((bool) typeof (ITask).Assembly.GetType("Microsoft.Build.Framework.TestInfo").GetField("s_runningTests", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue((object) null));
        return BuildEnvironmentHelper._runningTests.Value;
      }
    }

Specifically, the call to (ITask).Assembly.GetType("Microsoft.Build.Framework.TestInfo") was returning null because the FrameworkTests project didn't have the latest version of Microsoft.Build.Framework and the TestInfo class was added recently.

Features in .csproj are ignored.

I am trying to use the "Flow-Analysis" which should be added to a .csproj like this

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <Features>Flow-Analysis</Features>
  </PropertyGroup>

However when I try to use your library like this:

AnalyzerManager manager = new AnalyzerManager();
 ProjectAnalyzer analyzer = manager.GetProject(@"path/to/my/project.csproj");
AdhocWorkspace workspace = analyzer.GetWorkspace();
var project = workspace.CurrentSolution.Projects.First();
System.Console.WriteLine(project.ParseOptions.Features.Count);

The output will be 0, the feature is not added to my project.

Some features like the ControlFlowGraph need those to be used

Ex: http://source.roslyn.io/#Microsoft.CodeAnalysis/Operations/ControlFlowGraph.cs line 74

if (!operation.Syntax.SyntaxTree.Options.Features.ContainsKey("flow-analysis"))
{
    throw new InvalidOperationException(CodeAnalysisResources.FlowAnalysisFeatureDisabled);
}

VS Live Unit Testing

Hello,

Firs thanks for the job.
I have some problem when running tests with Live Unit Testing as it's not using CscCommandLineArgs. So the project has no document and no reference.

I m going to investigate a bit further on this. So I can compare Items from a run with CscCommandLineArgs and without.

Incorrect OutputKind in AdhocWorkspace

I've noticed when loading a project into the AdHocWorkspace the OutputKind enum is always set to ConsoleApplication (see below as an example).

Having looked through the Buildalyzer source code can't see where the project type is inferred, leading me to assume the reason it's set to ConsoleApplication is because it's the first property in the OutputKind enum so defaults to that.

var analyzer = new Analyzer();
var projectAnalyzer = analyzer.GetProject(@"../demo/ExampleDllLibrary.csproj");
var workspace = projectAnalyzer.GetWorkspace();
var project = workspace.CurrentSolution.Projects.FirstOrDefault(x => x.AssemblyName == "ExampleDllLibrary");
OutputKind kind = project.CompilationOptions.OutputKind;
Console.WriteLine(kind); // ConsoleApplication

Not being too savvy with the MSBuild API I'm wondering if you can point me in the right direction of where I'd be able to get this information so I can create a PR to fix it?

Missing 'NuGet' dependencies when ran on macos

Buildalyzer was crashing out from missing dependencies until I added in the following packages:

  • NuGet.Build.Tasks
  • NuGet.Common
  • NuGet.ProjectModel.
    It would throw an exception at runtime when trying to restore a project's dependencies, these dependencies might need to be added to buildalyzer for it to run smoothly under macos(this could be due to macos needing to use mono instead of dotnet?).

Add link to Buildalyzer blog post(s)

I came across this project before I read this blog post and have to admit I was very impressed but also very confused about what Buildalyzer was for. The blog post clears it up, so I think would be worth linking to from the readme?

Change fallback logging to TextWriter

StringBuilder wasn't a great fallback logging option to begin with. TextWriter provides more flexibility while still enabling string-based logging with a StringWriter.

Loading multiple projects to pass into a workspace

When loading a project and subsequently turning it into a workspace via the workspace extension method, I'm interested including any project dependencies that project may have and adding those to the workspace.

What is the best way of doing this without facing the cost of multiple analyzers? Looking at the data of the ProjectAnalyzer I see you can get a list of referenced projects, but from what I can see they're not loaded and there's no way to include them.

If this isn't possible yet then I'd be happy to look at contributing that option if you could give me a head start on where to look?

Strong name signing of Buildalyzer?

Hi

I am one of the maintainer of SpecFlow (https://github.com/techtalk/SpecFlow) and we want to use Buildalyzer to add .NET Standard/Core 2.0 to SpecFlow.
Our project is used by a lot of enterprises and they somehow like strong name signing. So we are signing our stuff also with a strong name.
Buildalyzer is currently not strong named signed. So that we can use it, we would need Buildalayzer strong named signed.

Would this be possible? If we provide a PR for that, would it be merged?

Some imports don't load correctly

The current working directory is usually the project folder, when loading a project in MSBuild.
Should I manually set the current directory to the project directory or should it be handled by Buildalyzer? Some imports may not be found because of the current working directory, maybe it can be set when calling MSBuild?

Trouble finding targets for Autofac

I introduced some integration tests and am now seeing the following error when building Autofac (cc @JasonBock)

Project "E:\Code\Buildalyzer\tests\repos\Autofac\src\Autofac\Autofac.csproj" (Clean target(s)):

Target Clean:
    __________________________________________________
    Project "E:\Code\Buildalyzer\tests\repos\Autofac\src\Autofac\Autofac.csproj" is building "E:\Code\Buildalyzer\tests\repos\Autofac\src\Autofac\Autofac.csproj" (Clean target(s)):

    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.targets(41,3): error MSB4019: The imported project "E:\NuGet\microsoft.testplatform.testhost\15.7.2\lib\netstandard1.5\Microsoft.CSharp.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

    Done building project "Autofac.csproj" -- FAILED.

Don't include newlines when formatting logs

A small thing, really, but kinda annoying. Formatting a log entry via the ILogger.Log formatter parameter adds a new line to the end. This makes it difficult to integrate with some logging solutions that also add a new line for you when you invoke them. Wouldn't it be better to just return the string without a new line and let the caller handle it?

Investigate failures on AppVeyor

I'm seeing some odd build failures when using (not building) Buildalyzer on AppVeyor. I think I've got a handle on what's going on, but want to get some notes down heading into the weekend.

The error I started seeing was this:

Microsoft.Build.Exceptions.InvalidProjectFileException: The imported project "C:\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.  C:\Program Files\dotnet\sdk\2.1.103\Microsoft.Common.CrossTargeting.targets
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject[T1](IElementLocation elementLocation, String resourceName, T1 arg0)
...

If you look at "Microsoft.Common.CrossTargeting.targets" it contains:

<!--
    This will import NuGet restore targets. We need restore to work before any package assets are available.
  -->
  <PropertyGroup>
    <NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'=='' and '$([MSBuild]::IsRunningFromVisualStudio())'=='true'">$(MSBuildToolsPath32)\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets</NuGetRestoreTargets>
    <NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'==''">$(MSBuildToolsPath)\NuGet.targets</NuGetRestoreTargets>
  </PropertyGroup>

  <Import Project="$(NuGetRestoreTargets)" />
-->

So it appears that the intrinsic method IsRunningFromVisualStudio() is true which causes us to pick the first branch, except the property MSBuildToolsPath32 is empty so we end up at the root before looking for the "NuGet.targets" file in the wrong place. That method just checks the mode from BuildEnvironmentHelper which gets set here.

My best guess is that AppVeyor either sets the "VSINSTALLDIR" or "VisualStudioVersion" environment variable which causes BuildEnvironmentHelper to determine we're running from Visual Studio here even though we're not.

We need to fail the VS test and instead pick the "NuGet.targets" file off the MSBuildToolsPath property. A couple thoughts:

  • Could figure out which of the two envionment variables is set in AppVeyor and unset them in the AppVeyor.yml file - that would help me but not the general case
  • Could unset both of these when running Buildalyzer and then set them back afterwards
  • Could short-circuit the whole thing by setting "MSBUILD_EXE_PATH" (see here) (leaning towards this option - it's also what DocFx does).

Problem building SDK-style .NET Framework projects

Build started 10/24/2017 4:03:49 PM.
__________________________________________________
Project "E:\Code\Wyam.Web\release\repo\src\core\Wyam.Common\Wyam.Common.csproj" (Clean target(s)):


Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.87
Build started 10/24/2017 4:03:50 PM.
__________________________________________________
Project "E:\Code\Wyam.Web\release\repo\src\core\Wyam.Common\Wyam.Common.csproj" (Compile target(s)):

Target ImplicitlyExpandNETStandardFacades:
  C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.NETFramework.targets(48,5): error MSB4062: The "GetDependsOnNETStandard" task could not be loaded from the assembly C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll. Could not load file or assembly 'file:///C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
Done building target "ImplicitlyExpandNETStandardFacades" in project "Wyam.Common.csproj" -- FAILED.

Done building project "Wyam.Common.csproj" -- FAILED.

Build FAILED.

C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.NETFramework.targets(48,5): error MSB4062: The "GetDependsOnNETStandard" task could not be loaded from the assembly C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll. Could not load file or assembly 'file:///C:\Program Files\dotnet\sdk\2.0.2\Microsoft\Microsoft.NET.Build.Extensions\tools\net46\Microsoft.NET.Build.Extensions.Tasks.dll' or one of its dependencies. The system cannot find the file specified. Confirm that the <UsingTask> declaration is correct, that the assembly and all its dependencies are available, and that the task contains a public class that implements Microsoft.Build.Framework.ITask.
    0 Warning(s)
    1 Error(s)

Time Elapsed 00:00:00.16

GetReferences returns null although the project does reference other assemblies

Buildalyzer is a really nice OSS project, by the way. I'm just getting started with it, and am having a problem. Thanks in advance!

I've got a .NET Core 2.1 preview project whose .csproj looks like this:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <Folder Include="wwwroot\" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.3" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="FluentCommandLineParser" Version="1.4.3" />
    <PackageReference Include="Microsoft.Extensions.Logging.Log4Net.AspNetCore" Version="2.0.3" />
  </ItemGroup>
  <ItemGroup>
    <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.1" />
  </ItemGroup>
</Project>

My code to display references looks like this:

                AnalyzerManager manager = new AnalyzerManager();
                Buildalyzer.ProjectAnalyzer analyzer = manager.GetProject(projectFilename);
                Project proj = analyzer.Load();
                IEnumerable<string> references = analyzer.GetReferences();
                if (references == null)
                {
                    Console.WriteLine("No references found. Quitting.");
                    return;
                }

                foreach (var r in references)
                    Console.WriteLine(r);

It always returns null for references. Is this not supported for .NET Core 2.* yet?

Bob

Compilation peformance

Hi,

I'm currently using Buildalyzer to generate an adhocworkspace and noticing that the initial compilation takes almost 40 seconds. The second run afterwards takes about 8 seconds, having done a bit of debugging it appears that it comes down to this line:

if (!projectInstance.Build("Compile", _logger == null ? null : new ILogger[] { _logger }))
{
    return null;
}

Is this level of performance expected, or could it be the way I'm using it, or are there any configuration options I can set to speed up compilation?

My usage seems pretty straight forward (see below), but I'm open to any suggestions as to what could be done to remove that initial 40 second penalty.

public static class WorkspaceManager
{
    public static Compilation LoadWorkspace(string filePath)
    {
        var manager = new AnalyzerManager();
        ProjectAnalyzer analyzer = manager.GetProject(filePath);

        var projectPath = analyzer.Project.DirectoryPath;

        var projects = analyzer.Project.Items.Where(x => x.ItemType == "ProjectReference");
        foreach (ProjectItem projItem in projects)
        {
            var p = Path.Combine(projectPath, projItem.EvaluatedInclude);
            analyzer.Manager.GetProject(p);    
        }
        
        Workspace workspace = analyzer.GetWorkspace(true);
        var compilation = workspace.CurrentSolution.Projects.FirstOrDefault().GetCompilationAsync().Result;
        return compilation;
    }
}

Wrong path for build tools when multitargeting

Seeing this error on CI builds:

C:\Program Files\dotnet\sdk\2.0.2\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props(29,3): error MSB4019: The imported project "C:\Program Files\dotnet\sdk\2.0.2\2.0\Microsoft.Common.props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.

The import in Sdk.props looks like this:

<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" />

It appears that MSBuildToolsVersion is getting set to "2.0" instead of "15.0" for some reason.

Found a related issue in DocFx that perfectly describes this behavior here: dotnet/docfx#1752 (comment) (Buildalyzer already sets the MSBuildExtensionsPath).

Microsoft.NET.Sdk error for some SDK .NET Framework projects

Seeing the following build error for some (but not all) SDK .NET Framework projects:

Project "E:\Code\Wyam.Web\release\repo\src\core\Wyam.Hosting\Wyam.Hosting.csproj" (Compile target(s)):

Target ImplicitlyExpandNETStandardFacades:
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.NETFramework.targets(57,5): error : The version of Microsoft.NET.Sdk used by this project is insufficient to support references to libraries targe
ting .NET Standard 1.5 or higher.  Please install version 2.0 or higher of the .NET Core SDK.
Done building target "ImplicitlyExpandNETStandardFacades" in project "Wyam.Hosting.csproj" -- FAILED.

Done building project "Wyam.Hosting.csproj" -- FAILED.

Build FAILED.

Suspect this may be related to the change made to support #23: using the VS toolchain instead of the SDK. Apparently the VS toolchain doesn't know how to deal with .NET Standard > 1.5.

Adding <DependsOnNETStandard>false</DependsOnNETStandard> to a SDK .NET Framework project causes the error to go away, but may introduce other problems.

Incorrect Tools Path (details see description)

Hi there,

I was looking into using the Buildalyzer nuget package for a .net framework app (actually a multi-targeted app - framework and core) that gets called as a subprocess from within a VSIX. The necessary Microsoft.Build libraries (Microsoft.Build.dll, Microsoft.Build.Framework.dll, Microsoft.Build.Tasks.Core.dll, Microsoft.Build.Utilities.Core.dll) are packages with the VSIX (yes, I know... I couldn't yet find a way around that...).
The projects for which to do a design time build inside the framework app are .net core style projects (netcoreapp2.0 and netstandard2.0). Unfortunately, the tools path in this particular case seems to be incorrect, leading to an "imported project not found" error (because it is looking for the Nuget.targets in the wrong place) caused by
<PropertyGroup> <NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'=='' and '$([MSBuild]::IsRunningFromVisualStudio())'=='true'">$(MSBuildToolsPath32)\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets</NuGetRestoreTargets> <NuGetRestoreTargets Condition="'$(NuGetRestoreTargets)'==''">$(MSBuildToolsPath)\NuGet.targets</NuGetRestoreTargets> </PropertyGroup>
in the C:\Program Files\dotnet\sdk\2.1.4\Microsoft.Common.CrossTargeting.targets.
I tried messing around with the BuildEnvironment property in the version that is here on GitHub, but ended up doing the design time build manually using a compiler directive to distinguish between the core and the framework build of the app.
I'd still prefer using this package if possible, though, since you are probably investing quite a bit more time than me to make this work for various scenarios. So hence the question: is it currently possible to cover this scenario? If so, what would be the right usage that I apparently couldn't figure out? If not, any chance it would be possible to look into this?

Best,
Bettina

Please release a new nuget package

Hi Dave,

I am porting my literate programming tool to .NET Core and found that your library is a great replacement for MSBuildWorkspace which sadly is absent in netcore. However, the version available as nuget package gives a lot of build errors which are fixed in the latest commit on GitHub.

Can you please release a new version of the nuget package, so I can get the latest and greatest version cleanly imported to my project?

Thanks,
Tommi

Support solution loading

My scenario requires that I take any solution and introspect upon projects within. However, this is currently not possible with Buildalyzer because it does not support solution loading.

It would be πŸ’― AMAZING πŸŽ‰ if Buildalyzer could be given any .sln file and analyze it for the consumer, surfacing all projects within.

[Recursive resource lookup bug]

(from #10)

@jp2masa Now I'm getting this exception: https://pastebin.com/VnuwCQKn

@daveaglick Oh, wow, you broke it good πŸ˜„.

On the one hand I think this is good because it means that you're actually getting past the previous problems and we're calling the MSBuild API successfully. On the other hand, this looks like it'll be nasty to track down since it's deep in the MSBuild libraries (looks like the method that kicks off the problem is Microsoft.Build.Shared.AssemblyResources.GetStringFromEngineResources). Seems like something might be off with the resources - perhaps there are extra MSBuild properties we need to set to correctly handle resources.

Is the project you're trying to analyze open source and available somewhere I could get it to try and reproduce?

Also, what platform are you running on?

Error in project compilation if dotnet-core-sdk 2.1 is used.

Steps to reproduce

Environment

here is my dotnet --info result

.NET γ‚³γƒžγƒ³γƒ‰ ラむン ツール (2.1.2)

Product Information:
 Version:            2.1.2
 Commit SHA-1 hash:  5695315371

Runtime Environment:
 OS Name:     Windows
 OS Version:  6.3.9600
 OS Platform: Windows
 RID:         win81-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.2\


Microsoft .NET Core Shared Framework Host



  Version  : 2.0.3

  Build    : a9190d4a75f4a982ae4b4fa8d1a24526566c69df

Steps

  1. create AnalyzerManager instance
  2. get ProjectAnalyzer with AnalyzerManager.GetProject for project which was created by dotnet new console
  3. get ProjectInstance with ProjectAnalyer().GetProject

Expected behavior

get ProjectInstance

Actual Behavior

I got following exception

Microsoft.Build.Exceptions.InvalidProjectFileException: Invalid static method invocation syntax: "[MSBuild]::IsRunningFromVisualStudio()". [MSBuild]::IsRunningFromVisualStudio Static method invocation should be of the form: $([FullTypeName]::Method()), e.g. $([System.IO.Path]::Combine(`a`, `b`)).   C:\Program Files\dotnet\sdk\2.1.2\Microsoft.Common.CurrentVersion.targets
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Evaluation.Expander`2.Function`1.Execute(Object objectInstance, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertyBody(String propertyBody, Object propertyValue, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveTypedAndEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.ExpandIntoStringLeaveEscaped(String expression, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.ConditionEvaluator.ConditionEvaluationState`2.ExpandIntoStringBreakEarly(String expression)
   at Microsoft.Build.Evaluation.StringExpressionNode.EvaluatesToEmpty(IConditionEvaluationState state)
   at Microsoft.Build.Evaluation.MultipleComparisonNode.BoolEvaluate(IConditionEvaluationState state)
   at Microsoft.Build.Evaluation.ConditionEvaluator.EvaluateConditionCollectingConditionedProperties[P,I](String condition, ParserOptions options, Expander`2 expander, ExpanderOptions expanderOptions, Dictionary`2 conditionedPropertiesTable, String evaluationDirectory, ElementLocation elementLocation, ILoggingService loggingServices, BuildEventContext buildEventContext, ProjectRootElementCache projectRootElementCache)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateConditionCollectingConditionedProperties(ProjectElement element, String condition, ExpanderOptions expanderOptions, ParserOptions parserOptions, ProjectRootElementCache projectRootElementCache)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyElement(ProjectPropertyElement propertyElement)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluatePropertyGroupElement(ProjectPropertyGroupElement propertyGroupElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(ILoggingService loggingService, BuildEventContext buildEventContext)
   at Microsoft.Build.Evaluation.Project.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
   at Buildalyzer.ProjectAnalyzer.Load()
   at Buildalyzer.ProjectAnalyzer.Compile()
   at buildalyzertest.Program.Main(String[] args) in G:\src\gitrepos\dotnet-sandbox\buildalyzer-error-with-core-sdk-2.1\buildalyzertest\Program.cs:line 15

Notes

This can be avoided by adding the following package in project which uses Buildalyzer.

  • Microsoft.Build, Version=15.5.180
  • Microsoft.Build.Tasks.Core, Version=15.5.180
  • Microsoft.Build.Utilities.Core, Version=15.5.180

or by putting global.json which specifies sdk/version = 2.0.x on processed csproj.(requires dotnet-sdk 2.0)

BadImageFormatException: Microsoft.Build.Tasks.CodeAnalysis

I was trying to use Buildalyzer to load .NET Core SDK project, but I was getting this exception:

System.BadImageFormatException: Could not load file or assembly 'Microsoft.Build.Tasks.CodeAnalysis, Version=2.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. An attempt was made to load a program with an incorrect format.

I thought that probably I was making some mistake, but then I downloaded this repo and tried to run the tests. The .NET Core and .NET Standard SDK project tests fail with the same exception.

Buidalyzer version: 0.1.4
Visual Studio version: 15.4

dotnet --info:

.NET Command Line Tools (2.0.2)

Product Information:
 Version:            2.0.2
 Commit SHA-1 hash:  a04b4bf512

Runtime Environment:
 OS Name:     Windows
 OS Version:  10.0.15063
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.0.2\

Microsoft .NET Core Shared Framework Host

  Version  : 2.0.0
  Build    : e8b8861ac7faf042c87a5c2f9f2d04c98b69f28d

Add support for virtual project files

There may be scenarios where a project file that isn't on disk needs to be loaded (I.e., if an existing project file gets transformed before load). We'll need at least the project file contents and a project directory.

Runtime error when trying to resolve dependencies [after 1.0.0 upgrade]

Hey @daveaglick , I just gave it a try with the just released 1.0.0 version. I upgraded my Roslyn versions and refactored the API accordingly. Everything builds fine, but when I try to analyse my test projects I get an exception out of ProjectAnalyzer.Build.

From the trace below, I suspect this could be to a messed up Windows/Unix path separator (i.e., / versus \)?

/usr/local/share/dotnet/sdk/2.1.302/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018: The "ResolvePackageAssets" task failed unexpectedly.
      /usr/local/share/dotnet/sdk/2.1.302/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018: System.IO.FileNotFoundException: Could not load file or assembly 'NuGet.Frameworks, Version=4.7.0.5, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the path specified.
      /usr/local/share/dotnet/sdk/2.1.302/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:
      /usr/local/share/dotnet/sdk/2.1.302/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018: File name: 'NuGet.Frameworks, Version=4.7.0.5, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ---> System.IO.DirectoryNotFoundException: Could not find a part of the path '/usr/local/share/dotnet/sdk/2.1.302/Sdks/..\'.
      /usr/local/share/dotnet/sdk/2.1.302/Sdks/Microsoft.NET.Sdk/targets/Microsoft.PackageDependencyResolution.targets(198,5): error MSB4018:    at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path)

Support for referenced projects

I'm just getting started with Buildalyzer (thanks for your great work!) and have code like this:

var manager = new AnalyzerManager();
var analyzer = manager.GetProject(initialPath);
var workspace = analyzer.GetWorkspace();
var solution = workspace.CurrentSolution;

Whilst this code executes OK, when I examine solution.Projects there is only the one project present. This is despite the fact that the project I'm loading references several other projects. They just don't seem to resolve.

I've tried:

  • calling analyzer.Load()
  • calling analyzer.Compile()
  • enumerating the source files and project references of analyzer, which fails because both enumerations are null
  • explicitly specifying a solution path when creating the AnalyzerManager thinking that might help it resolve projects, but it does not

Notes:

  • calling analyzer.Load() does not return null, but calling analyzer.Compile() does

To get further with this, I switched to using Buildalyzer source. I found that the clean was returning false. To diagnose further I added a logger and got this output:

Build started 16/10/2017 12:00:46 PM.

__________________________________________________

Project "C:\Users\Kent\Repository\QUT\Src\UnitTests\UnitTests.csproj" (Clean target(s)):



Target Clean:

    __________________________________________________

    Project "C:\Users\Kent\Repository\QUT\Src\UnitTests\UnitTests.csproj" is building "C:\Users\Kent\Repository\QUT\Src\UnitTests\UnitTests.csproj" (Clean target(s)):



    C:\Program Files\dotnet\sdk\2.0.2\Sdks\Microsoft.NET.Sdk\Sdk\Sdk.props(29,3): error MSB4019: The imported project "C:\Program Files\dotnet\sdk\2.0.2\2.0\Microsoft.Common.props" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.



    Done building project "UnitTests.csproj" -- FAILED.

I can confirm that the specified Microsoft.Common.props file does not exist, but I'm not sure why nor whether it should exist.

ProjectAnalyzer.Compile failed internally and return null in dotnet-sdk-2.1.300

Environment

my dotnet --info output;

.NET Core SDK (global.json γ‚’εζ˜ ):
 Version:   2.1.300
 Commit:    adab45bf0c

ランタむム環咃:
 OS Name:     Windows
 OS Version:  6.3.9600
 OS Platform: Windows
 RID:         win81-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.1.300\

Host (useful for support):
  Version: 2.1.0
  Commit:  caa7b7e2ba

.NET Core SDKs installed:
  1.0.0-preview2-003118 [C:\Program Files\dotnet\sdk]
  1.0.0-preview2-003121 [C:\Program Files\dotnet\sdk]
  1.0.0-preview2-003131 [C:\Program Files\dotnet\sdk]
  1.0.0-preview2-003133 [C:\Program Files\dotnet\sdk]
  1.0.0-preview2-003156 [C:\Program Files\dotnet\sdk]
  1.0.0-preview2-1-003177 [C:\Program Files\dotnet\sdk]
  1.0.4 [C:\Program Files\dotnet\sdk]
  1.1.0 [C:\Program Files\dotnet\sdk]
  2.0.0-preview1-005977 [C:\Program Files\dotnet\sdk]
  2.0.0 [C:\Program Files\dotnet\sdk]
  2.0.2 [C:\Program Files\dotnet\sdk]
  2.1.2 [C:\Program Files\dotnet\sdk]
  2.1.3 [C:\Program Files\dotnet\sdk]
  2.1.4 [C:\Program Files\dotnet\sdk]
  2.1.100 [C:\Program Files\dotnet\sdk]
  2.1.104 [C:\Program Files\dotnet\sdk]
  2.1.300-rc1-008673 [C:\Program Files\dotnet\sdk]
  2.1.300 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.0-rc1-final [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.0-rc2-3002702 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0-preview1-002111-00 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.3 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0-rc1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]

To install additional .NET Core runtimes or SDKs:
  https://aka.ms/dotnet-download

Steps to reproduce

  1. clone https://github.com/itn3000/buildalyzer-failed-sdk-2.1.300
  2. cd to buildalyzertest
  3. run dotnet run -- ../sampleclass/sampleclass.csproj

Expected result

output compilation results(success) and project items and exit.

Actual result

with dotnet-core-sdk 2.1(2.1.300), output compilation results(failed) and output project instance is null then exit.
but dotnet-core-sdk 2.0(2.1.4), expected results were output.

Workaround

add following packages into project that using Buildalyzer.

  • NuGet.Common
  • NuGet.ProjectModel

Properties like MSBuildThisFileDirectory don't work

Because of an MSBuild bug (dotnet/msbuild#3030) and the fact that Buildalyzer loads using an XmlReader instead of using a file name, properties like MSBuildThisFileDirectory used during project load don't work.

Minimal repro:

<Project ToolsVersion="15.0">
  <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), Directory.Build.props))\Directory.Build.props" />
  <Target Name="Build" />
</Project>

I get the error:

Microsoft.Build.Exceptions.InvalidProjectFileException: The expression "[MSBuild]::GetDirectoryNameOfFileAbove('', Directory.Build.props)" cannot be evaluated. The path is not of a legal form.
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject(String errorSubCategoryResourceName, IElementLocation elementLocation, String resourceName, Object[] args)
   at Microsoft.Build.Shared.ProjectErrorUtilities.ThrowInvalidProject[T1,T2](IElementLocation elementLocation, String resourceName, T1 arg0, T2 arg1)
   at Microsoft.Build.Evaluation.Expander`2.Function`1.Execute(Object objectInstance, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertyBody(String propertyBody, Object propertyValue, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveTypedAndEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.PropertyExpander`1.ExpandPropertiesLeaveEscaped(String expression, IPropertyProvider`1 properties, ExpanderOptions options, IElementLocation elementLocation, UsedUninitializedProperties usedUninitializedProperties)
   at Microsoft.Build.Evaluation.Expander`2.ExpandIntoStringLeaveEscaped(String expression, ExpanderOptions options, IElementLocation elementLocation)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpression(String directoryOfImportingFile, ProjectImportElement importElement, String unescapedExpression, Boolean throwOnFileNotExistsError, List`1& imports)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImportsFromUnescapedImportExpressionConditioned(String directoryOfImportingFile, ProjectImportElement importElement, List`1& projects, Boolean throwOnFileNotExistsError)
   at Microsoft.Build.Evaluation.Evaluator`4.ExpandAndLoadImports(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.EvaluateImportElement(String directoryOfImportingFile, ProjectImportElement importElement)
   at Microsoft.Build.Evaluation.Evaluator`4.PerformDepthFirstPass(ProjectRootElement currentProjectOrImport)
   at Microsoft.Build.Evaluation.Evaluator`4.Evaluate(ILoggingService loggingService, BuildEventContext buildEventContext)
   at Microsoft.Build.Evaluation.Project.Reevaluate(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.ReevaluateIfNecessary(ILoggingService loggingServiceForEvaluation, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.Project.Initialize(IDictionary`2 globalProperties, String toolsVersion, String subToolsetVersion, ProjectLoadSettings loadSettings)
   at Microsoft.Build.Evaluation.ProjectCollection.LoadProject(XmlReader xmlReader)
   at Buildalyzer.ProjectAnalyzer.Load()

Consider loading by filename when no "ProjectTweaker" is provided, even though it requires a whole new load of the Xml which you've already done, at least until MsBuild provides a solution itself.

Incorrect build env created based on running app

Hey @daveaglick, I don't agree with this logic that you have in EnvironmentFactory:

// If we're running on .NET Core, use the .NET Core SDK regardless of the project file
if (BuildEnvironment.IsRunningOnCore)
{
    return CreateCoreEnvironment(options);
}

Our tool, for instance, is built on .NET Core but we perform static analysis on .NET Framework apps as well. In our case, that check would always return true and, in most of the times, it'd be an incorrect decision (most of our customers are running .NET Framework).

I've done a few changes in our fork, but I can't put them together with the other PRs at the moment. I'm not sure what's the best approach here, but notice that the if statement above happens even before checking for a possibly specified targetFramework. What do you say?

Suggestion: Allow solution (project) global properties to be controlled via AnalyzerManager

I have a situation in which I'm loading a Web Application project using .NET Core. The following lines in that project type are problematic:

<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />

Since VSToolsPath is undefined and MSBuildExtensionsPath32 is set to C:\Program Files\dotnet\sdk\<version>, MSBuild ends up trying to load C:\Program Files\dotnet\sdk\<version>\Microsoft\VisualStudio\v$(VisualStudioVersion)\WebApplications\Microsoft.WebApplication.targets, which obviously doesn't exist (that file resides in the Visual Studio install directory). This causes AnalyzerManager.GetWorkspace() to blow up.

I've (very nastily) worked around this by calling Environment.SetEnvironmentVariable("VSToolsPath", <path_to_necessary_directory>), but the issue would be totally avoided if I could somehow pass these values to AnalyzerManager when constructing it or calling GetWorkspace(). Unfortunately, Buildalyzer currently doesn't expose the global/environment variables it sets to allow for mutation, so that's not an option - but I propose it should be! :)

.NET Framework builds failing in GetAssemblyVersion task

Builds are failing for .NET Framework projects:

Project "E:\Code\Buildalyzer\tests\projects\SdkFrameworkProject\SdkFrameworkProject.csproj" (Compile target(s)):

Target ResolveAssemblyReferences:
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3088: Could not read state file "obj\Debug\net462\SdkFrameworkProject.csprojAssemblyReference.cache". Exception has been thrown by the target of an invocation.
Done building target "ResolveAssemblyReferences" in project "SdkFrameworkProject.csproj".
Target GenerateTargetFrameworkMonikerAttribute:
  Skipping target "GenerateTargetFrameworkMonikerAttribute" because all output files are up-to-date with respect to the input files.
Target ResolveCodeAnalysisRuleSet:
    C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\Microsoft.CSharp.CurrentVersion.targets(134,9): warning MSB3884: Could not find rule set file "ManagedMinimumRules.ruleset".
Done building target "ResolveCodeAnalysisRuleSet" in project "SdkFrameworkProject.csproj".
Target GetAssemblyVersion:
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018: The "GetAssemblyVersion" task failed unexpectedly.
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018: System.NullReferenceException: Object reference not set to an instance of an object.
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018:    at Microsoft.NET.Build.Tasks.GetAssemblyVersion.ExecuteCore()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018:    at Microsoft.NET.Build.Tasks.TaskBase.Execute()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute()
    C:\Program Files\dotnet\sdk\2.1.300\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.GenerateAssemblyInfo.targets(161,5): error MSB4018:    at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext()
Done building target "GetAssemblyVersion" in project "SdkFrameworkProject.csproj" -- FAILED.

Done building project "SdkFrameworkProject.csproj" -- FAILED.

Build FAILED.

I'm still not totally sure why this target is having problems, but after some research it looks like we can turn off the ResolveAssemblyReference cache with the property DisableRarCache (see dotnet/msbuild@331cd4a) and that seems to fix the issue. This is also apparently what VS does for design-time builds. I suspect it has something to do with the way the RAR cache file name is generated, but not going to spend more time on it.

Cannot load solution containing solution folders

Code:

// initialPath: "C:\Users\Kent\Repository\XXX\Src\XXX.sln"
var manager = new AnalyzerManager(initialPath);

Results in:

System.ArgumentException: 'The path C:\Users\Kent\Repository\XXX\Src\Platform could not be found.'

The solution includes a solution folder in it called "Platform":

Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Platform", "Platform", "{43E194F0-7558-486E-AADA-A1DBB8855359}"
EndProject

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.