Skip to content

Commit 6829b7d

Browse files
dellis1972jonpryor
authored andcommitted
[Xamarin.Android.Build.Tasks] Support multidex + ' ' in SDK path (#575)
Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=33052 Fixes: https://bugzilla.xamarin.com/show_bug.cgi?id=38693 The google tooling around multidex is pretty broken on windows. It does not handle paths with spaces and has over quoting path issues. This is one reason why we are shipping our own Proguard. This commit completely removes the use of `mainDexClasses.bat` and introduces code which will create the ` multidex.keep` by making the required calls manually.
1 parent 611bb66 commit 6829b7d

File tree

3 files changed

+63
-31
lines changed

3 files changed

+63
-31
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/CreateMultiDexMainDexClassList.cs

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2011 Xamarin, Inc. All rights reserved.
1+
// Copyright (C) 2011 Xamarin, Inc. All rights reserved.
22

33
using System;
44
using System.Collections.Generic;
@@ -12,20 +12,27 @@
1212

1313
namespace Xamarin.Android.Tasks
1414
{
15-
public class CreateMultiDexMainDexClassList : ToolTask
15+
public class CreateMultiDexMainDexClassList : JavaToolTask
1616
{
1717
[Required]
1818
public string ClassesOutputDirectory { get; set; }
1919

2020
[Required]
21-
public string ProguardHome { get; set; }
21+
public string ProguardJarPath { get; set; }
22+
23+
[Required]
24+
public string AndroidSdkBuildToolsPath { get; set; }
2225

2326
[Required]
2427
public ITaskItem[] JavaLibraries { get; set; }
2528

2629
public string MultiDexMainDexListFile { get; set; }
2730
public ITaskItem[] CustomMainDexListFiles { get; set; }
2831

32+
Action<CommandLineBuilder> commandlineAction;
33+
string tempJar;
34+
bool writeOutputToKeepFile = false;
35+
2936
public override bool Execute ()
3037
{
3138
Log.LogDebugMessage ("CreateMultiDexMainDexClassList");
@@ -35,45 +42,69 @@ public override bool Execute ()
3542
Log.LogDebugTaskItems (" CustomMainDexListFiles:", CustomMainDexListFiles);
3643
Log.LogDebugMessage (" ToolExe: {0}", ToolExe);
3744
Log.LogDebugMessage (" ToolPath: {0}", ToolPath);
38-
Log.LogDebugMessage (" ProguardHome: {0}", ProguardHome);
45+
Log.LogDebugMessage (" ProguardJarPath: {0}", ProguardJarPath);
3946

4047
if (CustomMainDexListFiles != null && CustomMainDexListFiles.Any ()) {
4148
var content = string.Concat (CustomMainDexListFiles.Select (i => File.ReadAllText (i.ItemSpec)));
4249
File.WriteAllText (MultiDexMainDexListFile, content);
4350
return true;
4451
}
4552

46-
EnvironmentVariables = MonoAndroidHelper.GetProguardEnvironmentVaribles (ProguardHome);
53+
tempJar = Path.Combine (Path.GetTempPath (), Path.GetRandomFileName () + ".jar");
54+
commandlineAction = GenerateProguardCommands;
55+
// run proguard first
56+
var retval = base.Execute ();
57+
if (!retval || Log.HasLoggedErrors)
58+
return false;
59+
60+
commandlineAction = GenerateMainDexListBuilderCommands;
61+
// run java second
62+
63+
return base.Execute () && !Log.HasLoggedErrors;
4764

48-
return base.Execute ();
4965
}
5066

5167
protected override string GenerateCommandLineCommands ()
5268
{
5369
var cmd = new CommandLineBuilder ();
70+
commandlineAction (cmd);
71+
return cmd.ToString ();
72+
}
5473

55-
cmd.AppendSwitch ("--output");
56-
cmd.AppendFileNameIfNotNull (MultiDexMainDexListFile);
57-
74+
void GenerateProguardCommands (CommandLineBuilder cmd)
75+
{
76+
var enclosingChar = OS.IsWindows ? "\"" : string.Empty;
5877
var jars = JavaLibraries.Select (i => i.ItemSpec).Concat (new string [] { ClassesOutputDirectory });
59-
string files = string.Join (Path.PathSeparator.ToString (), jars.Select (s => '\'' + s + '\''));
60-
if (OS.IsWindows)
61-
cmd.AppendSwitch ('"' + files + '"');
62-
else
63-
cmd.AppendSwitch (files);
64-
65-
return cmd.ToString ();
78+
cmd.AppendSwitchIfNotNull ("-jar ", ProguardJarPath);
79+
cmd.AppendSwitchUnquotedIfNotNull ("-injars ", $"{enclosingChar}'" + string.Join ($"'{Path.PathSeparator}'", jars) + $"'{enclosingChar}");
80+
cmd.AppendSwitch ("-dontwarn");
81+
cmd.AppendSwitch ("-forceprocessing");
82+
cmd.AppendSwitchIfNotNull ("-outjars ", tempJar);
83+
cmd.AppendSwitchIfNotNull ("-libraryjars ", $"'{Path.Combine (AndroidSdkBuildToolsPath, "lib", "shrinkedAndroid.jar")}'");
84+
cmd.AppendSwitch ("-dontoptimize");
85+
cmd.AppendSwitch ("-dontobfuscate");
86+
cmd.AppendSwitch ("-dontpreverify");
87+
cmd.AppendSwitchIfNotNull ("-include ", $"'{Path.Combine (AndroidSdkBuildToolsPath, "mainDexClasses.rules")}'");
6688
}
6789

68-
protected override string ToolName {
69-
get {
70-
return OS.IsWindows ? "mainDexClasses.bat" : "mainDexClasses";
71-
}
90+
void GenerateMainDexListBuilderCommands(CommandLineBuilder cmd)
91+
{
92+
var jars = JavaLibraries.Select (i => i.ItemSpec).Concat (new string [] { ClassesOutputDirectory });
93+
cmd.AppendSwitchIfNotNull ("-Djava.ext.dirs=", Path.Combine (AndroidSdkBuildToolsPath, "lib"));
94+
cmd.AppendSwitch ("com.android.multidex.MainDexListBuilder");
95+
cmd.AppendSwitch (tempJar);
96+
cmd.AppendSwitchUnquotedIfNotNull ("", "\"" + string.Join ($"{Path.PathSeparator}", jars) + "\"");
97+
writeOutputToKeepFile = true;
7298
}
7399

74-
protected override string GenerateFullPathToTool ()
100+
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
75101
{
76-
return Path.Combine (ToolPath, ToolExe);
102+
var match = CodeErrorRegEx.Match (singleLine);
103+
var exceptionMatch = ExceptionRegEx.Match (singleLine);
104+
105+
if (writeOutputToKeepFile && !match.Success && !exceptionMatch.Success)
106+
File.AppendAllText (MultiDexMainDexListFile, singleLine);
107+
base.LogEventsFromTextOutput (singleLine, messageImportance);
77108
}
78109
}
79110
}

src/Xamarin.Android.Build.Tasks/Tasks/JavaToolTask.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ at com.android.dx.command.dexer.Main.main(Main.java:215)
6666
at com.android.dx.command.Main.main(Main.java:106)
6767
*/
6868
const string ExceptionRegExString = @"(?<exception>java.lang.+):(?<error>.+)";
69-
Regex codeErrorRegEx = new Regex (CodeErrorRegExString, RegexOptions.Compiled);
70-
Regex exceptionRegEx = new Regex (ExceptionRegExString, RegexOptions.Compiled);
69+
protected static readonly Regex CodeErrorRegEx = new Regex (CodeErrorRegExString, RegexOptions.Compiled);
70+
protected static readonly Regex ExceptionRegEx = new Regex (ExceptionRegExString, RegexOptions.Compiled);
7171
bool foundError = false;
7272
List<string> errorLines = new List<string> ();
7373
StringBuilder errorText = new StringBuilder ();
@@ -114,8 +114,8 @@ void LogFromException (string exception, string error) {
114114

115115
bool ProcessOutput (string singleLine)
116116
{
117-
var match = codeErrorRegEx.Match (singleLine);
118-
var exceptionMatch = exceptionRegEx.Match (singleLine);
117+
var match = CodeErrorRegEx.Match (singleLine);
118+
var exceptionMatch = ExceptionRegEx.Match (singleLine);
119119

120120
if (match.Success) {
121121
if (!string.IsNullOrEmpty (file)) {
@@ -157,8 +157,8 @@ bool ProcessOutput (string singleLine)
157157

158158
protected override void LogEventsFromTextOutput (string singleLine, MessageImportance messageImportance)
159159
{
160-
var match = codeErrorRegEx.Match (singleLine);
161-
var exceptionMatch = exceptionRegEx.Match (singleLine);
160+
var match = CodeErrorRegEx.Match (singleLine);
161+
var exceptionMatch = ExceptionRegEx.Match (singleLine);
162162

163163
if (match.Success || exceptionMatch.Success) {
164164
Log.LogMessage (MessageImportance.High, singleLine);

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1950,9 +1950,10 @@ because xbuild doesn't support framework reference assemblies.
19501950

19511951
<CreateMultiDexMainDexClassList
19521952
Condition="'$(AndroidEnableMultiDex)' == 'True' And '$(AndroidCustomMainDexListFile)' == ''"
1953-
ToolPath="$(MainDexClassesToolPath)"
1954-
ToolExe="$(MainDexClassesToolExe)"
1955-
ProguardHome="$(ProguardToolPath)"
1953+
ToolPath="$(JavaToolPath)"
1954+
ToolExe="$(JavaToolExe)"
1955+
ProguardJarPath="$(ProguardJarPath)"
1956+
AndroidSdkBuildToolsPath="$(AndroidSdkBuildToolsPath)"
19561957
ClassesOutputDirectory="$(IntermediateOutputPath)android\bin\classes"
19571958
JavaLibraries="@(_JavaLibrariesToCompile)"
19581959
MultiDexMainDexListFile="$(_AndroidMainDexListFile)"

0 commit comments

Comments
 (0)