Skip to content

Commit

Permalink
Use jar from java runtime and not local_jdk
Browse files Browse the repository at this point in the history
Work around and somewhat prepare for resolution of
bazelbuild/bazel#6955
  • Loading branch information
ittaiz committed Mar 27, 2019
1 parent 379c65e commit 1c21fab
Show file tree
Hide file tree
Showing 8 changed files with 409 additions and 6 deletions.
7 changes: 7 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
workspace(name = "io_bazel_rules_scala")

#used to test what happens when classpath is too large
#until https://github.com/bazelbuild/bazel/issues/6955 is resolved
local_repository(
name = "java_stub_template",
path = "java_stub_template"
)

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository")
load("//scala:scala.bzl", "scala_repositories")
Expand Down
Empty file added java_stub_template/WORKSPACE
Empty file.
5 changes: 5 additions & 0 deletions java_stub_template/file/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
filegroup(
name = "file",
srcs = ["file.txt"],
visibility = ["//visibility:public"],
)
369 changes: 369 additions & 0 deletions java_stub_template/file/file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,369 @@
#!/usr/bin/env bash
# Copyright 2014 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This script was generated from java_stub_template.txt. Please
# don't edit it directly.
#
# If present, these flags should either be at the beginning of the command
# line, or they should be wrapped in a --wrapper_script_flag=FLAG argument.
#
# --debug Launch the JVM in remote debugging mode listening
# --debug=<port> to the specified port or the port set in the
# DEFAULT_JVM_DEBUG_PORT environment variable (e.g.
# 'export DEFAULT_JVM_DEBUG_PORT=8000') or else the
# default port of 5005. The JVM starts suspended
# unless the DEFAULT_JVM_DEBUG_SUSPEND environment
# variable is set to 'n'.
# --main_advice=<class> Run an alternate main class with the usual main
# program and arguments appended as arguments.
# --main_advice_classpath=<classpath>
# Prepend additional class path entries.
# --jvm_flag=<flag> Pass <flag> to the "java" command itself.
# <flag> may contain spaces. Can be used multiple times.
# --jvm_flags=<flags> Pass space-separated flags to the "java" command
# itself. Can be used multiple times.
# --singlejar Start the program from the packed-up deployment
# jar rather than from the classpath.
# --print_javabin Print the location of java executable binary and exit.
# --classpath_limit=<length>
# Specify the maximum classpath length. If the classpath
# is shorter, this script passes it to Java as a command
# line flag, otherwise it creates a classpath jar.
#
# The remainder of the command line is passed to the program.

set -o posix

# Make it easy to insert 'set -x' or similar commands when debugging problems with this script.
eval "$JAVA_STUB_DEBUG"

# Prevent problems where the caller has exported CLASSPATH, causing our
# computed value to be copied into the environment and double-counted
# against the argv limit.
unset CLASSPATH

JVM_FLAGS_CMDLINE=()

# Processes an argument for the wrapper. Returns 0 if the given argument
# was recognized as an argument for this wrapper, and 1 if it was not.
function process_wrapper_argument() {
case "$1" in
--debug) JVM_DEBUG_PORT="${DEFAULT_JVM_DEBUG_PORT:-5005}" ;;
--debug=*) JVM_DEBUG_PORT="${1#--debug=}" ;;
--main_advice=*) MAIN_ADVICE="${1#--main_advice=}" ;;
--main_advice_classpath=*) MAIN_ADVICE_CLASSPATH="${1#--main_advice_classpath=}" ;;
--jvm_flag=*) JVM_FLAGS_CMDLINE+=( "${1#--jvm_flag=}" ) ;;
--jvm_flags=*) JVM_FLAGS_CMDLINE+=( ${1#--jvm_flags=} ) ;;
--singlejar) SINGLEJAR=1 ;;
--print_javabin) PRINT_JAVABIN=1 ;;
--classpath_limit=*)
CLASSPATH_LIMIT="${1#--classpath_limit=}"
echo "$CLASSPATH_LIMIT" | grep -q '^[0-9]\+$' || \
die "ERROR: $self failed, --classpath_limit is not a number"
;;
*)
return 1 ;;
esac
return 0
}

die() {
printf "%s: $1\n" "$0" "${@:2}" >&2
exit 1
}

# Windows
function is_windows() {
[[ "${OSTYPE}" =~ msys* ]] || [[ "${OSTYPE}" =~ cygwin* ]]
}

# macOS
function is_macos() {
[[ "${OSTYPE}" =~ darwin* ]]
}

# Parse arguments sequentially until the first unrecognized arg is encountered.
# Scan the remaining args for --wrapper_script_flag=X options and process them.
ARGS=()
for ARG in "$@"; do
if [[ "$ARG" == --wrapper_script_flag=* ]]; then
process_wrapper_argument "${ARG#--wrapper_script_flag=}" \
|| die "invalid wrapper argument '%s'" "$ARG"
elif [[ "${#ARGS}" -gt 0 ]] || ! process_wrapper_argument "$ARG"; then
ARGS+=( "$ARG" )
fi
done

# Find our runfiles tree. We need this to construct the classpath
# (unless --singlejar was passed).
#
# Call this program X. X was generated by a java_binary or java_test rule.
# X may be invoked in many ways:
# 1a) directly by a user, with $0 in the output tree
# 1b) via 'bazel run' (similar to case 1a)
# 2) directly by a user, with $0 in X's runfiles tree
# 3) by another program Y which has a data dependency on X, with $0 in Y's runfiles tree
# 4) via 'bazel test'
# 5) by a genrule cmd, with $0 in the output tree
# 6) case 3 in the context of a genrule
#
# For case 1, $0 will be a regular file, and the runfiles tree will be
# at $0.runfiles.
# For case 2, $0 will be a symlink to the file seen in case 1.
# For case 3, we use Y's runfiles tree, which will be a superset of X's.
# For case 4, $JAVA_RUNFILES and $TEST_SRCDIR should already be set.
# Case 5 is handled like case 1.
# Case 6 is handled like case 3.

# If we are running on Windows, convert the windows style path
# to unix style for detecting runfiles path.
if is_windows; then
self=$(cygpath --unix "$0")
else
self="$0"
fi

if [[ "$self" != /* ]]; then
self="$PWD/$self"
fi

if [[ "$SINGLEJAR" != 1 || "%needs_runfiles%" == 1 ]]; then
if [[ -z "$JAVA_RUNFILES" ]]; then
while true; do
if [[ -e "$self.runfiles" ]]; then
JAVA_RUNFILES="$self.runfiles"
break
fi
if [[ $self == *.runfiles/* ]]; then
JAVA_RUNFILES="${self%.runfiles/*}.runfiles"
break
fi
if [[ ! -L "$self" ]]; then
break
fi
readlink="$(readlink "$self")"
if [[ "$readlink" = /* ]]; then
self="$readlink"
else
# resolve relative symlink
self="${self%/*}/$readlink"
fi
done
if [[ -n "$JAVA_RUNFILES" ]]; then
export TEST_SRCDIR=${TEST_SRCDIR:-$JAVA_RUNFILES}
elif [[ -f "${self}_deploy.jar" && "%needs_runfiles%" == 0 ]]; then
SINGLEJAR=1;
else
die 'Cannot locate runfiles directory. (Set $JAVA_RUNFILES to inhibit searching.)'
fi
fi
fi

# If we are running on Windows, we need a windows style runfiles path for constructing CLASSPATH
if is_windows; then
JAVA_RUNFILES=$(cygpath --windows "$JAVA_RUNFILES")
fi

export JAVA_RUNFILES
export RUNFILES_MANIFEST_FILE="${JAVA_RUNFILES}/MANIFEST"
export RUNFILES_MANIFEST_ONLY=%runfiles_manifest_only%

if [ -z "$RUNFILES_MANIFEST_ONLY" ]; then
function rlocation() {
if [[ "$1" = /* ]]; then
echo $1
else
echo "$(dirname $RUNFILES_MANIFEST_FILE)/$1"
fi
}
else
if ! is_macos; then
# Read file into my_array
oifs=$IFS
IFS=$'\n'
my_array=( $(sed -e 's/\r//g' "$RUNFILES_MANIFEST_FILE") )
IFS=$oifs

# Process each runfile line into a [key,value] entry in runfiles_array
# declare -A is not supported on macOS because an old version of bash is used.
declare -A runfiles_array
for line in "${my_array[@]}"
do
line_split=($line)
runfiles_array[${line_split[0]}]=${line_split[@]:1}
done
fi

function rlocation() {
if [[ "$1" = /* ]]; then
echo $1
else
if is_macos; then
# Print the rest of line after the first space
# First, set the first column to empty and print rest of the line
# Second, use a trick of awk to remove leading and trailing spaces.
echo $(grep "^$1 " $RUNFILES_MANIFEST_FILE | awk '{ $1=""; print }' | awk '{ $1=$1; print }')
else
echo ${runfiles_array[$1]}
fi
fi
}
fi

if is_macos || [[ ${OSTYPE} == "freebsd" ]]; then
function md5func() { md5 -q $@ ; }
else
function md5func() { md5sum $@ | awk '{print $1}' ; }
fi

# Set JAVABIN to the path to the JVM launcher.
%javabin%

if [[ "$PRINT_JAVABIN" == 1 || "%java_start_class%" == "--print_javabin" ]]; then
echo -n "$JAVABIN"
exit 0
fi

if [[ "$SINGLEJAR" == 1 ]]; then
CLASSPATH="${self}_deploy.jar"
# Check for the deploy jar now. If it doesn't exist, we can print a
# more helpful error message than the JVM.
[[ -r "$CLASSPATH" ]] \
|| die "Option --singlejar was passed, but %s does not exist.\n (You may need to build it explicitly.)" "$CLASSPATH"
else
# Create the shortest classpath we can, by making it relative if possible.
RUNPATH="${JAVA_RUNFILES}/%workspace_prefix%"
RUNPATH="${RUNPATH#$PWD/}"
CLASSPATH=%classpath%
fi

# Export the locations which will be used to find the location of the classes from the classpath file.
export SELF_LOCATION="$self"
export CLASSLOADER_PREFIX_PATH="${RUNPATH}"

# If using Jacoco in offline instrumentation mode, the CLASSPATH contains instrumented files.
# We need to make the metadata jar with uninstrumented classes available for generating
# the lcov-compatible coverage report, and we don't want it on the classpath.
%set_jacoco_metadata%
%set_jacoco_main_class%
%set_jacoco_java_runfiles_root%
%set_java_coverage_new_implementation%

if [[ -n "$JVM_DEBUG_PORT" ]]; then
JVM_DEBUG_SUSPEND=${DEFAULT_JVM_DEBUG_SUSPEND:-"y"}
JVM_DEBUG_FLAGS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=${JVM_DEBUG_SUSPEND},address=${JVM_DEBUG_PORT}"

if [[ "$PERSISTENT_TEST_RUNNER" == "true" ]]; then
JVM_DEBUG_FLAGS+=",quiet=y"
fi
fi

if [[ -n "$MAIN_ADVICE_CLASSPATH" ]]; then
CLASSPATH="${MAIN_ADVICE_CLASSPATH}:${CLASSPATH}"
fi

# Check if TEST_TMPDIR is available to use for scratch.
if [[ -n "$TEST_TMPDIR" && -d "$TEST_TMPDIR" ]]; then
JVM_FLAGS+=" -Djava.io.tmpdir=$TEST_TMPDIR"
fi

ARGS=(
${JVM_DEBUG_FLAGS}
${JVM_FLAGS}
%jvm_flags%
"${JVM_FLAGS_CMDLINE[@]}"
${MAIN_ADVICE}
%java_start_class%
"${ARGS[@]}")


function create_and_run_classpath_jar() {
# Build class path as one single string separated by spaces
MANIFEST_CLASSPATH=""
if is_windows; then
IFS=';'
URI_PREFIX="file:/" # e.g. "file:/C:/temp/foo.jar"
else
IFS=':'
URI_PREFIX="file:$(pwd)/" # e.g. "file:/usr/local/foo.jar"
fi
for x in $CLASSPATH; do
# Add file:/ prefix and escaped space characters, it should be a URI.
x="${URI_PREFIX}${x// /%20}"
MANIFEST_CLASSPATH="$MANIFEST_CLASSPATH $x"
done
unset IFS

# Create manifest file
MANIFEST_FILE="$(mktemp -t XXXXXXXX.jar_manifest)"

(
echo "Manifest-Version: 1.0"
CLASSPATH_LINE="Class-Path:$MANIFEST_CLASSPATH"
# No line in the MANIFEST.MF file may be longer than 72 bytes.
# A space prefix indicates the line is still the content of the last attribute.
for ((i = 0; i < "${#CLASSPATH_LINE}"; i += 71)); do
PREFIX=" "
if ((i == 0)); then
PREFIX=""
fi
echo "$PREFIX${CLASSPATH_LINE:$i:71}"
done
echo "Created-By: Bazel"
) >$MANIFEST_FILE

# Create classpath JAR file
MANIFEST_JAR_FILE="$(mktemp -t XXXXXXXX-classpath.jar)"
if is_windows; then
MANIFEST_JAR_FILE="$(cygpath --windows "$MANIFEST_JAR_FILE")"
MANIFEST_FILE="$(cygpath --windows "$MANIFEST_FILE")"
fi
JARBIN="${JARBIN:-$(rlocation "$1")}"
$JARBIN cvfm "$MANIFEST_JAR_FILE" "$MANIFEST_FILE" >/dev/null || \
die "ERROR: $self failed because $JARBIN failed"

# Execute JAVA command
$JAVABIN -classpath "$MANIFEST_JAR_FILE" "${ARGS[@]}"
exit_code=$?
rm -f "$MANIFEST_FILE"
rm -f "$MANIFEST_JAR_FILE"
exit $exit_code
}

# If the user didn't specify a --classpath_limit, use the default value.
if [ -z "$CLASSPATH_LIMIT" ]; then
# Windows per-arg limit MAX_ARG_STRLEN == 8k
# Linux per-arg limit MAX_ARG_STRLEN == 128k
is_windows && CLASSPATH_LIMIT=7000 || CLASSPATH_LIMIT=120000
fi

#Difference from https://github.com/bazelbuild/bazel/blob/68c7e5a3c679be51f750d44aae146007f0f04b4d/src/main/java/com/google/devtools/build/lib/bazel/rules/java/java_stub_template.txt
JARBIN="%jarbin%"
PERCENTAGE_LITERAL="%"
JARBIN_LITERAL="${PERCENTAGE_LITERAL}jarbin${PERCENTAGE_LITERAL}"
# if jarbin is evaluated to empty string or not substituted fallback to previous behavior
# for backwards compatibility
if [ -z "$JARBIN" ] || [ "$JARBIN" == "$JARBIN_LITERAL" ] ; then
JARBIN="local_jdk/bin/jar"
fi
#Difference ends

if is_windows && (("${#CLASSPATH}" > ${CLASSPATH_LIMIT} )); then
create_and_run_classpath_jar "${JARBIN}.exe"
elif (("${#CLASSPATH}" > ${CLASSPATH_LIMIT})); then
create_and_run_classpath_jar "$JARBIN"
else
exec $JAVABIN -classpath $CLASSPATH "${ARGS[@]}"
fi
Loading

0 comments on commit 1c21fab

Please sign in to comment.