Improved Eclipse support for the Bazel project
Now the paths are 100% determined using Bazel query. To adapt to
another project, change the variables at the top of the
setup-eclipse.sh file. It also handles correctly java_plugins now.
Because we must do queries on the full workspace, it is not easy to
embed in a bazel build. I made a prototype for it but it is really
impractical.
--
MOS_MIGRATED_REVID=91580472
diff --git a/scripts/eclipse-generate.sh b/scripts/eclipse-generate.sh
new file mode 100755
index 0000000..e533550
--- /dev/null
+++ b/scripts/eclipse-generate.sh
@@ -0,0 +1,160 @@
+#!/bin/bash
+# Copyright 2015 Google Inc. 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.
+#
+# Generates eclipse files for Bazel
+
+set -eu
+
+progname=$0
+function usage() {
+ echo "Usage: $progname command args..." >&2
+ echo "Possible commands are:" >&2
+ echo " classpath java_paths lib_paths jre output_path" >&2
+ echo " factorypath project_name plugin_paths" >&2
+ echo " project project_name" >&2
+ echo " apt_settings output_path" >&2
+ exit 1
+}
+
+function read_entry() {
+ if [[ -e "${1// /_}" ]]; then
+ cat "$1"
+ else
+ echo "$1"
+ fi
+}
+
+function generate_classpath() {
+ if [[ "$#" != 4 ]]; then
+ usage
+ fi
+
+ java_paths="$(read_entry "$1")"
+ lib_paths="$(read_entry "$2")"
+ jre="$3"
+ output_path="$4"
+
+ cat <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+EOF
+
+ for path in $java_paths; do
+ echo " <classpathentry kind=\"src\" path=\"$path\"/>"
+ done
+
+ for path_pair in $lib_paths; do
+ path_arr=(${path_pair//:/ })
+ jar=${path_arr[0]}
+ source_path=${path_arr[1]-}
+ if [ -n "${source_path}" ]; then
+ echo " <classpathentry kind=\"lib\" path=\"${jar}\" sourcepath=\"${source_path}\"/>"
+ else
+ echo " <classpathentry kind=\"lib\" path=\"${jar}\"/>"
+ fi
+ done
+
+ # Write the end of the .classpath file
+ cat <<EOF
+ <classpathentry kind="output" path="${output_path}"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/${jre}">
+ <accessrules>
+ <accessrule kind="accessible" pattern="**"/>
+ </accessrules>
+ </classpathentry>
+</classpath>
+EOF
+}
+
+function generate_factorypath() {
+ if [ "$#" != 2 ]; then
+ usage
+ fi
+ project_name="$1"
+ plugin_paths="$(read_entry "$2")"
+
+ cat <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<factorypath>
+EOF
+
+ for path in $plugin_paths; do
+ echo " <factorypathentry kind=\"WKSPJAR\" id=\"/${project_name}/${path}\" enabled=\"true\" runInBatchMode=\"false\" />"
+ done
+
+ # Write the end of the .factorypath file
+ cat <<EOF
+</factorypath>
+EOF
+}
+
+function generate_project() {
+ if [ "$#" != 1 ]; then
+ usage
+ fi
+ project_name=$1
+ cat <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>${project_name}</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
+EOF
+}
+
+function generate_apt_settings() {
+ if [ "$#" != 1 ]; then
+ usage
+ fi
+ output_path=$1
+ cat <<EOF
+eclipse.preferences.version=1
+org.eclipse.jdt.apt.aptEnabled=true
+org.eclipse.jdt.apt.genSrcDir=${output_path}
+org.eclipse.jdt.apt.reconcileEnabled=true
+EOF
+}
+
+command=$1
+shift
+case "${command}" in
+ classpath)
+ generate_classpath "$@"
+ ;;
+ factorypath)
+ generate_factorypath "$@"
+ ;;
+ project)
+ generate_project "$@"
+ ;;
+ apt_settings)
+ generate_apt_settings "$@"
+ ;;
+ *)
+ usage
+ ;;
+esac
diff --git a/scripts/generate-classpath.sh b/scripts/generate-classpath.sh
deleted file mode 100755
index 2ee880b..0000000
--- a/scripts/generate-classpath.sh
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/bin/bash
-# Copyright 2015 Google Inc. 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.
-#
-# Generates an eclipse .classpath file for Bazel
-
-set -eu
-
-cd $(dirname "$0")
-cd ..
-
-source scripts/get_all_bazel_paths.sh || exit 1
-
-cat <<EOF
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-EOF
-
-for path in ${JAVA_PATHS}; do
- echo " <classpathentry kind=\"src\" path=\"$path\"/>"
-done
-
-# Find third party paths
-for path in ${THIRD_PARTY_JAR_PATHS}; do
- echo " <classpathentry kind=\"lib\" path=\"$path\"/>"
-done
-
-# Find protobuf generation
-for path in ${PROTOBUF_PATHS}; do
- echo " <classpathentry kind=\"lib\" path=\"$(dirname $path)/$(basename $path .proto_output)\" sourcepath=\"$path\"/>"
-done
-
-for path_pair in ${GENERATED_PATHS}; do
- path_arr=(${path_pair//:/ })
- jar=${path_arr[0]}
- source_path=${path_arr[1]}
- echo " <classpathentry kind=\"lib\" path=\"${jar}\" sourcepath=\"${source_path}\"/>"
-done
-
-# Write the end of the .classpath file
-cat <<EOF
- <classpathentry kind="lib" path="tools/jdk/jdk/lib/tools.jar"/>
- <classpathentry kind="output" path="${IDE_OUTPUT_PATH}"/>
- <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8">
- <accessrules>
- <accessrule kind="accessible" pattern="**"/>
- </accessrules>
- </classpathentry>
-</classpath>
-EOF
diff --git a/scripts/get_project_paths.sh b/scripts/get_project_paths.sh
new file mode 100755
index 0000000..9e90009
--- /dev/null
+++ b/scripts/get_project_paths.sh
@@ -0,0 +1,72 @@
+#!/bin/bash
+# Copyright 2015 Google Inc. 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.
+#
+# Gets all libraries needed for IDE support of a Bazel workspace
+
+set -eu
+
+cd $(dirname "$0")
+cd ..
+
+function query() {
+ ./output/bazel query "$@"
+}
+
+# Compile bazel
+([ -f "output/bazel" ] && [ -f "tools/jdk/JavaBuilder_deploy.jar" ] \
+ && [ -f "tools/jdk/ijar" ] && [ -f "tools/jdk/SingleJar_deploy.jar" ] \
+ && [ -e "tools/jdk/jdk" ]) || ./compile.sh >&2 || exit $?
+
+# Build everything
+./output/bazel build ${TARGET} >&2 || exit $?
+
+# Now for java each targets, find all sources and all jars
+DEPS=$(query 'filter("\.java$",
+ deps(kind("(java_binary|java_library|java_test|java_plugin)",
+ deps('"$TARGET"')))
+ except deps(//tools/...))')
+PATHS=$(echo "$DEPS" | sed 's|:|/|' | sed 's|^//||')
+
+# Java Files:
+JAVA_PATHS=$(echo "$PATHS" | sed 's_\(/java\(tests\)\{0,1\}\)/.*$_\1_' | sort -u)
+
+# Java plugins
+JAVA_PLUGINS_DEPS=$(query 'filter("\.jar$",
+ deps(kind(java_import,
+ deps(kind(java_plugin,
+ deps('"$TARGET"')))))
+ except deps(//tools/...))')
+PLUGIN_PATHS=$(echo "$JAVA_PLUGINS_DEPS" | sed 's|:|/|' | sed 's|^//||' | sort -u)
+
+# Jar Files:
+JAR_DEPS=$(query 'filter("\.jar$", deps(kind(java_import, deps('"$TARGET"')))
+ except deps(//tools/...))')
+JAR_FILES=$(echo "$JAR_DEPS" | sed 's|:|/|' | sed 's|^//||' | sort -u)
+
+# Generated files are direct dependencies of java rules that are not java rules,
+# filegroup or binaries.
+# We also handle genproto separately it is output in bazel-genfiles not in
+# bazel-bin.
+# We suppose that all files are generated in the same package than the library.
+GEN_LIBS=$(query 'let gendeps = kind(rule, deps(kind(java_*, deps('"$TARGET"')), 1))
+ - kind("(java_.*|filegroup|.*_binary|genproto)", deps('"$TARGET"'))
+ - deps(//tools/...)
+ in rdeps('"$TARGET"', set($gendeps), 1) - set($gendeps)' \
+ | sed 's|^//\(.*\):\(.*\)|bazel-bin/\1/lib\2.jar:bazel-genfiles/\1|')
+
+# Hack for genproto
+PROTOBUFS=$(bazel query 'kind(genproto, deps('"$TARGET"'))' \
+ | sed 's|^//\(.*\):\(.*\)$|bazel-bin/\1/lib\2.jar:bazel-bin/\1/lib\2.jar.proto_output/|')
+LIB_PATHS="${JAR_FILES} ${PROTOBUFS} ${GEN_LIBS}"
diff --git a/scripts/setup-eclipse.sh b/scripts/setup-eclipse.sh
index 68ce918..3639875 100755
--- a/scripts/setup-eclipse.sh
+++ b/scripts/setup-eclipse.sh
@@ -20,34 +20,28 @@
#
set -eu
+TARGET=//src/...
+JRE="JavaSE-1.8"
+PROJECT_NAME="bazel"
+OUTPUT_PATH="bazel-out/ide/classes"
+GENERATED_PATH="bazel-out/ide/generated"
+EXTRA_JARS="bazel-bazel/external/local-jdk/lib/tools.jar"
+source $(dirname "$0")/get_project_paths.sh
-cd $(dirname "$0")
-cd ..
+mkdir -p ${OUTPUT_PATH} ${GENERATED_PATH}
-# Simply creates a Eclipse java project
-if [ ! -f ".project" ]; then
- cat >.project <<'EOF'
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
- <name>bazel</name>
- <comment></comment>
- <projects>
- </projects>
- <buildSpec>
- <buildCommand>
- <name>org.eclipse.jdt.core.javabuilder</name>
- <arguments>
- </arguments>
- </buildCommand>
- </buildSpec>
- <natures>
- <nature>org.eclipse.jdt.core.javanature</nature>
- </natures>
-</projectDescription>
-EOF
+# Overwrite .classpath and .factorypath.
+./scripts/eclipse-generate.sh classpath "$JAVA_PATHS" "$LIB_PATHS $EXTRA_JARS" "$JRE" "$OUTPUT_PATH" >.classpath
+if [ -n "$PLUGIN_PATHS" ]; then
+ ./scripts/eclipse-generate.sh factorypath "$PROJECT_NAME" "$PLUGIN_PATHS" >.factorypath
+ mkdir -p .settings
+ # Write apt settings if not present.
+ [ -e ".settings/org.eclipse.jdt.apt.core.prefs" ] || \
+ ./scripts/eclipse-generate.sh apt_settings "$GENERATED_PATH" > .settings/org.eclipse.jdt.apt.core.prefs
fi
-
-./scripts/generate-classpath.sh >.classpath
+# Write .project if not present.
+[ -e ".project" ] || \
+ ./scripts/eclipse-generate.sh project "$PROJECT_NAME" > .project
echo
echo '***'