This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
[RFC] Per-directory libjava builds
- From: Paolo Bonzini <paolo dot bonzini at lu dot unisi dot ch>
- To: java-patches at gcc dot gnu dot org, GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 10 May 2005 11:44:58 +0200
- Subject: [RFC] Per-directory libjava builds
This patch builds libjava one directory at a time rather than one file
at a time. It improves build times by 20-30% on average; while Ralf
Wildenhues has been working on optimizing libtool, it is unlikely that
his work will make it to GCC anytime soon. This patch also provides
better coverage testing for gcj's multifile operation mode (as witnessed
by PR/21236, which this patch caused with three different failure modes).
real 23m10.220s
user 22m0.320s
sys 0m58.080s
real 31m41.051s
user 25m34.180s
sys 5m11.520s
As suggested by Per Bothner, this reduces libtool overhead, reduces the
duplication in reading dependencies, and probably reduces link
overheads. It can also produce better code, since intermodule
references get turned into intramodule references. Static linking
(which we don't really support very well anyway) might causes some
classes to be needlessly linked in.
The only thing to do is to avoid extra long command lines when making
Makefile.defs. Other than that (and some more testing to avoid other
latent bugs in multifile operation), it could be ready for committing.
Bootstrapped/regtested i686-pc-linux-gnu together with the PR21436 patch.
Paolo
Index: libjava/configure.ac
===================================================================
RCS file: /cvs/gcc/gcc/libjava/configure.ac,v
retrieving revision 1.28
diff -p -u -u -r1.28 configure.ac
--- libjava/configure.ac 29 Apr 2005 22:09:43 -0000 1.28
+++ libjava/configure.ac 10 May 2005 09:44:05 -0000
@@ -202,17 +202,6 @@ if test -z "$enable_hash_synchronization
enable_hash_synchronization=$enable_hash_synchronization_default
fi
-# Do we allow intermodule optimizations (i.e. compiling many files at once)?
-AC_ARG_ENABLE(libgcj-multifile,
- AS_HELP_STRING([--enable-libgcj-multifile]
- [allow compilation of several files at once]),
-[case "${enableval}" in
- yes) enable_libgcj_multifile=yes ;;
- no) enable_libgcj_multifile=no ;;
- *) AC_MSG_ERROR(bad value ${enableval} for --enable-libgcj-multifile) ;;
-esac],[enable_libgcj_multifile=no])
-AM_CONDITIONAL(ONESTEP, test "$enable_libgcj_multifile" = yes)
-
AC_ARG_WITH(java-home,
AS_HELP_STRING([--with-java-home=DIRECTORY],
[value of java.home system property]),
Index: libjava/Makefile.am
===================================================================
RCS file: /cvs/gcc/gcc/libjava/Makefile.am,v
retrieving revision 1.483
diff -p -u -u -r1.483 Makefile.am
--- libjava/Makefile.am 6 May 2005 23:05:56 -0000 1.483
+++ libjava/Makefile.am 10 May 2005 09:44:07 -0000
@@ -228,6 +228,61 @@ BOOTCLASSPATH = $(here)'$(CLASSPATH_SEPA
## ################################################################
+# Files for which we build .lo files
+all_native_compiled_source_files = \
+ $(java_source_files) \
+ $(built_java_source_files) \
+ $(xlib_java_source_files)
+
+# Files for which we build .class files
+all_java_source_files = \
+ $(all_native_compiled_source_files) \
+ $(gtk_awt_peer_source_files) \
+ $(gnu_xml_source_files) \
+ $(javax_imageio_source_files) \
+ $(javax_xml_source_files) \
+ $(gnu_java_beans_source_files) \
+ gnu/gcj/tools/gcj_dbtool/Main.java
+
+EXTRA_DIST = $(all_java_source_files)
+all_java_class_files = $(all_java_source_files:.java=.class)
+
+# Create two files with the lists of native and .class directories, and one
+# with the dependencies
+#
+# Each directory's filelist file depends on the corresponding Java source files
+# Each class file depends on the its directory's .stamp file
+# Below, one .lo file is built per directory when the filelist file changes
+
+Makefile.deps: Makefile
+ { $(foreach file, $(all_native_compiled_source_files), \
+ echo $(patsubst %/, %, $(dir $(file))); ) } \
+ | sort | uniq > native.dirs
+ { $(foreach file, $(all_java_source_files), \
+ echo $(patsubst %/, %, $(dir $(file))); ) } \
+ | sort | uniq > bytecompile.dirs
+ { $(foreach file, $(all_java_source_files), \
+ echo $(patsubst %/, %, $(dir $(file))).list: $(file); ) } \
+ > Makefile.deps
+ { $(foreach file, $(all_java_class_files), \
+ echo $(file): $(patsubst %/, %, $(dir $(file))).stamp; ) } \
+ >> Makefile.deps
+
+all_native_compiled_dirs := $(shell test -f native.dirs && cat native.dirs)
+all_java_dirs := $(shell test -f bytecompile.dirs && cat bytecompile.dirs)
+all_java_lo_files = $(all_native_compiled_dirs:=.lo)
+all_xlib_lo_files = gnu/gcj/xlib.lo gnu/awt/xlib.lo
+all_libgcj_lo_files = $(filter-out $(all_xlib_lo_files), $(all_java_lo_files))
+all_java_deps_files = $(all_java_dirs:=.deps)
+all_java_stamp_files = $(all_java_dirs:=.stamp)
+all_java_filelist_files = $(all_java_dirs:=.list)
+
+-include Makefile.deps
+-include $(all_java_deps_files)
+
+all_property_files = $(property_files) \
+ java/util/logging/logging.properties
+
##
## How to build libgcj.a and libgcj.jar
##
@@ -246,23 +301,22 @@ libgij_la_LDFLAGS = -rpath $(toolexeclib
# subsections in the linker, such as Alpha and MIPS.
libgcj0_convenience_la_SOURCES = prims.cc jni.cc exception.cc stacktrace.cc \
link.cc defineclass.cc interpret.cc verify.cc \
- $(nat_source_files) $(math_c_source_files) $(java_source_files) \
- $(built_java_source_files) \
+ $(nat_source_files) $(math_c_source_files) \
$(BOEHMGC_SRC) $(NOGC_SRC) \
$(BACKTRACE_SRC) \
$(POSIX_PLATFORM_SRC) $(WIN32_PLATFORM_SRC) $(ECOS_PLATFORM_SRC) \
$(DARWIN_CRT_SRC) \
$(POSIX_THREAD_SRC) $(WIN32_THREAD_SRC) $(NO_THREAD_SRC)
libgcj0_convenience_la_LIBADD = \
+ $(all_libgcj_lo_files) \
gnu-xml.lo javax-imageio.lo \
javax-xml.lo gnu-java-beans.lo \
external/sax/libsax-gcj.la \
external/w3c_dom/libw3c-gcj.la
+libgcj0_convenience_la_DEPENDENCIES = $(libgcj0_convenience_la_LIBADD)
noinst_LTLIBRARIES = libgcj0_convenience.la
-libgcj_la_SOURCES =
-
## Objects from C++ sources in subdirs.
nat_files = $(nat_source_files:.cc=.lo)
xlib_nat_files = $(xlib_nat_source_files:.cc=.lo)
@@ -344,7 +398,7 @@ jni/gtk-peer/gtk_jawt.c \
jni/classpath/native_state.c
## Java sources for Gtk peers.
-gtk_awt_peer_sources = \
+gtk_awt_peer_source_files = \
gnu/java/awt/peer/gtk/GdkTextLayout.java \
gnu/java/awt/peer/gtk/GdkFontMetrics.java \
gnu/java/awt/peer/gtk/GdkFontPeer.java \
@@ -393,7 +447,7 @@ gnu/java/awt/peer/gtk/GThreadMutex.java
gnu/java/awt/peer/gtk/GThreadNativeMethodRunner.java
-gtk_jni_headers = $(patsubst %.java,jniinclude/%.h,$(subst /,_,$(gtk_awt_peer_sources)))
+gtk_jni_headers = $(patsubst %.java,jniinclude/%.h,$(subst /,_,$(gtk_awt_peer_source_files)))
jniinclude/gnu_java_awt_peer_gtk_GdkGraphics.h: gnu/java/awt/peer/gtk/GdkGraphics.java
jniinclude/gnu_java_awt_peer_gtk_GdkGraphics2D.h: gnu/java/awt/peer/gtk/GdkGraphics2D.java
@@ -510,11 +564,10 @@ libjawt_la_LDFLAGS = \
$(LIBGCJ_LD_SYMBOLIC)
libjawt_la_LINK = $(LIBLINK)
-lib_gnu_awt_xlib_la_SOURCES = \
- $(xlib_java_source_files) \
- $(xlib_nat_source_files)
-lib_gnu_awt_xlib_la_DEPENDENCIES = libgcj-$(gcc_version).jar libgcj.la libgcj.spec
-lib_gnu_awt_xlib_la_LIBADD = $(xlib_javao_files)
+lib_gnu_awt_xlib_la_SOURCES = $(xlib_nat_source_files)
+lib_gnu_awt_xlib_la_LIBADD = $(all_xlib_lo_files)
+lib_gnu_awt_xlib_la_DEPENDENCIES = libgcj-$(gcc_version).jar libgcj.la libgcj.spec \
+ $(lib_gnu_awt_xlib_la_LIBADD)
## We require libstdc++-v3 to be in the same build tree.
lib_gnu_awt_xlib_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
@@ -528,21 +581,6 @@ lib_gnu_awt_xlib_la_LDFLAGS = ../libstdc
-version-info `grep -v '^\#' $(srcdir)/libtool-version` $(LIBGCJ_LD_SYMBOLIC)
lib_gnu_awt_xlib_la_LINK = $(LIBLINK)
-all_java_source_files = \
- $(java_source_files) \
- $(built_java_source_files) \
- $(gtk_awt_peer_sources) \
- $(xlib_java_source_files) \
- $(gnu_xml_source_files) \
- $(javax_imageio_source_files) \
- $(javax_xml_source_files) \
- $(gnu_java_beans_source_files)
-
-all_java_class_files = $(all_java_source_files:.java=.class)
-
-all_property_files = $(property_files) \
- java/util/logging/logging.properties
-
## Build property files into the library.
property_files = \
gnu/regexp/MessagesBundle.properties \
@@ -554,32 +592,24 @@ propertyo_files = $(property_files:.prop
%.properties.lo: %.properties
$(LTGCJCOMPILE) -o $@ -c $< -Wc,--resource,`echo $@ | sed "s/\.lo$$//"`
-if ONESTEP
-
-# Compile all classfiles in one go.
-
-classes.stamp: $(all_java_source_files) gnu/gcj/tools/gcj_dbtool/Main.java
- @echo Compiling Java sourcefiles...
- @: $(call write_entries_to_file,$?,libgcj.sourcelist)
- $(JAVAC) $(JCFLAGS) -classpath '' -bootclasspath $(BOOTCLASSPATH) -d $(here) @libgcj.sourcelist
- echo > classes.stamp
-# This next rule seems backward, but reflects the fact that 1) all
-# classfiles are compiled in one go when classes.stamp is built and 2)
-# anything which depends on a particular .class file must wait until
-# this file is built.
-$(all_java_class_files) gnu/gcj/tools/gcj_dbtool/Main.class: classes.stamp
-
-else # !ONESTEP
-
-# Compile each classfile individually.
-
-.java.class:
- $(JAVAC) $(JCFLAGS) -classpath '' -bootclasspath $(BOOTCLASSPATH) -d $(here) $<
+# Compile one directory in one go. If the files have to be compiled with the
+# binary compatibility ABI, only make the .class here -- the .lo is made
+# elsewhere in this Makefile.
+
+%.list:
+ $(mkinstalldirs) $(basename $@)
+ echo $? > $@
+
+$(all_java_lo_files): %.lo: %.stamp
+ $(LTGCJCOMPILE) -o $@ -c @${<:.stamp=.list}
+
+$(all_java_stamp_files): %.stamp: %.list
+ $(JAVAC) $(JCFLAGS) -classpath '' -bootclasspath $(BOOTCLASSPATH) -d $(here) \
+ -MD -MF ${@:.stamp=.deps} @$<
+ echo timestamp > $@
-classes.stamp: $(all_java_class_files) $(all_property_files)
- echo > classes.stamp
-
-endif
+classes.stamp: $(all_property_files) $(all_java_stamp_files)
+ echo timestamp > classes.stamp
libgcj-$(gcc_version).jar: classes.stamp
-@rm -f libgcj-$(gcc_version).jar
@@ -605,7 +635,9 @@ libgcj-$(gcc_version).jar: classes.stamp
$(ZIP) -ufM0E@ $@; \
done
-CLEANFILES = libgcj-$(gcc_version).jar classes.stamp
+CLEANFILES = libgcj-$(gcc_version).jar classes.stamp $(all_java_stamp_files) \
+ $(all_java_deps_files) $(all_java_filelist_files)
+DISTCLEANFILES = Makefile.deps native.dirs bytecompile.dirs
mostlyclean-local:
## Use libtool rm to remove each libtool object
@@ -628,16 +660,10 @@ clean-nat:
SUFFIXES = .class .java .h .properties
-$(javao_files) $(xlib_javao_files): %.lo: %.java
- $(LTGCJCOMPILE) -o $@ -c $<
-
## Pass the list of object files to libtool in a temporary file to
## avoid tripping platform command line length limits.
-libgcj.la: $(libgcj_la_OBJECTS) $(libgcj_la_DEPENDENCIES)
- @echo Creating list of files to link...
- @: $(call write_entries_to_file,$(libgcj_la_OBJECTS),libgcj.objectlist)
- $(libgcj_la_LINK) -objectlist libgcj.objectlist \
- $(libgcj_la_LIBADD) \
+libgcj.la: $(libgcj_la_DEPENDENCIES)
+ $(libgcj_la_LINK) $(libgcj_la_LIBADD) \
-rpath $(toolexeclibdir) $(libgcj_la_LDFLAGS) $(LIBS)
lib-gnu-awt-xlib.la: $(lib_gnu_awt_xlib_la_OBJECTS) $(lib_gnu_awt_xlib_la_DEPENDENCIES)
@@ -700,7 +726,7 @@ gnu-java-beans.lo: $(gnu_java_beans_sour
## Depend on the sources, even though we are going to compile the
## classes.
-gtk-awt-peer.lo: $(gtk_awt_peer_sources)
+gtk-awt-peer.lo: $(gtk_awt_peer_source_files)
## FIXME: this is ugly. We want to make sure the .class files have
## been built, but we don't want a real dependency on them as this
## would cause our target to be rebuilt whenever any .java file is