This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]