Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't find Java runtime on macOS (when installed using Homebrew) #277

Open
tcurdt opened this issue Feb 24, 2024 · 14 comments
Open

Can't find Java runtime on macOS (when installed using Homebrew) #277

tcurdt opened this issue Feb 24, 2024 · 14 comments
Assignees
Labels
enhancement macOS macOS related issues
Milestone

Comments

@tcurdt
Copy link

tcurdt commented Feb 24, 2024

I tried to run version 1.9.0 from KiCAD 8 on macOS 14.
It didn't find the installed java runtime.

The easy fix was to go into the plugin.ini and change the java path from java to /opt/homebrew/opt/openjdk/bin/java

I am just not sure where contribute a patch to the docs. But maybe people will find it in the issues.

@andrasfuchs andrasfuchs self-assigned this Mar 4, 2024
@andrasfuchs andrasfuchs added enhancement macOS macOS related issues labels Mar 4, 2024
@andrasfuchs andrasfuchs added this to To do in Freerouting Project Board via automation Mar 4, 2024
@andrasfuchs andrasfuchs added this to the Future milestone Mar 4, 2024
@andrasfuchs
Copy link
Collaborator

@tcurdt That's great insight, thank you for your contribution!

I don't have a Mac, so I don't think I will be able to fix it myself, but someone from the community might be able to do it.

I would start by looking into the Python scripts in the \integrations\KiCad\ folder, fixing the installjava.py as a first step.

@andrasfuchs andrasfuchs removed their assignment Mar 4, 2024
@tcurdt
Copy link
Author

tcurdt commented Mar 20, 2024

True. I would be nice if would the installation automatically.

I just looked at the code but this does not really make any sense to me (yet).

def get_local_java_executable_path(os_name):
    java_exe_path = os.path.join(tempfile.gettempdir(), f"jdk-21.*.*+*-jre", "bin", "java")
    if os_name == "windows":
        java_exe_path += ".exe"

    java_found_exes = sorted(
        [p for p in filter(lambda p: os.path.isfile(p), glob.glob(java_exe_path)) if re.search(r"jdk-21\.(\d+)\.(\d+)(\.\d+)?\+(\d+)-jre", p)],
        reverse=True,
        key=lambda p: re.search(r"jdk-21\.(\d+)\.(\d+)(\.\d+)?\+(\d+)-jre", p).groups() if re.search(r"jdk-21\.(\d+)\.(\d+)(\.\d+)?\+(\d+)-jre", p) else ()
    )

    if len(java_found_exes) >= 1:
        java_exe_path = java_found_exes[0]
        print(f"You already have a downloaded JRE ({java_exe_path}), we are going to use that.")
    else:
        java_exe_path = ""

    return java_exe_path

On my machine the search expression is /var/folders/2j/qlgsy9ys335cdkc03vd8byfr0000gn/T/jdk-21.*.*+*-jre/bin/java. Which I find a little odd.

This is a version that works for me and seems a little more flexible.
I tried to keep the old behaviour although I really don't understand the reasoning behind searching in tmp.

def get_local_java_executable_path(os_name):

    search_folders = [
        os.path.join(tempfile.gettempdir(), f"jdk-21.*.*+*-jre", "bin", "java"),
        os.path.join(f"/opt/homebrew/opt/openjdk", "bin", "java"),
    ]

    def find_java_exe_paths(folder):
        java_exe_path = folder
        if os_name == "windows":
            java_exe_path += ".exe"

        return sorted(
            [p for p in filter(lambda p: os.path.isfile(p), glob.glob(java_exe_path))],
            reverse=True,
            key=lambda p: re.search(r"jdk-21\.(\d+)\.(\d+)(\.\d+)?\+(\d+)-jre", p).groups() if re.search(r"jdk-21\.(\d+)\.(\d+)(\.\d+)?\+(\d+)-jre", p) else ()
        )

    java_exe_paths = [path for folder in search_folders for path in find_java_exe_paths(folder)]

    if java_exe_paths:
        java_exe_path = java_exe_paths[0]
        print(f"Using JRE at {java_exe_path}.")
    else:
        java_exe_path = ""
        print("No JRE found in the specified search folders.")

    return java_exe_path

HTH

@andrasfuchs
Copy link
Collaborator

Thanks, I'll look into it and try to integrate it into the KiCad plugin script.

The script above looks into the temp folder, because when an installed and up-to-date Java installation is not found, the script installs the proper runtime into the temp folder. So when we look for a valid installation we also need to check the temp folder to avoid repeated JDK downloads.

Is it always the case that the java executable doesn't included in PATH folders on Mac? (I'm not sure if it's called PATH on Mac.)
As far as I know both on Windows and Linux the java executable will be accessible from anywhere after the successful installation by default.

@andrasfuchs andrasfuchs self-assigned this Mar 21, 2024
@andrasfuchs andrasfuchs modified the milestones: Future, 2.0 Mar 21, 2024
@tcurdt
Copy link
Author

tcurdt commented Mar 21, 2024

AFAIK an interactive shell process and an application process might not have the same PATH setup. I think applications are really started through launchd and that's why they don't have all the user environment variables inherited.
So I am not sure just depending on the PATH is the right thing to do.

Copy link

Hey there!👋 This issue is stale because it has been inactive for 60 days. If this matter is still relevant, feel free to remove the stale label or add a comment. Otherwise, it will be closed in 7 days. But remember, with thousands of monthly active users, someone might just have the solution you need. This is a community-driven project, and your active participation is crucial. If the issue is critical for your work, consider contributing a fix yourself or hiring someone to help. I'm here to support your efforts and will review and merge pull requests as quickly as I can. Let's collaborate to keep improving our project! 🚀 Your involvement is invaluable, and together, we can ensure the continuous growth and success of our community. Thank you for being an integral part of this journey. Your engagement is what drives our project forward!

@tcurdt
Copy link
Author

tcurdt commented May 20, 2024

I guess the question is whether this should just be added to the docs or whether this should be fixed in code.

@andrasfuchs
Copy link
Collaborator

I started the investigation by chatting with ChatGPT, and I got this:

The /opt/homebrew/opt/openjdk/bin/java folder indicates that the OpenJDK was installed using Homebrew, a popular package manager for macOS. Homebrew installs packages and their dependencies into the /opt/homebrew directory by default on Apple Silicon Macs (M1 and later).

So, if you see Java in the /opt/homebrew/opt/openjdk/bin directory, it means that OpenJDK was installed via Homebrew, and this is where Homebrew places the binaries for the packages it manages.

Does this sound correct?

Also, as far as I know, you can install Temurin JRE without Homebrew, and then the java executable will be installed in /Library/Java/JavaVirtualMachines/<temurin_version>/Contents/Home/bin/java.

Could you confirm this?

@andrasfuchs andrasfuchs changed the title contribute some docs on finding the java runtime Can't find Java runtime on macOS (when installed using Homebrew) Jun 5, 2024
@tcurdt
Copy link
Author

tcurdt commented Jun 5, 2024

Yes, bottom line: there just isn't a fix location. There are a couple of common locations to check.
And installing via homebrew is very common - but the location differs for Arm and Intel machines.

Hence I would suggest to have a couple of locations to search.

You could also have a read here which feels a bit outdated though.

@andrasfuchs
Copy link
Collaborator

andrasfuchs commented Jun 5, 2024

I updated the check_java.py script according to the information I found on the link you sent me.

Could you check if that returns a correct Java path and version number for you?

@tcurdt
Copy link
Author

tcurdt commented Jun 5, 2024

I didn't have to time to run it yet - but I can tell you already that it ain't working like that:

$ echo $JAVA_HOME
/opt/homebrew/opt/openjdk

$ /usr/libexec/java_home
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.

Please keep in mind this is for an interactive session.
It's not certain that $JAVA_HOME is available in the Freerouting env.

@andrasfuchs
Copy link
Collaborator

Alright then, we will look for the $JAVA_HOME first, if that's not available and we are on macOS then we call the macOS specific /usr/libexec/java_home command, and if that fails as well, than we just try to call java -version in the current folder.

In the other script we install the Java JRE on the fly if the above fails or returns a non-sufficient version number.

I updated the script again, does it look better?

@tcurdt
Copy link
Author

tcurdt commented Jun 5, 2024

While the script looks better - none of that would have helped me and I would have opened the issue anyway.

$JAVA_HOME is unlikely to report something and /usr/libexec/java_home seems to only report on java runtimes that have Apples blessings.

I fear it's:

  1. check plugin.ini
  2. check $JAVA_HOME
  3. check /usr/libexec/java_home
  4. look at commons paths (see get_local_java_executable_path(os_name):)

I think the important distinction and most likely problem here is that the environment is not that of the user but coming from launchd.

@andrasfuchs
Copy link
Collaborator

andrasfuchs commented Jun 6, 2024

Alright, I think I see what you mean with the commons paths. They are useful as a fallback if we can't access the JAVA_HOME environment variable or we can't execute the java_home command on macOS.

I wonder if we can access any arbitrary folder (defined in the search_folders) in the environment where the KiCad plugin runs? So in order to have a robust solution, we would need to run the java -version for all options we have on a system, and flag them as usable only if they can be run, and their version number is >=21.

It's getting complicated, I have to say :) Anyway, I'll try to incorporate these changes without breaking anything for the other platforms...

@tcurdt
Copy link
Author

tcurdt commented Jun 6, 2024

I fear it's the "fun" of cross-platform :)

Folder access could be restricted if KiCad runs in a sandboxed environment (which I don't think it is - because then file access would be a much bigger hell).

But I think 1.-4. isn't so bad. Especially as (just as me) people can edit the plugin.ini there always is a way.

And support for java_home feels like a "nice to have" as that's just a pattern away.
Not sure I would bother and rather just maintain a list of paths. Because that really is a cross-platform mechanism.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement macOS macOS related issues
Projects
Development

No branches or pull requests

2 participants