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/README.md b/README.md index e0b99dd..4278ad6 100644 --- a/README.md +++ b/README.md @@ -29,25 +29,59 @@ 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: -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. diff --git a/source/mxj/IVirtualMachine.cpp b/source/mxj/IVirtualMachine.cpp index 03777ca..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 @@ -280,9 +282,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; } } diff --git a/source/mxj/JavaHomeOsx.c b/source/mxj/JavaHomeOsx.c index 1bfe469..05fad07 100644 --- a/source/mxj/JavaHomeOsx.c +++ b/source/mxj/JavaHomeOsx.c @@ -105,14 +105,39 @@ 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() { - //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; @@ -125,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]; @@ -136,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) { - privateEmbeddedHomeDirectory = strdup(embeddedHome); + // 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 = res; break; } } @@ -161,7 +189,6 @@ char *getEmbeddedHomeDirectory() } } return privateEmbeddedHomeDirectory; -#endif } 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)