From 376604084e7323b36e6984bce429b003b3a1e5b5 Mon Sep 17 00:00:00 2001 From: Christophe B Date: Mon, 29 Aug 2022 17:43:10 +0200 Subject: [PATCH 1/8] Command line build x64 and aarch64 --- CMakeLists.txt | 2 +- source/projects/mxj-common.cmake | 2 +- source/projects/mxj_safe/CMakeLists.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b108324..c2a540a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16) if (APPLE) if (CMAKE_OSX_ARCHITECTURES STREQUAL "" OR CMAKE_OSX_ARCHITECTURES STREQUAL "i386") - set(CMAKE_OSX_ARCHITECTURES x86_64) # override the old max-api values permitting i386 + set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") # override the old max-api values permitting i386 endif () if (CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) diff --git a/source/projects/mxj-common.cmake b/source/projects/mxj-common.cmake index 9f25c1d..471b04a 100644 --- a/source/projects/mxj-common.cmake +++ b/source/projects/mxj-common.cmake @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 3.16) if (APPLE) if (CMAKE_OSX_ARCHITECTURES STREQUAL "" OR CMAKE_OSX_ARCHITECTURES STREQUAL "i386") - set(CMAKE_OSX_ARCHITECTURES x86_64) # override the old max-api values permitting i386 + set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") # override the old max-api values permitting i386 endif () if (CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) diff --git a/source/projects/mxj_safe/CMakeLists.txt b/source/projects/mxj_safe/CMakeLists.txt index 58e44b5..02afbdc 100755 --- a/source/projects/mxj_safe/CMakeLists.txt +++ b/source/projects/mxj_safe/CMakeLists.txt @@ -11,7 +11,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/../../max-sdk-base/script/max-pretarget.cmak if (APPLE) if (CMAKE_OSX_ARCHITECTURES STREQUAL "" OR CMAKE_OSX_ARCHITECTURES STREQUAL "i386") - set(CMAKE_OSX_ARCHITECTURES x86_64) # override the old max-api values permitting i386 + set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") # override the old max-api values permitting i386 endif () if (CMAKE_OSX_DEPLOYMENT_TARGET STREQUAL "") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.9) From 513ce41a0f3617e102752c99f8376797e749bd19 Mon Sep 17 00:00:00 2001 From: Christophe B Date: Mon, 29 Aug 2022 17:58:07 +0200 Subject: [PATCH 2/8] Remove precondition to getEmbeddedHomeDirectory only x86_64 and allow search for aarch64 --- source/mxj/JavaHomeOsx.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/source/mxj/JavaHomeOsx.c b/source/mxj/JavaHomeOsx.c index 1bfe469..8e3ae4c 100644 --- a/source/mxj/JavaHomeOsx.c +++ b/source/mxj/JavaHomeOsx.c @@ -109,10 +109,6 @@ static bool privateEmbeddedHomeDirectorySearched = false; // Search already done // (folder jre in max-mxj package) char *getEmbeddedHomeDirectory() { - //for osx we only look at embedded binaries for 64 bit -#if !defined(__x86_64__) - return NULL; -#else if (!privateEmbeddedHomeDirectorySearched) // Search embedded jre if not searched yet { privateEmbeddedHomeDirectorySearched = true; @@ -161,7 +157,6 @@ char *getEmbeddedHomeDirectory() } } return privateEmbeddedHomeDirectory; -#endif } From 72fa6372ae5a48097973a2e40dcc5648aae1a1e4 Mon Sep 17 00:00:00 2001 From: Christophe B Date: Mon, 29 Aug 2022 18:00:56 +0200 Subject: [PATCH 3/8] Display error if returning without starting JVM --- source/mxj/IVirtualMachine.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/mxj/IVirtualMachine.cpp b/source/mxj/IVirtualMachine.cpp index 03777ca..26d2f8b 100644 --- a/source/mxj/IVirtualMachine.cpp +++ b/source/mxj/IVirtualMachine.cpp @@ -280,9 +280,10 @@ void IVirtualMachine::startJVM() if(dylib!=NULL) { - handle= dlopen(dylib,RTLD_NOW + RTLD_GLOBAL); - if(handle==NULL) + handle = dlopen(dylib, RTLD_NOW + RTLD_GLOBAL); + if (handle == NULL) { + error("Cannot open dylib: %s", dlerror()); return; } } From 074430b1892ffd3df8cb881fdd5b40668267c41b Mon Sep 17 00:00:00 2001 From: Christophe B Date: Mon, 29 Aug 2022 18:05:21 +0200 Subject: [PATCH 4/8] Search jli and dylib only if not provided through environment variables --- source/mxj/IVirtualMachine.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/source/mxj/IVirtualMachine.cpp b/source/mxj/IVirtualMachine.cpp index 26d2f8b..f95bfb8 100644 --- a/source/mxj/IVirtualMachine.cpp +++ b/source/mxj/IVirtualMachine.cpp @@ -254,9 +254,8 @@ void IVirtualMachine::startJVM() char * baseDir = getJavaHome(); - char * dylib = findLib(baseDir); - char * jli = getJavaJli(); - + char * dylib; + char * jli; //we look to the environment for an embedded path char * embeddedEnvironment = getenv("EMBEDDED_JVM_LIBRARY_PATH"); @@ -264,11 +263,14 @@ void IVirtualMachine::startJVM() if(embeddedEnvironment!=NULL) dylib = embeddedEnvironment; + else + dylib = findLib(baseDir); //embedded users must also provide the full path to the JLI library if(embeddedJliEnvironment!=NULL) jli = embeddedJliEnvironment; - + else + jli = getJavaJli(); //the jvm can still launch if jli is not present //in the case of Apple java 1.6 for example this will not result in a problem From 185650e481017837122f86345681bb6c585416ea Mon Sep 17 00:00:00 2001 From: Christophe B Date: Tue, 30 Aug 2022 15:48:41 +0200 Subject: [PATCH 5/8] Add a comment about Zulu JRE embedding --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e0b99dd..982efdb 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ jre/Contents/Plugins jre/Contents/Resources jre/Contents/Frameworks +If you want to use a zulu jre, you must extract its content to match the above structure. + The JRE can be found here after installing a java internet plugin: "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/" Copy that folder and rename it "jre" From 1b15996b0c081a6411078153b5026bc3cbd0643d Mon Sep 17 00:00:00 2001 From: Christophe B Date: Wed, 31 Aug 2022 18:16:14 +0200 Subject: [PATCH 6/8] Use specific embedded jre folders for osx x86_64 and aarch64 --- source/mxj/JavaHomeOsx.c | 68 +++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/source/mxj/JavaHomeOsx.c b/source/mxj/JavaHomeOsx.c index 8e3ae4c..05fad07 100644 --- a/source/mxj/JavaHomeOsx.c +++ b/source/mxj/JavaHomeOsx.c @@ -105,6 +105,35 @@ static inline bool hasEnding(const char *fullString, const char *ending) static char *privateEmbeddedHomeDirectory = NULL; static bool privateEmbeddedHomeDirectorySearched = false; // Search already done? avoid doing it several times +/** + * @brief Get the Embedded Home Directory From Binary Path object + * @param mxjSuffix can be mxj mxj~ and mxj_safe objects + * @param fullName can be mxj mxj~ and mxj_safe objects binary path + * @param jreHomeToCheck jre path to check, should be either jre, or jre-x64 or jre-arm64 + * @return char* directory found newly allocated (must be free later) or null + */ +char *getEmbeddedHomeDirectoryFromBinaryPath(const char *mxjSuffix, const char *fullName,const char * jreHomeToCheck) +{ + // Replace binary suffix in path by jre home relative path + + const int maxxxLen = (int)(strlen(fullName) + strlen(jreHomeToCheck) + 1); // In case mxjSuffix is smaller than jreHome, take precautions + char embeddedHome[maxxxLen]; + memset(embeddedHome, 0, maxxxLen); // Clear it + // Set to fullName + strncpy(embeddedHome, fullName, maxxxLen - 1); // Keep last 0 + // Remove mxj suffix + embeddedHome[strlen(fullName) - strlen(mxjSuffix)] = 0; + // Append jre home + strncat(embeddedHome, jreHomeToCheck, maxxxLen - 1); // Keep last 0 + + // Check for folder + if (fileExists(embeddedHome, true)) + { + return strdup(embeddedHome); + } + return NULL; +} + // Function to retreive eventually the existence of embedded JRE home directory // (folder jre in max-mxj package) char *getEmbeddedHomeDirectory() @@ -121,9 +150,6 @@ char *getEmbeddedHomeDirectory() { if (myPluginInfo.dli_fname != NULL) { - const char *jreHome = "jre/Contents/Home"; - - // Check all possible suffixes (call can be made from mxj, mxj~ and mxj_safe objects) for (int q = 0; (mxjSuffixes[q] != NULL) && (privateEmbeddedHomeDirectory == NULL); ++q) { const char *mxjSuffix = mxjSuffixes[q]; @@ -132,22 +158,28 @@ char *getEmbeddedHomeDirectory() const char *fullName = myPluginInfo.dli_fname; // Full binary path name if (fullName != NULL) { - // Replace mxj suffix in path by jre home relative path - - const int maxxxLen = (int)(strlen(fullName) + strlen(jreHome) + 1); // In case mxjSuffix is smaller than jreHome, take precautions - char embeddedHome[maxxxLen]; - memset(embeddedHome, 0, maxxxLen); // Clear it - // Set to fullName - strncpy(embeddedHome, fullName, maxxxLen - 1); // Keep last 0 - // Remove mxj suffix - embeddedHome[strlen(fullName) - strlen(mxjSuffix)] = 0; - // Append jre home - strncat(embeddedHome, jreHome, maxxxLen - 1); // Keep last 0 - - // Check for folder - if (fileExists(embeddedHome, true)) + char *res; + // If a Universal jre exists or for a single architecture application, or Intel application under Rosetta + res = getEmbeddedHomeDirectoryFromBinaryPath(mxjSuffix, fullName, "jre/Contents/Home"); + if (res==NULL) + { + // Mostly Java distribution are not universal so we have to embed both architectures separately + // Use the same jre names as in open jdk downloads + res = getEmbeddedHomeDirectoryFromBinaryPath(mxjSuffix, fullName, + #ifdef __x86_64__ + "jre/jre_x64/Contents/Home" + #elif __aarch64__ + "jre/jre_aarch64/Contents/Home" + #else + // Should never happend, anyway it will cause a build error + #endif + ); + } + + // Store result + if (res!=NULL) { - privateEmbeddedHomeDirectory = strdup(embeddedHome); + privateEmbeddedHomeDirectory = res; break; } } From e0468677d0c26b0b3897f92fcf5c93f6058e5bdb Mon Sep 17 00:00:00 2001 From: Christophe B Date: Fri, 2 Sep 2022 18:00:08 +0200 Subject: [PATCH 7/8] Improves README for embedding JRE. --- README.md | 35 +++++++++++++++++++++++++++++------ 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 982efdb..2e632a1 100644 --- a/README.md +++ b/README.md @@ -36,20 +36,43 @@ Download and install Cmake. Build as on macOS. ## MXJ rules for searching for Java: -On OSX, it searches in that order: embeded JRE, on system JDK, on system JRE -The search for an embeded JRE is done in the application, in the folder MyApp.app/Contents/Resources/C74/packages/max-mxj/jre -The JRE must have the structure : + +### MacOS +On OSX, it searches in that order: embedded JRE, on system JDK, on system JRE. + +The search for an embedded JRE is done in the application, in the folder MyApp.app/Contents/Resources/C74/packages/max-mxj/jre +The JRE must have the structure for a single architecture: jre/Contents/Home jre/Contents/MacOS jre/Contents/Plugins jre/Contents/Resources jre/Contents/Frameworks +For MacOS universal application, you must either use an universal JRE (no one seems to be available at the moment), or use one JRE per architecture: +jre/jre_x64/Contents/Home +jre/jre_x64/Contents/MacOS +jre/jre_x64/Contents/Plugins +jre/jre_x64/Contents/Resources +jre/jre_x64/Contents/Frameworks +jre/jre_aarch64/Contents/Home +jre/jre_aarch64/Contents/MacOS +jre/jre_aarch64/Contents/Plugins +jre/jre_aarch64/Contents/Resources +jre/jre_aarch64/Contents/Frameworks + If you want to use a zulu jre, you must extract its content to match the above structure. The JRE can be found here after installing a java internet plugin: "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/" -Copy that folder and rename it "jre" +Copy that folder and rename it "jre". + +### Windows +On Windows, it searches in that order: embedded JRE, on system JDK, on system JRE +The search for an embedded JRE is done in the application, it must be a folder named "jre" placed in the same folder as the application .exe + +### JDK/JRE providers: +https://adoptium.net/temurin/releases/ +https://adoptopenjdk.net/releases.html +https://www.oracle.com/java/technologies/downloads/ -On Windows, it searches in that order: embeded JRE, on system JDK, on system JRE -The search for an embeded JRE is done in the application, it must be a folder named "jre" placed in the same folder as the application .exe +You can download a zipped version and rename the unzipped folder according to the requirements. From 45a191175c882d291f361b39645c962c176affdb Mon Sep 17 00:00:00 2001 From: Christophe B Date: Fri, 9 Sep 2022 10:06:20 +0200 Subject: [PATCH 8/8] Update windows build instructions --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2e632a1..4278ad6 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,20 @@ Use the badges above to go directly to the CI services. ## To build (Windows) -Download the Windows x86 Java SE Development Kit 8 (from http://www.oracle.com and install it in the default location (C:\Program Files (x86)\Java). Rename 'C:\Program Files (x86)\Java\jdk1.8.0_xxx' to 'C:\Program Files (x86)\Java\jdk1.8.0'. +Download the Windows x64 Java SE Development Kit 8 (from http://www.oracle.com and install it in the default location (C:\Program Files\Java). Download and install Cmake. +Define variable JAVA_HOME with `rundll32.exe sysdm.cpl,EditEnvironmentVariables` +* JAVA_HOME => "C:\Program Files\Java\jdk1.8.0_xxx" + +* after that, launch a new shell, then from max-mxj folder: +* `mkdir build` +* `cd build` +* `set CUSTOM_FLAG="-DWIN64:Bool=True"` +* `cmake -G "Visual Studio 15 2017 Win64" ..` (update version according to your Visual studio version, Win64 is mandatory) +* `cmake --build .` (or open the VS project in this build folder and build there) +* `cmake --build . --config Release` -Build as on macOS. ## MXJ rules for searching for Java: