Skip to content

Commit

Permalink
[Build] Some updates to alloew the new project system to see the refe…
Browse files Browse the repository at this point in the history
…rence assemblies
  • Loading branch information
RobertvanderHulst committed Aug 21, 2024
1 parent 6f4ecb7 commit 36efbba
Show file tree
Hide file tree
Showing 3 changed files with 224 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -243,3 +243,4 @@ XSharp/src/Setup/Preprocessed.iss
.antlr/
/src/Tools/VFPXPorter/Source/VFPXPorterLib/Data/Templates/Tools/XSharp.VFP.UI.dll
*.chw
/src/Compiler/src/Compiler/XSharpBuildTask/XSharp.Build.dll
10 changes: 4 additions & 6 deletions src/Compiler/src/Compiler/XSharpBuildTask/ManagedCompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public int CodePage
set { _store[nameof(CodePage)] = value; }
get { return _store.GetOrDefault(nameof(CodePage), 0); }
}

[Output]
public ITaskItem[] CommandLineArgs
{
Expand All @@ -104,7 +104,7 @@ public string DebugType
set { _store[nameof(DebugType)] = value; }
get { return (string)_store[nameof(DebugType)]; }
}

public string SourceLink
{
set { _store[nameof(SourceLink)] = value; }
Expand Down Expand Up @@ -260,15 +260,13 @@ public ITaskItem OutputAssembly
get { return (ITaskItem)_store[nameof(OutputAssembly)]; }
}



[Output]
public ITaskItem OutputRefAssembly
{
set { _store[nameof(OutputRefAssembly)] = value; }
get { return (ITaskItem)_store[nameof(OutputRefAssembly)]; }
}

public string Platform
{
set { _store[nameof(Platform)] = value; }
Expand Down Expand Up @@ -862,7 +860,7 @@ internal void AddResponseFileCommandsForSwitchesSinceInitialReleaseThatAreNeeded
AddEmbeddedFilesToCommandLine(commandLine);
AddAnalyzerConfigFilesToCommandLine(commandLine);
}

/// <summary>
/// Adds a "/features:" switch to the command line for each provided feature.
/// </summary>
Expand Down
219 changes: 219 additions & 0 deletions src/Compiler/src/Compiler/XSharpBuildTask/Xsc.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using System.IO;
using System.Diagnostics;
using Roslyn.Utilities;
using System.Collections.Generic;

namespace XSharp.Build
{
Expand Down Expand Up @@ -259,6 +260,32 @@ public string Dialect
#endregion
#region properties copied from the csc task

#region New in X# 3.0

public string? ProjectName
{
set { _store[nameof(ProjectName)] = value; }
get { return (string?)_store[nameof(ProjectName)]; }
}
public bool ReportIVTs
{
set { _store[nameof(ReportIVTs)] = value; }
get { return _store.GetOrDefault(nameof(ReportIVTs), false); }
}

public string? TargetFramework
{
set { _store[nameof(TargetFramework)] = value; }
get { return (string?)_store[nameof(TargetFramework)]; }
}
public string? InterceptorsPreviewNamespaces
{
set { _store[nameof(InterceptorsPreviewNamespaces)] = value; }
get { return (string?)_store[nameof(InterceptorsPreviewNamespaces)]; }
}


#endregion
public bool AllowUnsafeBlocks
{
set { _store[nameof(AllowUnsafeBlocks)] = value; }
Expand Down Expand Up @@ -530,6 +557,19 @@ protected internal override void AddResponseFileCommands(CommandLineBuilderExten
throw;
}
}
/// <summary>
/// Generate the arguments to pass directly to the managed tool. These do not include
/// arguments in the response file.
/// </summary>
/// <remarks>
/// This will be the same value whether the build occurs on .NET Core or .NET Framework.
/// </remarks>
internal string GenerateToolArguments()
{
var builder = new CommandLineBuilderExtension();
AddCommandLineCommands(builder);
return builder.ToString();
}

protected override string GetResponseFileSwitch(string responseFilePath)
{
Expand All @@ -538,8 +578,40 @@ protected override string GetResponseFileSwitch(string responseFilePath)
return base.GetResponseFileSwitch(responseFilePath);
}

protected List<string> GenerateCommandLineArgsList(string responseFileCommands)
{
var argumentList = new List<string>();
var builder = new StringBuilder();
CommandLineUtilities.SplitCommandLineIntoArguments(GenerateToolArguments(), removeHashComments: true, builder, argumentList, out _);
CommandLineUtilities.SplitCommandLineIntoArguments(responseFileCommands, removeHashComments: true, builder, argumentList,out _);
return argumentList;
}

protected internal ITaskItem[] GenerateCommandLineArgsTaskItems(string responseFileCommands) =>
GenerateCommandLineArgsTaskItems(GenerateCommandLineArgsList(responseFileCommands));

protected static ITaskItem[] GenerateCommandLineArgsTaskItems(List<string> commandLineArgs)
{
var items = new ITaskItem[commandLineArgs.Count];
for (var i = 0; i < commandLineArgs.Count; i++)
{
items[i] = new TaskItem(commandLineArgs[i]);
}

return items;
}

protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands)
{
if (ProvideCommandLineArgs)
{
CommandLineArgs = GenerateCommandLineArgsTaskItems(responseFileCommands);
}

if (SkipCompilerExecution)
{
return 0;
}
int iResult;
DateTime start = DateTime.Now;
iResult = base.ExecuteTool(pathToTool, responseFileCommands, commandLineCommands);
Expand Down Expand Up @@ -920,5 +992,152 @@ protected override void LogEventsFromTextOutput(string singleLine, MessageImport
}

}
internal static class CommandLineUtilities
{
/// <summary>
/// Split a command line by the same rules as Main would get the commands except the original
/// state of backslashes and quotes are preserved. For example in normal Windows command line
/// parsing the following command lines would produce equivalent Main arguments:
///
/// - /r:a,b
/// - /r:"a,b"
///
/// This method will differ as the latter will have the quotes preserved. The only case where
/// quotes are removed is when the entire argument is surrounded by quotes without any inner
/// quotes.
/// </summary>
/// <remarks>
/// Rules for command line parsing, according to MSDN:
///
/// Arguments are delimited by white space, which is either a space or a tab.
///
/// A string surrounded by double quotation marks ("string") is interpreted
/// as a single argument, regardless of white space contained within.
/// A quoted string can be embedded in an argument.
///
/// A double quotation mark preceded by a backslash (\") is interpreted as a
/// literal double quotation mark character (").
///
/// Backslashes are interpreted literally, unless they immediately precede a
/// double quotation mark.
///
/// If an even number of backslashes is followed by a double quotation mark,
/// one backslash is placed in the argv array for every pair of backslashes,
/// and the double quotation mark is interpreted as a string delimiter.
///
/// If an odd number of backslashes is followed by a double quotation mark,
/// one backslash is placed in the argv array for every pair of backslashes,
/// and the double quotation mark is "escaped" by the remaining backslash,
/// causing a literal double quotation mark (") to be placed in argv.
/// </remarks>
public static List<string> SplitCommandLineIntoArguments(string commandLine, bool removeHashComments)
{
return SplitCommandLineIntoArguments(commandLine, removeHashComments, out _);
}

public static List<string> SplitCommandLineIntoArguments(string commandLine, bool removeHashComments, out char? illegalChar)
{
var list = new List<string>();
SplitCommandLineIntoArguments(commandLine, removeHashComments, new StringBuilder(), list, out illegalChar);
return list;
}

public static void SplitCommandLineIntoArguments(string commandLine, bool removeHashComments, StringBuilder builder, List<string> list, out char? illegalChar)
{
var i = 0;

builder.Length = 0;
illegalChar = null;
while (i < commandLine.Length)
{
while (i < commandLine.Length && char.IsWhiteSpace(commandLine[i]))
{
i++;
}

if (i == commandLine.Length)
{
break;
}

if (commandLine[i] == '#' && removeHashComments)
{
break;
}

var quoteCount = 0;
builder.Length = 0;
while (i < commandLine.Length && (!char.IsWhiteSpace(commandLine[i]) || (quoteCount % 2 != 0)))
{
var current = commandLine[i];
switch (current)
{
case '\\':
{
var slashCount = 0;
do
{
builder.Append(commandLine[i]);
i++;
slashCount++;
} while (i < commandLine.Length && commandLine[i] == '\\');

// Slashes not followed by a quote character can be ignored for now
if (i >= commandLine.Length || commandLine[i] != '"')
{
break;
}

// If there is an odd number of slashes then it is escaping the quote
// otherwise it is just a quote.
if (slashCount % 2 == 0)
{
quoteCount++;
}

builder.Append('"');
i++;
break;
}

case '"':
builder.Append(current);
quoteCount++;
i++;
break;

default:
if ((current >= 0x1 && current <= 0x1f) || current == '|')
{
if (illegalChar == null)
{
illegalChar = current;
}
}
else
{
builder.Append(current);
}

i++;
break;
}
}

// If the quote string is surrounded by quotes with no interior quotes then
// remove the quotes here.
if (quoteCount == 2 && builder[0] == '"' && builder[builder.Length - 1] == '"')
{
builder.Remove(0, length: 1);
builder.Remove(builder.Length - 1, length: 1);
}

if (builder.Length > 0)
{
list.Add(builder.ToString());
}
}
}
}

}

0 comments on commit 36efbba

Please sign in to comment.