Skip to content

Commit

Permalink
Merge pull request #5238 from Nirmal4G/patch-1
Browse files Browse the repository at this point in the history
Add BaseOutputPath to common targets
  • Loading branch information
rainersigwald authored Dec 7, 2020
2 parents 1fcfd01 + f7e97bd commit 7528963
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 58 deletions.
186 changes: 186 additions & 0 deletions src/Tasks.UnitTests/OutputPathTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System;
using System.IO;

using Microsoft.Build.Evaluation;
using Microsoft.Build.Shared;
using Microsoft.Build.UnitTests;

using Shouldly;

using Xunit;
using Xunit.Abstractions;

namespace Microsoft.Build.Tasks.UnitTests
{
public sealed class OutputPathTests : IDisposable
{
private readonly ITestOutputHelper _output;
private readonly string _projectRelativePath = Path.Combine("src", "test", "test.csproj");

public OutputPathTests(ITestOutputHelper output)
{
_output = output;
ObjectModelHelpers.DeleteTempProjectDirectory();
}

public void Dispose()
{
ObjectModelHelpers.DeleteTempProjectDirectory();
}

/// <summary>
/// Test when both BaseOutputPath and OutputPath are not specified.
/// </summary>
[Fact]
public void BothBaseOutputPathAndOutputPathWereNotSpecified()
{
// Arrange
var baseOutputPath = "bin";

var projectFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(_projectRelativePath,
$@"<Project DefaultTargets=`Build` xmlns=`msbuildnamespace` ToolsVersion=`msbuilddefaulttoolsversion`>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.props`/>
<PropertyGroup>
<Platform>AnyCPU</Platform>
<Configuration>Debug</Configuration>
</PropertyGroup>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.targets`/>
<Target Name=`Build`/>
</Project>");

// Act
Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory(projectFilePath, touchProject: false);

project.Build(new MockLogger(_output)).ShouldBeFalse();

// Assert
project.GetPropertyValue("BaseOutputPath").ShouldBe(baseOutputPath.WithTrailingSlash());
project.GetPropertyValue("BaseOutputPathWasSpecified").ShouldBe(string.Empty);
project.GetPropertyValue("_OutputPathWasMissing").ShouldBe("true");
}

/// <summary>
/// Test when BaseOutputPath is specified without the OutputPath.
/// </summary>
[Fact]
public void BaseOutputPathWasSpecifiedAndIsOverridable()
{
// Arrange
var baseOutputPath = Path.Combine("build", "bin");

var projectFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(_projectRelativePath,
$@"<Project DefaultTargets=`Build` xmlns=`msbuildnamespace` ToolsVersion=`msbuilddefaulttoolsversion`>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.props`/>
<PropertyGroup>
<Platform>AnyCPU</Platform>
<Configuration>Debug</Configuration>
<BaseOutputPath>{baseOutputPath}</BaseOutputPath>
</PropertyGroup>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.targets`/>
<Target Name=`Build`/>
</Project>");

// Act
Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory(projectFilePath, touchProject: false);

project.Build(new MockLogger(_output)).ShouldBeTrue();

// Assert
project.GetPropertyValue("BaseOutputPath").ShouldBe(baseOutputPath.WithTrailingSlash());
project.GetPropertyValue("BaseOutputPathWasSpecified").ShouldBe("true");
project.GetPropertyValue("_OutputPathWasMissing").ShouldBe("true");
}

/// <summary>
/// Test when both BaseOutputPath and OutputPath are specified.
/// </summary>
[Fact]
public void BothBaseOutputPathAndOutputPathWereSpecified()
{
// Arrange
var baseOutputPath = Path.Combine("build", "bin");
var outputPath = Path.Combine("bin", "Debug");
var outputPathAlt = Path.Combine("bin", "Release");

var projectFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(_projectRelativePath,
$@"<Project DefaultTargets=`Build` xmlns=`msbuildnamespace` ToolsVersion=`msbuilddefaulttoolsversion`>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.props`/>
<PropertyGroup>
<Platform>AnyCPU</Platform>
<Configuration>Debug</Configuration>
</PropertyGroup>
<PropertyGroup>
<BaseOutputPath>{baseOutputPath}</BaseOutputPath>
<OutputPath Condition=`'$(Platform)|$(Configuration)' == 'AnyCPU|Debug'`>{outputPath}</OutputPath>
<OutputPath Condition=`'$(Platform)|$(Configuration)' == 'AnyCPU|Release'`>{outputPathAlt}</OutputPath>
</PropertyGroup>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.targets`/>
<Target Name=`Build`/>
</Project>");

// Act
Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory(projectFilePath, touchProject: false);

project.Build(new MockLogger(_output)).ShouldBeTrue();

// Assert
project.GetPropertyValue("BaseOutputPath").ShouldBe(baseOutputPath.WithTrailingSlash());
project.GetPropertyValue("OutputPath").ShouldBe(outputPath.WithTrailingSlash());
project.GetPropertyValue("BaseOutputPathWasSpecified").ShouldBe("true");
project.GetPropertyValue("_OutputPathWasMissing").ShouldBe(string.Empty);
}

/// <summary>
/// Test for [MSBuild]::NormalizePath and [MSBuild]::NormalizeDirectory returning current directory instead of current Project directory.
/// </summary>
[ConditionalFact(typeof(NativeMethodsShared), nameof(NativeMethodsShared.IsWindows), Skip = "Skipping this test for now until we have a consensus about this issue.")]
public void MSBuildNormalizePathShouldReturnProjectDirectory()
{
// Arrange
var configuration = "Debug";
var baseOutputPath = "bin";

var projectFilePath = ObjectModelHelpers.CreateFileInTempProjectDirectory(_projectRelativePath,
$@"<Project DefaultTargets=`Build` xmlns=`msbuildnamespace` ToolsVersion=`msbuilddefaulttoolsversion`>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.props`/>
<PropertyGroup Condition=`'$(OutputPath)' == ''`>
<OutputPath>$([MSBuild]::NormalizeDirectory('{baseOutputPath}', '{configuration}'))</OutputPath>
</PropertyGroup>
<Import Project=`$(MSBuildToolsPath)\Microsoft.Common.targets`/>
<Target Name=`Build`/>
</Project>");

// Act
Project project = ObjectModelHelpers.LoadProjectFileInTempProjectDirectory(projectFilePath, touchProject: false);

project.Build(new MockLogger(_output)).ShouldBeTrue();

// Assert
project.GetPropertyValue("Configuration").ShouldBe(configuration);
project.GetPropertyValue("BaseOutputPath").ShouldBe(baseOutputPath.WithTrailingSlash());

var expectedOutputPath = FileUtilities.CombinePaths(project.DirectoryPath, baseOutputPath, configuration).WithTrailingSlash();
project.GetPropertyValue("OutputPath").ShouldBe(expectedOutputPath);
}
}
}
2 changes: 1 addition & 1 deletion src/Tasks/Microsoft.Common.CrossTargeting.targets
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
<PropertyGroup Condition="'$(ImportDirectoryBuildTargets)' == 'true' and '$(DirectoryBuildTargetsPath)' == ''">
<_DirectoryBuildTargetsFile Condition="'$(_DirectoryBuildTargetsFile)' == ''">Directory.Build.targets</_DirectoryBuildTargetsFile>
<_DirectoryBuildTargetsBasePath Condition="'$(_DirectoryBuildTargetsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), '$(_DirectoryBuildTargetsFile)'))</_DirectoryBuildTargetsBasePath>
<DirectoryBuildTargetsPath Condition="'$(_DirectoryBuildTargetsBasePath)' != '' and '$(_DirectoryBuildTargetsFile)' != ''">$([System.IO.Path]::Combine('$(_DirectoryBuildTargetsBasePath)', '$(_DirectoryBuildTargetsFile)'))</DirectoryBuildTargetsPath>
<DirectoryBuildTargetsPath Condition="'$(_DirectoryBuildTargetsBasePath)' != '' and '$(_DirectoryBuildTargetsFile)' != ''">$([MSBuild]::NormalizePath('$(_DirectoryBuildTargetsBasePath)', '$(_DirectoryBuildTargetsFile)'))</DirectoryBuildTargetsPath>
</PropertyGroup>

<Import Project="$(DirectoryBuildTargetsPath)" Condition="'$(ImportDirectoryBuildTargets)' == 'true' and exists('$(DirectoryBuildTargetsPath)')"/>
Expand Down
Loading

0 comments on commit 7528963

Please sign in to comment.