diff --git a/Makefile b/Makefile
index 57568473c..7d6b76706 100644
--- a/Makefile
+++ b/Makefile
@@ -53,7 +53,15 @@ xa-all: $(PACKAGES) $(XA_INTEGRATION_OUTPUTS)
run-all-tests: run-tests run-test-jnimarshal run-test-generator-core run-ptests
-prepare:: prepare-external
+include build-tools/scripts/msbuild.mk
+
+prepare:: prepare-bootstrap prepare-external
+
+prepare-bootstrap: bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll
+
+bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll: src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj \
+ $(wildcard src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/*.cs)
+ $(MSBUILD) $(MSBUILD_FLAGS) src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj
prepare-external: $(PACKAGES) $(NUNIT_CONSOLE)
git submodule update --init --recursive
@@ -65,7 +73,6 @@ clean:
include build-tools/scripts/mono.mk
include build-tools/scripts/jdk.mk
-include build-tools/scripts/msbuild.mk
$(PACKAGES) $(NUNIT_CONSOLE):
nuget restore
diff --git a/build-tools/scripts/PrepareWindows.targets b/build-tools/scripts/PrepareWindows.targets
index 2c68c94b6..7cbba368f 100644
--- a/build-tools/scripts/PrepareWindows.targets
+++ b/build-tools/scripts/PrepareWindows.targets
@@ -19,8 +19,12 @@
DestinationFiles="$(_NuGet)"
/>
-
-
+
+
\ No newline at end of file
diff --git a/build-tools/scripts/jdk.mk b/build-tools/scripts/jdk.mk
index 65d686386..79a800c53 100644
--- a/build-tools/scripts/jdk.mk
+++ b/build-tools/scripts/jdk.mk
@@ -26,157 +26,22 @@
# Location of the JDK `/bin` directory, which contains `java/`javac`/etc.
OS ?= $(shell uname)
-JI_JAVAC_PATH = javac
-JI_JAR_PATH = jar
-JI_JDK_BIN_PATH = $(dir $(shell which java))
+_INCLUDE_MK = bin/Build$(CONFIGURATION)/JdkInfo.mk
+prepare:: $(_INCLUDE_MK)
-# Filter on <= JI_MAX_JDK
-ifneq ($(JI_MAX_JDK),)
-_VERSION_MAX := | awk '$$1 <= $(JI_MAX_JDK)'
-endif #JI_MAX_JDK
-
-# Sort numerically on version numbers with `sort -n`, filtering on $(JI_MAX_JDK) if needed
-# Replace each line so it starts with a number (sed 's/...'\1 &/), sort on the leading number, then remove the leading number.
-# Grab the last path name printed.
-_VERSION_SORT := sed 's/[^0-9]*\([0-9.]*\)/\1 &/' $(_VERSION_MAX) | sort -n | sed 's/^[0-9.]* //g' | tail -1
+-include $(_INCLUDE_MK)
ifeq ($(OS),Darwin)
-
-_MONO_BITNESS = $(shell file `which $(word 1, $(RUNTIME))` | awk 'BEGIN { val = "32-bit" } /64-bit/ { val = "64-bit" } END { print val; }')
-
-ifeq ($(_MONO_BITNESS),32-bit)
-# The only 32-bit JVM I know of is the Apple-provided one.
-JI_JVM_PATH = /System/Library/Frameworks/JavaVM.framework/JavaVM
-endif # 32-bit
-
-# Darwin supports three possible search locations:
-#
-# 1. `/Library/Java/JavaVirtualMachines/jdk*`
-# These are where 3rd party JDKs are installed, such as the Oracle JDK.
-# This is the preferred search directory.
-#
-# 2. The Xcode.app MacOSX.platform SDK, which is for the ancient JDK6 that
-# continues to be available
-#
-# 3. A "locally" hosted .pkg, in case Xcode.app isn't installed.
-
-_DARWIN_JDK_FALLBACK_DIRS = $(wildcard /Library/Java/JavaVirtualMachines/jdk*)
-_DARWIN_JDK_JNI_INCLUDE_DIR = Contents/Home/include
-_DARWIN_JDK_JNI_OS_INCLUDE_DIR = $(_DARWIN_JDK_JNI_INCLUDE_DIR)/darwin
-
-_XCODE_APP_JAVAVM_FRAMEWORK_PATH = \
- $(word 1, $(wildcard /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX*.sdk/System/Library/Frameworks/JavaVM.framework/Headers))
-
-
-_LOCAL_JDK_PKG = JavaDeveloper-2013005_dp__11m4609.pkg
-_LOCAL_JDK_URL = http://storage.bos.xamarin.com/android-sdk-tool/archives/$(FALLBACK_JDK_PKG)
-_LOCAL_JDK_HEADERS = LocalJDK/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
-
-# Ancient source for (3)
-_APPLE_JDK6_URL = http://adcdownload.apple.com/Developer_Tools/java_for_os_x_2013005_developer_package/java_for_os_x_2013005_dp__11m4609.dmg
-
-ifneq ($(_DARWIN_JDK_FALLBACK_DIRS),)
-_DARWIN_JDK_ROOT := $(shell ls -dtr $(_DARWIN_JDK_FALLBACK_DIRS) | $(_VERSION_SORT))
-JI_JDK_BIN_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin
-JI_JAVAC_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin/javac
-JI_JAR_PATH = $(_DARWIN_JDK_ROOT)/Contents/Home/bin/jar
-JI_JDK_INCLUDE_PATHS = \
- $(_DARWIN_JDK_ROOT)/$(_DARWIN_JDK_JNI_INCLUDE_DIR) \
- $(_DARWIN_JDK_ROOT)/$(_DARWIN_JDK_JNI_OS_INCLUDE_DIR)
-
-ifeq ($(_MONO_BITNESS),64-bit)
-JI_JVM_PATH = $(shell find $(_DARWIN_JDK_ROOT)/Contents/Home -name libjli.dylib)
-endif # 64-bit
-
-else # (1) failed; try Xcode.app's copy?
-ifneq ($(_XCODE_APP_JAVAVM_FRAMEWORK_PATH),)
-JI_JDK_INCLUDE_PATHS = $(_XCODE_APP_JAVAVM_FRAMEWORK_PATH)
-else # (2) failed; hail mary pass!
-JI_JDK_INCLUDE_PATHS = LocalJDK/System/Library/Frameworks/JavaVM.framework/Versions/A/Headers
-
-bin/Build$(CONFIGURATION)/JdkHeaders.props: $(JI_JDK_INCLUDE_PATHS)/jni.h
-
-$(JI_JDK_INCLUDE_PATHS)/jni.h:
- @if [ ! -f $(_LOCAL_JDK_PKG) ]; then \
- curl -o $(_LOCAL_JDK_PKG) $(_LOCAL_JDK_URL) ; \
- fi
- -mkdir LocalJDK
- _jdk="$$(cd `dirname "$(_LOCAL_JDK_PKG)"`; pwd)/`basename "$(_LOCAL_JDK_PKG)"`" ; \
- (cd LocalJDK; xar -xf $$_jdk)
- (cd LocalJDK; gunzip -c JavaEssentialsDev.pkg/Payload | cpio -i)
-endif # (3)
-endif # (1)
-
-endif # Darwin
-
+_JDKS_ROOT := /Library/Java/JavaVirtualMachines
+endif # $(OS)=Darwin
ifeq ($(OS),Linux)
+_JDKS_ROOT := /usr/lib/jvm
+endif # $(OS)=Linux
-# This is for all linux distributions with which and java installed
-_DEFAULT_LINUX_JAVA_ROOT = $(shell java -XshowSettings:properties -help 2>&1 | grep java.home | sed 's/^.*java.home = //g')/../
-_DEFAULT_LINUX_JAVA_INCLUDE_DIRS = $(_DEFAULT_LINUX_JAVA_ROOT)/include/
-_LINUX_JAVA_FALLBACK_DIRS = /usr/lib/jvm/java*
-_LINUX_JAVA_JNI_INCLUDE_DIR = include
-_LINUX_JAVA_ROOT = $(_DEFAULT_LINUX_JAVA_ROOT)
-_LINUX_JAVA_ARCH_64 = amd64
-_LINUX_JAVA_ARCH_32 = i386
-
-_DESKTOP_JAVA_INCLUDE_DIRS = $(_DEFAULT_LINUX_JAVA_INCLUDE_DIRS)
-
-ifeq ($(wildcard $(_DESKTOP_JAVA_INCLUDE_DIRS)),)
-_DESKTOP_JAVA_INCLUDE_DIRS = $(wildcard $(JAVA_HOME)/include)
-_LINUX_JAVA_ROOT = $(JAVA_HOME)
-endif # No default Java location, $JAVA_HOME check
-
-ifeq ($(wildcard $(_DESKTOP_JAVA_INCLUDE_DIRS)),)
-LATEST_JDK := $(shell ls -dtr $(_LINUX_JAVA_FALLBACK_DIRS) | $(_VERSION_SORT))
-_DESKTOP_JAVA_INCLUDE_DIRS = $(LATEST_JDK)/$(_LINUX_JAVA_JNI_INCLUDE_DIR)
-_LINUX_JAVA_ROOT = $(LATEST_JDK)
-endif # No $JAVA_HOME, find the latest version
-
-JI_JDK_INCLUDE_PATHS = $(_DESKTOP_JAVA_INCLUDE_DIRS) $(_DESKTOP_JAVA_INCLUDE_DIRS)/linux
-
-ifneq ($(wildcard $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_64)/server/libjvm.so),)
-JI_JVM_PATH = $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_64)/server/libjvm.so
-endif # Find 64-bit libjvm
-
-ifeq ($(JI_JVM_PATH),) # (1) No 64-bit java arch
-ifneq ($(wildcard $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_32)/server/libjvm.so),) # (2) check 32-bit instead, even on a 64-bit system
-JI_JVM_PATH = $(_LINUX_JAVA_ROOT)/jre/lib/$(_LINUX_JAVA_ARCH_32)/server/libjvm.so
-endif # (2)
-endif # (1)
-
-JI_JDK_BIN_PATH = $(_LINUX_JAVA_ROOT)/bin
-JI_JAVAC_PATH = $(_LINUX_JAVA_ROOT)/bin/javac
-JI_JAR_PATH = $(_LINUX_JAVA_ROOT)/bin/jar
-
-endif # Linux
-
-$(JI_JVM_PATH):
- @echo "error: No JVM found\!";
- @exit 1
-
-bin/Build$(CONFIGURATION)/JdkInfo.props: $(JI_JDK_INCLUDE_PATHS) $(JI_JVM_PATH)
- -mkdir -p `dirname "$@"`
- -rm "$@"
- echo '' > "$@"
- echo ' ' >> "$@"
- echo " " >> "$@"
- echo ' ' >> "$@"
- echo " $(JI_JVM_PATH)" >> "$@"
- echo ' ' >> "$@"
- echo ' ' >> "$@"
- for p in $(JI_JDK_INCLUDE_PATHS); do \
- echo " " >> "$@"; \
- done
- echo ' ' >> "$@"
- echo ' ' >> "$@"
- echo ' ' >> "$@"
- echo ' ' >> "$@"
- echo " $(JI_JDK_BIN_PATH)" >> "$@"
- echo " $(JI_JAVAC_PATH)" >> "$@"
- echo " $(JI_JAR_PATH)" >> "$@"
- echo ' ' >> "$@"
- echo '' >> "$@"
+$(_INCLUDE_MK): bin/Build$(CONFIGURATION)/Java.Interop.BootstrapTasks.dll
+ $(MSBUILD) $(MSBUILD_FLAGS) build-tools/scripts/jdk.targets /t:GetPreferredJdkRoot \
+ /p:JdksRoot="$(_JDKS_ROOT)" \
+ $(if $(JI_MAX_JDK),"/p:MaximumJdkVersion=$(JI_MAX_JDK)")
diff --git a/build-tools/scripts/jdk.targets b/build-tools/scripts/jdk.targets
new file mode 100644
index 000000000..df083e8aa
--- /dev/null
+++ b/build-tools/scripts/jdk.targets
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj
index ee37a9159..83567f08d 100644
--- a/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj
+++ b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks.csproj
@@ -33,15 +33,17 @@
+
+
-
+
\ No newline at end of file
diff --git a/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs
index aca5a8007..e1ab52470 100644
--- a/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs
+++ b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/JdkInfo.cs
@@ -2,9 +2,12 @@
using Microsoft.Build.Utilities;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
+using System.Text.RegularExpressions;
+using System.Xml.Linq;
namespace Java.Interop.BootstrapTasks
{
@@ -14,66 +17,243 @@ public class JdkInfo : Task
const string MDREG_KEY = @"SOFTWARE\Novell\Mono for Android";
const string MDREG_JAVA_SDK = "JavaSdkDirectory";
+ public string JdksRoot { get; set; }
+
+ public string MaximumJdkVersion { get; set; }
+
+ static Regex VersionExtractor = new Regex (@"(?[\d]+(\.\d+)+)", RegexOptions.Compiled);
+
+ [Required]
+ public ITaskItem PropertyFile { get; set; }
+
[Required]
- public ITaskItem Output { get; set; }
+ public ITaskItem MakeFragmentFile { get; set; }
[Output]
- public string JavaSdkDirectory { get; set; }
+ public string JavaHomePath { get; set; }
public override bool Execute ()
{
Log.LogMessage (MessageImportance.Low, $"Task {nameof (JdkInfo)}");
- Log.LogMessage (MessageImportance.Low, $" {nameof (Output)}: {Output}");
+ Log.LogMessage (MessageImportance.Low, $" {nameof (JdksRoot)}: {JdksRoot}");
+ Log.LogMessage (MessageImportance.Low, $" {nameof (MakeFragmentFile)}: {MakeFragmentFile}");
+ Log.LogMessage (MessageImportance.Low, $" {nameof (MaximumJdkVersion)}: {MaximumJdkVersion}");
+ Log.LogMessage (MessageImportance.Low, $" {nameof (PropertyFile)}: {PropertyFile}");
+
+ var maxVersion = GetMaxJdkVersion ();
+ var java_home = GetJavaHomePathFromEnvironment ();
+ if (java_home != null) {
+ var java_home_v = GetVersionFromPath (java_home);
+ if (maxVersion != null && java_home_v != null && java_home_v > maxVersion) {
+ Log.LogMessage (MessageImportance.Low, $" Skipping JAVA_HOME default value of `{java_home}` as it exceeds MaximumJdkVersion={MaximumJdkVersion}.");
+ java_home = null;
+ }
+ if (java_home != null && !Directory.Exists (Path.Combine (java_home, "include"))) {
+ Log.LogMessage (MessageImportance.Low, $" Skipping JAVA_HOME default value of `{java_home}` as it does not contain an `include` subdirectory.");
+ java_home = null;
+ }
+ }
+ java_home = java_home ?? GetJavaHomePathFromMachine (maxVersion);
- var javaSdkPath = GetJavaSdkPath ();
- if (string.IsNullOrEmpty(javaSdkPath)) {
- Log.LogError ("JavaSdkPath is blank");
+ if (string.IsNullOrEmpty (java_home)) {
+ Log.LogError ("Could not determine JAVA_HOME location. Please set JdksRoot or export the JAVA_HOME environment variable.");
return false;
}
- Log.LogMessage (MessageImportance.Low, $" JavaSdkPath: {javaSdkPath}");
-
- var jvmPath = Path.Combine (javaSdkPath, "jre", "bin", "server", "jvm.dll");
- if (!File.Exists (jvmPath)) {
- Log.LogError ($"JdkJvmPath not found at {jvmPath}");
+ var includes = new List () {
+ Path.Combine (java_home, "include"),
+ };
+ includes.AddRange (Directory.GetDirectories (includes [0]));
+
+ var jarPath = FindExecutablesInDirectory (Path.Combine (java_home, "bin"), "jar").First ();
+ var javacPath = FindExecutablesInDirectory (Path.Combine (java_home, "bin"), "javac").First ();
+ var jdkJvmPaths = OS.IsMacOS
+ ? FindLibrariesInDirectory (java_home, "jli")
+ : FindLibrariesInDirectory (Path.Combine (java_home, "jre"), "jvm");
+ var jdkJvmPath = jdkJvmPaths.First ();
+
+ FileExists (jarPath);
+ FileExists (javacPath);
+ FileExists (jdkJvmPath);
+ if (Log.HasLoggedErrors) {
return false;
}
- var javaIncludePath = Path.Combine (javaSdkPath, "include");
- var includes = new List { javaIncludePath };
- includes.AddRange (Directory.GetDirectories (javaIncludePath)); //Include dirs such as "win32"
-
- var includeXmlTags = new StringBuilder ();
- foreach (var include in includes) {
- includeXmlTags.AppendLine ($"");
- }
-
- Directory.CreateDirectory (Path.GetDirectoryName (Output.ItemSpec));
- File.WriteAllText (Output.ItemSpec, $@"
-
-
-
- {jvmPath}
-
-
- {includeXmlTags}
-
-
-
-
- {Path.Combine (javaSdkPath, "bin", "javac.exe")}
- {Path.Combine (javaSdkPath, "bin", "jar.exe")}
-
-");
-
- JavaSdkDirectory = javaSdkPath;
- Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (JavaSdkDirectory)}: {JavaSdkDirectory}");
+ JavaHomePath = java_home;
+
+ Directory.CreateDirectory (Path.GetDirectoryName (PropertyFile.ItemSpec));
+ Directory.CreateDirectory (Path.GetDirectoryName (MakeFragmentFile.ItemSpec));
+
+ WritePropertyFile (jarPath, javacPath, jdkJvmPath, includes);
+ WriteMakeFragmentFile (jarPath, javacPath, jdkJvmPath, includes);
+
+ Log.LogMessage (MessageImportance.Low, $" [Output] {nameof (JavaHomePath)}: {JavaHomePath}");
return !Log.HasLoggedErrors;
}
- string GetJavaSdkPath ()
+ Version GetMaxJdkVersion ()
+ {
+ if (string.IsNullOrEmpty (MaximumJdkVersion))
+ return null;
+ if (!MaximumJdkVersion.Contains (".")) {
+ MaximumJdkVersion += ".0";
+ }
+ return new Version (MaximumJdkVersion);
+ }
+
+ Version GetVersionFromPath (string path)
{
+ var m = VersionExtractor.Match (path);
+ if (!m.Success)
+ return null;
+ Version v;
+ if (!Version.TryParse (m.Groups ["version"].Value, out v)) {
+ return null;
+ }
+ return v;
+ }
+
+ void FileExists (string path)
+ {
+ if (!File.Exists (path)) {
+ var name = Path.GetFileName (path);
+ Log.LogError ($"Could not determine location of `{name}`; tried `{path}`.");
+ }
+ }
+
+ void WritePropertyFile (string jarPath, string javacPath, string jdkJvmPath, IEnumerable includes)
+ {
+ var msbuild = XNamespace.Get ("http://schemas.microsoft.com/developer/msbuild/2003");
+ var project = new XElement (msbuild + "Project",
+ new XElement (msbuild + "Choose",
+ new XElement (msbuild + "When", new XAttribute ("Condition", " '$(JdkJvmPath)' == '' "),
+ new XElement (msbuild + "PropertyGroup",
+ new XElement (msbuild + "JdkJvmPath", jdkJvmPath)),
+ new XElement (msbuild + "ItemGroup",
+ includes.Select (i => new XElement (msbuild + "JdkIncludePath", new XAttribute ("Include", i)))))),
+ new XElement (msbuild + "PropertyGroup",
+ new XElement (msbuild + "JavaCPath", new XAttribute ("Condition", " '$(JavaCPath)' == '' "),
+ javacPath),
+ new XElement (msbuild + "JarPath", new XAttribute ("Condition", " '$(JarPath)' == '' "),
+ jarPath)));
+ project.Save (PropertyFile.ItemSpec);
+ }
+
+ void WriteMakeFragmentFile (string jarPath, string javacPath, string jdkJvmPath, IEnumerable includes)
+ {
+ using (var o = new StreamWriter (MakeFragmentFile.ItemSpec)) {
+ o.WriteLine ($"JI_JAR_PATH := {jarPath}");
+ o.WriteLine ($"JI_JAVAC_PATH := {javacPath}");
+ o.WriteLine ($"JI_JDK_INCLUDE_PATHS := {string.Join (" ", includes)}");
+ o.WriteLine ($"JI_JVM_PATH := {jdkJvmPath}");
+ }
+ }
+
+ string GetJavaHomePathFromEnvironment ()
+ {
+ var java_home = Environment.GetEnvironmentVariable ("JAVA_HOME");
+ if (!string.IsNullOrEmpty (java_home))
+ return java_home;
+ return null;
+ }
+
+ string GetJavaHomePathFromMachine (Version maxVersion)
+ {
+ var java_homes = GetJavaHomePathsFromDirectory (JdksRoot)
+ .Concat (GetJavaHomePathsFromJava ())
+ .Concat (GetJavaHomePathsFromWindowsRegistry ())
+ .Distinct ()
+ .Where (d => Directory.Exists (d))
+ .Select (jh => new {
+ Path = jh,
+ Version = GetVersionFromPath (jh),
+ })
+ .Where (v => maxVersion == null ? true : v.Version <= maxVersion)
+ .OrderByDescending (v => v.Version)
+ .Select (v => v.Path)
+ .ToList ();
+
+ foreach (var p in java_homes) {
+ Log.LogMessage (MessageImportance.Low, $" Possible JAVA_HOME location: {p}");
+ }
+
+ return java_homes.FirstOrDefault ();
+ }
+
+ IEnumerable GetJavaHomePathsFromDirectory (string jdksRoot)
+ {
+ if (string.IsNullOrEmpty (jdksRoot))
+ yield break;
+ if (!Directory.Exists (jdksRoot))
+ yield break;
+ foreach (var d in Directory.EnumerateDirectories (jdksRoot)) {
+ var h = d;
+ if (OS.IsMacOS)
+ h = Path.Combine (h, "Contents", "Home");
+ yield return h;
+ }
+ }
+
+ IEnumerable GetJavaHomePathsFromJava ()
+ {
+ var javas = Environment.GetEnvironmentVariable ("PATH").Split (Path.PathSeparator)
+ .SelectMany (p => FindExecutablesInDirectory (p, "java"));
+
+ foreach (var exe in javas) {
+ const string JavaHome = "java.home = ";
+ string java_home = null;
+ Exec (exe, "-XshowSettings:properties -version", (o, e) => {
+ int i = e.Data?.IndexOf (JavaHome) ?? -1;
+ if (i < 0)
+ return;
+ Log.LogMessage (MessageImportance.Low, $" {e.Data}");
+ java_home = e.Data.Substring (JavaHome.Length + i);
+ // `java -XshowSettings:properties -version | grep java.home` ends with `/jre` on macOS.
+ // We need the parent dir so we can properly lookup the `include` directories
+ if (java_home.EndsWith ("jre", StringComparison.OrdinalIgnoreCase)) {
+ java_home = Path.GetDirectoryName (java_home);
+ }
+ });
+ if (string.IsNullOrEmpty (java_home))
+ continue;
+ yield return java_home;
+ }
+ }
+
+ void Exec (string java, string arguments, DataReceivedEventHandler output)
+ {
+ Log.LogMessage (MessageImportance.Low, $" Tool {java} execution started with arguments: {arguments}");
+ var psi = new ProcessStartInfo () {
+ FileName = java,
+ Arguments = arguments,
+ UseShellExecute = false,
+ RedirectStandardInput = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ WindowStyle = ProcessWindowStyle.Hidden,
+ };
+ var p = new Process () {
+ StartInfo = psi,
+ };
+ p.OutputDataReceived += output;
+ p.ErrorDataReceived += output;
+
+ using (p) {
+ p.StartInfo = psi;
+ p.Start ();
+ p.BeginOutputReadLine ();
+ p.BeginErrorReadLine ();
+ p.WaitForExit ();
+ }
+ }
+
+ IEnumerable GetJavaHomePathsFromWindowsRegistry ()
+ {
+ if (Path.DirectorySeparatorChar == '/')
+ yield break;
+
// check the user specified path
var roots = new [] { RegistryEx.CurrentUser, RegistryEx.LocalMachine };
const RegistryEx.Wow64 wow = RegistryEx.Wow64.Key32;
@@ -81,7 +261,7 @@ string GetJavaSdkPath ()
foreach (var root in roots) {
if (CheckRegistryKeyForExecutable (root, regKey, MDREG_JAVA_SDK, wow, "bin", JARSIGNER))
- return RegistryEx.GetValueString (root, regKey, MDREG_JAVA_SDK, wow);
+ yield return RegistryEx.GetValueString (root, regKey, MDREG_JAVA_SDK, wow);
}
string subkey = @"SOFTWARE\JavaSoft\Java Development Kit";
@@ -97,20 +277,17 @@ string GetJavaSdkPath ()
// No matter what the CurrentVersion is, look for 1.6 or 1.7 or 1.8
if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.8", "JavaHome", wow64, "bin", JARSIGNER))
- return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.8", "JavaHome", wow64);
+ yield return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.8", "JavaHome", wow64);
if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.7", "JavaHome", wow64, "bin", JARSIGNER))
- return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.7", "JavaHome", wow64);
+ yield return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.7", "JavaHome", wow64);
if (CheckRegistryKeyForExecutable (RegistryEx.LocalMachine, subkey + "\\" + "1.6", "JavaHome", wow64, "bin", JARSIGNER))
- return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.6", "JavaHome", wow64);
+ yield return RegistryEx.GetValueString (RegistryEx.LocalMachine, subkey + "\\" + "1.6", "JavaHome", wow64);
}
Log.LogMessage (MessageImportance.Low, $" Key {key_name} not found.");
}
-
- // We ran out of things to check..
- return null;
}
string GetMDRegistryKey ()
@@ -131,7 +308,7 @@ private bool CheckRegistryKeyForExecutable (UIntPtr key, string subkey, string v
return false;
}
- if (!FindExecutableInDirectory (exe, Path.Combine (path, subdir)).Any ()) {
+ if (!FindExecutablesInDirectory (Path.Combine (path, subdir), exe).Any ()) {
Log.LogMessage (MessageImportance.Low, $" Key {key_name} found:\n Path does not contain {exe} in \\{subdir} ({path}).");
return false;
}
@@ -141,24 +318,33 @@ private bool CheckRegistryKeyForExecutable (UIntPtr key, string subkey, string v
return true;
}
- IEnumerable FindExecutableInDirectory (string executable, string dir)
+ IEnumerable FindExecutablesInDirectory (string dir, string executable)
{
- foreach (var exe in Executables (executable))
- if (File.Exists (Path.Combine (dir, exe)))
- yield return dir;
+ foreach (var exe in Executables (executable)) {
+ var p = Path.Combine (dir, exe);
+ if (File.Exists (p))
+ yield return p;
+ }
}
IEnumerable Executables (string executable)
{
- yield return executable;
var pathExt = Environment.GetEnvironmentVariable ("PATHEXT");
var pathExts = pathExt?.Split (new char [] { Path.PathSeparator }, StringSplitOptions.RemoveEmptyEntries);
- if (pathExts == null)
+ if (pathExts == null) {
+ yield return executable;
yield break;
+ }
foreach (var ext in pathExts)
yield return Path.ChangeExtension (executable, ext);
}
+
+ IEnumerable FindLibrariesInDirectory (string dir, string libraryName)
+ {
+ var library = string.Format (OS.NativeLibraryFormat, libraryName);
+ return Directory.EnumerateFiles (dir, library, SearchOption.AllDirectories);
+ }
}
}
diff --git a/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/OS.cs b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/OS.cs
new file mode 100644
index 000000000..585c20ec5
--- /dev/null
+++ b/src/Java.Interop.BootstrapTasks/Java.Interop.BootstrapTasks/OS.cs
@@ -0,0 +1,22 @@
+using System;
+using System.IO;
+
+namespace Java.Interop.BootstrapTasks {
+ class OS {
+ public static readonly bool IsWindows = Path.DirectorySeparatorChar == '\\';
+ public static readonly bool IsMacOS = !IsWindows && Directory.Exists ("/Applications");
+ public static readonly bool IsLinux = !IsWindows && !IsMacOS;
+
+ public static readonly string NativeLibraryFormat;
+
+ static OS ()
+ {
+ if (IsWindows)
+ NativeLibraryFormat = "{0}.dll";
+ if (IsMacOS)
+ NativeLibraryFormat = "lib{0}.dylib";
+ if (IsLinux)
+ NativeLibraryFormat = "lib{0}.so";
+ }
+ }
+}