diff --git a/README.md b/README.md index 557243b5f0..f3fd26c8b7 100644 --- a/README.md +++ b/README.md @@ -67,21 +67,29 @@ java \ -Dlog.level=ALL \ -noverify \ -Xmx1G \ - -jar ./plugins/org.eclipse.equinox.launcher_1.5.200.v20180922-1751.jar \ - -configuration ./config_linux \ - -data /path/to/data \ --add-modules=ALL-SYSTEM \ --add-opens java.base/java.util=ALL-UNNAMED \ - --add-opens java.base/java.lang=ALL-UNNAMED + --add-opens java.base/java.lang=ALL-UNNAMED \ + -jar ./plugins/org.eclipse.equinox.launcher_1.5.200.v20180922-1751.jar \ + -configuration ./config_linux \ + -data /path/to/data ``` 1. Choose a value for `-configuration`: this is the path to your platform's configuration directory. For Linux, use `./config_linux`. For windows, use `./config_win`. For mac/OS X, use `./config_mac`. 2. Change the filename of the jar in `-jar ./plugins/...` to match the version you built or downloaded. 3. Choose a value for `-data`: An absolute path to your data directory. eclipse.jdt.ls stores workspace specific information in it. This should be unique per workspace/project. - If you want to debug eclipse.jdt.ls itself, add `-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=1044` right after `java` and ensure nothing else is running on port 1044. If you want to debug from the start of execution, change `suspend=n` to `suspend=y` so the JVM will wait for your debugger prior to starting the server. +There is also a python wrapper script available that makes the start up of eclipse.jdt.ls more convenient (no need to juggle with Java options etc.). A sample usage is described below. + +```bash +./org.eclipse.jdt.ls.product/target/repository/bin/jdtls \ + -configuration ~/.cache/jdtls \ + -data /path/to/data +``` + +All shown Java options will be set by the wrapper script. Please, note that the `-configuaration` options points to a user's folder to ensure that the configuration folder in `org.eclipse.jdt.ls.product/target/repository/config_*` remains untouched. Development Setup ----------------- diff --git a/org.eclipse.jdt.ls.product/pom.xml b/org.eclipse.jdt.ls.product/pom.xml index ce5cb9a98b..29e2ff2649 100644 --- a/org.eclipse.jdt.ls.product/pom.xml +++ b/org.eclipse.jdt.ls.product/pom.xml @@ -66,7 +66,7 @@ maven-resources-plugin - 3.0.1 + 3.2.0 copy-config-mac @@ -158,6 +158,21 @@ + + copy-launch-script + package + + copy-resources + + + ${project.build.directory}/repository/bin/ + + + ${basedir}/scripts + + + + @@ -171,7 +186,7 @@ - org.codehaus.mojo diff --git a/org.eclipse.jdt.ls.product/publish-assembly.xml b/org.eclipse.jdt.ls.product/publish-assembly.xml index ee3d4c4fda..26f2597581 100644 --- a/org.eclipse.jdt.ls.product/publish-assembly.xml +++ b/org.eclipse.jdt.ls.product/publish-assembly.xml @@ -9,8 +9,9 @@ ${basedir}/target/repository - / + + bin/** config_linux/** config_mac/** config_win/** diff --git a/org.eclipse.jdt.ls.product/scripts/jdtls b/org.eclipse.jdt.ls.product/scripts/jdtls new file mode 100755 index 0000000000..cce0b52620 --- /dev/null +++ b/org.eclipse.jdt.ls.product/scripts/jdtls @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +import jdtls + +jdtls() + diff --git a/org.eclipse.jdt.ls.product/scripts/jdtls.py b/org.eclipse.jdt.ls.product/scripts/jdtls.py new file mode 100644 index 0000000000..6b04f9f211 --- /dev/null +++ b/org.eclipse.jdt.ls.product/scripts/jdtls.py @@ -0,0 +1,93 @@ +import argparse +import glob +import os +import platform +import re +import subprocess +import sys +from pathlib import Path + +def get_java_executable(validate_java_version): + java_executable = 'java' + + if 'JAVA_HOME' in os.environ: + java_exec_to_test = Path(os.environ['JAVA_HOME']) / 'bin' / 'java' + if java_exec_to_test.is_file(): + java_executable = java_exec_to_test.resolve() + + if not validate_java_version: + return java_executable + + out = subprocess.check_output([java_executable, '-version'], stderr = subprocess.STDOUT, universal_newlines=True) + + matches = re.finditer(r"(?P\d+)\.\d+\.\d+", out) + for matchNum, match in enumerate(matches): + java_major_version = int(match.group("major")) + + if java_major_version < 11: + raise Exception("jdtls requires at least Java 11") + + return java_executable + + raise Exception("Could not determine Java version") + +def find_equinox_launcher(jdtls_base_directory): + plugins_dir = jdtls_base_directory / "plugins" + launchers = glob.glob('org.eclipse.equinox.launcher_*.jar', root_dir = plugins_dir) + if len(launchers) > 0: + return plugins_dir / launchers[0] + + raise Exception("Cannot find equinox launcher") + +def get_shared_config_path(jdtls_base_path): + system = platform.system() + + if system == 'Linux': + config_dir = 'config_linux' + elif system == 'Darwin': + config_dir = 'config_mac' + elif system == 'Windows': + config_dir = 'config_win' + else: + raise Exception("Unknown platform {} detected".format(platform)) + + return jdtls_base_path / config_dir + +def jdtls(): + parser = argparse.ArgumentParser() + parser.add_argument("--validate-java-version", default=True, action=argparse.BooleanOptionalAction) + parser.add_argument("--jvm-arg", + default=[], + action="append", + help="An additional JVM option (can be used multiple times. Note, use with equal sign. For example: --jvm-arg=-Dlog.level=ALL") + + known_args, args = parser.parse_known_args(sys.argv[1:]) + java_executable = get_java_executable(known_args.validate_java_version) + + jdtls_base_path = Path(__file__).parent.parent + shared_config_path = get_shared_config_path(jdtls_base_path) + jar_path = find_equinox_launcher(jdtls_base_path) + + os.system(("{java_exec}" + " -Declipse.application=org.eclipse.jdt.ls.core.id1" + " -Dosgi.bundles.defaultStartLevel=4" + " -Declipse.product=org.eclipse.jdt.ls.core.product" + " -Dosgi.checkConfiguration=true" + " -Dosgi.sharedConfiguration.area='{shared_config_path}'" + " -Dosgi.sharedConfiguration.area.readOnly=true" + " -Dosgi.configuration.cascaded=true" + " -noverify" + " -Xms1G" + " --add-modules=ALL-SYSTEM" + " --add-opens java.base/java.util=ALL-UNNAMED" + " --add-opens java.base/java.lang=ALL-UNNAMED" + " {jvm_options}" + " -jar '{jar_path}'" + " {args}").format( + java_exec = java_executable, + shared_config_path = shared_config_path, + jar_path = jar_path, + jvm_options = " ".join(f"'{w}'" for w in known_args.jvm_arg), + args = " ".join(f"'{w}'" for w in args))) + +sys.modules[__name__] = jdtls