Buildalyzer Documentation

repository·main·Indexed 20 days ago

https://github.com/buildalyzer/buildalyzer

A utility for performing design-time MSBuild builds of .NET projects to programmatically inspect project properties, resolved references, and source files. It includes the Buildalyzer.Workspaces extension for converting analysis results into Roslyn AdhocWorkspaces. Key components include AnalyzerManager for coordination and ProjectAnalyzer for executing high-performance design-time builds.

Tokens
1.8K
Snippets
6
Records
8
Agent score
22%

What's inside Buildalyzer

  1. How AnalyzerManager and ProjectAnalyzer work together

    main

    Buildalyzer uses two primary classes to coordinate project analysis:

    1. AnalyzerManager: The entry point. It coordinates loading individual projects and can consolidate information from a solution file if a solution path is provided to its constructor. It maintains a collection of loaded projects in its Projects property (IReadOnlyDictionary<string, ProjectAnalyzer>).
    2. ProjectAnalyzer: Represents a specific project. It handles the MSBuild configuration and executes a design-time build. A design-time build evaluates MSBuild tasks and targets to resolve references and source files without actually invoking the compiler, making it high-performance.

    To use them, create an AnalyzerManager, use GetProject(path) to obtain an IProjectAnalyzer, and then call Build() to perform the analysis.

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

    main

    The Buildalyzer.Workspaces package provides extension methods to convert Buildalyzer analysis into a Roslyn AdhocWorkspace. This allows you to use Buildalyzer's resolution logic within the Roslyn compiler API.

    Option 1: Automatic Workspace Creation Use analyzer.GetWorkspace() to create a new workspace populated with the project's data.

    Option 2: Adding to an existing Workspace Use analyzer.AddToWorkspace(workspace) to add a project to a workspace you have already instantiated. This method attempts to resolve project references within the workspace so that Roslyn projects correctly reference each other.

    using Buildalyzer.Workspaces;
    using Microsoft.CodeAnalysis;
    
    // Option 1
    AnalyzerManager manager = new AnalyzerManager();
    IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
    AdhocWorkspace workspace = analyzer.GetWorkspace();
    
    // Option 2
    AdhocWorkspace customWorkspace = new AdhocWorkspace();
    Project roslynProject = analyzer.AddToWorkspace(customWorkspace);
  3. Install Buildalyzer and Buildalyzer.Workspaces

    main

    Buildalyzer and its extension Buildalyzer.Workspaces both target .NET Standard 2.0. You can install them via NuGet Package Manager or the .NET CLI.

    Buildalyzer

    $ Install-Package Buildalyzer
    # or
    $ dotnet add package Buildalyzer

    Buildalyzer.Workspaces

    $ Install-Package Buildalyzer.Workspaces
    # or
    $ dotnet add package Buildalyzer.Workspaces
    dotnet add package Buildalyzer
  4. Configure LoggerPathDll for SingleFile Publish

    main

    If your application is published as a SingleFile executable, MSBuild requires the physical path to the logger DLLs. You must provide the path to the following files via the LoggerPathDll variable:

    • MsBuildPipeLogger.Logger.dll
    • Buildalyzer.logger.dll

    Note: If these files are located in the same root directory where the project is running, you do not need to explicitly provide the path.

  5. Analyze MSBuild binary log files (.binlog)

    main

    If you already have an MSBuild binary log file, you can analyze it directly using AnalyzerManager.Analyze(path) instead of performing a new build.

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

    main

    Buildalyzer uses Microsoft.Extensions.Logging. You can provide an ILoggerFactory to the AnalyzerManager constructor to capture MSBuild output.

    Alternatively, you can capture logs into a StringWriter by configuring AnalyzerManagerOptions:

    StringWriter log = new StringWriter();
    AnalyzerManagerOptions options = new AnalyzerManagerOptions
    {
        LogWriter = log
    };
    AnalyzerManager manager = new AnalyzerManager(path, options);
    // After build, check log.ToString() for error messages
    StringWriter log = new StringWriter();
    AnalyzerManagerOptions options = new AnalyzerManagerOptions
    {
        LogWriter = log
    };
    AnalyzerManager manager = new AnalyzerManager(path, options);
  7. Adjust MSBuild Global Properties

    main

    You can modify MSBuild properties before loading or compiling a project. You can view current properties via ProjectAnalyzer.GlobalProperties.

    There are two scopes for setting properties:

    1. Global Scope: Use AnalyzerManager.SetGlobalProperty(key, value) or AnalyzerManager.RemoveGlobalProperty(key) to apply properties to all projects managed by that manager.
    2. Project Scope: Use ProjectAnalyzer.SetGlobalProperty(key, value) or ProjectAnalyzer.RemoveGlobalProperty(key) to apply properties only to that specific project.

    Warning: Changing these properties may prevent the project from loading or being interpreted correctly.

  8. Analyze MSBuild projects with ProjectAnalyzer.Build()

    main

    To perform a design-time build and retrieve project information, call Build() on an IProjectAnalyzer instance. This returns an IAnalyzerResults object, which is a collection of AnalyzerResult objects (one for each target framework in a multi-targeted project).

    Each AnalyzerResult provides access to:

    • TargetFramework: The specific framework for that result.
    • SourceFiles: Full paths of all resolved source files.
    • References: Full paths of all resolved references.
    • ProjectReferences: Full paths of all resolved project files.
    • Properties: An IReadOnlyDictionary<string, string> of all MSBuild properties.
    • GetProperty(string): Helper to get a specific MSBuild property value.
    • Items: An IReadOnlyDictionary<string, ProjectItem[]> of all MSBuild items. Each ProjectItem contains ItemSpec (the name/spec) and Metadata (an IReadOnlyDictionary<string, string>).
    AnalyzerManager manager = new AnalyzerManager();
    IProjectAnalyzer analyzer = manager.GetProject(@"C:\MyCode\MyProject.csproj");
    IAnalyzerResults results = analyzer.Build();
    
    // Accessing data from the first result
    var result = results.First();
    string[] files = result.SourceFiles;
    string myProp = result.GetProperty("MyCustomProperty");