diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/D8.cs b/src/Xamarin.Android.Build.Tasks/Tasks/D8.cs
index 797d63e657c..78717d986d5 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/D8.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/D8.cs
@@ -80,7 +80,7 @@ protected virtual CommandLineBuilder GetCommandLineBuilder ()
// Create response file with all D8/R8 arguments to avoid command line length limits
responseFilePath = CreateResponseFile ();
- cmd.AppendSwitch ($"@{responseFilePath}");
+ cmd.AppendSwitch ($"\"@{responseFilePath}\"");
return cmd;
}
@@ -91,7 +91,7 @@ protected virtual CommandLineBuilder GetCommandLineBuilder ()
///
protected virtual string CreateResponseFile ()
{
- var responseFile = Path.GetTempFileName ();
+ var responseFile = CreateResponseFilePath ();
Log.LogDebugMessage ($"[{MainClass}] response file: {responseFile}");
using var response = new StreamWriter (responseFile, append: false, encoding: Files.UTF8withoutBOM);
@@ -170,6 +170,8 @@ protected virtual string CreateResponseFile ()
return responseFile;
}
+ protected virtual string CreateResponseFilePath () => Path.GetTempFileName ();
+
///
/// Writes a single argument to the response file.
/// R8/D8 response files treat each line as a complete argument, so no quoting is needed.
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs b/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs
index 4809a4bac60..55be2657710 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/JavaSourceUtils.cs
@@ -90,7 +90,7 @@ protected override string GenerateCommandLineCommands ()
// Arguments sent to java.exe
cmd.AppendSwitchIfNotNull ("-jar ", JavaSourceUtilsJar);
- cmd.AppendSwitch ($"@{responseFilePath}");
+ cmd.AppendSwitch ($"\"@{responseFilePath}\"");
return cmd.ToString ();
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/D8Tests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/D8Tests.cs
index f86c0b4f9d4..7ed141a91f0 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/D8Tests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/D8Tests.cs
@@ -6,6 +6,7 @@
using Microsoft.Build.Utilities;
using NUnit.Framework;
using Xamarin.Android.Tasks;
+using Xamarin.Android.Tools;
namespace Xamarin.Android.Build.Tests
{
@@ -73,7 +74,7 @@ public void ResponseFileContainsLibAndInputJars ()
FileAssert.Exists (responseFilePath, "Response file should exist");
// Verify the response file is referenced in the command line
- Assert.IsTrue (commandLine.Contains ($"@{responseFilePath}"), "Command line should reference the response file");
+ Assert.IsTrue (commandLine.Contains ($"\"@{responseFilePath}\""), "Command line should quote the response file");
// Read and verify response file content
string [] responseFileContent = File.ReadAllLines (responseFilePath);
@@ -116,16 +117,19 @@ public void ResponseFileHandlesPathsWithSpaces ()
JarPath = "d8.jar",
JavaPlatformJarPath = platformJar,
OutputDirectory = tempDir,
+ ResponseFileDirectory = pathWithSpaces,
JavaLibrariesToEmbed = new ITaskItem [] {
new TaskItem (inputJar),
},
};
- d8Task.TestGenerateCommandLineCommands ();
+ string commandLine = d8Task.TestGenerateCommandLineCommands ();
string responseFilePath = d8Task.ResponseFilePath;
try {
+ Assert.IsNotNull (responseFilePath, "Response file path should not be null");
FileAssert.Exists (responseFilePath, "Response file should exist");
+ Assert.IsTrue (commandLine.Contains ($"\"@{responseFilePath}\""), "Command line should quote a response file path containing spaces");
string responseFileContent = File.ReadAllText (responseFilePath);
// Paths with spaces should NOT be quoted (R8/D8 treats each line as a complete argument)
@@ -150,30 +154,30 @@ internal class D8TestTask : D8
///
public string ResponseFilePath { get; private set; }
+ public string ResponseFileDirectory { get; set; }
+
+ protected override string CreateResponseFilePath ()
+ {
+ if (!ResponseFileDirectory.IsNullOrEmpty ()) {
+ return Path.Combine (ResponseFileDirectory, Path.GetRandomFileName ());
+ }
+ return base.CreateResponseFilePath ();
+ }
+
+ protected override string CreateResponseFile ()
+ {
+ var responseFile = base.CreateResponseFile ();
+ ResponseFilePath = responseFile;
+ return responseFile;
+ }
+
///
/// Test method that generates command line without actually running the task.
///
public string TestGenerateCommandLineCommands ()
{
var cmd = GetCommandLineBuilder ();
- // Capture the response file path after command line generation
- ResponseFilePath = GetResponseFilePathFromCommandLine (cmd.ToString ());
return cmd.ToString ();
}
-
- private static string GetResponseFilePathFromCommandLine (string commandLine)
- {
- // Find the @filepath argument
- var startIndex = commandLine.IndexOf ("@", StringComparison.Ordinal);
- if (startIndex < 0) return null;
-
- // Check if '@' is the last character
- if (startIndex + 1 >= commandLine.Length) return null;
-
- var endIndex = commandLine.IndexOf (" ", startIndex, StringComparison.Ordinal);
- if (endIndex < 0) endIndex = commandLine.Length;
-
- return commandLine.Substring (startIndex + 1, endIndex - startIndex - 1);
- }
}
}