Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
418 changes: 418 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/JdkInfo.cs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions src/Xamarin.Android.Tools.AndroidSdk/OS.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public class OS

internal readonly static string ProgramFilesX86;

internal readonly static string NativeLibraryFormat;

static OS ()
{
IsWindows = Path.DirectorySeparatorChar == '\\';
Expand All @@ -20,6 +22,13 @@ static OS ()
if (IsWindows) {
ProgramFilesX86 = GetProgramFilesX86 ();
}

if (IsWindows)
NativeLibraryFormat = "{0}.dll";
if (IsMac)
NativeLibraryFormat = "lib{0}.dylib";
if (!IsWindows && !IsMac)
NativeLibraryFormat = "lib{0}.so";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to special-case Linux here as well. In theory the code can run on e.g. the *BSD family of Unix systems (other than macOS) and if you know you're running on Linux then you can check what distribution you're on and use that distribution's mechanisms to detect Java instances (e.g. on Debian + family you can use /usr/sbin/update-java-alternatives -l but you can't use it, say, on Manjaro)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't special-case systems I'm not running. :-)

BSD contributions welcome. In the meantime, there is support for $JAVA_HOME and $PATH already.

}

//From Managed.Windows.Forms/XplatUI
Expand Down
69 changes: 68 additions & 1 deletion src/Xamarin.Android.Tools.AndroidSdk/ProcessUtils.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,24 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using System.IO;
using System.Threading;
using System.Threading.Tasks;

namespace Xamarin.Android.Tools
{
public static class ProcessUtils
{
static string[] ExecutableFileExtensions;

static ProcessUtils ()
{
var pathExt = Environment.GetEnvironmentVariable ("PATHEXT");
var pathExts = pathExt?.Split (new char [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries) ?? new string [0];

ExecutableFileExtensions = pathExts;
}

public static async Task<int> StartProcess (ProcessStartInfo psi, TextWriter stdout, TextWriter stderr, CancellationToken cancellationToken, Action<Process> onStarted = null)
{
cancellationToken.ThrowIfCancellationRequested ();
Expand Down Expand Up @@ -119,6 +130,62 @@ public static Task<TResult> ExecuteToolAsync<TResult> (string exe, Func<string,

return tcs.Task;
}

internal static void Exec (ProcessStartInfo processStartInfo, DataReceivedEventHandler output)
{
processStartInfo.UseShellExecute = false;
processStartInfo.RedirectStandardInput = false;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.CreateNoWindow = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

var p = new Process () {
StartInfo = processStartInfo,
};
p.OutputDataReceived += output;
p.ErrorDataReceived += output;

using (p) {
p.Start ();
p.BeginOutputReadLine ();
p.BeginErrorReadLine ();
p.WaitForExit ();
}
}

internal static IEnumerable<string> FindExecutablesInPath (string executable)
{
var path = Environment.GetEnvironmentVariable ("PATH");
var pathDirs = path.Split (new char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);

foreach (var dir in pathDirs) {
foreach (var exe in FindExecutablesInDirectory (dir, executable)) {
yield return exe;
}
}
}

internal static IEnumerable<string> FindExecutablesInDirectory (string dir, string executable)
{
foreach (var exe in ExecutableFiles (executable)) {
var exePath = Path.Combine (dir, exe);
if (File.Exists (exePath))
yield return exePath;
}
}

internal static IEnumerable<string> ExecutableFiles (string executable)
{
if (ExecutableFileExtensions == null || ExecutableFileExtensions.Length == 0) {
yield return executable;
yield break;
}

foreach (var ext in ExecutableFileExtensions)
yield return Path.ChangeExtension (executable, ext);
yield return executable;
}
}
}

45 changes: 7 additions & 38 deletions src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,70 +122,39 @@ public string NdkHostPlatform {
/// </summary>
public bool ValidateAndroidSdkLocation (string loc)
{
return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory (Adb, Path.Combine (loc, "platform-tools")).Any ();
return !string.IsNullOrEmpty (loc) && ProcessUtils.FindExecutablesInDirectory (Path.Combine (loc, "platform-tools"), Adb).Any ();
}

/// <summary>
/// Checks that a value is the location of a Java SDK.
/// </summary>
public virtual bool ValidateJavaSdkLocation (string loc)
{
return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory (JarSigner, Path.Combine (loc, "bin")).Any ();
return !string.IsNullOrEmpty (loc) && ProcessUtils.FindExecutablesInDirectory (Path.Combine (loc, "bin"), JarSigner).Any ();
}

/// <summary>
/// Checks that a value is the location of an Android SDK.
/// </summary>
public bool ValidateAndroidNdkLocation (string loc)
{
return !string.IsNullOrEmpty (loc) && FindExecutableInDirectory (NdkStack, loc).Any ();
return !string.IsNullOrEmpty (loc) && ProcessUtils.FindExecutablesInDirectory (loc, NdkStack).Any ();
}

protected IEnumerable<string> FindExecutableInPath (string executable)
{
var path = Environment.GetEnvironmentVariable ("PATH");
var pathDirs = path.Split (new char[] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);

foreach (var dir in pathDirs) {
foreach (var directory in FindExecutableInDirectory (executable, dir)) {
yield return directory;
}
}
}

protected IEnumerable<string> FindExecutableInDirectory (string executable, string dir)
{
foreach (var exe in Executables (executable))
if (File.Exists (Path.Combine (dir, exe)))
yield return dir;
}

IEnumerable<string> Executables (string executable)
{
yield return executable;
var pathExt = Environment.GetEnvironmentVariable ("PATHEXT");
var pathExts = pathExt?.Split (new char [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);

if (pathExts == null)
yield break;

foreach (var ext in pathExts)
yield return Path.ChangeExtension (executable, ext);
}

protected string NullIfEmpty (string s)
protected static string NullIfEmpty (string s)
{
if (s == null || s.Length != 0)
return s;

return null;
}

string GetExecutablePath (string dir, string exe)
static string GetExecutablePath (string dir, string exe)
{
if (string.IsNullOrEmpty (dir))
return exe;
foreach (var e in Executables (exe))

foreach (var e in ProcessUtils.ExecutableFiles (exe))
if (File.Exists (Path.Combine (dir, e)))
return e;
return exe;
Expand Down
24 changes: 12 additions & 12 deletions src/Xamarin.Android.Tools.AndroidSdk/Sdks/AndroidSdkUnix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override string NdkHostPlatform64Bit {

public override string PreferedAndroidSdkPath {
get {
var config_file = GetUnixConfigFile ();
var config_file = GetUnixConfigFile (Logger);
var androidEl = config_file.Root.Element ("android-sdk");

if (androidEl != null) {
Expand All @@ -57,7 +57,7 @@ public override string PreferedAndroidSdkPath {

public override string PreferedAndroidNdkPath {
get {
var config_file = GetUnixConfigFile ();
var config_file = GetUnixConfigFile (Logger);
var androidEl = config_file.Root.Element ("android-ndk");

if (androidEl != null) {
Expand All @@ -72,7 +72,7 @@ public override string PreferedAndroidNdkPath {

public override string PreferedJavaSdkPath {
get {
var config_file = GetUnixConfigFile ();
var config_file = GetUnixConfigFile (Logger);
var javaEl = config_file.Root.Element ("java-sdk");

if (javaEl != null) {
Expand All @@ -92,7 +92,7 @@ protected override IEnumerable<string> GetAllAvailableAndroidSdks ()
yield return preferedSdkPath;

// Look in PATH
foreach (var path in FindExecutableInPath (Adb)) {
foreach (var path in ProcessUtils.FindExecutablesInPath (Adb)) {
// Strip off "platform-tools"
var dir = Path.GetDirectoryName (path);

Expand All @@ -113,7 +113,7 @@ protected override string GetJavaSdkPath ()
return preferedJavaSdkPath;

// Look in PATH
foreach (var path in FindExecutableInPath (JarSigner)) {
foreach (var path in ProcessUtils.FindExecutablesInPath (JarSigner)) {
// Strip off "bin"
var dir = Path.GetDirectoryName (path);

Expand Down Expand Up @@ -160,7 +160,7 @@ protected override IEnumerable<string> GetAllAvailableAndroidNdks ()
yield return preferedNdkPath;

// Look in PATH
foreach (var path in FindExecutableInPath (NdkStack)) {
foreach (var path in ProcessUtils.FindExecutablesInPath (NdkStack)) {
if (ValidateAndroidNdkLocation (path))
yield return path;
}
Expand All @@ -176,7 +176,7 @@ public override void SetPreferredAndroidSdkPath (string path)
{
path = NullIfEmpty (path);

var doc = GetUnixConfigFile ();
var doc = GetUnixConfigFile (Logger);
var androidEl = doc.Root.Element ("android-sdk");

if (androidEl == null) {
Expand All @@ -192,7 +192,7 @@ public override void SetPreferredJavaSdkPath (string path)
{
path = NullIfEmpty (path);

var doc = GetUnixConfigFile ();
var doc = GetUnixConfigFile (Logger);
var javaEl = doc.Root.Element ("java-sdk");

if (javaEl == null) {
Expand All @@ -208,7 +208,7 @@ public override void SetPreferredAndroidNdkPath (string path)
{
path = NullIfEmpty (path);

var doc = GetUnixConfigFile ();
var doc = GetUnixConfigFile (Logger);
var androidEl = doc.Root.Element ("android-ndk");

if (androidEl == null) {
Expand Down Expand Up @@ -275,16 +275,16 @@ private static string UnixConfigPath {
}
}

private XDocument GetUnixConfigFile ()
internal static XDocument GetUnixConfigFile (Action<TraceLevel, string> logger)
{
var file = UnixConfigPath;
XDocument doc = null;
if (File.Exists (file)) {
try {
doc = XDocument.Load (file);
} catch (Exception ex) {
Logger (TraceLevel.Error, "Could not load monodroid configuration file");
Logger (TraceLevel.Verbose, ex.ToString ());
logger (TraceLevel.Error, "Could not load monodroid configuration file");
logger (TraceLevel.Verbose, ex.ToString ());

// move out of the way and create a new one
doc = new XDocument (new XElement ("monodroid"));
Expand Down
Loading