Repository: mesonbuild/meson

Issue:
Meson 0.48.0 Module environment.py Function search_version() Does Not Handle JDK 11
This is a followup to my Issue #4139 against 0.47.2. There is an additonal issue in the detect_java_compiler() function triggered by JDK 11.

Module environment.py function detect_java_compiler()  uses the "javac -version" external command to extract the Java compiler version information. It then uses the search_version() function to try to extract the version number from the "javac -version" output.  The regular expression assigned to version_regex requires a period in the version string. on my Linux systems, starting with OpenJDK 11 (GA version 11+28 released 25 Sep 2018), the output of "javac -version" is simply "11" (Debian Sid and openSUSE Tumbleweed) or "11-ea" (Fedora Rawhide).  I considered trying to fiddle with version_regex, then reconsidered when I read the comments:
    # This regex is reaching magic levels. If it ever needs
    # to be updated, do not complexify but convert to something
    # saner instead.

I propose to handle Java compiler versioning with "something saner instead".  I haven't used a lot of different JDK compilers, but in my experience we're just looking for the second "word" in the output of "javac -version".  Instead of using search_version(), how about just grabbing that word?

I propose replacing this environment.py code starting line 747 in 0.48.0:

        version = search_version(err)
        if 'javac' in out or 'javac' in err:
            return JavaCompiler(exelist, version)
        raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')

with this code:

        if 'javac' in err:
            parts = err.split()
            if (len(parts) > 1):
                version = parts[1]
                return JavaCompiler(exelist, version)
        elif 'javac' in out:
            parts = out.split()
            if (len(parts) > 1):
                version = parts[1]
                return JavaCompiler(exelist, version)

Note that this incorporates the fix suggested in Issue #4139 as well, which is to get the version info from the correct stream (stderr versus stdout).



Discussion:
Uh-oh, I made a mistake above. We do NOT want to remove the line

    raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')

I meant to say replace the following code starting line 747:

    version = search_version(err)
    if 'javac' in out or 'javac' in err:
        return JavaCompiler(exelist, version)

My apologies.

Also, please excuse my speaking Python with a C accent.  This is the proper idiom for the test on 'parts':

        if len(parts) > 1:
Debian Sid just upgraded OpenJDK 11 to 11.0.1. Now "javac -version" outputs "javac 11.0.1" to stdout.
Since it contains a period now, the search_version() function would work again. I would still recommend
the simpler approach of using the second word of the "javac -version" output.

Same issue with Fedora Rawhide upgrading to OpenJDK 12. javac -version outputs "javac 12".

Here's a update to the proposed code for Meson 0.49.2.

Replace:

            version = search_version(err if 'javac' in err else out)
            return JavaCompiler(exelist, version)

with:

            parts = (err if 'javac' in err else out).split()
            if len(parts) > 1:
                version = parts[1]
                return JavaCompiler(exelist, version)

Or alternatively, if we want to keep going even if 'javac -version' doesn't provide a version, replace
with:

        version = ''
        parts = (err if 'javac' in err else out).split()
        if len(parts) > 1:
            version = parts[1]
        return JavaCompiler(exelist, version)
Or just apply a workaround if needed. Replace with:

            version = search_version(err if 'javac' in err else out)
            if not version:
                parts = (err if 'javac' in err else out).split()
                if len(parts) > 1:
                    version = parts[1]
            return JavaCompiler(exelist, version)

Please file a full pull request.
It's about time I learned how to do that. It might take a while, but it's
not a very urgent issue. Will do.

On Thu, Feb 21, 2019 at 3:16 PM Jussi Pakkanen <notifications@github.com>
wrote:

> Please file a full pull request.
>
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub
> <https://github.com/mesonbuild/meson/issues/4322#issuecomment-466169795>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AfYYrb64d8_K1HAdd5BrD-XrUJ0keiE0ks5vPwzGgaJpZM4XHT3m>
> .
>


-- 
James Ronald Lovell <ron163264@gmail.com>
Huntsville, AL, USA
A distributed system is one in which the failure of a computer you
didn't even know existed can render your own computer unusable.
-Leslie Lamport

That last workaround needs to be changed for 0.49.2 because search_version now returns 'unknown version' instead of the empty string when no version can be matched. New code:

        if 'javac' in out or 'javac' in err:
            version = search_version(err if 'javac' in err else out)
            if not version or version == 'unknown version':
                parts = (err if 'javac' in err else out).split()
                if len(parts) > 1:
                    version = parts[1]
            return JavaCompiler(exelist, version)


Resolving patch:
diff --git a/mesonbuild/environment.py b/mesonbuild/environment.py
--- a/mesonbuild/environment.py
+++ b/mesonbuild/environment.py
@@ -931,6 +931,10 @@ def detect_java_compiler(self):
             raise EnvironmentException('Could not execute Java compiler "%s"' % ' '.join(exelist))
         if 'javac' in out or 'javac' in err:
             version = search_version(err if 'javac' in err else out)
+            if not version or version == 'unknown version':
+                parts = (err if 'javac' in err else out).split()
+                if len(parts) > 1:
+                    version = parts[1]
             return JavaCompiler(exelist, version)
         raise EnvironmentException('Unknown compiler "' + ' '.join(exelist) + '"')
 


Test patch: