[m-rev.] for review: improvements to the Java launcher scripts

Julien Fischer jfischer at opturion.com
Sat Jul 23 02:10:10 AEST 2022


On Mon, 18 Jul 2022, Peter Wang wrote:

>>> I see that the java launcher from JDK 9+ supports the JDK_JAVA_OPTIONS
>>> variable so perhaps we can use that?
>>
>> We still support Java 8 (and that's not going anywhere soon). I would
>> like to avoid the same names as the variables supported by the Java
>> tools themselves.  How about we change all of the variables in the
>> Mercury launchers that can be overridden to have a MERCURY_ prefix,
>> e.g.
>>
>>      MERCURY_JAVA
>>      MERCURY_JAVA_OPTIONS
>>
>> (There's some precedent for doing this since the shell scripts we use
>> in the C grades have MERCURY_C_COMPILER etc.)
>>
>> That should reduce the risk of clashes with (a) Java itself and (b)
>> other stuff written in Java.

The following diff does the above and addresses the other review
comments.

diff --git a/NEWS b/NEWS
index 3732d41..dc27c9f 100644
--- a/NEWS
+++ b/NEWS
@@ -408,6 +408,14 @@ Changes to the Mercury compiler
  * The deprecated option `--trail-segments` has been deleted and the grade
    component `trseg` is no longer accepted as a synonym for `tr`.

+* `--javac-flags` is now accepted as a synonym for `--java-flags`. Similarly
+  `--javac-flag` is now accepted as synonym for `--java-flags`.
+
+* The new options `--java-runtime-flags` and `--java-runtime-flags` can be
+  used to set flags for the Java interpreter in the launcher shell scripts or
+  batch files generated by the compiler when creating executables in the `java`
+  grade.
+
  Changes to the extras distribution
  ----------------------------------

diff --git a/compiler/compile_target_code.m b/compiler/compile_target_code.m
index c20b994..e8ff771 100644
--- a/compiler/compile_target_code.m
+++ b/compiler/compile_target_code.m
@@ -2,6 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %-----------------------------------------------------------------------------%
  % Copyright (C) 2002-2012 The University of Melbourne.
+% Copyright (C) 2013-2022 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %-----------------------------------------------------------------------------%
@@ -871,7 +872,8 @@ compile_java_files(Globals, ProgressStream, ErrorStream,
      ),

      globals.lookup_string_option(Globals, java_compiler, JavaCompiler),
-    globals.lookup_accumulating_option(Globals, java_flags, JavaFlagsList),
+    globals.lookup_accumulating_option(Globals, java_compiler_flags,
+        JavaFlagsList),
      globals.lookup_bool_option(Globals, restricted_command_line,
          RestrictedCommandLine),
      (
diff --git a/compiler/module_cmds.m b/compiler/module_cmds.m
index 6d11495..29856e2 100644
--- a/compiler/module_cmds.m
+++ b/compiler/module_cmds.m
@@ -910,6 +910,11 @@ write_java_shell_script(Globals, MainModuleName, JarFileName, Stream, !IO) :-
          MercuryStdLibs ++ ["$CLASSPATH" | UserClasspath],
      ClassPath = string.join_list("${SEP}", Java_Incl_Dirs),

+    globals.lookup_accumulating_option(Globals, java_runtime_flags,
+        RuntimeFlags),
+    RuntimeOpts0 = string.join_list(" ", RuntimeFlags),
+    RuntimeOpts = escape_single_quotes_for_shell_script(RuntimeOpts0),
+
      globals.lookup_string_option(Globals, java_interpreter, Java),
      mangle_sym_name_for_java(MainModuleName, module_qual, ".", ClassName),

@@ -923,8 +928,10 @@ write_java_shell_script(Globals, MainModuleName, JarFileName, Stream, !IO) :-
          "esac\n",
          "CLASSPATH=", ClassPath, "\n",
          "export CLASSPATH\n",
-        "JAVA=${JAVA:-", Java, "}\n",
-        "exec \"$JAVA\" jmercury.", ClassName, " \"$@\"\n"
+        "MERCURY_JAVA=${MERCURY_JAVA:-'", Java, "'}\n",
+        "MERCURY_JAVA_OPTIONS=${MERCURY_JAVA_OPTIONS:-'", RuntimeOpts, "'}\n",
+        "exec \"$MERCURY_JAVA\" $MERCURY_JAVA_OPTIONS jmercury.", ClassName,
+            " \"$@\"\n"
      ], !IO).

      % For the MSYS version of the Java launcher script, there are a few
@@ -959,6 +966,11 @@ write_java_msys_shell_script(Globals, MainModuleName, JarFileName, Stream,
          Java_Incl_Dirs0),
      ClassPath = string.join_list("\\;", Java_Incl_Dirs),

+    globals.lookup_accumulating_option(Globals, java_runtime_flags,
+        RuntimeFlags),
+    RuntimeOpts0 = string.join_list(" ", RuntimeFlags),
+    RuntimeOpts = escape_single_quotes_for_shell_script(RuntimeOpts0),
+
      globals.lookup_string_option(Globals, java_interpreter, Java),
      mangle_sym_name_for_java(MainModuleName, module_qual, ".", ClassName),

@@ -968,10 +980,21 @@ write_java_msys_shell_script(Globals, MainModuleName, JarFileName, Stream,
          "DIR=$( cd \"${DIR}\" && pwd -W )\n",
          "CLASSPATH=", ClassPath, "\n",
          "export CLASSPATH\n",
-        "JAVA=${JAVA:-", Java, "}\n",
-        "exec \"$JAVA\" jmercury.", ClassName, " \"$@\"\n"
+        "MERCURY_JAVA=${MERCURY_JAVA:-'", Java, "'}\n",
+        "MERCURY_JAVA_OPTIONS=${MERCURY_JAVA_OPTIONS:-'", RuntimeOpts, "'}\n",
+        "exec \"$MERCURY_JAVA\" $MERCURY_JAVA_OPTIONS jmercury.", ClassName,
+            " \"$@\"\n"
      ], !IO).

+:- func escape_single_quotes_for_shell_script(string) = string.
+
+escape_single_quotes_for_shell_script(S) =
+    ( if string.contains_char(S, '\'') then
+        string.replace_all(S, "'", "'\\''")
+    else
+        S
+    ).
+
  :- pred write_java_batch_file(globals::in, module_name::in, file_name::in,
      io.text_output_stream::in, io::di, io::uo) is det.

@@ -984,16 +1007,22 @@ write_java_batch_file(Globals, MainModuleName, JarFileName, Stream, !IO) :-
          ["%CLASSPATH%" | UserClasspath],
      ClassPath = string.join_list(";", Java_Incl_Dirs),

+    globals.lookup_accumulating_option(Globals, java_runtime_flags,
+        RuntimeFlags),
+    RuntimeOpts = string.join_list(" ", RuntimeFlags),
+
      globals.lookup_string_option(Globals, java_interpreter, Java),
      mangle_sym_name_for_java(MainModuleName, module_qual, ".", ClassName),

      io.write_strings(Stream, [
          "@echo off\n",
          "rem Automatically generated by the Mercury compiler.\n",
-        "setlocal\n",
+        "setlocal enableextensions\n",
          "set DIR=%~dp0\n",
          "set CLASSPATH=", ClassPath, "\n",
-        Java, " jmercury.", ClassName, " %*\n"
+        "if not defined MERCURY_JAVA_OPTIONS set MERCURY_JAVA_OPTIONS=",
+            RuntimeOpts, "\n",
+        Java, " %MERCURY_JAVA_OPTIONS% jmercury.", ClassName, " %*\n"
      ], !IO).

  get_mercury_std_libs_for_java(Globals, !:StdLibs) :-
diff --git a/compiler/options.m b/compiler/options.m
index c036a12..8d24e5275 100644
--- a/compiler/options.m
+++ b/compiler/options.m
@@ -2,7 +2,7 @@
  % vim: ft=mercury ts=4 sw=4 et
  %---------------------------------------------------------------------------%
  % Copyright (C) 1994-2012 The University of Melbourne.
-% Copyright (C) 2013-2021 The Mercury team.
+% Copyright (C) 2013-2022 The Mercury team.
  % This file may only be copied under the terms of the GNU General
  % Public License - see the file COPYING in the Mercury distribution.
  %---------------------------------------------------------------------------%
@@ -962,10 +962,12 @@
      % Java
      ;       java_compiler
      ;       java_interpreter
-    ;       java_flags
-    ;       quoted_java_flag
+    ;       java_compiler_flags
+    ;       quoted_java_compiler_flag
      ;       java_classpath
      ;       java_object_file_extension
+    ;       java_runtime_flags
+    ;       quoted_java_runtime_flag

      % C#
      ;       csharp_compiler
@@ -1898,10 +1900,12 @@ optdef(oc_target_comp, csharp_compiler_type,            string("mono")).
      % Java
  optdef(oc_target_comp, java_compiler,                   string("javac")).
  optdef(oc_target_comp, java_interpreter,                string("java")).
-optdef(oc_target_comp, java_flags,                      accumulating([])).
-optdef(oc_target_comp, quoted_java_flag,                string_special).
+optdef(oc_target_comp, java_compiler_flags,             accumulating([])).
+optdef(oc_target_comp, quoted_java_compiler_flag,       string_special).
  optdef(oc_target_comp, java_classpath,                  accumulating([])).
  optdef(oc_target_comp, java_object_file_extension,      string(".class")).
+optdef(oc_target_comp, java_runtime_flags,              accumulating([])).
+optdef(oc_target_comp, quoted_java_runtime_flag,        string_special).

      % C#
  optdef(oc_target_comp, csharp_compiler,                 string("csc")).
@@ -2950,14 +2954,18 @@ long_option("csharp-compiler-type", csharp_compiler_type).
  long_option("java-compiler",        java_compiler).
  long_option("javac",                java_compiler).
  long_option("java-interpreter",     java_interpreter).
-long_option("java-flags",           java_flags).
-long_option("java-flag",            quoted_java_flag).
+long_option("javac-flags",          java_compiler_flags).
+long_option("javac-flag",           quoted_java_compiler_flag).
+long_option("java-flags",           java_compiler_flags).
+long_option("java-flag",            quoted_java_compiler_flag).
  % XXX we should consider the relationship between java_debug and target_debug
  % more carefully. Perhaps target_debug could imply Java debug if the target
  % is Java. However for the moment they are just synonyms.
  long_option("java-debug",           target_debug).
  long_option("java-classpath",       java_classpath).
  long_option("java-object-file-extension", java_object_file_extension).
+long_option("java-runtime-flags",   java_runtime_flags).
+long_option("java-runtime-flag",    quoted_java_runtime_flag).

  long_option("csharp-compiler",      csharp_compiler).
  long_option("csharp-flags",         csharp_flags).
@@ -3430,9 +3438,13 @@ special_handler(Option, SpecialData, !.OptionTable, Result, !OptOptions) :-
              SpecialData = string(Flag),
              handle_quoted_flag(msvc_flags, Flag, !OptionTable)
          ;
-            Option = quoted_java_flag,
+            Option = quoted_java_compiler_flag,
              SpecialData = string(Flag),
-            handle_quoted_flag(java_flags, Flag, !OptionTable)
+            handle_quoted_flag(java_compiler_flags, Flag, !OptionTable)
+        ;
+            Option = quoted_java_runtime_flag,
+            SpecialData = string(Flag),
+            handle_quoted_flag(java_runtime_flags, Flag, !OptionTable)
          ;
              Option = quoted_csharp_flag,
              SpecialData = string(Flag),
@@ -6382,18 +6394,24 @@ options_help_target_code_compilation(Stream, !IO) :-
          "\tSpecify which Java interpreter to use.",
          "\tThe default is `java'",

+        "--javac-flags <options>, --javac-flag <option>",
          "--java-flags <options>, --java-flag <option>",
          "\tSpecify options to be passed to the Java compiler.",
-        "\t`--java-flag' should be used for single words which need",
-        "\tto be quoted when passed to the shell.",
+        "\t`--java-flag' or `--javac-flag' should be used for single words",
+        "\twhich need to be quoted when passed to the shell.",

          "--java-classpath <path>",
-        "\tSet the classpath for the Java compiler.",
+        "\tSet the classpath for the Java compiler and interpreter.",

          "--java-object-file-extension <ext>",
          "\tSpecify an extension for Java object (bytecode) files",
          "\tBy default this is `.class'.",

+        "--java-runtime-flags <options>, java-runtime-flag <option>",
+        "\tSpecify options to be passed to the Java interpreter.",
+        "\t`--java-runtime-flag' should be used for single words which need",
+        "\tto be quoted when passed to the shell.",
+
          "--csharp-compiler <csc>",
          "\tSpecify the name of the C# Compiler. The default is `csc'.",
          "--csharp-flags <options>, --csharp-flag <option>",
diff --git a/doc/user_guide.texi b/doc/user_guide.texi
index 833b648..b8e6d47 100644
--- a/doc/user_guide.texi
+++ b/doc/user_guide.texi
@@ -345,11 +345,19 @@ for further details.)
  When targeting Java,
  @samp{mmc} will package up all of the class files for the executable
  into a Java archive (JAR) named @file{@var{filename}.jar}.
-If you are using the Windows command line interpreter @samp{cmd.exe},
- at samp{mmc} will generate a batch file called @file{@var{filename}.bat}
-that invokes the program using the Java interpreter.
-Otherwise, it will generate a shell script called @file{@var{filename}}
-that also invokes the program using the Java interpreter.
+It will also generate a launcher that invokes the program using the Java
+interpreter.
+If you are using the Windows command line interpreter @samp{cmd.exe}, this
+launcher will be a batch file called @file{@var{filename}.bat}.
+Otherwise, the launcher will be a shell script called @file{@var{filename}}.
+Java runtime flags can be set using @samp{mmc}'s @samp{--java-runtime-flags} or
+ at samp{--java-runtime-flag} options.
+Such Java runtime flags will be included in the generated launcher shell script
+or batch file.
+You may override any runtime flags set at (Mercury) compile time by setting the
+variable @var{MERCURY_JAVA_OPTIONS} in the environment.
+Classpath settings made using @samp{mmc}'s @samp{--java-classpath} option will
+also be included in the generated launcher shell script or batch file.

  If you use Mmake or @samp{mmc --make},
  then you do not need to understand the details
@@ -9950,8 +9958,12 @@ Specify which Java interpreter to use.  The default is @samp{java}.
  @sp 1
  @item --java-flags @var{options}
  @itemx --java-flag @var{option}
+ at itemx --javac-flags @var{options}
+ at itemx --javac-flag @var{option}
  @findex --java-flags
  @findex --java-flag
+ at findex --javac-flags
+ at findex --javac-flags
  @cindex Java compiler options
  Specify options to be passed to the Java compiler.
  @samp{--java-flag} should be used for single words which need
@@ -9962,7 +9974,7 @@ to be quoted when passed to the shell.
  @findex --java-classpath
  @cindex classpath
  @cindex Directories
-Set the classpath for the Java compiler.
+Set the classpath for the Java compiler and interpreter.

  @sp 1
  @item --java-object-file-extension @var{extension}
@@ -9972,6 +9984,16 @@ Specify an extension for Java object (bytecode) files.  By default this
  is @samp{.class}.

  @sp 1
+ at item --java-runtime-flags @var{options}
+ at itemx --java-runtime-flag @var{option}
+ at findex --java-runtime-flags
+ at findex --java-runtime
+ at cindex Java runtime options
+Specify options to be passed to the Java interpreter.
+ at samp{--java-runtime-flag} should be used for single words which need
+to be quoted when passed to the shell.
+
+ at sp 1
  @item --csharp-compiler @var{compiler-name}
  @findex --csharp-compiler
  @cindex C# compiler

Julien.


More information about the reviews mailing list