Buildalyzer icon indicating copy to clipboard operation
Buildalyzer copied to clipboard

Wrong "OutputPath" and "OutDir"?

Open mcreek opened this issue 3 years ago • 5 comments

With Buildalyzer (version 4.1.3) I'm analyzing CSPROJ files which are part of a solution file. For build-output configuration I'm using one common "common.props" file instead of configuring it at all csproj files individually.

Example of file "common.props"

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        ...
        <OutputPath>$(SolutionDir)\build\bin\$(Configuration)\</OutputPath>
        ...
    </PropertyGroup>
</Project>

This "common.props" file is included in each csproj file with

<Import Project="..\..\Common.props" />

and the "OutputPath" Property is removed in each csproj file .

My directory structure is:

SampleApp
|--SampleApp.sln
|--common.props
|
|--build
|   |--bin
|       |--debug
|       |--release
|
|--src
    |--SampleAppProj_1
    |   |--SampleAppProj_1.csproj
    |   |-- ...
    |
    |--SampleAppProj_2
        |--SampleAppProj_1.csproj
        |-- ...

Analyzing the projects with code:

public void Test(string projectFile)
{
    AnalyzerManager manager = new AnalyzerManager();
    IProjectAnalyzer analyzer = manager.GetProject(projectFile);
    analyzer.SetGlobalProperty("Configuration", "debug");

    string tempDir = Path.Combine(Path.GetDirectoryName(projectFile), "Temp") + Path.DirectorySeparatorChar;
    EnvironmentOptions options = new EnvironmentOptions();
    options.GlobalProperties["IntermediateOutputPath"] = tempDir; //designation of intermediate output file directory
    options.TargetsToBuild.Remove("Clean"); //see https://github.com/daveaglick/Buildalyzer/issues/105)

    IAnalyzerResults results = analyzer.Build(options);
    IAnalyzerResult analyzerResult = results.First();

    System.Diagnostics.Debug.WriteLine(analyzerResult.GetProperty("OutputPath"));
}

This will print out for "OutputPath": "<drive>\SampleApp\src\SampleAppProj_1\\build\bin\debug" instead of "<drive>\SampleApp\build\bin\debug" Same for "OutDir" property.

I'am doing something wrong? How can I get the correct "OutputPath" and "OutDir"?

mcreek avatar Mar 22 '22 15:03 mcreek

Buildalyzer doesn't actually process the project file on its own (at least not beyond very rudimentary parsing to figure out how to call MSBuild), and the values in IAnalyzerResult come directly from MSBuild logging. So that's all to say that if the OutputPath and OutDir props aren't coming over correctly, then it's because MSBuild isn't resolving them as you expect when Buildalyzer calls it.

There's a few reasons why this could be:

  • The working path might be different from when Visual Studio or another environment runs MSBuild to when Buildalyzer does.
  • Other global props might be set that Buildalyzer doesn't know about, particularly if whatever you normally build with is setting environment variables or something.
  • Buildalyzer might be finding the wrong MSBuild that treats things differently than you expect.

The best way to diagnose what's going on here is probably to log what Buildalyzer is doing and then do it yourself from the command line. For example:

StringWriter log = new StringWriter();
AnalyzerManager manager = new AnalyzerManager(
    new AnalyzerManagerOptions
    {
        LogWriter = log
    });
// ...
System.Diagnostics.Debug.WriteLine(log.ToString());

That'll let you see exactly what command line Buildalyzer ran and from where and then you can run it yourself and compare.

The next step after that would probably be to generate a binary log and open it with the Structured Log Viewer. That should let you see exactly what's going on under the hood, how and why those output values are being set the way they are, and where or if the common.props file is being processed:

IProjectAnalyzer analyzer = manager.GetProject(projectFile);
analyzer .AddBinaryLogger("myproject.binlog")));

To really get down to what the differences are, use the Project System Tools extension to generate a binary log file from Visual Studio too and compare the two.

daveaglick avatar Apr 20 '22 18:04 daveaglick

Thank you for response and the description how to analyze it. I will try to analyze it but I will need some time for it.

mcreek avatar Apr 22 '22 08:04 mcreek

Please use Directory.Build.props and Directory.Build.targets instead of "common.props".

OutputPath property is a relativ path and BaseOutputPath should be used. image

image

see also .NET 8.0 SDK Artifacts output layout

Bertk avatar Jan 15 '24 11:01 Bertk