Skip to content

Commit d94e14d

Browse files
authored
Merge pull request #609 from hvitved/csharp/autobuilder/fixes
C#: Autobuilder fixes
2 parents 57de628 + 1e9fe00 commit d94e14d

File tree

13 files changed

+164
-99
lines changed

13 files changed

+164
-99
lines changed

csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs

Lines changed: 72 additions & 48 deletions
Large diffs are not rendered by default.

csharp/autobuilder/Semmle.Autobuild/AspBuildRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ namespace Semmle.Autobuild
77
/// </summary>
88
class AspBuildRule : IBuildRule
99
{
10-
public BuildScript Analyse(Autobuilder builder)
10+
public BuildScript Analyse(Autobuilder builder, bool auto)
1111
{
1212
var command = new CommandBuilder(builder.Actions).
1313
RunCommand(builder.Actions.PathCombine(builder.SemmleJavaHome, "bin", "java")).

csharp/autobuilder/Semmle.Autobuild/AutobuildOptions.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Linq;
3+
using System.Text.RegularExpressions;
34

45
namespace Semmle.Autobuild
56
{
@@ -37,14 +38,14 @@ public void ReadEnvironment(IBuildActions actions)
3738
{
3839
RootDirectory = actions.GetCurrentDirectory();
3940
VsToolsVersion = actions.GetEnvironmentVariable(prefix + "VSTOOLS_VERSION");
40-
MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS");
41+
MsBuildArguments = actions.GetEnvironmentVariable(prefix + "MSBUILD_ARGUMENTS").AsStringWithExpandedEnvVars(actions);
4142
MsBuildPlatform = actions.GetEnvironmentVariable(prefix + "MSBUILD_PLATFORM");
4243
MsBuildConfiguration = actions.GetEnvironmentVariable(prefix + "MSBUILD_CONFIGURATION");
4344
MsBuildTarget = actions.GetEnvironmentVariable(prefix + "MSBUILD_TARGET");
44-
DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS");
45+
DotNetArguments = actions.GetEnvironmentVariable(prefix + "DOTNET_ARGUMENTS").AsStringWithExpandedEnvVars(actions);
4546
DotNetVersion = actions.GetEnvironmentVariable(prefix + "DOTNET_VERSION");
4647
BuildCommand = actions.GetEnvironmentVariable(prefix + "BUILD_COMMAND");
47-
Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsList(new string[0]);
48+
Solution = actions.GetEnvironmentVariable(prefix + "SOLUTION").AsListWithExpandedEnvVars(actions, new string[0]);
4849

4950
IgnoreErrors = actions.GetEnvironmentVariable(prefix + "IGNORE_ERRORS").AsBool("ignore_errors", false);
5051
Buildless = actions.GetEnvironmentVariable(prefix + "BUILDLESS").AsBool("buildless", false);
@@ -92,12 +93,29 @@ public static Language AsLanguage(this string key)
9293
}
9394
}
9495

95-
public static string[] AsList(this string value, string[] defaultValue)
96+
public static string[] AsListWithExpandedEnvVars(this string value, IBuildActions actions, string[] defaultValue)
9697
{
9798
if (value == null)
9899
return defaultValue;
99100

100-
return value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToArray();
101+
return value.
102+
Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).
103+
Select(s => AsStringWithExpandedEnvVars(s, actions)).ToArray();
104+
}
105+
106+
static readonly Regex linuxEnvRegEx = new Regex(@"\$([a-zA-Z_][a-zA-Z_0-9]*)", RegexOptions.Compiled);
107+
108+
public static string AsStringWithExpandedEnvVars(this string value, IBuildActions actions)
109+
{
110+
if (string.IsNullOrEmpty(value))
111+
return value;
112+
113+
// `Environment.ExpandEnvironmentVariables` only works with Windows-style
114+
// environment variables
115+
var windowsStyle = actions.IsWindows()
116+
? value
117+
: linuxEnvRegEx.Replace(value, m => $"%{m.Groups[1].Value}%");
118+
return actions.EnvironmentExpandEnvironmentVariables(windowsStyle);
101119
}
102120
}
103121
}

csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ interface IBuildRule
1616
/// Analyse the files and produce a build script.
1717
/// </summary>
1818
/// <param name="builder">The files and options relating to the build.</param>
19-
BuildScript Analyse(Autobuilder builder);
19+
/// <param name="auto">Whether this build rule is being automatically applied.</param>
20+
BuildScript Analyse(Autobuilder builder, bool auto);
2021
}
2122

2223
/// <summary>
@@ -135,9 +136,9 @@ public Autobuilder(IBuildActions actions, AutobuildOptions options)
135136
foreach (var solution in options.Solution)
136137
{
137138
if (actions.FileExists(solution))
138-
ret.Add(new Solution(this, solution));
139+
ret.Add(new Solution(this, solution, true));
139140
else
140-
Log(Severity.Error, $"The specified solution file {solution} was not found");
141+
Log(Severity.Error, $"The specified project or solution file {solution} was not found");
141142
}
142143
return ret;
143144
}
@@ -172,7 +173,7 @@ IEnumerable<IProjectOrSolution> FindFiles(string extension, Func<string, Project
172173
return ret;
173174

174175
// Then look for `.sln` files
175-
ret = FindFiles(".sln", f => new Solution(this, f))?.ToList();
176+
ret = FindFiles(".sln", f => new Solution(this, f, false))?.ToList();
176177
if (ret != null)
177178
return ret;
178179

@@ -250,17 +251,17 @@ BuildScript CheckExtractorRun(bool warnOnFailure) =>
250251
switch (GetCSharpBuildStrategy())
251252
{
252253
case CSharpBuildStrategy.CustomBuildCommand:
253-
attempt = new BuildCommandRule().Analyse(this) & CheckExtractorRun(true);
254+
attempt = new BuildCommandRule().Analyse(this, false) & CheckExtractorRun(true);
254255
break;
255256
case CSharpBuildStrategy.Buildless:
256257
// No need to check that the extractor has been executed in buildless mode
257-
attempt = new StandaloneBuildRule().Analyse(this);
258+
attempt = new StandaloneBuildRule().Analyse(this, false);
258259
break;
259260
case CSharpBuildStrategy.MSBuild:
260-
attempt = new MsBuildRule().Analyse(this) & CheckExtractorRun(true);
261+
attempt = new MsBuildRule().Analyse(this, false) & CheckExtractorRun(true);
261262
break;
262263
case CSharpBuildStrategy.DotNet:
263-
attempt = new DotNetRule().Analyse(this) & CheckExtractorRun(true);
264+
attempt = new DotNetRule().Analyse(this, false) & CheckExtractorRun(true);
264265
break;
265266
case CSharpBuildStrategy.Auto:
266267
var cleanTrapFolder =
@@ -285,20 +286,20 @@ BuildScript IntermediateAttempt(BuildScript s) =>
285286

286287
attempt =
287288
// First try .NET Core
288-
IntermediateAttempt(new DotNetRule().Analyse(this)) |
289+
IntermediateAttempt(new DotNetRule().Analyse(this, true)) |
289290
// Then MSBuild
290-
(() => IntermediateAttempt(new MsBuildRule().Analyse(this))) |
291+
(() => IntermediateAttempt(new MsBuildRule().Analyse(this, true))) |
291292
// And finally look for a script that might be a build script
292-
(() => new BuildCommandAutoRule().Analyse(this) & CheckExtractorRun(true)) |
293+
(() => new BuildCommandAutoRule().Analyse(this, true) & CheckExtractorRun(true)) |
293294
// All attempts failed: print message
294295
AutobuildFailure();
295296
break;
296297
}
297298

298299
return
299300
attempt &
300-
(() => new AspBuildRule().Analyse(this)) &
301-
(() => new XmlBuildRule().Analyse(this));
301+
(() => new AspBuildRule().Analyse(this, false)) &
302+
(() => new XmlBuildRule().Analyse(this, false));
302303
}
303304

304305
/// <summary>
@@ -337,13 +338,13 @@ enum CSharpBuildStrategy
337338
BuildScript GetCppBuildScript()
338339
{
339340
if (Options.BuildCommand != null)
340-
return new BuildCommandRule().Analyse(this);
341+
return new BuildCommandRule().Analyse(this, false);
341342

342343
return
343344
// First try MSBuild
344-
new MsBuildRule().Analyse(this) |
345+
new MsBuildRule().Analyse(this, true) |
345346
// Then look for a script that might be a build script
346-
(() => new BuildCommandAutoRule().Analyse(this)) |
347+
(() => new BuildCommandAutoRule().Analyse(this, true)) |
347348
// All attempts failed: print message
348349
AutobuildFailure();
349350
}

csharp/autobuilder/Semmle.Autobuild/BuildActions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ public interface IBuildActions
113113
/// Loads the XML document from <paramref name="filename"/>.
114114
/// </summary>
115115
XmlDocument LoadXml(string filename);
116+
117+
/// <summary>
118+
/// Expand all Windows-style environment variables in <paramref name="s"/>,
119+
/// Environment.ExpandEnvironmentVariables()
120+
/// </summary>
121+
string EnvironmentExpandEnvironmentVariables(string s);
116122
}
117123

118124
/// <summary>
@@ -187,6 +193,8 @@ XmlDocument IBuildActions.LoadXml(string filename)
187193

188194
string IBuildActions.GetFullPath(string path) => Path.GetFullPath(path);
189195

196+
public string EnvironmentExpandEnvironmentVariables(string s) => Environment.ExpandEnvironmentVariables(s);
197+
190198
public static readonly IBuildActions Instance = new SystemBuildActions();
191199
}
192200
}

csharp/autobuilder/Semmle.Autobuild/BuildCommandAutoRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class BuildCommandAutoRule : IBuildRule
2525
"build"
2626
};
2727

28-
public BuildScript Analyse(Autobuilder builder)
28+
public BuildScript Analyse(Autobuilder builder, bool auto)
2929
{
3030
builder.Log(Severity.Info, "Attempting to locate build script");
3131

csharp/autobuilder/Semmle.Autobuild/BuildCommandRule.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
/// </summary>
66
class BuildCommandRule : IBuildRule
77
{
8-
public BuildScript Analyse(Autobuilder builder)
8+
public BuildScript Analyse(Autobuilder builder, bool auto)
99
{
1010
if (builder.Options.BuildCommand == null)
1111
return BuildScript.Failure;

csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,22 +14,25 @@ namespace Semmle.Autobuild
1414
/// </summary>
1515
class DotNetRule : IBuildRule
1616
{
17-
public BuildScript Analyse(Autobuilder builder)
17+
public BuildScript Analyse(Autobuilder builder, bool auto)
1818
{
1919
if (!builder.ProjectsOrSolutionsToBuild.Any())
2020
return BuildScript.Failure;
2121

22-
var notDotNetProject = builder.ProjectsOrSolutionsToBuild.
23-
SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)).
24-
OfType<Project>().
25-
FirstOrDefault(p => !p.DotNetProject);
26-
if (notDotNetProject != null)
22+
if (auto)
2723
{
28-
builder.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject);
29-
return BuildScript.Failure;
30-
}
24+
var notDotNetProject = builder.ProjectsOrSolutionsToBuild.
25+
SelectMany(p => Enumerators.Singleton(p).Concat(p.IncludedProjects)).
26+
OfType<Project>().
27+
FirstOrDefault(p => !p.DotNetProject);
28+
if (notDotNetProject != null)
29+
{
30+
builder.Log(Severity.Info, "Not using .NET Core because of incompatible project {0}", notDotNetProject);
31+
return BuildScript.Failure;
32+
}
3133

32-
builder.Log(Severity.Info, "Attempting to build using .NET Core");
34+
builder.Log(Severity.Info, "Attempting to build using .NET Core");
35+
}
3336

3437
return WithDotNet(builder, dotNet =>
3538
{

csharp/autobuilder/Semmle.Autobuild/MsBuildRule.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,13 @@ class MsBuildRule : IBuildRule
1313
/// </summary>
1414
const string MsBuild = "msbuild";
1515

16-
public BuildScript Analyse(Autobuilder builder)
16+
public BuildScript Analyse(Autobuilder builder, bool auto)
1717
{
1818
if (!builder.ProjectsOrSolutionsToBuild.Any())
1919
return BuildScript.Failure;
2020

21-
builder.Log(Severity.Info, "Attempting to build using MSBuild");
21+
if (auto)
22+
builder.Log(Severity.Info, "Attempting to build using MSBuild");
2223

2324
var vsTools = GetVcVarsBatFile(builder);
2425

csharp/autobuilder/Semmle.Autobuild/Project.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ public Project(Autobuilder builder, string path) : base(builder, path)
3939
{
4040
projFile = builder.Actions.LoadXml(FullPath);
4141
}
42-
catch (XmlException)
42+
catch (Exception e) when (e is XmlException || e is FileNotFoundException)
4343
{
44-
builder.Log(Severity.Info, $"Skipping project file {path} as it is not a valid XML document.");
44+
builder.Log(Severity.Info, $"Unable to read project file {path}.");
4545
return;
4646
}
4747

@@ -80,7 +80,7 @@ public Project(Autobuilder builder, string path) : base(builder, path)
8080
var projectFilesIncludes = root.SelectNodes("//msbuild:Project/msbuild:ItemGroup/msbuild:ProjectFiles/@Include", mgr).OfType<XmlNode>();
8181
foreach (var include in projectFileIncludes.Concat(projectFilesIncludes))
8282
{
83-
var includePath = builder.Actions.IsWindows() ? include.Value : include.Value.Replace("\\", "/");
83+
var includePath = builder.Actions.PathCombine(include.Value.Split('\\', StringSplitOptions.RemoveEmptyEntries));
8484
ret.Add(new Project(builder, builder.Actions.PathCombine(Path.GetDirectoryName(this.FullPath), includePath)));
8585
}
8686
return ret;

0 commit comments

Comments
 (0)