Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple values passed to WithProperty are overridden #1106

Open
nickmacd opened this issue Jul 25, 2016 · 6 comments · May be fixed by #2110
Open

Multiple values passed to WithProperty are overridden #1106

nickmacd opened this issue Jul 25, 2016 · 6 comments · May be fixed by #2110
Assignees
Labels

Comments

@nickmacd
Copy link

nickmacd commented Jul 25, 2016

What You Are Seeing?

MSBuildSettingsExtensions​.WithProperty(MSBuildSettings, ​string, ​String[]) does not work as intended for multiple values of some properties (Maybe all, I don't know). Each value seems to overwrite, so only the last supplied parameter will be applied.

Calling .WithProperty("WarningsNotAsErrors", "1573", "1591") results in /warnaserror-:1591

It looks like method which is used to parse the property dictionary inside MSBuildRunner:

private static IEnumerable<string> GetPropertyArguments(IDictionary<string, IList<string>> properties)
{
    foreach (var propertyKey in properties.Keys)
    {
        foreach (var propertyValue in properties[propertyKey])
        {
            yield return string.Concat("/p:", propertyKey, "=", propertyValue);
        }
    }  
}

Will return "/p:WarningsNotAsErrors=1573", "/p:WarningsNotAsErrors=1591". Which may override when applied sequentially.

Possibly the method could be amended to

private static IEnumerable<string> GetPropertyArguments(IDictionary<string, IList<string>> properties)
{
    foreach (var propertyKey in properties.Keys)
    {
        var values = string.Join(",", properties[propertyKey]);
        yield return string.Concat("/p:", propertyKey, "=", values);
    }  
}

Which would return "/p:WarningsNotAsErrors=1573,1591". I'm not sure how this would affect other properties that are used, if a switch must be declared multiple times with single values it would break that.

What is Expected?

Calling .WithProperty("WarningsNotAsErrors", "1573", "1591") would then become /warnaserror-:1573,1591 when run.

What version of Cake are you using?

0.14.0.0

Are you running on a 32 or 64 bit system?

64

What environment are you running on? Windows? Linux? Mac?

Windows 7

Are you running on a CI Server? If so, which one?

No, running from powershell script locally

How Did You Get This To Happen? (Steps to Reproduce)

Add .WithProperty("WarningsNotAsErrors", "1573", "1591") to any MSBuildSettings.

Run in Diagnostic.

Check the value sent to CoreCompile vs the Executing line.

Output Log

Run with -Mono and -Experimental:

log.txt

@agc93
Copy link
Member

agc93 commented Jul 26, 2016

Are we sure that all of the other MSBuild options also support the "comma delimited values with a single key" format that WarningsNotAsErrors does? Because the GetPropertyArguments method is used for all properties..

@nickmacd
Copy link
Author

Unfortunately I can't even find documentation confirming that duplicate /property assigns to the same key will overwrite, I'm just inferring from results.

I've looked through the msbuild switches, compiler options and common build parameters. In most cases it's comma or semicolon delimitation, but in some it's only comma, and some only semicolon.
So you're correct and a complete switch to comma delimitation would most likely break things. Although I'm not certain that these would work currently anyway, as I've not yet seen a cakescript utilising a WithProperty with multiple values.

As a change is not really viable, possibly another method could be added to account for comma delimited properties?

 public static MSBuildSettings WithCommaDelimitedProperty(this MSBuildSettings settings, string name, params string[] values)
        {
            if (settings == null)
            {
                throw new ArgumentNullException("settings");
            }

            IList<string> currentValue;
            currentValue = new List<string>(
                settings.Properties.TryGetValue(name, out currentValue) && currentValue != null
                    ? currentValue.Concat(values)
                    : values);

            settings.Properties[name] = String.Join(",", currentValue);

            return settings;
        }

It would let GetPropertyArguments function the same, while dealing with the comma delimited case.

@devlead
Copy link
Member

devlead commented Oct 21, 2016

This will need to be investigated, we could probably step thru the MSBuild source and see what it does. If someone wants to contribute / do the work I'll happily review a PR.

@martinscholz83
Copy link
Contributor

HI @devlead, i have step thru MSBuild sources and it seems that they support either comma's or semicolons (,;) as a separator if a switch has multiple values. See here. So i think it's fine what @nickmacd has suggested that we can switch to comma separation with a small change around values. You have to set it between quotes.

foreach (var propertyKey in properties.Keys)
{
var values = string.Join(",", properties[propertyKey]);
yield return string.Concat("/p:", propertyKey, "=",  '"', ,values, '"');
}

@martinscholz83
Copy link
Contributor

And as you see here, duplicate properties are always will overwrite.

@mschlaffer
Copy link

@devlead: confirming what @martinscholz83 and @nickmacd found is still valid.

  • Calling ".WithProperty("WarningsNotAsErrors", "1573", "1591")" results in cake executing MSBuild with "/p:WarningsNotAsErrors=1573 /p:WarningsNotAsErrors=1591"
  • MSBuild simply overwrites properties if they are specified multiple times
  • The intended and supported way for multiple parameters in MSBuild is a comma or semicolon separated list. Not all command line arguments support this, though.
    • the actual separator usage can be seen here. it is split by one of the valid separators and then further processed as a list
  • Every parameter is unquoted before it is processed, so adding quotes around the parameter is fine

In total Cake's current handling for multiple parameters in the "MSBuildSettingsExtensions.WithProperty" method basically results in MSBuild discarding everything except the last parameter. As this definitely doesn't seem to be the intended behavior I would consider this a bug that should be fixed, even though it might change the behavior of old scripts that tried to use multiple parameters (but didn't actually).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants