[SYSTEMDS-2663, 2664] Prepare native instructions for release 2.0

* pulled in a few CMake tricks from gpu codegen dev branch to unify lib naming
* verify MKL and OpenBLAS working
* cleanup native lib loader class (NativeHelper)
* build script for Windows

Closes #1063
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 2bb8c04..9489f8f 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -21,7 +21,7 @@
 
 cmake_minimum_required(VERSION 3.8)
 cmake_policy(SET CMP0074 NEW) # make use of <package>_ROOT variable
-project (systemds)
+project (systemds LANGUAGES CXX)
 
 # All custom find modules
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
@@ -41,8 +41,19 @@
 set(MATH_LIBRARIES "")
 
 # sets the installation path to src/main/cpp/lib
-set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR})
-install(TARGETS systemds LIBRARY DESTINATION lib)
+if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
+  set(CMAKE_INSTALL_PREFIX "${CMAKE_SOURCE_DIR}" CACHE PATH "sets the installation path to src/main/cpp/lib" FORCE)
+endif()
+
+# sets the installation path to src/main/cpp/lib
+# install(TARGETS systemds LIBRARY DESTINATION lib)
+install(TARGETS systemds RUNTIME DESTINATION lib)
+
+# unify library filenames to libsystemds_<...>
+if (WIN32)
+    set(CMAKE_IMPORT_LIBRARY_PREFIX lib CACHE INTERNAL "")
+    set(CMAKE_SHARED_LIBRARY_PREFIX lib CACHE INTERNAL "")
+endif()
 
 set(CMAKE_BUILD_TYPE Release)
 
diff --git a/src/main/cpp/build.bat b/src/main/cpp/build.bat
new file mode 100644
index 0000000..93c3819
--- /dev/null
+++ b/src/main/cpp/build.bat
@@ -0,0 +1,38 @@
+@ECHO OFF
+::-------------------------------------------------------------
+::
+:: Licensed to the Apache Software Foundation (ASF) under one
+:: or more contributor license agreements.  See the NOTICE file
+:: distributed with this work for additional information
+:: regarding copyright ownership.  The ASF licenses this file
+:: to you under the Apache License, Version 2.0 (the
+:: "License"); you may not use this file except in compliance
+:: with the License.  You may obtain a copy of the License at
+::
+::   http://www.apache.org/licenses/LICENSE-2.0
+::
+:: Unless required by applicable law or agreed to in writing,
+:: software distributed under the License is distributed on an
+:: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+:: KIND, either express or implied.  See the License for the
+:: specific language governing permissions and limitations
+:: under the License.
+::
+::-------------------------------------------------------------
+
+:: This shell script compiles the required shared libraries for Windows on x86-64
+:: Make sure to have run "\"%INTEL_ROOT%\"\compilervars.bat intel64 vs2019" and set OpenBLAS_HOME to where
+:: libopenblas.lib is located
+
+:: configure and compile INTEL MKL
+cmake -S . -B INTEL -DUSE_INTEL_MKL=ON -DCMAKE_BUILD_TYPE=Release
+cmake --build INTEL --target install --config Release
+rmdir /Q /S INTEL
+
+:: configure and compile OPENBLAS
+cmake . -B OPENBLAS -DUSE_OPEN_BLAS=ON -DCMAKE_BUILD_TYPE=Release
+cmake --build OPENBLAS --target install --config Release
+rmdir /Q /S OPENBLAS
+
+echo.
+echo "Make sure to re-run mvn package to make use of the newly compiled libraries"
\ No newline at end of file
diff --git a/src/main/cpp/cmake/FindOpenBLAS.cmake b/src/main/cpp/cmake/FindOpenBLAS.cmake
index 8870d15..a67b3bf 100644
--- a/src/main/cpp/cmake/FindOpenBLAS.cmake
+++ b/src/main/cpp/cmake/FindOpenBLAS.cmake
@@ -46,7 +46,7 @@
  )
 
 FIND_PATH(OpenBLAS_INCLUDE_DIR NAMES cblas.h PATHS ${Open_BLAS_INCLUDE_SEARCH_PATHS})
-FIND_LIBRARY(OpenBLAS_LIB NAMES openblas PATHS ${Open_BLAS_LIB_SEARCH_PATHS})
+FIND_LIBRARY(OpenBLAS_LIB NAMES openblas libopenblas PATHS ${Open_BLAS_LIB_SEARCH_PATHS})
 
 SET(OpenBLAS_FOUND ON)
 
diff --git a/src/main/cpp/lib/libsystemds_mkl-Linux-x86_64.so b/src/main/cpp/lib/libsystemds_mkl-Linux-x86_64.so
index c2a3795..800fe13 100644
--- a/src/main/cpp/lib/libsystemds_mkl-Linux-x86_64.so
+++ b/src/main/cpp/lib/libsystemds_mkl-Linux-x86_64.so
Binary files differ
diff --git a/src/main/cpp/lib/libsystemds_mkl-Windows-AMD64.dll b/src/main/cpp/lib/libsystemds_mkl-Windows-AMD64.dll
new file mode 100644
index 0000000..2960551
--- /dev/null
+++ b/src/main/cpp/lib/libsystemds_mkl-Windows-AMD64.dll
Binary files differ
diff --git a/src/main/cpp/lib/libsystemds_openblas-Linux-x86_64.so b/src/main/cpp/lib/libsystemds_openblas-Linux-x86_64.so
index bfef446..6e45343 100644
--- a/src/main/cpp/lib/libsystemds_openblas-Linux-x86_64.so
+++ b/src/main/cpp/lib/libsystemds_openblas-Linux-x86_64.so
Binary files differ
diff --git a/src/main/cpp/lib/libsystemds_openblas-Windows-AMD64.dll b/src/main/cpp/lib/libsystemds_openblas-Windows-AMD64.dll
new file mode 100644
index 0000000..a39d40c
--- /dev/null
+++ b/src/main/cpp/lib/libsystemds_openblas-Windows-AMD64.dll
Binary files differ
diff --git a/src/main/cpp/lib/systemds_mkl-Windows-AMD64.dll b/src/main/cpp/lib/systemds_mkl-Windows-AMD64.dll
deleted file mode 100644
index 4723e26..0000000
--- a/src/main/cpp/lib/systemds_mkl-Windows-AMD64.dll
+++ /dev/null
Binary files differ
diff --git a/src/main/cpp/lib/systemds_openblas-Windows-AMD64.dll b/src/main/cpp/lib/systemds_openblas-Windows-AMD64.dll
deleted file mode 100644
index 5e16569..0000000
--- a/src/main/cpp/lib/systemds_openblas-Windows-AMD64.dll
+++ /dev/null
Binary files differ
diff --git a/src/main/java/org/apache/sysds/utils/NativeHelper.java b/src/main/java/org/apache/sysds/utils/NativeHelper.java
index 59fd243..36ec816 100644
--- a/src/main/java/org/apache/sysds/utils/NativeHelper.java
+++ b/src/main/java/org/apache/sysds/utils/NativeHelper.java
@@ -146,7 +146,20 @@
 		LOG.info("Unsupported architecture for native BLAS:" + SystemUtils.OS_ARCH);
 		return false;
 	}
-	
+
+	/**
+	 * Note: we only support Windows and Linux at the moment.
+	 *
+	 * @return true if operating system is supported
+	 */
+	private static boolean isSupportedOS() {
+		if(SystemUtils.IS_OS_LINUX || SystemUtils.IS_OS_WINDOWS) {
+			return true;
+		}
+		LOG.info("Unsupported architecture for native BLAS:" + SystemUtils.OS_ARCH);
+		return false;
+	}
+
 	/**
 	 * Check if native BLAS libraries have been successfully loaded
 	 * @return true if CURRENT_NATIVE_BLAS_STATE is SUCCESSFULLY_LOADED_NATIVE_BLAS_AND_IN_USE or
@@ -173,11 +186,12 @@
 	// Performing loading in a method instead of a static block will throw a detailed stack trace in case of fatal errors
 	private static void performLoading(String customLibPath, String userSpecifiedBLAS) {
 		if((customLibPath != null) && customLibPath.equalsIgnoreCase("none"))
-				customLibPath = null;
+			customLibPath = null;
 
 		// attemptedLoading variable ensures that we don't try to load SystemDS and other dependencies
 		// again and again especially in the parfor (hence the double-checking with synchronized).
-		if(shouldReload(customLibPath) && isSupportedBLAS(userSpecifiedBLAS) && isSupportedArchitecture()) {
+		if(shouldReload(customLibPath) && isSupportedBLAS(userSpecifiedBLAS) && isSupportedArchitecture()
+			&& isSupportedOS()) {
 			long start = System.nanoTime();
 			synchronized(NativeHelper.class) {
 				if(shouldReload(customLibPath)) {
@@ -188,23 +202,16 @@
 						blas = new String[] { "mkl", "openblas" };
 					}
 
-					if(SystemUtils.IS_OS_WINDOWS) {
-						if (checkAndLoadBLAS(customLibPath, blas) &&
-								(loadLibraryHelper("systemds_" + blasType + "-Windows-AMD64") ||
-								loadBLAS(customLibPath, "systemds_" + blasType + "-Windows-AMD64", null))
-						)
+					if(checkAndLoadBLAS(customLibPath, blas)) {
+						String platform_suffix = (SystemUtils.IS_OS_WINDOWS ? "-Windows-AMD64.dll" : "-Linux-x86_64.so");
+						String library_name = "libsystemds_" + blasType + platform_suffix;
+						if(loadLibraryHelperFromResource(library_name) ||
+						   loadBLAS(customLibPath, library_name,"Loading native helper with customLibPath."))
 						{
 							LOG.info("Using native blas: " + blasType + getNativeBLASPath());
 							CURRENT_NATIVE_BLAS_STATE = NativeBlasState.SUCCESSFULLY_LOADED_NATIVE_BLAS_AND_IN_USE;
 						}
 					}
-					else {
-						if (checkAndLoadBLAS(customLibPath, blas) &&
-								loadLibraryHelper("libsystemds_" + blasType + "-Linux-x86_64.so")) {
-							LOG.info("Using native blas: " + blasType + getNativeBLASPath());
-							CURRENT_NATIVE_BLAS_STATE = NativeBlasState.SUCCESSFULLY_LOADED_NATIVE_BLAS_AND_IN_USE;
-						}
-					}
 				}
 			}
 			double timeToLoadInMilliseconds = (System.nanoTime()-start)*1e-6;
@@ -212,8 +219,8 @@
 				LOG.warn("Time to load native blas: " + timeToLoadInMilliseconds + " milliseconds.");
 		}
 		else if(LOG.isDebugEnabled() && !isSupportedBLAS(userSpecifiedBLAS)) {
-			LOG.debug("Using internal Java BLAS as native BLAS support the configuration 'sysds.native.blas'=" +
-					userSpecifiedBLAS + ".");
+			LOG.debug("Using internal Java BLAS as native BLAS support instead of the configuration " +
+				"'sysds.native.blas'=" + userSpecifiedBLAS + ".");
 		}
 	}
 	
@@ -223,15 +230,19 @@
 
 		boolean isLoaded = false;
 		for (String blas : listBLAS) {
-			if (blas.equalsIgnoreCase("mkl")) {
-					isLoaded = loadBLAS(customLibPath, "mkl_rt", null);
-			} else if (blas.equalsIgnoreCase("openblas")) {
-				// no need for gomp on windows
-				if (SystemUtils.IS_OS_WINDOWS || loadBLAS(customLibPath, "gomp",
-						"gomp required for loading OpenBLAS-enabled SystemDS library")) {
-					isLoaded = loadBLAS(customLibPath, "openblas", null);
-				}
+			if (blas.equalsIgnoreCase("mkl"))
+				isLoaded = loadBLAS(customLibPath, "mkl_rt", "");
+			else if (blas.equalsIgnoreCase("openblas")) {
+				// OpenBLAS 0.3.10 binary distribution [1] for windows comes with a libopenblas.dll, so let's try this
+				// first. Make sure the directory of that dll is on your PATH env var or pointed to by customLibPath.
+				// [1] https://github.com/xianyi/OpenBLAS/releases
+				isLoaded = loadBLAS(customLibPath, "libopenblas", "");
+				if(!isLoaded)
+					isLoaded = loadBLAS(customLibPath, "openblas", "");
 			}
+			else
+				LOG.warn("Not trying to load unknown blas type " + blas);
+
 			if (isLoaded) {
 				blasType = blas;
 				break;
@@ -288,13 +299,13 @@
 			String libPath = customLibPath + File.separator + System.mapLibraryName(blas);
 			try {
 				System.load(libPath);
-				// Print to stdout as this feature is intended for cloud environment
-				System.out.println("Loaded the library:" + libPath);
+				LOG.info("Loaded the library:" + libPath);
 				return true;
 			}
-			catch (UnsatisfiedLinkError e1) { 
-				// Print to stdout as this feature is intended for cloud environment
-				System.out.println("Unable to load " + libPath + ":" + e1.getMessage());
+			catch (UnsatisfiedLinkError e) {
+				LOG.warn("Unable to load " + blas + " from " + libPath +
+						". Trying once more with System.loadLibrary(" + blas +
+						") \n Message from exception was: " + e.getMessage());
 			}
 		}
 
@@ -304,22 +315,25 @@
 			return true;
 		}
 		catch (UnsatisfiedLinkError e) {
-			System.out.println(System.getProperty("java.library.path"));
-			if(optionalMsg != null)
-				LOG.debug("Unable to load " + blas + "(" + optionalMsg + "):" + e.getMessage());
-			else
-				LOG.debug("Unable to load " + blas + ":" + e.getMessage());
+			LOG.debug("java.library.path: " + System.getProperty("java.library.path"));
+			LOG.debug("Unable to load " + blas + (optionalMsg == null ? "" : (" (" + optionalMsg + ")")) +
+				" \n Message from exception was: " + e.getMessage());
 			return false;
 		}
 	}
 
-
-	private static boolean loadLibraryHelper(String path)  {
+	/**
+	 * Attempts to load the JNI shared library from the sysds jar
+	 *
+	 * @param libFileName library file name)
+	 * @return true if successfully loaded BLAS
+	 */
+	private static boolean loadLibraryHelperFromResource(String libFileName)  {
 		OutputStream out = null;
-		try(InputStream in = NativeHelper.class.getResourceAsStream("/lib/"+path)) {
+		try(InputStream in = NativeHelper.class.getResourceAsStream("/lib/"+ libFileName)) {
 			// This logic is added because Java does not allow to load library from a resource file.
 			if(in != null) {
-				File temp = File.createTempFile(path, "");
+				File temp = File.createTempFile(libFileName, "");
 				temp.deleteOnExit();
 				out = FileUtils.openOutputStream(temp);
 				IOUtils.copy(in, out);
@@ -327,10 +341,10 @@
 				return true;
 			}
 			else
-				LOG.warn("No lib available in the jar:" + path);
+				LOG.warn("No lib available in the jar:" + libFileName);
 		}
 		catch(IOException e) {
-			LOG.warn("Unable to load library " + path + " from resource:" + e.getMessage());
+			LOG.warn("Unable to load library " + libFileName + " from resource:" + e.getMessage());
 		}
 		finally {
 			IOUtilFunctions.closeSilently(out);