[msbuild] support custom proguard via ProguardToolPath for multidex etc. (#267)

We had ProguardToolPath and it could be used for custom proguard tools,
which should be useful if we want to support Java8 based libraries which
doesn't work with the one in Android SDK. In theory.

In fact, it was not sufficient because proguard is also used by multidex.
To support multidex, we have to generate correct mainDexClasses rules
that should depend on Android SDK path, not proguard.

To support custom proguard, we need PROGUARD_HOME environment variable
in mainDexClasses(.bat). That actually uncovered another issue we had:
we were using ToolTask.EnvironmentOverride which is [Obsolete] and
converts every entry to lowercase, which can work on Windows but not
elsewhere i.e. even if we had PROGUARD_HOME, it became proguard_home(!)
Therefore we use ToolTask.EnvironmentVariables instead from now on.

Due to xbuild property parser issue, it differentiates MSBuild on
Windows and xbuild elsewhere to give some additional env. variables.
This commit is contained in:
Atsushi Eno 2016-10-18 03:51:53 +09:00 коммит произвёл Jonathan Pryor
Родитель eb45485f10
Коммит a967b24cf3
4 изменённых файлов: 55 добавлений и 41 удалений

Просмотреть файл

@ -17,6 +17,11 @@ namespace Xamarin.Android.Tasks
[Required]
public string ClassesOutputDirectory { get; set; }
[Required]
public string ProguardHome { get; set; }
public string MSBuildRuntimeType { get; set; }
[Required]
public ITaskItem[] JavaLibraries { get; set; }
@ -32,13 +37,22 @@ namespace Xamarin.Android.Tasks
Log.LogDebugTaskItems (" CustomMainDexListFiles:", CustomMainDexListFiles);
Log.LogDebugMessage (" ToolExe: {0}", ToolExe);
Log.LogDebugMessage (" ToolPath: {0}", ToolPath);
Log.LogDebugMessage (" MSBuildRuntimeType: {0}", MSBuildRuntimeType);
Log.LogDebugMessage (" ProguardHome: {0}", ProguardHome);
if (CustomMainDexListFiles != null && CustomMainDexListFiles.Any ()) {
var content = string.Concat (CustomMainDexListFiles.Select (i => File.ReadAllText (i.ItemSpec)));
File.WriteAllText (MultiDexMainDexListFile, content);
return true;
}
// Windows seems to need special care, needs JAVA_TOOL_OPTIONS.
// On the other hand, xbuild has a bug and fails to parse '=' in the value, so we skip JAVA_TOOL_OPTIONS on Mono runtime.
EnvironmentVariables =
string.IsNullOrEmpty (MSBuildRuntimeType) || MSBuildRuntimeType == "Mono" ?
new string [] { "PROGUARD_HOME=" + ProguardHome } :
new string [] { "JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8", "PROGUARD_HOME=" + ProguardHome };
return base.Execute ();
}
@ -69,17 +83,6 @@ namespace Xamarin.Android.Tasks
{
return Path.Combine (ToolPath, ToolExe);
}
// Windows seems to need special care.
protected override StringDictionary EnvironmentOverride {
get {
var sd = base.EnvironmentOverride ?? new StringDictionary ();
var opts = sd.ContainsKey ("JAVA_TOOL_OPTIONS") ? sd ["JAVA_TOOL_OPTIONS"] : null;
opts += " -Dfile.encoding=UTF8";
sd ["JAVA_TOOL_OPTIONS"] = opts;
return sd;
}
}
}
}

Просмотреть файл

@ -20,6 +20,9 @@ namespace Xamarin.Android.Tasks
[Required]
public string JavaPlatformJackPath { get; set; }
[Required]
public string AndroidSdkDirectory { get; set; }
[Required]
public string [] InputJackFiles { get; set; }
@ -112,7 +115,7 @@ namespace Xamarin.Android.Tasks
// skip invalid lines
}
var configs = ProguardConfigurationFiles
.Replace ("{sdk.dir}", Path.GetDirectoryName (Path.GetDirectoryName (ProguardJarPath)) + Path.DirectorySeparatorChar)
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
.Replace ("{intermediate.common.xamarin}", ProguardCommonXamarinConfiguration)
.Replace ("{intermediate.references}", ProguardGeneratedReferenceConfiguration)
.Replace ("{intermediate.application}", ProguardGeneratedApplicationConfiguration)

Просмотреть файл

@ -22,11 +22,18 @@ namespace Xamarin.Android.Tasks
{
public string ProguardJarPath { get; set; }
public string ProguardToolPath { get; set; }
public string JavaToolPath { get; set; }
public string MSBuildRuntimeType { get; set; }
[Required]
public string JavaPlatformJarPath { get; set; }
[Required]
public string AndroidSdkDirectory { get; set; }
[Required]
public string ClassesOutputDirectory { get; set; }
@ -79,6 +86,8 @@ namespace Xamarin.Android.Tasks
public override bool Execute ()
{
Log.LogDebugMessage ("Proguard");
Log.LogDebugMessage (" AndroidSdkDirectory: {0}", AndroidSdkDirectory);
Log.LogDebugMessage (" MSBuildRuntimeType: {0}", MSBuildRuntimeType);
Log.LogDebugMessage (" JavaPlatformJarPath: {0}", JavaPlatformJarPath);
Log.LogDebugMessage (" ClassesOutputDirectory: {0}", ClassesOutputDirectory);
Log.LogDebugMessage (" AcwMapFile: {0}", AcwMapFile);
@ -97,6 +106,13 @@ namespace Xamarin.Android.Tasks
Log.LogDebugMessage (" PrintSeedsOutput: {0}", PrintSeedsOutput);
Log.LogDebugMessage (" PrintMappingOutput: {0}", PrintMappingOutput);
// Windows seems to need special care, needs JAVA_TOOL_OPTIONS.
// On the other hand, xbuild has a bug and fails to parse '=' in the value, so we skip JAVA_TOOL_OPTIONS on Mono runtime.
EnvironmentVariables =
string.IsNullOrEmpty (MSBuildRuntimeType) || MSBuildRuntimeType == "Mono" ?
new string [] { "PROGUARD_HOME=" + ProguardHome } :
new string [] { "JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8", "PROGUARD_HOME=" + ProguardHome };
return base.Execute ();
}
@ -150,7 +166,7 @@ namespace Xamarin.Android.Tasks
GetType ().Assembly.GetManifestResourceStream ("proguard_xamarin.cfg").CopyTo (xamcfg);
var configs = ProguardConfigurationFiles
.Replace ("{sdk.dir}", Path.GetDirectoryName (Path.GetDirectoryName (ProguardHome)) + Path.DirectorySeparatorChar)
.Replace ("{sdk.dir}", AndroidSdkDirectory + Path.DirectorySeparatorChar)
.Replace ("{intermediate.common.xamarin}", ProguardCommonXamarinConfiguration)
.Replace ("{intermediate.references}", ProguardGeneratedReferenceConfiguration)
.Replace ("{intermediate.application}", ProguardGeneratedApplicationConfiguration)
@ -186,36 +202,22 @@ namespace Xamarin.Android.Tasks
cmd.AppendSwitchIfNotNull ("-printusage ", PrintUsageOutput);
cmd.AppendSwitchIfNotNull ("-printmapping ", PrintMappingOutput);
}
// http://stackoverflow.com/questions/5701126/compile-with-proguard-gives-exception-local-variable-type-mismatch#7587680
cmd.AppendSwitch ("-optimizations !code/allocation/variable");
return cmd.ToString ();
}
protected override string GenerateFullPathToTool ()
{
if (UseProguard)
return Path.Combine (ToolPath, ToolExe);
return Path.Combine (ProguardToolPath, "bin", ToolExe);
return Path.Combine (JavaToolPath, ToolName);
}
// Windows seems to need special care.
protected override StringDictionary EnvironmentOverride {
get {
var sd = base.EnvironmentOverride ?? new StringDictionary ();
if (OS.IsWindows) {
if (!sd.ContainsKey ("PROGUARD_HOME"))
sd.Add ("PROGUARD_HOME", ProguardHome);
}
var opts = sd.ContainsKey ("JAVA_TOOL_OPTIONS") ? sd ["JAVA_TOOL_OPTIONS"] : null;
opts += " -Dfile.encoding=UTF8";
sd ["JAVA_TOOL_OPTIONS"] = opts;
return sd;
}
}
string ProguardHome {
get {
return Path.GetDirectoryName (Path.GetDirectoryName (UseProguard ? ToolPath : ProguardJarPath));
}
get { return UseProguard ? ProguardToolPath : Path.GetDirectoryName (Path.GetDirectoryName (ProguardJarPath)); }
}
}
}

Просмотреть файл

@ -742,14 +742,15 @@ because xbuild doesn't support framework reference assemblies.
/>
</CreateProperty>
<CreateProperty Value="$(AndroidSdkDirectory)\tools\proguard\lib\proguard.jar">
<Output TaskParameter="Value" PropertyName="ProguardJarPath"
Condition="'$(ProguardJarPath)' == ''"
/>
</CreateProperty>
<CreateProperty Value="$(AndroidSdkDirectory)\tools\proguard\">
<Output TaskParameter="Value" PropertyName="ProguardToolPath"
Condition="'$(UseProguard)' == 'True' And '$(ProguardToolPath)' == ''"
Condition="'$(ProguardToolPath)' == ''"
/>
</CreateProperty>
<CreateProperty Value="$(ProguardToolPath)lib\proguard.jar">
<Output TaskParameter="Value" PropertyName="ProguardJarPath"
Condition="'$(ProguardJarPath)' == ''"
/>
</CreateProperty>
@ -1883,6 +1884,7 @@ because xbuild doesn't support framework reference assemblies.
StubSourceDirectory="$(IntermediateOutputPath)android\src"
JavaSourceFiles="@(AndroidJavaSource)"
JavaPlatformJackPath="$(_JavaPlatformJackPath)"
AndroidSdkDirectory="$(_AndroidSdkDirectory)"
InputJackFiles="@(_PreprocessedJavaLibrary)"
OutputDexDirectory="$(IntermediateOutputPath)android\bin"
ToolPath="$(JavaToolPath)"
@ -2021,8 +2023,10 @@ because xbuild doesn't support framework reference assemblies.
<Proguard
Condition="'$(AndroidEnableProguard)' == 'True' and '$(_ProguardProjectConfiguration)' != ''"
ProguardJarPath="$(ProguardJarPath)"
AndroidSdkDirectory="$(_AndroidSdkDirectory)"
JavaToolPath="$(JavaToolPath)"
ToolPath="$(ProguardToolPath)"
MSBuildRuntimeType="$(MSBuildRuntimeType)"
ProguardToolPath="$(ProguardToolPath)"
ToolExe="$(ProguardToolExe)"
UseProguard="$(UseProguard)"
JavaPlatformJarPath="$(JavaPlatformJarPath)"
@ -2048,6 +2052,8 @@ because xbuild doesn't support framework reference assemblies.
Condition="'$(AndroidEnableMultiDex)' == 'True' And '$(AndroidCustomMainDexListFile)' == ''"
ToolPath="$(MainDexClassesToolPath)"
ToolExe="$(MainDexClassesToolExe)"
MSBuildRuntimeType="$(MSBuildRuntimeType)"
ProguardHome="$(ProguardToolPath)"
ClassesOutputDirectory="$(IntermediateOutputPath)android\bin\classes"
JavaLibraries="@(_JavaLibrariesToCompile)"
MultiDexMainDexListFile="$(_AndroidMainDexListFile)"