public inbox for java-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] Create sdk style directory on install
@ 2008-06-12 20:56 Joshua Sumali
  2008-06-13 10:42 ` Andrew Haley
  2008-06-13 12:42 ` Matthias Klose
  0 siblings, 2 replies; 18+ messages in thread
From: Joshua Sumali @ 2008-06-12 20:56 UTC (permalink / raw)
  To: java-patches; +Cc: Thomas Fitzsimmons

[-- Attachment #1: Type: text/plain, Size: 699 bytes --]

Hi,

Attached is a patch to create a sdk style directory when 
--enable-java-home is passed to configure. The patch is basically a 
merge of java-gcj-compat into libgcj.

To have this work, at the minimum, pass the following to ./configure: 
--enable-java-home --with-arch-directory=(your arch). 
--with-arch-directory specifies what to use for the 
java-1.5.0-gcj-1.5.0.0/jre/lib/<arch> directory (e.g. I use i386).

I've only included the diff to configure.ac and Makefile.am since 
including the configure and Makefile.in makes the patch quite big, so be 
sure to autoconf && automake before trying this patch. I can upload the 
renerated files somewhere if it's absolutely needed, though.

Josh

[-- Attachment #2: gcc-libjava-sdk-home-symlink.patch --]
[-- Type: text/x-patch, Size: 13708 bytes --]

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 136724)
+++ ChangeLog	(working copy)
@@ -1,3 +1,19 @@
+2008-06-12  Joshua Sumali  <jsumali@redhat.com>
+
+	* configure.ac (java-home): new AC_ARG_ENABLE.
+	(CREATE_JAVA_HOME): new AM_CONDITIONAL.
+	(gcc-suffix): new AC_ARG_WITH.
+	(arch-directory): Likewise.
+	(os-directory): Likewise.
+	(origin-name): Likewise.
+	(arch-suffix): Likewise.
+	(jvm-root-dir): Likewise.
+	(jvm-jar-dir): Likewise.
+	* Makefile.am (install-data-local): Install an sdk style directory if
+	--enable-java-home is passed to configure.
+	* configure: Regenerate.
+	* Makefile.in: Regenerate.
+
 2008-06-07  Joseph Myers  <joseph@codesourcery.com>
 
 	* configure.host (strongarm*-elf, xscale*-elf): Remove.
Index: Makefile.am
===================================================================
--- Makefile.am	(revision 136724)
+++ Makefile.am	(working copy)
@@ -85,7 +85,7 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
-endif
+endif 
 
 bin_SCRIPTS = addr2name.awk
 
@@ -528,8 +528,134 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/gij$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/gjar$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/gjdoc$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/grmic$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/gjavah$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/gappletviewer$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/gjarsigner$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/grmiregistry$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/gkeytool$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/gorbd$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/gnative2ascii$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/grmid$(gcc_suffix) $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/gtnameserv$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/gserialver$(gcc_suffix) \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/grmiregistry$(gcc_suffix) \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/gkeytool$(gcc_suffix) $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/gij$(gcc_suffix) $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/gorbd$(gcc_suffix) $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/grmid$(gcc_suffix) $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/gtnameserv$(gcc_suffix) $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $(DESTDIR)$(JVM_ROOT_DIR); \
+	  ln -s $(JRE_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $(DESTDIR)$(JVM_JAR_ROOT_DIR); \
+	  ln -s $(SDK_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	GIJ_VERSION=$$($(DESTDIR)$(bindir)/gij --version | head -n2 | tail -n1 \
+	  | awk '{print $$5}'); \
+	ln -sf $$RELATIVE/libgcj-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	if [ -f $$RELATIVE/libjawt.so ]; then \
+	  ln -sf $$RELATIVE/libjawt.so \
+	    $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	fi; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	if [ -f $$RELATIVE/src-$$GIJ_VERSION.zip ]; then \
+	  ln -sf $$RELATIVE/src-$$GIJ_VERSION.zip \
+	    $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip; \
+	fi;
+endif
 
-
 ## ################################################################
 
 ##
Index: configure.ac
===================================================================
--- configure.ac	(revision 136724)
+++ configure.ac	(working copy)
@@ -117,6 +117,7 @@
 AC_CHECK_PROGS([JAR], [jar fastjar gjar], no)
 AC_PATH_PROG([ZIP], [zip], no)
 AC_PATH_PROG([UNZIP], [unzip], unzip)
+AC_PATH_PROG([PERL], [perl], perl)
 
 # We need a jar that supports -@.  This is a GNU extension.
 if test "$JAR" != no; then
@@ -1625,6 +1626,183 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)
 
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  if test "x${prefix}" = "xNONE"
+  then
+    sdk_prefix=/usr
+  else
+    sdk_prefix=$prefix
+  fi
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${sdk_prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir=${sdk_prefix}/lib/jvm])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${sdk_prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=${sdk_prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
+  AC_SUBST(JAVA_HOME_DIR)
+  AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$sdk_prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-12 20:56 [patch] Create sdk style directory on install Joshua Sumali
@ 2008-06-13 10:42 ` Andrew Haley
  2008-06-13 12:42 ` Matthias Klose
  1 sibling, 0 replies; 18+ messages in thread
From: Andrew Haley @ 2008-06-13 10:42 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches, Thomas Fitzsimmons

Joshua Sumali wrote:

> Attached is a patch to create a sdk style directory when
> --enable-java-home is passed to configure. The patch is basically a
> merge of java-gcj-compat into libgcj.
> 
> To have this work, at the minimum, pass the following to ./configure:
> --enable-java-home --with-arch-directory=(your arch).
> --with-arch-directory specifies what to use for the
> java-1.5.0-gcj-1.5.0.0/jre/lib/<arch> directory (e.g. I use i386).
> 
> I've only included the diff to configure.ac and Makefile.am since
> including the configure and Makefile.in makes the patch quite big, so be
> sure to autoconf && automake before trying this patch. I can upload the
> renerated files somewhere if it's absolutely needed, though.

This is OK, thanks.  Please don't post autogenerated files.

Andrew.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-12 20:56 [patch] Create sdk style directory on install Joshua Sumali
  2008-06-13 10:42 ` Andrew Haley
@ 2008-06-13 12:42 ` Matthias Klose
  2008-06-16 14:37   ` Joshua Sumali
  1 sibling, 1 reply; 18+ messages in thread
From: Matthias Klose @ 2008-06-13 12:42 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches, Thomas Fitzsimmons

Joshua Sumali schrieb:
> Hi,
> 
> Attached is a patch to create a sdk style directory when
> --enable-java-home is passed to configure. The patch is basically a
> merge of java-gcj-compat into libgcj.
> 
> To have this work, at the minimum, pass the following to ./configure:
> --enable-java-home --with-arch-directory=(your arch).
> --with-arch-directory specifies what to use for the
> java-1.5.0-gcj-1.5.0.0/jre/lib/<arch> directory (e.g. I use i386).
> 
> I've only included the diff to configure.ac and Makefile.am since
> including the configure and Makefile.in makes the patch quite big, so be
> sure to autoconf && automake before trying this patch. I can upload the
> renerated files somewhere if it's absolutely needed, though.

- please use `transform' to install the binaries; just using gcc_suffix is
  inconsistant with current installation. Same for using GIJ_VERSION.

- symlinks for man pages are not installed. intended?

- + for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns ...
  I think this is fedora specific to support jpackage?  It doesn't hurt
  to have these symlinks. Maybe the same should be added for IcedTea?

- Is the --with-arch-directory really needed? Shouldn't we just use the
  default.

+
jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+
sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}

why using the long version at all? afaik no packaging allows installation of two
such packages at the same time (with same jre_link and different jre_dir's). And
it makes it difficult for people writing into the ext subdirectory because this
changes across minor version upgrades.

- The new configure options should be documented in gcc/doc/install.texi
  (and maybe something about the jpackage compatible (?) layout).

- what is the rationale of --with-jvm-jar-dir ?

Matthias

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-13 12:42 ` Matthias Klose
@ 2008-06-16 14:37   ` Joshua Sumali
  2008-06-18 20:39     ` Joshua Sumali
  0 siblings, 1 reply; 18+ messages in thread
From: Joshua Sumali @ 2008-06-16 14:37 UTC (permalink / raw)
  To: java-patches; +Cc: Thomas Fitzsimmons

Matthias Klose wrote:
> Joshua Sumali schrieb:
>   
>> Hi,
>>
>> Attached is a patch to create a sdk style directory when
>> --enable-java-home is passed to configure. The patch is basically a
>> merge of java-gcj-compat into libgcj.
>>
>> To have this work, at the minimum, pass the following to ./configure:
>> --enable-java-home --with-arch-directory=(your arch).
>> --with-arch-directory specifies what to use for the
>> java-1.5.0-gcj-1.5.0.0/jre/lib/<arch> directory (e.g. I use i386).
>>
>> I've only included the diff to configure.ac and Makefile.am since
>> including the configure and Makefile.in makes the patch quite big, so be
>> sure to autoconf && automake before trying this patch. I can upload the
>> renerated files somewhere if it's absolutely needed, though.
>>     
>
> - please use `transform' to install the binaries; just using gcc_suffix is
>   inconsistant with current installation. Same for using GIJ_VERSION.
>   
I will look into this.
> - symlinks for man pages are not installed. intended?
>   
I don't think this was part of java-gcj-compat, so it is not included in 
my patch.
> - + for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns ...
>   I think this is fedora specific to support jpackage?  It doesn't hurt
>   to have these symlinks. Maybe the same should be added for IcedTea?
>
> - Is the --with-arch-directory really needed? Shouldn't we just use the
>   default.
>   
Yes, I believe this is necessary for different archs when building an 
rpm. I can't remember off the top of my head, but for x86 the directory 
is jre/lib/i386 and x86_64 is perhaps x86_64 or amd64. Anyways, the 
java-1.5.0-gcj spec file shows configure with 
"--with-arch-directory=%{_arch}".
> +
> jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
> +
> sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
> +  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
> +  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
>
> why using the long version at all? 
I can't provide an exact answer, as I have just merged what was in 
java-gcj-compat into this patch. Perhaps fitzsim could provide insight, 
but I think for Fedora at least, we use the long version (sdk_dir) for 
jvm installs.
> afaik no packaging allows installation of two
> such packages at the same time (with same jre_link and different jre_dir's). 
What do you mean by "same jre_link and different jre_dir" exactly?
> And
> it makes it difficult for people writing into the ext subdirectory because this
> changes across minor version upgrades
> - The new configure options should be documented in gcc/doc/install.texi
>   (and maybe something about the jpackage compatible (?) layout).
>   
Sure, I can do this.
> - what is the rationale of --with-jvm-jar-dir ?
>   
It's to provide some control as to where we're installing the jar 
symlinks. Default is /usr/lib/jvm-exports, but I'm not sure if this is 
consistent across all distros, so I think it's nice to have an option to 
change this location.
> Matthias
>   

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-16 14:37   ` Joshua Sumali
@ 2008-06-18 20:39     ` Joshua Sumali
  2008-06-19  9:54       ` Andrew Haley
  0 siblings, 1 reply; 18+ messages in thread
From: Joshua Sumali @ 2008-06-18 20:39 UTC (permalink / raw)
  To: java-patches; +Cc: Thomas Fitzsimmons

[-- Attachment #1: Type: text/plain, Size: 3972 bytes --]

Joshua Sumali wrote:
> Matthias Klose wrote:
>>
>> - please use `transform' to install the binaries; just using 
>> gcc_suffix is
>>   inconsistant with current installation. Same for using GIJ_VERSION.
>>   
> I will look into this.
>> - symlinks for man pages are not installed. intended?
>>   
> I don't think this was part of java-gcj-compat, so it is not included 
> in my patch.
>> - + for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns ...
>>   I think this is fedora specific to support jpackage?  It doesn't hurt
>>   to have these symlinks. Maybe the same should be added for IcedTea?
>>
>> - Is the --with-arch-directory really needed? Shouldn't we just use the
>>   default.
>>   
> Yes, I believe this is necessary for different archs when building an 
> rpm. I can't remember off the top of my head, but for x86 the 
> directory is jre/lib/i386 and x86_64 is perhaps x86_64 or amd64. 
> Anyways, the java-1.5.0-gcj spec file shows configure with 
> "--with-arch-directory=%{_arch}".
>> +
>> jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre 
>>
>> +
>> sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix} 
>>
>> +  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
>> +  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
>>
>> why using the long version at all? 
> I can't provide an exact answer, as I have just merged what was in 
> java-gcj-compat into this patch. Perhaps fitzsim could provide 
> insight, but I think for Fedora at least, we use the long version 
> (sdk_dir) for jvm installs.
>> afaik no packaging allows installation of two
>> such packages at the same time (with same jre_link and different 
>> jre_dir's). 
> What do you mean by "same jre_link and different jre_dir" exactly?
>> And
>> it makes it difficult for people writing into the ext subdirectory 
>> because this
>> changes across minor version upgrades
>> - The new configure options should be documented in gcc/doc/install.texi
>>   (and maybe something about the jpackage compatible (?) layout).
>>   
> Sure, I can do this.
>> - what is the rationale of --with-jvm-jar-dir ?
>>   
> It's to provide some control as to where we're installing the jar 
> symlinks. Default is /usr/lib/jvm-exports, but I'm not sure if this is 
> consistent across all distros, so I think it's nice to have an option 
> to change this location.
>> Matthias
>>   
>
Hi,

Please see the two (updated) patches. The updated patch for the 
"Packager files" thread is now part of the sdk-home patch attached here, 
since I had to modify configure.ac to generate those packager files this 
time around.

gcc-install-and-docs.patch creates man and info pages for aot-compile 
and rebuild-gcj-db, and also documents the new install options 
(--enable-java-home, --with-arch-directory, --with-python-dir) as 
requested by Matthias.
gcc-libjava-sdk-home-update.patch is mostly the same as the first patch 
I posted here, except with these main changes:

    - aot-compile and rebuild-gcj-db are now installed in $bindir
    - if --with-python-dir is not specified (say, in a regular upstream 
build) , classfile.py and aotcompile.py are installed in 
$(prefix)/share/python. Otherwise, those Python modules will be 
installed in the path specified with --with-python-dir. I modified 
aot-compile -> aot-compile.in to append whichever path classfile.py and 
aotcompile.py was installed in, so that it can actually find these 
modules (it wouldn't look in $(prefix)/share/python by default).
    - the SDK symlinked binaries, as well as aot-compile and 
rebuild-gcj-db are now `transformed' as requested by Matthias.

Outstanding issues:
1. @Matthias, I'm still not sure what you mean by "Same for using 
GIJ_VERSION". Also, the issue about "why using the long version at all?"
2. rebuild-gcj-db doesn't have a licence header on the top of the 
file... is this required? And if so, what's the right thing to do about it?

Josh

[-- Attachment #2: gcc-install-and-docs.patch --]
[-- Type: text/x-patch, Size: 8419 bytes --]

Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 136891)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,9 @@
+2008-06-18  Joshua Sumali  <jsumali@redhat.com>
+
+	* doc/install.texi (--enable-java-home): Document.
+	(--with-arch-directory): Likewise.
+	(--with-python-dir): Likewise.
+
 2008-06-16  Jan Hubicka  <jh@suse.cz>
 
 	* tree-outof-ssa.c (pass_out_of_ssa): Do not depend on PROP_alias.
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 136892)
+++ gcc/doc/install.texi	(working copy)
@@ -1602,6 +1602,20 @@
 @item --with-win32-nlsapi=ansi, unicows or unicode
 Indicates how MinGW @samp{libgcj} translates between UNICODE
 characters and the Win32 API@.
+
+@item --enable-java-home
+If enabled, this creates a JPackage compatible SDK environment during install.
+Note that if --enable-java-home is used, --with-arch-directory=ARCH must also
+be specified.
+
+@item --with-arch-directory=ARCH
+Specifies the name to use for the @file{jre/lib/ARCH} directory in the SDK 
+environment created when --enable-java-home is passed. Typical names for this 
+directory include i386, amd64, ia64, etc.
+
+@item --with-python-dir=DIR
+Specifies where to install the Python modules used for aot-compile.
+
 @table @code
 @item ansi
 Use the single-byte @code{char} and the Win32 A functions natively,
Index: gcc/java/ChangeLog
===================================================================
--- gcc/java/ChangeLog	(revision 136890)
+++ gcc/java/ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2008-06-18  Joshua Sumali  <jsumali@redhat.com>
+
+	* Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and
+	doc/rebuild-gcj-db.1
+	(java.uninstall): Likewise.
+	(java.maintainer-clean): Likewise.
+	(aot-compile.pod): New rule.
+	(rebuild-gcj-db.pod): New rule.
+	(java.install-man): Install doc/aot-compile.1 and doc/rebuild-gcj-db.1
+	* gcj.texi: Add new sections for aot-compile and rebuild-gcj-db.
+
 2008-06-15  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
 	* gcj.texi: Expand TABs, remove whitespace from blank lines.
Index: gcc/java/gcj.texi
===================================================================
--- gcc/java/gcj.texi	(revision 136890)
+++ gcc/java/gcj.texi	(working copy)
@@ -72,6 +72,11 @@
                             Generate stubs for Remote Method Invocation.
 * gc-analyze: (gcj)Invoking gc-analyze.
                             Analyze Garbage Collector (GC) memory dumps.
+* aot-compile: (gcj)Invoking aot-compile.
+                            Compile bytecode to native and generate databases.
+* rebuild-gcj-db: (gcj)Invoking rebuild-gcj-db.
+                            Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 @end direntry
 @end format
 
@@ -115,6 +120,9 @@
 * Invoking jv-convert:: Converting from one encoding to another
 * Invoking grmic::      Generate stubs for Remote Method Invocation.
 * Invoking gc-analyze:: Analyze Garbage Collector (GC) memory dumps.
+* Invoking aot-compile:: Compile bytecode to native and generate databases.
+* Invoking rebuild-gcj-db:: Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 * About CNI::           Description of the Compiled Native Interface
 * System properties::   Modifying runtime behavior of the libgcj library
 * Resources::           Where to look for more information
@@ -921,7 +929,7 @@
   [@option{-v}] [@option{-m}] [@option{--version}] [@option{--help}]
 
 @c man end
-@c man begin SEEALSO gij
+@c man begin SEEALSO gcj-dbtool
 gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
 and the Info entries for @file{gcj} and @file{gcc}.
 @c man end
@@ -1219,6 +1227,87 @@
 
 @c man end
 
+@node Invoking aot-compile
+@chapter Invoking aot-compile
+
+@c man title aot-compile Compile bytecode to native and generate databases
+
+@ignore
+
+@c man begin SYNOPSIS aot-compile
+aot-compile [@option{OPTION}] @dots{} @var{SRCDIR} @var{DSTDIR}
+
+aot-compile [@option{-M, --make}=@var{PATH}] [@option{-C, --gcj}=@var{PATH}]
+  [@option{-D, --dbtool}=@var{PATH}] [@option{-m, --makeflags}=@var{FLAGS}] 
+  [@option{-c, --gcjflags}=@var{FLAGS}] [@option{-l, --ldflags}=@var{FLAGS}] 
+  [@option{-e, --exclude}=@var{PATH}]
+@c man end
+
+@c man begin SEEALSO aot-compile
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION aot-compile
+@code{aot-compile} is a script that searches a directory for Java bytecode
+(as class files, or in jars) and uses @code{gcj} to compile it to native
+code and generate the databases from it.
+@c man end
+
+@c man begin OPTIONS aot-compile
+@table @gcctabopt
+@item -M, --make=@var{PATH}
+Specify the path to the @code{make} executable to use.
+
+@item -C, --gcj=@var{PATH}
+Specify the path to the @code{gcj} executable to use.
+
+@item -D, --dbtool=@var{PATH}
+Specify the path to the @code{gcj-dbtool} executable to use.
+
+@item -m, --makeflags=@var{FLAGS}
+Specify flags to pass to @code{make} during the build.
+
+@item -c, --gcjflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during compilation, in addition to
+'-fPIC -findirect-dispatch -fjni'.
+
+@item -l, --ldflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during linking, in addition to
+'-Wl,-Bsymbolic'.
+
+@item -e, --exclude=@var{PATH}
+Do not compile @var{PATH}.
+
+@end table
+
+@c man end
+
+@node Invoking rebuild-gcj-db
+@chapter Invoking rebuild-gcj-db
+
+@c man title rebuild-gcj-db Merge the per-solib databases made by aot-compile into one system-wide database.
+@ignore
+
+@c man begin SYNOPSIS rebuild-gcj-db
+rebuild-gcj-db
+@c man end
+
+@c man begin SEEALSO rebuild-gcj-db
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION rebuild-gcj-db
+@code{rebuild-gcj-db} is a script that merges the per-solib databases made by
+@code{aot-compile} into one system-wide database so @code{gij} can find the 
+solibs.
+@c man end
+
 @node About CNI
 @chapter About CNI
 
Index: gcc/java/Make-lang.in
===================================================================
--- gcc/java/Make-lang.in	(revision 136890)
+++ gcc/java/Make-lang.in	(working copy)
@@ -143,8 +143,9 @@
 java.html: $(build_htmldir)/java/index.html
 
 JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
-                doc/jv-convert.1 doc/grmic.1\
-		doc/gcj-dbtool.1 doc/gc-analyze.1
+                doc/jv-convert.1 doc/grmic.1 \
+                doc/gcj-dbtool.1 doc/gc-analyze.1 doc/aot-compile.1 \
+                doc/rebuild-gcj-db.1
 
 java.man: $(JAVA_MANFILES)
 
@@ -189,6 +190,8 @@
 	-rm -rf $(DESTDIR)$(man1dir)/gij$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/jv-convert$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/gcj-dbtool$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/aot-compile$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/rebuild-gcj-db$(man1ext)
 
 java.install-info: $(DESTDIR)$(infodir)/gcj.info
 
@@ -223,6 +226,8 @@
 	-rm -f $(docobjdir)/grmic.1
 	-rm -f $(docobjdir)/gcj-dbtool.1
 	-rm -f $(docobjdir)/gc-analyze.1
+	-rm -f $(docobjdir)/aot-compile.1
+	-rm -f $(docobjdir)/rebuild-gcj-db.1
 #\f
 # Stage hooks:
 # The main makefile has already created stage?/java.
@@ -353,15 +358,21 @@
 	-$(TEXI2POD) -D gcj-dbtool < $< > $@
 gc-analyze.pod: java/gcj.texi
 	-$(TEXI2POD) -D gc-analyze < $< > $@
+aot-compile.pod: java/gcj.texi
+	-$(TEXI2POD) -D aot-compile < $< > $@
+rebuild-gcj-db.pod: java/gcj.texi
+	-$(TEXI2POD) -D rebuild-gcj-db < $< > $@
 
 # Install the man pages.
 java.install-man: installdirs \
                   $(DESTDIR)$(man1dir)/$(JAVA_INSTALL_NAME)$(man1ext) \
 		  $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS:%=doc/%.1) \
 		  doc/gij.1 doc/jv-convert.1 doc/grmic.1 \
-		  doc/gcj-dbtool.1 doc/gc-analyze.1
+		  doc/gcj-dbtool.1 doc/gc-analyze.1 \
+		  doc/aot-compile.1 doc/rebuild-gcj-db.1
 	for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS) \
-		gij jv-convert grmic gcj-dbtool gc-analyze ; do \
+		gij jv-convert grmic gcj-dbtool gc-analyze aot-compile \
+		rebuild-gcj-db; do \
 	  tool_transformed_name=`echo $$tool|sed '$(program_transform_name)'`; \
 	  man_name=$(DESTDIR)$(man1dir)/$${tool_transformed_name}$(man1ext); \
 	  rm -f $$man_name ; \

[-- Attachment #3: gcc-libjava-sdk-home-update.patch --]
[-- Type: text/x-patch, Size: 46921 bytes --]

Index: libjava/contrib/rebuild-gcj-db.in
===================================================================
--- libjava/contrib/rebuild-gcj-db.in	(revision 0)
+++ libjava/contrib/rebuild-gcj-db.in	(revision 0)
@@ -0,0 +1,16 @@
+#!/bin/bash
+# rebuild-gcj-db
+
+# Rebuild all the standard databases.
+for base in /usr/lib*; do
+   dbLocation=`@prefix@/bin/gcj-dbtool@gcc_suffix@ -p $base`
+   libdir=$base/gcj
+   if ! test -d $libdir; then
+      # No shared libraries here.
+      continue
+   fi
+   dirname $dbLocation | xargs mkdir -p
+   @prefix@/bin/gcj-dbtool@gcc_suffix@ -n $dbLocation 64
+   find $libdir -follow -name '*.db' -print0 | \
+      xargs -0 @prefix@/bin/gcj-dbtool@gcc_suffix@ -m $dbLocation $dbLocation
+done
Index: libjava/contrib/aotcompile.py.in
===================================================================
--- libjava/contrib/aotcompile.py.in	(revision 0)
+++ libjava/contrib/aotcompile.py.in	(revision 0)
@@ -0,0 +1,412 @@
+# -*- python -*-
+
+## Copyright (C) 2005, 2006, 2008 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import classfile
+import copy
+import md5
+import operator
+import os
+import sys
+import cStringIO as StringIO
+import zipfile
+
+PATHS = {"make":   "@MAKE@",
+         "gcj":    "@prefix@/bin/gcj@gcc_suffix@",
+         "dbtool": "@prefix@/bin/gcj-dbtool@gcc_suffix@"}
+
+MAKEFLAGS = []
+GCJFLAGS = ["-fPIC", "-findirect-dispatch", "-fjni"]
+LDFLAGS = ["-Wl,-Bsymbolic"]
+
+MAX_CLASSES_PER_JAR = 1024
+MAX_BYTES_PER_JAR = 1048576
+
+MAKEFILE = "Makefile"
+
+MAKEFILE_HEADER = '''\
+GCJ = %(gcj)s
+DBTOOL = %(dbtool)s
+GCJFLAGS = %(gcjflags)s
+LDFLAGS = %(ldflags)s
+
+%%.o: %%.jar
+	$(GCJ) -c $(GCJFLAGS) $< -o $@
+
+TARGETS = \\
+%(targets)s
+
+all: $(TARGETS)'''
+
+MAKEFILE_JOB = '''
+%(base)s_SOURCES = \\
+%(jars)s
+
+%(base)s_OBJECTS = \\
+$(%(base)s_SOURCES:.jar=.o)
+
+%(dso)s: $(%(base)s_OBJECTS)
+	$(GCJ) -shared $(GCJFLAGS) $(LDFLAGS) $^ -o $@
+
+%(db)s: $(%(base)s_SOURCES)
+	$(DBTOOL) -n $@ 64
+	for jar in $^; do \\
+            $(DBTOOL) -f $@ $$jar \\
+                %(libdir)s/%(dso)s; \\
+        done'''
+
+ZIPMAGIC, CLASSMAGIC = "PK\x03\x04", "\xca\xfe\xba\xbe"
+
+class Error(Exception):
+    pass
+
+class Compiler:
+    def __init__(self, srcdir, libdir, prefix = None):
+        self.srcdir = os.path.abspath(srcdir)
+        self.libdir = os.path.abspath(libdir)
+        if prefix is None:
+            self.dstdir = self.libdir
+        else:
+            self.dstdir = os.path.join(prefix, self.libdir.lstrip(os.sep))
+
+        # Calling code may modify these parameters
+        self.gcjflags = copy.copy(GCJFLAGS)
+        self.ldflags = copy.copy(LDFLAGS)
+        self.makeflags = copy.copy(MAKEFLAGS)
+        self.exclusions = []
+
+    def compile(self):
+        """Search srcdir for classes and jarfiles, then generate
+        solibs and mappings databases for them all in libdir."""
+        if not os.path.isdir(self.dstdir):
+            os.makedirs(self.dstdir)
+        oldcwd = os.getcwd()
+        os.chdir(self.dstdir)
+        try:            
+            jobs = self.getJobList()
+            if not jobs:
+                raise Error, "nothing to do"
+            self.writeMakefile(MAKEFILE, jobs)
+            for job in jobs:
+                job.writeJars()
+            system([PATHS["make"]] + self.makeflags)
+            for job in jobs:
+                job.clean()
+            os.unlink(MAKEFILE)
+        finally:
+            os.chdir(oldcwd)
+
+    def getJobList(self):
+        """Return all jarfiles and class collections in srcdir."""
+        jobs = weed_jobs(find_jobs(self.srcdir, self.exclusions))
+        set_basenames(jobs)
+        return jobs
+
+    def writeMakefile(self, path, jobs):
+        """Generate a makefile to build the solibs and mappings
+        databases for the specified list of jobs."""
+        fp = open(path, "w")
+        print >>fp, MAKEFILE_HEADER % {
+            "gcj": PATHS["gcj"],
+            "dbtool": PATHS["dbtool"],
+            "gcjflags": " ".join(self.gcjflags),
+            "ldflags": " ".join(self.ldflags),
+            "targets": " \\\n".join(reduce(operator.add, [
+                (job.dsoName(), job.dbName()) for job in jobs]))}
+        for job in jobs:
+            values = job.ruleArguments()
+            values["libdir"] = self.libdir
+            print >>fp, MAKEFILE_JOB % values
+        fp.close()
+
+def find_jobs(dir, exclusions = ()):
+    """Scan a directory and find things to compile: jarfiles (zips,
+    wars, ears, rars, etc: we go by magic rather than file extension)
+    and directories of classes."""
+    def visit((classes, zips), dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            magic = open(path, "r").read(4)
+            if magic == ZIPMAGIC:
+                zips.append(path)
+            elif magic == CLASSMAGIC:
+                classes.append(path)
+    classes, paths = [], []
+    os.path.walk(dir, visit, (classes, paths))
+    # Convert the list of classes into a list of directories
+    while classes:
+        # XXX this requires the class to be correctly located in its heirachy.
+        path = classes[0][:-len(os.sep + classname(classes[0]) + ".class")]
+        paths.append(path)
+        classes = [cls for cls in classes if not cls.startswith(path)]
+    # Handle exclusions.  We're really strict about them because the
+    # option is temporary in aot-compile-rpm and dead options left in
+    # specfiles will hinder its removal.
+    for path in exclusions:
+        if path in paths:
+            paths.remove(path)
+        else:
+            raise Error, "%s: path does not exist or is not a job" % path
+    # Build the list of jobs
+    jobs = []
+    paths.sort()
+    for path in paths:
+        if os.path.isfile(path):
+            job = JarJob(path)
+        else:
+            job = DirJob(path)
+        if len(job.classes):
+            jobs.append(job)
+    return jobs
+
+class Job:
+    """A collection of classes that will be compiled as a unit."""
+    
+    def __init__(self, path):
+        self.path, self.classes, self.blocks = path, {}, None
+
+    def addClass(self, bytes):
+        """Subclasses call this from their __init__ method for
+        every class they find."""
+        self.classes[md5.new(bytes).digest()] = bytes
+
+    def __makeBlocks(self):
+        """Split self.classes into chunks that can be compiled to
+        native code by gcj.  In the majority of cases this is not
+        necessary -- the job will have come from a jarfile which will
+        be equivalent to the one we generate -- but this only happens
+        _if_ the job was a jarfile and _if_ the jarfile isn't too big
+        and _if_ the jarfile has the correct extension and _if_ all
+        classes are correctly named and _if_ the jarfile has no
+        embedded jarfiles.  Fitting a special case around all these
+        conditions is tricky to say the least.
+
+        Note that this could be called at the end of each subclass's
+        __init__ method.  The reason this is not done is because we
+        need to parse every class file.  This is slow, and unnecessary
+        if the job is subsetted."""
+        names = {}
+        for hash, bytes in self.classes.items():
+            name = classname(bytes)
+            if not names.has_key(name):
+                names[name] = []
+            names[name].append(hash)
+        names = names.items()
+        # We have to sort somehow, or the jars we generate 
+        # We sort by name in a simplistic attempt to keep related
+        # classes together so inter-class optimisation can happen.
+        names.sort()
+        self.blocks, bytes = [[]], 0
+        for name, hashes in names:
+            for hash in hashes:
+                if len(self.blocks[-1]) >= MAX_CLASSES_PER_JAR \
+                   or bytes >= MAX_BYTES_PER_JAR:
+                    self.blocks.append([])
+                    bytes = 0
+                self.blocks[-1].append((name, hash))
+                bytes += len(self.classes[hash])
+
+    # From Archit Shah:
+    #   The implementation and the documentation don't seem to match.
+    #  
+    #    [a, b].isSubsetOf([a]) => True
+    #  
+    #   Identical copies of all classes this collection do not exist
+    #   in the other. I think the method should be named isSupersetOf
+    #   and the documentation should swap uses of "this" and "other"
+    #
+    # XXX think about this when I've had more sleep...
+    def isSubsetOf(self, other):
+        """Returns True if identical copies of all classes in this
+        collection exist in the other."""
+        for item in other.classes.keys():
+            if not self.classes.has_key(item):
+                return False
+        return True
+
+    def __targetName(self, ext):
+        return self.basename + ext
+
+    def tempJarName(self, num):
+        return self.__targetName(".%d.jar" % (num + 1))
+
+    def tempObjName(self, num):
+        return self.__targetName(".%d.o" % (num + 1))
+
+    def dsoName(self):
+        """Return the filename of the shared library that will be
+        built from this job."""
+        return self.__targetName(".so")
+
+    def dbName(self):
+        """Return the filename of the mapping database that will be
+        built from this job."""
+        return self.__targetName(".db")
+
+    def ruleArguments(self):
+        """Return a dictionary of values that when substituted
+        into MAKEFILE_JOB will create the rules required to build
+        the shared library and mapping database for this job."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        return {
+            "base": "".join(
+                [c.isalnum() and c or "_" for c in self.dsoName()]),
+            "jars": " \\\n".join(
+                [self.tempJarName(i) for i in xrange(len(self.blocks))]),
+            "dso": self.dsoName(),
+            "db": self.dbName()}
+
+    def writeJars(self):
+        """Generate jarfiles that can be native compiled by gcj."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for block, i in zip(self.blocks, xrange(len(self.blocks))):
+            jar = zipfile.ZipFile(self.tempJarName(i), "w", zipfile.ZIP_STORED)
+            for name, hash in block:
+                jar.writestr(
+                    zipfile.ZipInfo("%s.class" % name), self.classes[hash])
+            jar.close()
+
+    def clean(self):
+        """Delete all temporary files created during this job's build."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for i in xrange(len(self.blocks)):
+            os.unlink(self.tempJarName(i))
+            os.unlink(self.tempObjName(i))
+
+class JarJob(Job):
+    """A Job whose origin was a jarfile."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        self._walk(zipfile.ZipFile(path, "r"))
+
+    def _walk(self, zf):
+        for name in zf.namelist():
+            bytes = zf.read(name)
+            if bytes.startswith(ZIPMAGIC):
+                self._walk(zipfile.ZipFile(StringIO.StringIO(bytes)))
+            elif bytes.startswith(CLASSMAGIC):
+                self.addClass(bytes)
+
+class DirJob(Job):
+    """A Job whose origin was a directory of classfiles."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        os.path.walk(path, DirJob._visit, self)
+
+    def _visit(self, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            fp = open(path, "r")
+            magic = fp.read(4)
+            if magic == CLASSMAGIC:
+                self.addClass(magic + fp.read())
+    
+def weed_jobs(jobs):
+    """Remove any jarfiles that are completely contained within
+    another.  This is more common than you'd think, and we only
+    need one nativified copy of each class after all."""
+    jobs = copy.copy(jobs)
+    while True:
+        for job1 in jobs:
+            for job2 in jobs:
+                if job1 is job2:
+                    continue
+                if job1.isSubsetOf(job2):
+                    msg = "subsetted %s" % job2.path
+                    if job2.isSubsetOf(job1):
+                        if (isinstance(job1, DirJob) and
+                            isinstance(job2, JarJob)):
+                            # In the braindead case where a package
+                            # contains an expanded copy of a jarfile
+                            # the jarfile takes precedence.
+                            continue
+                        msg += " (identical)"
+                    warn(msg)
+                    jobs.remove(job2)
+                    break
+            else:
+                continue
+            break
+        else:
+            break
+        continue
+    return jobs
+
+def set_basenames(jobs):
+    """Ensure that each jarfile has a different basename."""
+    names = {}
+    for job in jobs:
+        name = os.path.basename(job.path)
+        if not names.has_key(name):
+            names[name] = []
+        names[name].append(job)
+    for name, set in names.items():
+        if len(set) == 1:
+            set[0].basename = name
+            continue
+        # prefix the jar filenames to make them unique
+        # XXX will not work in most cases -- needs generalising
+        set = [(job.path.split(os.sep), job) for job in set]
+        minlen = min([len(bits) for bits, job in set])
+        set = [(bits[-minlen:], job) for bits, job in set]
+        bits = apply(zip, [bits for bits, job in set])
+        while True:
+            row = bits[-2]
+            for bit in row[1:]:
+                if bit != row[0]:
+                    break
+            else:
+                del bits[-2]
+                continue
+            break
+        set = zip(
+            ["_".join(name) for name in apply(zip, bits[-2:])],
+            [job for bits, job in set])
+        for name, job in set:
+            warn("building %s as %s" % (job.path, name))
+            job.basename = name
+    # XXX keep this check until we're properly general
+    names = {}
+    for job in jobs:
+        name = job.basename
+        if names.has_key(name):
+            raise Error, "%s: duplicate jobname" % name
+        names[name] = 1
+
+def system(command):
+    """Execute a command."""
+    status = os.spawnv(os.P_WAIT, command[0], command)
+    if status > 0:
+        raise Error, "%s exited with code %d" % (command[0], status)
+    elif status < 0:
+        raise Error, "%s killed by signal %d" % (command[0], -status)
+
+def warn(msg):
+    """Print a warning message."""
+    print >>sys.stderr, "%s: warning: %s" % (
+        os.path.basename(sys.argv[0]), msg)
+
+def classname(bytes):
+    """Extract the class name from the bytes of a class file."""
+    klass = classfile.Class(bytes)
+    return klass.constants[klass.constants[klass.name][1]][1]
Index: libjava/contrib/aot-compile-rpm.in
===================================================================
--- libjava/contrib/aot-compile-rpm.in	(revision 0)
+++ libjava/contrib/aot-compile-rpm.in	(revision 0)
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir@")
+import aotcompile
+import os
+
+def libdir():
+    cmd = "%s -p" % aotcompile.PATHS["dbtool"]
+    dir = os.path.abspath(os.popen(cmd, "r").readline().rstrip())
+    dir, base = os.path.split(dir)
+    if base != "classmap.db":
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    dir, base = os.path.split(dir)
+    if not base.startswith("gcj-"):
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    return dir
+
+def writeSourceList(srcdir, dstpath):
+    def visit(fp, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.isfile(path):
+                print >>fp, path
+    dstdir = os.path.dirname(dstpath)
+    if not os.path.isdir(dstdir):
+        os.makedirs(dstdir)
+    os.path.walk(srcdir, visit, open(dstpath, "w"))
+
+def copy(srcdir, dstdir, suffix):
+    srcdir = os.path.join(srcdir, suffix.lstrip(os.sep))
+    dstdir = os.path.join(dstdir, suffix.lstrip(os.sep))
+    os.makedirs(os.path.dirname(dstdir))
+    aotcompile.system(("/bin/cp", "-a", srcdir, dstdir))
+
+try:
+    name = os.environ.get("RPM_PACKAGE_NAME")
+    if name is None:
+        raise aotcompile.Error, "not for use outside rpm specfiles"
+    arch = os.environ.get("RPM_ARCH")
+    if arch == "noarch":
+        raise aotcompile.Error, "cannot be used on noarch packages"
+    srcdir = os.environ.get("RPM_BUILD_ROOT")
+    if srcdir in (None, "/"):
+        raise aotcompile.Error, "bad $RPM_BUILD_ROOT"
+    tmpdir = os.path.join(os.getcwd(), "aot-compile-rpm")
+    if os.path.exists(tmpdir):
+        raise aotcompile.Error, "%s exists" % tmpdir
+    dstdir = os.path.join(libdir(), "gcj", name)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir, tmpdir)
+    compiler.gcjflags[0:0] = os.environ.get("RPM_OPT_FLAGS", "").split() 
+
+    # XXX: This script should not accept options, because having
+    # them it cannot be integrated into rpm.  But, gcj cannot
+    # build each and every jarfile yet, so we must be able to
+    # exclude until it can.
+    # XXX --exclude is also used in the jonas rpm to stop
+    # everything being made a subset of the mammoth client
+    # jarfile. Should adjust the subset checker's bias to
+    # favour many small jarfiles over one big one.
+    try:
+        options, exclusions = sys.argv[1:], []
+        while options:
+            if options.pop(0) != "--exclude":
+                raise ValueError
+            compiler.exclusions.append(
+                os.path.join(srcdir, options.pop(0).lstrip(os.sep)))
+    except:
+        print >>sys.stderr, "usage: %s [--exclude PATH]..." % (
+            os.path.basename(sys.argv[0]))
+        sys.exit(1)
+
+    sourcelist = os.path.join(tmpdir, "sources.list")
+    writeSourceList(os.getcwd(), sourcelist)
+    compiler.gcjflags.append("-fsource-filename=" + sourcelist)
+
+    compiler.compile()
+    copy(tmpdir, srcdir, dstdir)
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/contrib/classfile.py
===================================================================
--- libjava/contrib/classfile.py	(revision 0)
+++ libjava/contrib/classfile.py	(revision 0)
@@ -0,0 +1,221 @@
+## Copyright (C) 2004, 2005 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+"""Read Java(TM) class files."""
+
+import cStringIO as StringIO
+import struct
+
+class Class:
+    def __init__(self, arg):
+        if hasattr(arg, "read"):
+            self.fp = arg
+        elif type(arg) == type(""):
+            if arg.startswith("\xca\xfe\xba\xbe"):
+                self.fp = StringIO.StringIO(arg)
+            else:
+                self.fp = open(arg, "r")
+        else:
+            raise TypeError, type(arg)
+
+        magic = self._read_int()
+        assert magic == 0xcafebabeL
+        minor, major = self._read(">HH")        
+        self.version = (major, minor)
+
+        self.pool_integrity_checks = None
+        try:
+            assert False
+        except AssertionError:
+            self.pool_integrity_checks = []
+
+        self._read_constants_pool()
+
+        self.access_flags = self._read_short()
+        self.name = self._read_reference_Class()
+        self.super = self._read_reference_Class()
+
+        self.interfaces = self._read_interfaces()
+        self.fields = self._read_fieldsormethods()
+        self.methods = self._read_fieldsormethods()
+        self.attributes = self._read_attributes()
+
+        if self.pool_integrity_checks is not None:
+            for index, tag in self.pool_integrity_checks:
+                assert self.constants[index][0] == tag
+
+        del self.fp, self.pool_integrity_checks
+
+    def __repr__(self):
+        result = []
+        attrs = [attr for attr in dir(self)
+                 if not attr.startswith("_") and attr != "Member"]
+        attrs.sort()
+        for attr in attrs:
+            result.append("%-13s %s" % (
+                attr + ":", attr == "constants" and
+                "<ELIDED>" or repr(getattr(self, attr))))
+        return "\n".join(result)
+
+    def _read_constants_pool(self):
+        self.constants = {}
+        skip = False
+        for i in xrange(1, self._read_short()):
+            if skip:
+                skip = False
+                continue
+            tag = {
+                1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
+                6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
+                10: "Methodref", 11: "InterfaceMethodref",
+                12: "NameAndType"}[self._read_byte()]
+            skip = tag in ("Long", "Double") # crack crack crack!
+            self.constants[i] = (tag, getattr(self, "_read_constant_" + tag)())
+
+    def _read_interfaces(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self._read_reference_Class())
+        return result
+
+    def _read_fieldsormethods(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self.Member(self))
+        return result
+
+    class Member:
+        def __init__(self, source):
+            self.access_flags = source._read_short()
+            self.name = source._read_reference_Utf8()
+            self.descriptor = source._read_reference_Utf8()
+            self.attributes = source._read_attributes()
+
+        def __repr__(self):
+            result = []
+            attrs = [attr for attr in dir(self) if not attr.startswith("_")]
+            attrs.sort()
+            for attr in attrs:
+                value = getattr(self, attr)
+                if attr == "attributes" and value.has_key("Code"):
+                    value = value.copy()
+                    value.update({"Code": "<ELIDED>"})
+                result.append("%-13s %s" % (
+                    attr + ":", repr(value).replace(
+                        "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
+            return ("\n%s" % (15 * " ")).join(result)
+
+    def _read_attributes(self):
+        result = {}
+        for i in xrange(self._read_short()):
+            name = self._read_reference_Utf8()
+            data = self.fp.read(self._read_int())
+            assert not result.has_key(name)
+            result[name] = data
+        return result
+
+    # Constants pool reference reader convenience functions
+
+    def _read_reference_Utf8(self):
+        return self._read_references("Utf8")[0]
+
+    def _read_reference_Class(self):
+        return self._read_references("Class")[0]
+
+    def _read_reference_Class_NameAndType(self):
+        return self._read_references("Class", "NameAndType")
+
+    def _read_references(self, *args):
+        result = []
+        for arg in args:
+            index = self._read_short()
+            if self.pool_integrity_checks is not None:
+                self.pool_integrity_checks.append((index, arg))
+            result.append(index)
+        return result
+
+    # Constants pool constant reader functions
+
+    def _read_constant_Utf8(self):
+        constant = self.fp.read(self._read_short())
+        try:
+            constant = constant.decode("utf-8")
+        except UnicodeError:
+            constant = _bork_utf8_decode(constant)
+        try:
+            constant = constant.encode("us-ascii")
+        except UnicodeError:
+            pass
+        return constant
+
+    def _read_constant_Integer(self):
+        return self._read_int()
+
+    def _read_constant_Float(self):
+        return self._read(">f")[0]
+
+    def _read_constant_Long(self):
+        return self._read(">q")[0]
+
+    def _read_constant_Double(self):
+        return self._read(">d")[0]
+
+    _read_constant_Class = _read_reference_Utf8
+    _read_constant_String = _read_reference_Utf8
+    _read_constant_Fieldref = _read_reference_Class_NameAndType
+    _read_constant_Methodref = _read_reference_Class_NameAndType
+    _read_constant_InterfaceMethodref = _read_reference_Class_NameAndType
+
+    def _read_constant_NameAndType(self):
+        return self._read_reference_Utf8(), self._read_reference_Utf8()
+
+    # Generic reader functions
+
+    def _read_int(self):
+        # XXX how else to read 32 bits on a 64-bit box?
+        h, l = map(long, self._read(">HH"))
+        return (h << 16) + l
+
+    def _read_short(self):
+        return self._read(">H")[0]
+
+    def _read_byte(self):
+        return self._read("B")[0]
+
+    def _read(self, fmt):
+        return struct.unpack(fmt, self.fp.read(struct.calcsize(fmt)))
+
+def _bork_utf8_decode(data):
+    # more crack!
+    bytes, unicode = map(ord, data), ""
+    while bytes:
+        b1 = bytes.pop(0)
+        if b1 & 0x80:
+            assert b1 & 0x40
+            b2 = bytes.pop(0)
+            assert b2 & 0xC0 == 0x80
+            if b1 & 0x20:
+                assert not b1 & 0x10
+                b3 = bytes.pop(0)
+                assert b3 & 0xC0 == 0x80
+                unicode += unichr(
+                    ((b1 & 0x0f) << 12) + ((b2 & 0x3f) << 6) + (b3 & 0x3f))
+            else:
+                unicode += unichr(((b1 & 0x1f) << 6) + (b2 & 0x3f))
+        else:
+            unicode += unichr(b1)
+    return unicode
+
+if __name__ == "__main__":
+    print Class("/usr/share/katana/build/ListDependentClasses.class")
+
Index: libjava/contrib/aot-compile.in
===================================================================
--- libjava/contrib/aot-compile.in	(revision 0)
+++ libjava/contrib/aot-compile.in	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2006 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir@")
+import aotcompile
+import getopt
+import os
+
+usage = """\
+Usage: %s [OPTION...] SRCDIR DSTDIR
+AOT-compile all Java bytecode in SRCDIR into DSTDIR.
+
+Options:
+  -M, --make=PATH        make executable to use (%s)
+  -C, --gcj=PATH         gcj executable to use (%s)
+  -D, --dbtool=PATH      gcj-dbtool executable to use (%s)
+  -m, --makeflags=FLAGS  flags to pass to make during build
+  -c, --gcjflags=FLAGS   flags to pass to gcj during compilation
+                           in addition to %s
+  -l, --ldflags=FLAGS    flags to pass to gcj during linking
+                           in addition to %s
+  -e, --exclude=PATH     do not compile PATH
+
+Extra flags may also be passed using the AOT_MAKEFLAGS, AOT_GCJFLAGS
+and AOT_LDFLAGS environment variables.""" % (
+    os.path.basename(sys.argv[0]),
+    aotcompile.PATHS["make"],
+    aotcompile.PATHS["gcj"],
+    aotcompile.PATHS["dbtool"],
+    repr(" ".join(aotcompile.GCJFLAGS)),
+    repr(" ".join(aotcompile.LDFLAGS)))
+
+try:
+    if os.environ.has_key("RPM_PACKAGE_NAME"):
+        raise aotcompile.Error, "not for use within rpm specfiles"
+
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            "M:C:D:m:c:l:e:",
+            ["make=", "gcj=", "dbtool=",
+             "makeflags=" "gcjflags=", "ldflags=",
+             "exclude="])
+        srcdir, dstdir = args
+    except:
+        print >>sys.stderr, usage
+        sys.exit(1)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir)
+    for o, a in opts:
+        if o in ("-M", "--make"):
+            aotcompile.PATHS["make"] = a
+        if o in ("-C", "--gcj"):
+            aotcompile.PATHS["gcj"] = a
+        if o in ("-D", "--dbtool"):
+            aotcompile.PATHS["dbtool"] = a
+        if o in ("-m", "--makeflags"):
+            compiler.makeflags[0:0] = a.split()
+        if o in ("-c", "--gcjflags"):
+            compiler.gcjflags[0:0] = a.split()
+        if o in ("-l", "--ldflags"):
+            compiler.ldflags[0:0] = a.split()
+        if o in ("-e", "--exclude"):
+            compiler.exclusions.append(a)
+    
+    compiler.makeflags[0:0] = os.environ.get("AOT_MAKEFLAGS", "").split() 
+    compiler.gcjflags[0:0] = os.environ.get("AOT_GCJFLAGS", "").split() 
+    compiler.ldflags[0:0] = os.environ.get("AOT_LDFLAGS", "").split() 
+
+    compiler.compile()
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/ChangeLog
===================================================================
--- libjava/ChangeLog	(revision 136894)
+++ libjava/ChangeLog	(working copy)
@@ -1,3 +1,29 @@
+2008-06-18  Joshua Sumali  <jsumali@redhat.com>
+
+	* configure.ac (java-home): new AC_ARG_ENABLE.
+	(CREATE_JAVA_HOME): new AM_CONDITIONAL.
+	(gcc-suffix): new AC_ARG_WITH.
+	(arch-directory): Likewise.
+	(os-directory): Likewise.
+	(origin-name): Likewise.
+	(arch-suffix): Likewise.
+	(jvm-root-dir): Likewise.
+	(jvm-jar-dir): Likewise.
+	(python-dir): Likewise.
+	(AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
+	contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
+	* Makefile.am (install-data-local): Install Python modules for
+	aot-compile. Also install an sdk style directory if	--enable-java-home
+	is passed to configure.
+	(bin_SCRIPTS): add contrib/rebuild-gcj-db and contrib/aot-compile.
+	* contrib/aot-compile.in: New file.
+	* contrib/aotcompile.py.in: Likewise.
+	* contrib/aot-compile-rpm.in: Likewise.
+	* contrib/classfile.py: Likewise.
+	* contrib/rebuild-gcj-db.in: Likewise.
+	* configure: Regenerate.
+	* Makefile.in: Regenerate.
+
 2008-06-17  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
 	* configure: Regenerate.
Index: libjava/Makefile.am
===================================================================
--- libjava/Makefile.am	(revision 136724)
+++ libjava/Makefile.am	(working copy)
@@ -85,9 +85,9 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
-endif
+endif 
 
-bin_SCRIPTS = addr2name.awk
+bin_SCRIPTS = addr2name.awk contrib/rebuild-gcj-db contrib/aot-compile
 
 if BUILD_ECJ1
 ## We build ecjx and not ecj1 because in one mode, ecjx will not work
@@ -528,8 +528,153 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
+## Install Python modules for aot-compile.
+	$(mkinstalldirs) $(DESTDIR)$(python_mod_dir); \
+	$(INSTALL_DATA) $(srcdir)/contrib/classfile.py \
+	  $(DESTDIR)$(python_mod_dir)/classfile.py; \
+	$(INSTALL_DATA) contrib/aotcompile.py \
+	  $(DESTDIR)$(python_mod_dir)/aotcompile.py;
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/`echo grmic | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/`echo gjavah | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/`echo gappletviewer | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/`echo gjarsigner | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo gnative2ascii | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/`echo gserialver | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $(DESTDIR)$(JVM_ROOT_DIR); \
+	  ln -s $(JRE_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $(DESTDIR)$(JVM_JAR_ROOT_DIR); \
+	  ln -s $(SDK_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	GIJ_VERSION=$$($(DESTDIR)$(bindir)/gij --version | head -n2 | tail -n1 \
+	  | awk '{print $$5}'); \
+	ln -sf $$RELATIVE/libgcj-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	if [ -f $$RELATIVE/libjawt.so ]; then \
+	  ln -sf $$RELATIVE/libjawt.so \
+	    $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	fi; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	if [ -f $$RELATIVE/src-$$GIJ_VERSION.zip ]; then \
+	  ln -sf $$RELATIVE/src-$$GIJ_VERSION.zip \
+	    $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip; \
+	fi;
+endif
 
-
 ## ################################################################
 
 ##
Index: libjava/configure.ac
===================================================================
--- libjava/configure.ac	(revision 136724)
+++ libjava/configure.ac	(working copy)
@@ -1625,6 +1625,206 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)
 
+AC_ARG_WITH([python-dir],
+            AS_HELP_STRING([--with-python-dir],
+                           [the location to install Python modules]),
+            [with_python_dir=$withval], [with_python_dir=""])
+
+if test "x${with_python_dir}" = "x"
+then
+  if test "x${prefix}" = "xNONE"
+  then
+    python_mod_dir=/usr/share/python
+  else
+    python_mod_dir=${prefix}/share/python
+  fi
+else
+  python_mod_dir=$with_python_dir
+fi
+AC_MSG_RESULT(Python modules dir: ${python_mod_dir});
+AC_SUBST(python_mod_dir)
+
+# needed for aot-compile-rpm
+MAKE=`which make`
+AC_SUBST(MAKE)
+
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  if test "x${prefix}" = "xNONE"
+  then
+    sdk_prefix=/usr
+  else
+    sdk_prefix=$prefix
+  fi
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${sdk_prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir=${sdk_prefix}/lib/jvm])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${sdk_prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=${sdk_prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
+  AC_SUBST(JAVA_HOME_DIR)
+  AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$sdk_prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc
@@ -1633,6 +1833,10 @@
 gcj/Makefile
 include/Makefile
 testsuite/Makefile
+contrib/aotcompile.py
+contrib/aot-compile
+contrib/aot-compile-rpm
+contrib/rebuild-gcj-db
 ])
 
 if test ${multilib} = yes; then

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-18 20:39     ` Joshua Sumali
@ 2008-06-19  9:54       ` Andrew Haley
  2008-06-19 14:24         ` Joshua Sumali
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Haley @ 2008-06-19  9:54 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches, Thomas Fitzsimmons

Joshua Sumali wrote:

> 
> Please see the two (updated) patches. The updated patch for the
> "Packager files" thread is now part of the sdk-home patch attached here,
> since I had to modify configure.ac to generate those packager files this
> time around.
> 
> gcc-install-and-docs.patch creates man and info pages for aot-compile
> and rebuild-gcj-db, and also documents the new install options
> (--enable-java-home, --with-arch-directory, --with-python-dir) as
> requested by Matthias.
> gcc-libjava-sdk-home-update.patch is mostly the same as the first patch
> I posted here, except with these main changes:
> 
>    - aot-compile and rebuild-gcj-db are now installed in $bindir
>    - if --with-python-dir is not specified (say, in a regular upstream
> build) , classfile.py and aotcompile.py are installed in
> $(prefix)/share/python. Otherwise, those Python modules will be
> installed in the path specified with --with-python-dir. I modified
> aot-compile -> aot-compile.in to append whichever path classfile.py and
> aotcompile.py was installed in, so that it can actually find these
> modules (it wouldn't look in $(prefix)/share/python by default).
>    - the SDK symlinked binaries, as well as aot-compile and
> rebuild-gcj-db are now `transformed' as requested by Matthias.

OK, thanks.

> Outstanding issues:
> 1. @Matthias, I'm still not sure what you mean by "Same for using
> GIJ_VERSION". Also, the issue about "why using the long version at all?"
> 2. rebuild-gcj-db doesn't have a licence header on the top of the
> file... is this required? And if so, what's the right thing to do about it?

Make it GPL.

Andrew.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-19  9:54       ` Andrew Haley
@ 2008-06-19 14:24         ` Joshua Sumali
  2008-06-20  4:13           ` Joshua Sumali
  2008-06-26 18:18           ` Joshua Sumali
  0 siblings, 2 replies; 18+ messages in thread
From: Joshua Sumali @ 2008-06-19 14:24 UTC (permalink / raw)
  To: java-patches; +Cc: Thomas Fitzsimmons

[-- Attachment #1: Type: text/plain, Size: 1770 bytes --]

Andrew Haley wrote:
> Joshua Sumali wrote:
>
>   
>> Please see the two (updated) patches. The updated patch for the
>> "Packager files" thread is now part of the sdk-home patch attached here,
>> since I had to modify configure.ac to generate those packager files this
>> time around.
>>
>> gcc-install-and-docs.patch creates man and info pages for aot-compile
>> and rebuild-gcj-db, and also documents the new install options
>> (--enable-java-home, --with-arch-directory, --with-python-dir) as
>> requested by Matthias.
>> gcc-libjava-sdk-home-update.patch is mostly the same as the first patch
>> I posted here, except with these main changes:
>>
>>    - aot-compile and rebuild-gcj-db are now installed in $bindir
>>    - if --with-python-dir is not specified (say, in a regular upstream
>> build) , classfile.py and aotcompile.py are installed in
>> $(prefix)/share/python. Otherwise, those Python modules will be
>> installed in the path specified with --with-python-dir. I modified
>> aot-compile -> aot-compile.in to append whichever path classfile.py and
>> aotcompile.py was installed in, so that it can actually find these
>> modules (it wouldn't look in $(prefix)/share/python by default).
>>    - the SDK symlinked binaries, as well as aot-compile and
>> rebuild-gcj-db are now `transformed' as requested by Matthias.
>>     
>
> OK, thanks.
>
>   
>> Outstanding issues:
>> 1. @Matthias, I'm still not sure what you mean by "Same for using
>> GIJ_VERSION". Also, the issue about "why using the long version at all?"
>> 2. rebuild-gcj-db doesn't have a licence header on the top of the
>> file... is this required? And if so, what's the right thing to do about it?
>>     
>
> Make it GPL.
>
> Andrew.
>   
Updated rebuild-gcj-db with license header.

Josh

[-- Attachment #2: gcc-libjava-sdk-home-update2.patch --]
[-- Type: text/x-patch, Size: 47181 bytes --]

Index: libjava/contrib/rebuild-gcj-db.in
===================================================================
--- libjava/contrib/rebuild-gcj-db.in	(revision 0)
+++ libjava/contrib/rebuild-gcj-db.in	(revision 0)
@@ -0,0 +1,24 @@
+#!/bin/bash
+# rebuild-gcj-db
+
+## Copyright (C) 2000, 2002, 2003, 2008 Free Software Foundation
+##
+##   This file is part of libgcj.
+##
+## This software is copyrighted work licensed under the terms of the
+## Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+## details.
+
+# Rebuild all the standard databases.
+for base in /usr/lib*; do
+   dbLocation=`@prefix@/bin/gcj-dbtool@gcc_suffix@ -p $base`
+   libdir=$base/gcj
+   if ! test -d $libdir; then
+      # No shared libraries here.
+      continue
+   fi
+   dirname $dbLocation | xargs mkdir -p
+   @prefix@/bin/gcj-dbtool@gcc_suffix@ -n $dbLocation 64
+   find $libdir -follow -name '*.db' -print0 | \
+      xargs -0 @prefix@/bin/gcj-dbtool@gcc_suffix@ -m $dbLocation $dbLocation
+done
Index: libjava/contrib/aotcompile.py.in
===================================================================
--- libjava/contrib/aotcompile.py.in	(revision 0)
+++ libjava/contrib/aotcompile.py.in	(revision 0)
@@ -0,0 +1,412 @@
+# -*- python -*-
+
+## Copyright (C) 2005, 2006, 2008 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import classfile
+import copy
+import md5
+import operator
+import os
+import sys
+import cStringIO as StringIO
+import zipfile
+
+PATHS = {"make":   "@MAKE@",
+         "gcj":    "@prefix@/bin/gcj@gcc_suffix@",
+         "dbtool": "@prefix@/bin/gcj-dbtool@gcc_suffix@"}
+
+MAKEFLAGS = []
+GCJFLAGS = ["-fPIC", "-findirect-dispatch", "-fjni"]
+LDFLAGS = ["-Wl,-Bsymbolic"]
+
+MAX_CLASSES_PER_JAR = 1024
+MAX_BYTES_PER_JAR = 1048576
+
+MAKEFILE = "Makefile"
+
+MAKEFILE_HEADER = '''\
+GCJ = %(gcj)s
+DBTOOL = %(dbtool)s
+GCJFLAGS = %(gcjflags)s
+LDFLAGS = %(ldflags)s
+
+%%.o: %%.jar
+	$(GCJ) -c $(GCJFLAGS) $< -o $@
+
+TARGETS = \\
+%(targets)s
+
+all: $(TARGETS)'''
+
+MAKEFILE_JOB = '''
+%(base)s_SOURCES = \\
+%(jars)s
+
+%(base)s_OBJECTS = \\
+$(%(base)s_SOURCES:.jar=.o)
+
+%(dso)s: $(%(base)s_OBJECTS)
+	$(GCJ) -shared $(GCJFLAGS) $(LDFLAGS) $^ -o $@
+
+%(db)s: $(%(base)s_SOURCES)
+	$(DBTOOL) -n $@ 64
+	for jar in $^; do \\
+            $(DBTOOL) -f $@ $$jar \\
+                %(libdir)s/%(dso)s; \\
+        done'''
+
+ZIPMAGIC, CLASSMAGIC = "PK\x03\x04", "\xca\xfe\xba\xbe"
+
+class Error(Exception):
+    pass
+
+class Compiler:
+    def __init__(self, srcdir, libdir, prefix = None):
+        self.srcdir = os.path.abspath(srcdir)
+        self.libdir = os.path.abspath(libdir)
+        if prefix is None:
+            self.dstdir = self.libdir
+        else:
+            self.dstdir = os.path.join(prefix, self.libdir.lstrip(os.sep))
+
+        # Calling code may modify these parameters
+        self.gcjflags = copy.copy(GCJFLAGS)
+        self.ldflags = copy.copy(LDFLAGS)
+        self.makeflags = copy.copy(MAKEFLAGS)
+        self.exclusions = []
+
+    def compile(self):
+        """Search srcdir for classes and jarfiles, then generate
+        solibs and mappings databases for them all in libdir."""
+        if not os.path.isdir(self.dstdir):
+            os.makedirs(self.dstdir)
+        oldcwd = os.getcwd()
+        os.chdir(self.dstdir)
+        try:            
+            jobs = self.getJobList()
+            if not jobs:
+                raise Error, "nothing to do"
+            self.writeMakefile(MAKEFILE, jobs)
+            for job in jobs:
+                job.writeJars()
+            system([PATHS["make"]] + self.makeflags)
+            for job in jobs:
+                job.clean()
+            os.unlink(MAKEFILE)
+        finally:
+            os.chdir(oldcwd)
+
+    def getJobList(self):
+        """Return all jarfiles and class collections in srcdir."""
+        jobs = weed_jobs(find_jobs(self.srcdir, self.exclusions))
+        set_basenames(jobs)
+        return jobs
+
+    def writeMakefile(self, path, jobs):
+        """Generate a makefile to build the solibs and mappings
+        databases for the specified list of jobs."""
+        fp = open(path, "w")
+        print >>fp, MAKEFILE_HEADER % {
+            "gcj": PATHS["gcj"],
+            "dbtool": PATHS["dbtool"],
+            "gcjflags": " ".join(self.gcjflags),
+            "ldflags": " ".join(self.ldflags),
+            "targets": " \\\n".join(reduce(operator.add, [
+                (job.dsoName(), job.dbName()) for job in jobs]))}
+        for job in jobs:
+            values = job.ruleArguments()
+            values["libdir"] = self.libdir
+            print >>fp, MAKEFILE_JOB % values
+        fp.close()
+
+def find_jobs(dir, exclusions = ()):
+    """Scan a directory and find things to compile: jarfiles (zips,
+    wars, ears, rars, etc: we go by magic rather than file extension)
+    and directories of classes."""
+    def visit((classes, zips), dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            magic = open(path, "r").read(4)
+            if magic == ZIPMAGIC:
+                zips.append(path)
+            elif magic == CLASSMAGIC:
+                classes.append(path)
+    classes, paths = [], []
+    os.path.walk(dir, visit, (classes, paths))
+    # Convert the list of classes into a list of directories
+    while classes:
+        # XXX this requires the class to be correctly located in its heirachy.
+        path = classes[0][:-len(os.sep + classname(classes[0]) + ".class")]
+        paths.append(path)
+        classes = [cls for cls in classes if not cls.startswith(path)]
+    # Handle exclusions.  We're really strict about them because the
+    # option is temporary in aot-compile-rpm and dead options left in
+    # specfiles will hinder its removal.
+    for path in exclusions:
+        if path in paths:
+            paths.remove(path)
+        else:
+            raise Error, "%s: path does not exist or is not a job" % path
+    # Build the list of jobs
+    jobs = []
+    paths.sort()
+    for path in paths:
+        if os.path.isfile(path):
+            job = JarJob(path)
+        else:
+            job = DirJob(path)
+        if len(job.classes):
+            jobs.append(job)
+    return jobs
+
+class Job:
+    """A collection of classes that will be compiled as a unit."""
+    
+    def __init__(self, path):
+        self.path, self.classes, self.blocks = path, {}, None
+
+    def addClass(self, bytes):
+        """Subclasses call this from their __init__ method for
+        every class they find."""
+        self.classes[md5.new(bytes).digest()] = bytes
+
+    def __makeBlocks(self):
+        """Split self.classes into chunks that can be compiled to
+        native code by gcj.  In the majority of cases this is not
+        necessary -- the job will have come from a jarfile which will
+        be equivalent to the one we generate -- but this only happens
+        _if_ the job was a jarfile and _if_ the jarfile isn't too big
+        and _if_ the jarfile has the correct extension and _if_ all
+        classes are correctly named and _if_ the jarfile has no
+        embedded jarfiles.  Fitting a special case around all these
+        conditions is tricky to say the least.
+
+        Note that this could be called at the end of each subclass's
+        __init__ method.  The reason this is not done is because we
+        need to parse every class file.  This is slow, and unnecessary
+        if the job is subsetted."""
+        names = {}
+        for hash, bytes in self.classes.items():
+            name = classname(bytes)
+            if not names.has_key(name):
+                names[name] = []
+            names[name].append(hash)
+        names = names.items()
+        # We have to sort somehow, or the jars we generate 
+        # We sort by name in a simplistic attempt to keep related
+        # classes together so inter-class optimisation can happen.
+        names.sort()
+        self.blocks, bytes = [[]], 0
+        for name, hashes in names:
+            for hash in hashes:
+                if len(self.blocks[-1]) >= MAX_CLASSES_PER_JAR \
+                   or bytes >= MAX_BYTES_PER_JAR:
+                    self.blocks.append([])
+                    bytes = 0
+                self.blocks[-1].append((name, hash))
+                bytes += len(self.classes[hash])
+
+    # From Archit Shah:
+    #   The implementation and the documentation don't seem to match.
+    #  
+    #    [a, b].isSubsetOf([a]) => True
+    #  
+    #   Identical copies of all classes this collection do not exist
+    #   in the other. I think the method should be named isSupersetOf
+    #   and the documentation should swap uses of "this" and "other"
+    #
+    # XXX think about this when I've had more sleep...
+    def isSubsetOf(self, other):
+        """Returns True if identical copies of all classes in this
+        collection exist in the other."""
+        for item in other.classes.keys():
+            if not self.classes.has_key(item):
+                return False
+        return True
+
+    def __targetName(self, ext):
+        return self.basename + ext
+
+    def tempJarName(self, num):
+        return self.__targetName(".%d.jar" % (num + 1))
+
+    def tempObjName(self, num):
+        return self.__targetName(".%d.o" % (num + 1))
+
+    def dsoName(self):
+        """Return the filename of the shared library that will be
+        built from this job."""
+        return self.__targetName(".so")
+
+    def dbName(self):
+        """Return the filename of the mapping database that will be
+        built from this job."""
+        return self.__targetName(".db")
+
+    def ruleArguments(self):
+        """Return a dictionary of values that when substituted
+        into MAKEFILE_JOB will create the rules required to build
+        the shared library and mapping database for this job."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        return {
+            "base": "".join(
+                [c.isalnum() and c or "_" for c in self.dsoName()]),
+            "jars": " \\\n".join(
+                [self.tempJarName(i) for i in xrange(len(self.blocks))]),
+            "dso": self.dsoName(),
+            "db": self.dbName()}
+
+    def writeJars(self):
+        """Generate jarfiles that can be native compiled by gcj."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for block, i in zip(self.blocks, xrange(len(self.blocks))):
+            jar = zipfile.ZipFile(self.tempJarName(i), "w", zipfile.ZIP_STORED)
+            for name, hash in block:
+                jar.writestr(
+                    zipfile.ZipInfo("%s.class" % name), self.classes[hash])
+            jar.close()
+
+    def clean(self):
+        """Delete all temporary files created during this job's build."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for i in xrange(len(self.blocks)):
+            os.unlink(self.tempJarName(i))
+            os.unlink(self.tempObjName(i))
+
+class JarJob(Job):
+    """A Job whose origin was a jarfile."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        self._walk(zipfile.ZipFile(path, "r"))
+
+    def _walk(self, zf):
+        for name in zf.namelist():
+            bytes = zf.read(name)
+            if bytes.startswith(ZIPMAGIC):
+                self._walk(zipfile.ZipFile(StringIO.StringIO(bytes)))
+            elif bytes.startswith(CLASSMAGIC):
+                self.addClass(bytes)
+
+class DirJob(Job):
+    """A Job whose origin was a directory of classfiles."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        os.path.walk(path, DirJob._visit, self)
+
+    def _visit(self, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            fp = open(path, "r")
+            magic = fp.read(4)
+            if magic == CLASSMAGIC:
+                self.addClass(magic + fp.read())
+    
+def weed_jobs(jobs):
+    """Remove any jarfiles that are completely contained within
+    another.  This is more common than you'd think, and we only
+    need one nativified copy of each class after all."""
+    jobs = copy.copy(jobs)
+    while True:
+        for job1 in jobs:
+            for job2 in jobs:
+                if job1 is job2:
+                    continue
+                if job1.isSubsetOf(job2):
+                    msg = "subsetted %s" % job2.path
+                    if job2.isSubsetOf(job1):
+                        if (isinstance(job1, DirJob) and
+                            isinstance(job2, JarJob)):
+                            # In the braindead case where a package
+                            # contains an expanded copy of a jarfile
+                            # the jarfile takes precedence.
+                            continue
+                        msg += " (identical)"
+                    warn(msg)
+                    jobs.remove(job2)
+                    break
+            else:
+                continue
+            break
+        else:
+            break
+        continue
+    return jobs
+
+def set_basenames(jobs):
+    """Ensure that each jarfile has a different basename."""
+    names = {}
+    for job in jobs:
+        name = os.path.basename(job.path)
+        if not names.has_key(name):
+            names[name] = []
+        names[name].append(job)
+    for name, set in names.items():
+        if len(set) == 1:
+            set[0].basename = name
+            continue
+        # prefix the jar filenames to make them unique
+        # XXX will not work in most cases -- needs generalising
+        set = [(job.path.split(os.sep), job) for job in set]
+        minlen = min([len(bits) for bits, job in set])
+        set = [(bits[-minlen:], job) for bits, job in set]
+        bits = apply(zip, [bits for bits, job in set])
+        while True:
+            row = bits[-2]
+            for bit in row[1:]:
+                if bit != row[0]:
+                    break
+            else:
+                del bits[-2]
+                continue
+            break
+        set = zip(
+            ["_".join(name) for name in apply(zip, bits[-2:])],
+            [job for bits, job in set])
+        for name, job in set:
+            warn("building %s as %s" % (job.path, name))
+            job.basename = name
+    # XXX keep this check until we're properly general
+    names = {}
+    for job in jobs:
+        name = job.basename
+        if names.has_key(name):
+            raise Error, "%s: duplicate jobname" % name
+        names[name] = 1
+
+def system(command):
+    """Execute a command."""
+    status = os.spawnv(os.P_WAIT, command[0], command)
+    if status > 0:
+        raise Error, "%s exited with code %d" % (command[0], status)
+    elif status < 0:
+        raise Error, "%s killed by signal %d" % (command[0], -status)
+
+def warn(msg):
+    """Print a warning message."""
+    print >>sys.stderr, "%s: warning: %s" % (
+        os.path.basename(sys.argv[0]), msg)
+
+def classname(bytes):
+    """Extract the class name from the bytes of a class file."""
+    klass = classfile.Class(bytes)
+    return klass.constants[klass.constants[klass.name][1]][1]
Index: libjava/contrib/aot-compile-rpm.in
===================================================================
--- libjava/contrib/aot-compile-rpm.in	(revision 0)
+++ libjava/contrib/aot-compile-rpm.in	(revision 0)
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir@")
+import aotcompile
+import os
+
+def libdir():
+    cmd = "%s -p" % aotcompile.PATHS["dbtool"]
+    dir = os.path.abspath(os.popen(cmd, "r").readline().rstrip())
+    dir, base = os.path.split(dir)
+    if base != "classmap.db":
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    dir, base = os.path.split(dir)
+    if not base.startswith("gcj-"):
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    return dir
+
+def writeSourceList(srcdir, dstpath):
+    def visit(fp, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.isfile(path):
+                print >>fp, path
+    dstdir = os.path.dirname(dstpath)
+    if not os.path.isdir(dstdir):
+        os.makedirs(dstdir)
+    os.path.walk(srcdir, visit, open(dstpath, "w"))
+
+def copy(srcdir, dstdir, suffix):
+    srcdir = os.path.join(srcdir, suffix.lstrip(os.sep))
+    dstdir = os.path.join(dstdir, suffix.lstrip(os.sep))
+    os.makedirs(os.path.dirname(dstdir))
+    aotcompile.system(("/bin/cp", "-a", srcdir, dstdir))
+
+try:
+    name = os.environ.get("RPM_PACKAGE_NAME")
+    if name is None:
+        raise aotcompile.Error, "not for use outside rpm specfiles"
+    arch = os.environ.get("RPM_ARCH")
+    if arch == "noarch":
+        raise aotcompile.Error, "cannot be used on noarch packages"
+    srcdir = os.environ.get("RPM_BUILD_ROOT")
+    if srcdir in (None, "/"):
+        raise aotcompile.Error, "bad $RPM_BUILD_ROOT"
+    tmpdir = os.path.join(os.getcwd(), "aot-compile-rpm")
+    if os.path.exists(tmpdir):
+        raise aotcompile.Error, "%s exists" % tmpdir
+    dstdir = os.path.join(libdir(), "gcj", name)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir, tmpdir)
+    compiler.gcjflags[0:0] = os.environ.get("RPM_OPT_FLAGS", "").split() 
+
+    # XXX: This script should not accept options, because having
+    # them it cannot be integrated into rpm.  But, gcj cannot
+    # build each and every jarfile yet, so we must be able to
+    # exclude until it can.
+    # XXX --exclude is also used in the jonas rpm to stop
+    # everything being made a subset of the mammoth client
+    # jarfile. Should adjust the subset checker's bias to
+    # favour many small jarfiles over one big one.
+    try:
+        options, exclusions = sys.argv[1:], []
+        while options:
+            if options.pop(0) != "--exclude":
+                raise ValueError
+            compiler.exclusions.append(
+                os.path.join(srcdir, options.pop(0).lstrip(os.sep)))
+    except:
+        print >>sys.stderr, "usage: %s [--exclude PATH]..." % (
+            os.path.basename(sys.argv[0]))
+        sys.exit(1)
+
+    sourcelist = os.path.join(tmpdir, "sources.list")
+    writeSourceList(os.getcwd(), sourcelist)
+    compiler.gcjflags.append("-fsource-filename=" + sourcelist)
+
+    compiler.compile()
+    copy(tmpdir, srcdir, dstdir)
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/contrib/classfile.py
===================================================================
--- libjava/contrib/classfile.py	(revision 0)
+++ libjava/contrib/classfile.py	(revision 0)
@@ -0,0 +1,221 @@
+## Copyright (C) 2004, 2005 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+"""Read Java(TM) class files."""
+
+import cStringIO as StringIO
+import struct
+
+class Class:
+    def __init__(self, arg):
+        if hasattr(arg, "read"):
+            self.fp = arg
+        elif type(arg) == type(""):
+            if arg.startswith("\xca\xfe\xba\xbe"):
+                self.fp = StringIO.StringIO(arg)
+            else:
+                self.fp = open(arg, "r")
+        else:
+            raise TypeError, type(arg)
+
+        magic = self._read_int()
+        assert magic == 0xcafebabeL
+        minor, major = self._read(">HH")        
+        self.version = (major, minor)
+
+        self.pool_integrity_checks = None
+        try:
+            assert False
+        except AssertionError:
+            self.pool_integrity_checks = []
+
+        self._read_constants_pool()
+
+        self.access_flags = self._read_short()
+        self.name = self._read_reference_Class()
+        self.super = self._read_reference_Class()
+
+        self.interfaces = self._read_interfaces()
+        self.fields = self._read_fieldsormethods()
+        self.methods = self._read_fieldsormethods()
+        self.attributes = self._read_attributes()
+
+        if self.pool_integrity_checks is not None:
+            for index, tag in self.pool_integrity_checks:
+                assert self.constants[index][0] == tag
+
+        del self.fp, self.pool_integrity_checks
+
+    def __repr__(self):
+        result = []
+        attrs = [attr for attr in dir(self)
+                 if not attr.startswith("_") and attr != "Member"]
+        attrs.sort()
+        for attr in attrs:
+            result.append("%-13s %s" % (
+                attr + ":", attr == "constants" and
+                "<ELIDED>" or repr(getattr(self, attr))))
+        return "\n".join(result)
+
+    def _read_constants_pool(self):
+        self.constants = {}
+        skip = False
+        for i in xrange(1, self._read_short()):
+            if skip:
+                skip = False
+                continue
+            tag = {
+                1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
+                6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
+                10: "Methodref", 11: "InterfaceMethodref",
+                12: "NameAndType"}[self._read_byte()]
+            skip = tag in ("Long", "Double") # crack crack crack!
+            self.constants[i] = (tag, getattr(self, "_read_constant_" + tag)())
+
+    def _read_interfaces(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self._read_reference_Class())
+        return result
+
+    def _read_fieldsormethods(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self.Member(self))
+        return result
+
+    class Member:
+        def __init__(self, source):
+            self.access_flags = source._read_short()
+            self.name = source._read_reference_Utf8()
+            self.descriptor = source._read_reference_Utf8()
+            self.attributes = source._read_attributes()
+
+        def __repr__(self):
+            result = []
+            attrs = [attr for attr in dir(self) if not attr.startswith("_")]
+            attrs.sort()
+            for attr in attrs:
+                value = getattr(self, attr)
+                if attr == "attributes" and value.has_key("Code"):
+                    value = value.copy()
+                    value.update({"Code": "<ELIDED>"})
+                result.append("%-13s %s" % (
+                    attr + ":", repr(value).replace(
+                        "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
+            return ("\n%s" % (15 * " ")).join(result)
+
+    def _read_attributes(self):
+        result = {}
+        for i in xrange(self._read_short()):
+            name = self._read_reference_Utf8()
+            data = self.fp.read(self._read_int())
+            assert not result.has_key(name)
+            result[name] = data
+        return result
+
+    # Constants pool reference reader convenience functions
+
+    def _read_reference_Utf8(self):
+        return self._read_references("Utf8")[0]
+
+    def _read_reference_Class(self):
+        return self._read_references("Class")[0]
+
+    def _read_reference_Class_NameAndType(self):
+        return self._read_references("Class", "NameAndType")
+
+    def _read_references(self, *args):
+        result = []
+        for arg in args:
+            index = self._read_short()
+            if self.pool_integrity_checks is not None:
+                self.pool_integrity_checks.append((index, arg))
+            result.append(index)
+        return result
+
+    # Constants pool constant reader functions
+
+    def _read_constant_Utf8(self):
+        constant = self.fp.read(self._read_short())
+        try:
+            constant = constant.decode("utf-8")
+        except UnicodeError:
+            constant = _bork_utf8_decode(constant)
+        try:
+            constant = constant.encode("us-ascii")
+        except UnicodeError:
+            pass
+        return constant
+
+    def _read_constant_Integer(self):
+        return self._read_int()
+
+    def _read_constant_Float(self):
+        return self._read(">f")[0]
+
+    def _read_constant_Long(self):
+        return self._read(">q")[0]
+
+    def _read_constant_Double(self):
+        return self._read(">d")[0]
+
+    _read_constant_Class = _read_reference_Utf8
+    _read_constant_String = _read_reference_Utf8
+    _read_constant_Fieldref = _read_reference_Class_NameAndType
+    _read_constant_Methodref = _read_reference_Class_NameAndType
+    _read_constant_InterfaceMethodref = _read_reference_Class_NameAndType
+
+    def _read_constant_NameAndType(self):
+        return self._read_reference_Utf8(), self._read_reference_Utf8()
+
+    # Generic reader functions
+
+    def _read_int(self):
+        # XXX how else to read 32 bits on a 64-bit box?
+        h, l = map(long, self._read(">HH"))
+        return (h << 16) + l
+
+    def _read_short(self):
+        return self._read(">H")[0]
+
+    def _read_byte(self):
+        return self._read("B")[0]
+
+    def _read(self, fmt):
+        return struct.unpack(fmt, self.fp.read(struct.calcsize(fmt)))
+
+def _bork_utf8_decode(data):
+    # more crack!
+    bytes, unicode = map(ord, data), ""
+    while bytes:
+        b1 = bytes.pop(0)
+        if b1 & 0x80:
+            assert b1 & 0x40
+            b2 = bytes.pop(0)
+            assert b2 & 0xC0 == 0x80
+            if b1 & 0x20:
+                assert not b1 & 0x10
+                b3 = bytes.pop(0)
+                assert b3 & 0xC0 == 0x80
+                unicode += unichr(
+                    ((b1 & 0x0f) << 12) + ((b2 & 0x3f) << 6) + (b3 & 0x3f))
+            else:
+                unicode += unichr(((b1 & 0x1f) << 6) + (b2 & 0x3f))
+        else:
+            unicode += unichr(b1)
+    return unicode
+
+if __name__ == "__main__":
+    print Class("/usr/share/katana/build/ListDependentClasses.class")
+
Index: libjava/contrib/aot-compile.in
===================================================================
--- libjava/contrib/aot-compile.in	(revision 0)
+++ libjava/contrib/aot-compile.in	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2006 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir@")
+import aotcompile
+import getopt
+import os
+
+usage = """\
+Usage: %s [OPTION...] SRCDIR DSTDIR
+AOT-compile all Java bytecode in SRCDIR into DSTDIR.
+
+Options:
+  -M, --make=PATH        make executable to use (%s)
+  -C, --gcj=PATH         gcj executable to use (%s)
+  -D, --dbtool=PATH      gcj-dbtool executable to use (%s)
+  -m, --makeflags=FLAGS  flags to pass to make during build
+  -c, --gcjflags=FLAGS   flags to pass to gcj during compilation
+                           in addition to %s
+  -l, --ldflags=FLAGS    flags to pass to gcj during linking
+                           in addition to %s
+  -e, --exclude=PATH     do not compile PATH
+
+Extra flags may also be passed using the AOT_MAKEFLAGS, AOT_GCJFLAGS
+and AOT_LDFLAGS environment variables.""" % (
+    os.path.basename(sys.argv[0]),
+    aotcompile.PATHS["make"],
+    aotcompile.PATHS["gcj"],
+    aotcompile.PATHS["dbtool"],
+    repr(" ".join(aotcompile.GCJFLAGS)),
+    repr(" ".join(aotcompile.LDFLAGS)))
+
+try:
+    if os.environ.has_key("RPM_PACKAGE_NAME"):
+        raise aotcompile.Error, "not for use within rpm specfiles"
+
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            "M:C:D:m:c:l:e:",
+            ["make=", "gcj=", "dbtool=",
+             "makeflags=" "gcjflags=", "ldflags=",
+             "exclude="])
+        srcdir, dstdir = args
+    except:
+        print >>sys.stderr, usage
+        sys.exit(1)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir)
+    for o, a in opts:
+        if o in ("-M", "--make"):
+            aotcompile.PATHS["make"] = a
+        if o in ("-C", "--gcj"):
+            aotcompile.PATHS["gcj"] = a
+        if o in ("-D", "--dbtool"):
+            aotcompile.PATHS["dbtool"] = a
+        if o in ("-m", "--makeflags"):
+            compiler.makeflags[0:0] = a.split()
+        if o in ("-c", "--gcjflags"):
+            compiler.gcjflags[0:0] = a.split()
+        if o in ("-l", "--ldflags"):
+            compiler.ldflags[0:0] = a.split()
+        if o in ("-e", "--exclude"):
+            compiler.exclusions.append(a)
+    
+    compiler.makeflags[0:0] = os.environ.get("AOT_MAKEFLAGS", "").split() 
+    compiler.gcjflags[0:0] = os.environ.get("AOT_GCJFLAGS", "").split() 
+    compiler.ldflags[0:0] = os.environ.get("AOT_LDFLAGS", "").split() 
+
+    compiler.compile()
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/ChangeLog
===================================================================
--- libjava/ChangeLog	(revision 136894)
+++ libjava/ChangeLog	(working copy)
@@ -1,3 +1,29 @@
+2008-06-18  Joshua Sumali  <jsumali@redhat.com>
+
+	* configure.ac (java-home): new AC_ARG_ENABLE.
+	(CREATE_JAVA_HOME): new AM_CONDITIONAL.
+	(gcc-suffix): new AC_ARG_WITH.
+	(arch-directory): Likewise.
+	(os-directory): Likewise.
+	(origin-name): Likewise.
+	(arch-suffix): Likewise.
+	(jvm-root-dir): Likewise.
+	(jvm-jar-dir): Likewise.
+	(python-dir): Likewise.
+	(AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
+	contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
+	* Makefile.am (install-data-local): Install Python modules for
+	aot-compile. Also install an sdk style directory if	--enable-java-home
+	is passed to configure.
+	(bin_SCRIPTS): add contrib/rebuild-gcj-db and contrib/aot-compile.
+	* contrib/aot-compile.in: New file.
+	* contrib/aotcompile.py.in: Likewise.
+	* contrib/aot-compile-rpm.in: Likewise.
+	* contrib/classfile.py: Likewise.
+	* contrib/rebuild-gcj-db.in: Likewise.
+	* configure: Regenerate.
+	* Makefile.in: Regenerate.
+
 2008-06-17  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
 	* configure: Regenerate.
Index: libjava/Makefile.am
===================================================================
--- libjava/Makefile.am	(revision 136724)
+++ libjava/Makefile.am	(working copy)
@@ -85,9 +85,9 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
-endif
+endif 
 
-bin_SCRIPTS = addr2name.awk
+bin_SCRIPTS = addr2name.awk contrib/rebuild-gcj-db contrib/aot-compile
 
 if BUILD_ECJ1
 ## We build ecjx and not ecj1 because in one mode, ecjx will not work
@@ -528,8 +528,153 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
+## Install Python modules for aot-compile.
+	$(mkinstalldirs) $(DESTDIR)$(python_mod_dir); \
+	$(INSTALL_DATA) $(srcdir)/contrib/classfile.py \
+	  $(DESTDIR)$(python_mod_dir)/classfile.py; \
+	$(INSTALL_DATA) contrib/aotcompile.py \
+	  $(DESTDIR)$(python_mod_dir)/aotcompile.py;
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/`echo grmic | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/`echo gjavah | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/`echo gappletviewer | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/`echo gjarsigner | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo gnative2ascii | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/`echo gserialver | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $(DESTDIR)$(JVM_ROOT_DIR); \
+	  ln -s $(JRE_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $(DESTDIR)$(JVM_JAR_ROOT_DIR); \
+	  ln -s $(SDK_DIR) $(JRE_LNK); \
+	  ln -s $(SDK_DIR) $(SDK_LNK); \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	GIJ_VERSION=$$($(DESTDIR)$(bindir)/gij --version | head -n2 | tail -n1 \
+	  | awk '{print $$5}'); \
+	ln -sf $$RELATIVE/libgcj-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	if [ -f $$RELATIVE/libjawt.so ]; then \
+	  ln -sf $$RELATIVE/libjawt.so \
+	    $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	fi; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$$GIJ_VERSION.jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	if [ -f $$RELATIVE/src-$$GIJ_VERSION.zip ]; then \
+	  ln -sf $$RELATIVE/src-$$GIJ_VERSION.zip \
+	    $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip; \
+	fi;
+endif
 
-
 ## ################################################################
 
 ##
Index: libjava/configure.ac
===================================================================
--- libjava/configure.ac	(revision 136724)
+++ libjava/configure.ac	(working copy)
@@ -1625,6 +1625,206 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)
 
+AC_ARG_WITH([python-dir],
+            AS_HELP_STRING([--with-python-dir],
+                           [the location to install Python modules]),
+            [with_python_dir=$withval], [with_python_dir=""])
+
+if test "x${with_python_dir}" = "x"
+then
+  if test "x${prefix}" = "xNONE"
+  then
+    python_mod_dir=/usr/share/python
+  else
+    python_mod_dir=${prefix}/share/python
+  fi
+else
+  python_mod_dir=$with_python_dir
+fi
+AC_MSG_RESULT(Python modules dir: ${python_mod_dir});
+AC_SUBST(python_mod_dir)
+
+# needed for aot-compile-rpm
+MAKE=`which make`
+AC_SUBST(MAKE)
+
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  if test "x${prefix}" = "xNONE"
+  then
+    sdk_prefix=/usr
+  else
+    sdk_prefix=$prefix
+  fi
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${sdk_prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir=${sdk_prefix}/lib/jvm])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${sdk_prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=${sdk_prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
+  AC_SUBST(JAVA_HOME_DIR)
+  AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$sdk_prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc
@@ -1633,6 +1833,10 @@
 gcj/Makefile
 include/Makefile
 testsuite/Makefile
+contrib/aotcompile.py
+contrib/aot-compile
+contrib/aot-compile-rpm
+contrib/rebuild-gcj-db
 ])
 
 if test ${multilib} = yes; then

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-19 14:24         ` Joshua Sumali
@ 2008-06-20  4:13           ` Joshua Sumali
  2008-06-26 18:18           ` Joshua Sumali
  1 sibling, 0 replies; 18+ messages in thread
From: Joshua Sumali @ 2008-06-20  4:13 UTC (permalink / raw)
  To: java-patches

Joshua Sumali wrote:
> Andrew Haley wrote:
>> Joshua Sumali wrote:
>>
>>  
>>> Please see the two (updated) patches. The updated patch for the
>>> "Packager files" thread is now part of the sdk-home patch attached 
>>> here,
>>> since I had to modify configure.ac to generate those packager files 
>>> this
>>> time around.
>>>
>>> gcc-install-and-docs.patch creates man and info pages for aot-compile
>>> and rebuild-gcj-db, and also documents the new install options
>>> (--enable-java-home, --with-arch-directory, --with-python-dir) as
>>> requested by Matthias.
>>> gcc-libjava-sdk-home-update.patch is mostly the same as the first patch
>>> I posted here, except with these main changes:
>>>
>>>    - aot-compile and rebuild-gcj-db are now installed in $bindir
>>>    - if --with-python-dir is not specified (say, in a regular upstream
>>> build) , classfile.py and aotcompile.py are installed in
>>> $(prefix)/share/python. Otherwise, those Python modules will be
>>> installed in the path specified with --with-python-dir. I modified
>>> aot-compile -> aot-compile.in to append whichever path classfile.py and
>>> aotcompile.py was installed in, so that it can actually find these
>>> modules (it wouldn't look in $(prefix)/share/python by default).
>>>    - the SDK symlinked binaries, as well as aot-compile and
>>> rebuild-gcj-db are now `transformed' as requested by Matthias.
>>>     
>>
>> OK, thanks.
>>
>>  
>>> Outstanding issues:
>>> 1. @Matthias, I'm still not sure what you mean by "Same for using
>>> GIJ_VERSION". Also, the issue about "why using the long version at 
>>> all?"
>>> 2. rebuild-gcj-db doesn't have a licence header on the top of the
>>> file... is this required? And if so, what's the right thing to do 
>>> about it?
>>>     
>>
>> Make it GPL.
>>
>> Andrew.
>>   
> Updated rebuild-gcj-db with license header.
>
> Josh
Actually, please don't do anything with this patch yet. I've noticed a 
problem with rpm packaging as the sdk-home and python stuff gets 
installed into its hardcoded paths instead of using $(prefix). This 
makes the rpm build fail in the %install section since the files are 
still installed into the --prefix specified in `./configure 
--prefix=<...>` instead of the prefix specified by `make prefix=<...> 
install`. Fixing this problem ...

Josh

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-19 14:24         ` Joshua Sumali
  2008-06-20  4:13           ` Joshua Sumali
@ 2008-06-26 18:18           ` Joshua Sumali
  2008-06-30 10:20             ` Andrew Haley
  1 sibling, 1 reply; 18+ messages in thread
From: Joshua Sumali @ 2008-06-26 18:18 UTC (permalink / raw)
  To: java-patches

[-- Attachment #1: Type: text/plain, Size: 2251 bytes --]

Joshua Sumali wrote:
> Andrew Haley wrote:
>> Joshua Sumali wrote:
>>
>>  
>>> Please see the two (updated) patches. The updated patch for the
>>> "Packager files" thread is now part of the sdk-home patch attached 
>>> here,
>>> since I had to modify configure.ac to generate those packager files 
>>> this
>>> time around.
>>>
>>> gcc-install-and-docs.patch creates man and info pages for aot-compile
>>> and rebuild-gcj-db, and also documents the new install options
>>> (--enable-java-home, --with-arch-directory, --with-python-dir) as
>>> requested by Matthias.
>>> gcc-libjava-sdk-home-update.patch is mostly the same as the first patch
>>> I posted here, except with these main changes:
>>>
>>>    - aot-compile and rebuild-gcj-db are now installed in $bindir
>>>    - if --with-python-dir is not specified (say, in a regular upstream
>>> build) , classfile.py and aotcompile.py are installed in
>>> $(prefix)/share/python. Otherwise, those Python modules will be
>>> installed in the path specified with --with-python-dir. I modified
>>> aot-compile -> aot-compile.in to append whichever path classfile.py and
>>> aotcompile.py was installed in, so that it can actually find these
>>> modules (it wouldn't look in $(prefix)/share/python by default).
>>>    - the SDK symlinked binaries, as well as aot-compile and
>>> rebuild-gcj-db are now `transformed' as requested by Matthias.
>>>     
>>
>> OK, thanks.
>>
>>  
>>> Outstanding issues:
>>> 1. @Matthias, I'm still not sure what you mean by "Same for using
>>> GIJ_VERSION". Also, the issue about "why using the long version at 
>>> all?"
>>> 2. rebuild-gcj-db doesn't have a licence header on the top of the
>>> file... is this required? And if so, what's the right thing to do 
>>> about it?
>>>     
>>
>> Make it GPL.
>>
>> Andrew.
>>   
> Updated rebuild-gcj-db with license header.
>
> Josh
Hi,

Updated documentation, and sdk patch attached. I think this one is ready 
to go in.

-cleaned up the sdk patch -- no more $$GIJ_VERSION, and only 
'java-1.5.0-gcj-1.5.0.0' is installed in /usr/lib/jvm is installed (as 
requested by Matthias). /usr/lib/jvm/{java-1.5.0-gcj, jre-1.5.0-gcj} 
symlinks are instead to be installed by the packages (I believe this is 
the right approach).

Josh

[-- Attachment #2: gcc-libjava-sdk-home-update3.patch --]
[-- Type: text/x-patch, Size: 47511 bytes --]

Index: libjava/contrib/rebuild-gcj-db.in
===================================================================
--- libjava/contrib/rebuild-gcj-db.in	(revision 0)
+++ libjava/contrib/rebuild-gcj-db.in	(revision 0)
@@ -0,0 +1,24 @@
+#!/bin/bash
+# rebuild-gcj-db
+
+## Copyright (C) 2000, 2002, 2003, 2008 Free Software Foundation
+##
+##   This file is part of libgcj.
+##
+## This software is copyrighted work licensed under the terms of the
+## Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+## details.
+
+# Rebuild all the standard databases.
+for base in /usr/lib*; do
+   dbLocation=`@prefix@/bin/gcj-dbtool@gcc_suffix@ -p $base`
+   libdir=$base/gcj
+   if ! test -d $libdir; then
+      # No shared libraries here.
+      continue
+   fi
+   dirname $dbLocation | xargs mkdir -p
+   @prefix@/bin/gcj-dbtool@gcc_suffix@ -n $dbLocation 64
+   find $libdir -follow -name '*.db' -print0 | \
+      xargs -0 @prefix@/bin/gcj-dbtool@gcc_suffix@ -m $dbLocation $dbLocation
+done
Index: libjava/contrib/aotcompile.py.in
===================================================================
--- libjava/contrib/aotcompile.py.in	(revision 0)
+++ libjava/contrib/aotcompile.py.in	(revision 0)
@@ -0,0 +1,412 @@
+# -*- python -*-
+
+## Copyright (C) 2005, 2006, 2008 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import classfile
+import copy
+import md5
+import operator
+import os
+import sys
+import cStringIO as StringIO
+import zipfile
+
+PATHS = {"make":   "@MAKE@",
+         "gcj":    "@prefix@/bin/gcj@gcc_suffix@",
+         "dbtool": "@prefix@/bin/gcj-dbtool@gcc_suffix@"}
+
+MAKEFLAGS = []
+GCJFLAGS = ["-fPIC", "-findirect-dispatch", "-fjni"]
+LDFLAGS = ["-Wl,-Bsymbolic"]
+
+MAX_CLASSES_PER_JAR = 1024
+MAX_BYTES_PER_JAR = 1048576
+
+MAKEFILE = "Makefile"
+
+MAKEFILE_HEADER = '''\
+GCJ = %(gcj)s
+DBTOOL = %(dbtool)s
+GCJFLAGS = %(gcjflags)s
+LDFLAGS = %(ldflags)s
+
+%%.o: %%.jar
+	$(GCJ) -c $(GCJFLAGS) $< -o $@
+
+TARGETS = \\
+%(targets)s
+
+all: $(TARGETS)'''
+
+MAKEFILE_JOB = '''
+%(base)s_SOURCES = \\
+%(jars)s
+
+%(base)s_OBJECTS = \\
+$(%(base)s_SOURCES:.jar=.o)
+
+%(dso)s: $(%(base)s_OBJECTS)
+	$(GCJ) -shared $(GCJFLAGS) $(LDFLAGS) $^ -o $@
+
+%(db)s: $(%(base)s_SOURCES)
+	$(DBTOOL) -n $@ 64
+	for jar in $^; do \\
+            $(DBTOOL) -f $@ $$jar \\
+                %(libdir)s/%(dso)s; \\
+        done'''
+
+ZIPMAGIC, CLASSMAGIC = "PK\x03\x04", "\xca\xfe\xba\xbe"
+
+class Error(Exception):
+    pass
+
+class Compiler:
+    def __init__(self, srcdir, libdir, prefix = None):
+        self.srcdir = os.path.abspath(srcdir)
+        self.libdir = os.path.abspath(libdir)
+        if prefix is None:
+            self.dstdir = self.libdir
+        else:
+            self.dstdir = os.path.join(prefix, self.libdir.lstrip(os.sep))
+
+        # Calling code may modify these parameters
+        self.gcjflags = copy.copy(GCJFLAGS)
+        self.ldflags = copy.copy(LDFLAGS)
+        self.makeflags = copy.copy(MAKEFLAGS)
+        self.exclusions = []
+
+    def compile(self):
+        """Search srcdir for classes and jarfiles, then generate
+        solibs and mappings databases for them all in libdir."""
+        if not os.path.isdir(self.dstdir):
+            os.makedirs(self.dstdir)
+        oldcwd = os.getcwd()
+        os.chdir(self.dstdir)
+        try:            
+            jobs = self.getJobList()
+            if not jobs:
+                raise Error, "nothing to do"
+            self.writeMakefile(MAKEFILE, jobs)
+            for job in jobs:
+                job.writeJars()
+            system([PATHS["make"]] + self.makeflags)
+            for job in jobs:
+                job.clean()
+            os.unlink(MAKEFILE)
+        finally:
+            os.chdir(oldcwd)
+
+    def getJobList(self):
+        """Return all jarfiles and class collections in srcdir."""
+        jobs = weed_jobs(find_jobs(self.srcdir, self.exclusions))
+        set_basenames(jobs)
+        return jobs
+
+    def writeMakefile(self, path, jobs):
+        """Generate a makefile to build the solibs and mappings
+        databases for the specified list of jobs."""
+        fp = open(path, "w")
+        print >>fp, MAKEFILE_HEADER % {
+            "gcj": PATHS["gcj"],
+            "dbtool": PATHS["dbtool"],
+            "gcjflags": " ".join(self.gcjflags),
+            "ldflags": " ".join(self.ldflags),
+            "targets": " \\\n".join(reduce(operator.add, [
+                (job.dsoName(), job.dbName()) for job in jobs]))}
+        for job in jobs:
+            values = job.ruleArguments()
+            values["libdir"] = self.libdir
+            print >>fp, MAKEFILE_JOB % values
+        fp.close()
+
+def find_jobs(dir, exclusions = ()):
+    """Scan a directory and find things to compile: jarfiles (zips,
+    wars, ears, rars, etc: we go by magic rather than file extension)
+    and directories of classes."""
+    def visit((classes, zips), dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            magic = open(path, "r").read(4)
+            if magic == ZIPMAGIC:
+                zips.append(path)
+            elif magic == CLASSMAGIC:
+                classes.append(path)
+    classes, paths = [], []
+    os.path.walk(dir, visit, (classes, paths))
+    # Convert the list of classes into a list of directories
+    while classes:
+        # XXX this requires the class to be correctly located in its heirachy.
+        path = classes[0][:-len(os.sep + classname(classes[0]) + ".class")]
+        paths.append(path)
+        classes = [cls for cls in classes if not cls.startswith(path)]
+    # Handle exclusions.  We're really strict about them because the
+    # option is temporary in aot-compile-rpm and dead options left in
+    # specfiles will hinder its removal.
+    for path in exclusions:
+        if path in paths:
+            paths.remove(path)
+        else:
+            raise Error, "%s: path does not exist or is not a job" % path
+    # Build the list of jobs
+    jobs = []
+    paths.sort()
+    for path in paths:
+        if os.path.isfile(path):
+            job = JarJob(path)
+        else:
+            job = DirJob(path)
+        if len(job.classes):
+            jobs.append(job)
+    return jobs
+
+class Job:
+    """A collection of classes that will be compiled as a unit."""
+    
+    def __init__(self, path):
+        self.path, self.classes, self.blocks = path, {}, None
+
+    def addClass(self, bytes):
+        """Subclasses call this from their __init__ method for
+        every class they find."""
+        self.classes[md5.new(bytes).digest()] = bytes
+
+    def __makeBlocks(self):
+        """Split self.classes into chunks that can be compiled to
+        native code by gcj.  In the majority of cases this is not
+        necessary -- the job will have come from a jarfile which will
+        be equivalent to the one we generate -- but this only happens
+        _if_ the job was a jarfile and _if_ the jarfile isn't too big
+        and _if_ the jarfile has the correct extension and _if_ all
+        classes are correctly named and _if_ the jarfile has no
+        embedded jarfiles.  Fitting a special case around all these
+        conditions is tricky to say the least.
+
+        Note that this could be called at the end of each subclass's
+        __init__ method.  The reason this is not done is because we
+        need to parse every class file.  This is slow, and unnecessary
+        if the job is subsetted."""
+        names = {}
+        for hash, bytes in self.classes.items():
+            name = classname(bytes)
+            if not names.has_key(name):
+                names[name] = []
+            names[name].append(hash)
+        names = names.items()
+        # We have to sort somehow, or the jars we generate 
+        # We sort by name in a simplistic attempt to keep related
+        # classes together so inter-class optimisation can happen.
+        names.sort()
+        self.blocks, bytes = [[]], 0
+        for name, hashes in names:
+            for hash in hashes:
+                if len(self.blocks[-1]) >= MAX_CLASSES_PER_JAR \
+                   or bytes >= MAX_BYTES_PER_JAR:
+                    self.blocks.append([])
+                    bytes = 0
+                self.blocks[-1].append((name, hash))
+                bytes += len(self.classes[hash])
+
+    # From Archit Shah:
+    #   The implementation and the documentation don't seem to match.
+    #  
+    #    [a, b].isSubsetOf([a]) => True
+    #  
+    #   Identical copies of all classes this collection do not exist
+    #   in the other. I think the method should be named isSupersetOf
+    #   and the documentation should swap uses of "this" and "other"
+    #
+    # XXX think about this when I've had more sleep...
+    def isSubsetOf(self, other):
+        """Returns True if identical copies of all classes in this
+        collection exist in the other."""
+        for item in other.classes.keys():
+            if not self.classes.has_key(item):
+                return False
+        return True
+
+    def __targetName(self, ext):
+        return self.basename + ext
+
+    def tempJarName(self, num):
+        return self.__targetName(".%d.jar" % (num + 1))
+
+    def tempObjName(self, num):
+        return self.__targetName(".%d.o" % (num + 1))
+
+    def dsoName(self):
+        """Return the filename of the shared library that will be
+        built from this job."""
+        return self.__targetName(".so")
+
+    def dbName(self):
+        """Return the filename of the mapping database that will be
+        built from this job."""
+        return self.__targetName(".db")
+
+    def ruleArguments(self):
+        """Return a dictionary of values that when substituted
+        into MAKEFILE_JOB will create the rules required to build
+        the shared library and mapping database for this job."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        return {
+            "base": "".join(
+                [c.isalnum() and c or "_" for c in self.dsoName()]),
+            "jars": " \\\n".join(
+                [self.tempJarName(i) for i in xrange(len(self.blocks))]),
+            "dso": self.dsoName(),
+            "db": self.dbName()}
+
+    def writeJars(self):
+        """Generate jarfiles that can be native compiled by gcj."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for block, i in zip(self.blocks, xrange(len(self.blocks))):
+            jar = zipfile.ZipFile(self.tempJarName(i), "w", zipfile.ZIP_STORED)
+            for name, hash in block:
+                jar.writestr(
+                    zipfile.ZipInfo("%s.class" % name), self.classes[hash])
+            jar.close()
+
+    def clean(self):
+        """Delete all temporary files created during this job's build."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for i in xrange(len(self.blocks)):
+            os.unlink(self.tempJarName(i))
+            os.unlink(self.tempObjName(i))
+
+class JarJob(Job):
+    """A Job whose origin was a jarfile."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        self._walk(zipfile.ZipFile(path, "r"))
+
+    def _walk(self, zf):
+        for name in zf.namelist():
+            bytes = zf.read(name)
+            if bytes.startswith(ZIPMAGIC):
+                self._walk(zipfile.ZipFile(StringIO.StringIO(bytes)))
+            elif bytes.startswith(CLASSMAGIC):
+                self.addClass(bytes)
+
+class DirJob(Job):
+    """A Job whose origin was a directory of classfiles."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        os.path.walk(path, DirJob._visit, self)
+
+    def _visit(self, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            fp = open(path, "r")
+            magic = fp.read(4)
+            if magic == CLASSMAGIC:
+                self.addClass(magic + fp.read())
+    
+def weed_jobs(jobs):
+    """Remove any jarfiles that are completely contained within
+    another.  This is more common than you'd think, and we only
+    need one nativified copy of each class after all."""
+    jobs = copy.copy(jobs)
+    while True:
+        for job1 in jobs:
+            for job2 in jobs:
+                if job1 is job2:
+                    continue
+                if job1.isSubsetOf(job2):
+                    msg = "subsetted %s" % job2.path
+                    if job2.isSubsetOf(job1):
+                        if (isinstance(job1, DirJob) and
+                            isinstance(job2, JarJob)):
+                            # In the braindead case where a package
+                            # contains an expanded copy of a jarfile
+                            # the jarfile takes precedence.
+                            continue
+                        msg += " (identical)"
+                    warn(msg)
+                    jobs.remove(job2)
+                    break
+            else:
+                continue
+            break
+        else:
+            break
+        continue
+    return jobs
+
+def set_basenames(jobs):
+    """Ensure that each jarfile has a different basename."""
+    names = {}
+    for job in jobs:
+        name = os.path.basename(job.path)
+        if not names.has_key(name):
+            names[name] = []
+        names[name].append(job)
+    for name, set in names.items():
+        if len(set) == 1:
+            set[0].basename = name
+            continue
+        # prefix the jar filenames to make them unique
+        # XXX will not work in most cases -- needs generalising
+        set = [(job.path.split(os.sep), job) for job in set]
+        minlen = min([len(bits) for bits, job in set])
+        set = [(bits[-minlen:], job) for bits, job in set]
+        bits = apply(zip, [bits for bits, job in set])
+        while True:
+            row = bits[-2]
+            for bit in row[1:]:
+                if bit != row[0]:
+                    break
+            else:
+                del bits[-2]
+                continue
+            break
+        set = zip(
+            ["_".join(name) for name in apply(zip, bits[-2:])],
+            [job for bits, job in set])
+        for name, job in set:
+            warn("building %s as %s" % (job.path, name))
+            job.basename = name
+    # XXX keep this check until we're properly general
+    names = {}
+    for job in jobs:
+        name = job.basename
+        if names.has_key(name):
+            raise Error, "%s: duplicate jobname" % name
+        names[name] = 1
+
+def system(command):
+    """Execute a command."""
+    status = os.spawnv(os.P_WAIT, command[0], command)
+    if status > 0:
+        raise Error, "%s exited with code %d" % (command[0], status)
+    elif status < 0:
+        raise Error, "%s killed by signal %d" % (command[0], -status)
+
+def warn(msg):
+    """Print a warning message."""
+    print >>sys.stderr, "%s: warning: %s" % (
+        os.path.basename(sys.argv[0]), msg)
+
+def classname(bytes):
+    """Extract the class name from the bytes of a class file."""
+    klass = classfile.Class(bytes)
+    return klass.constants[klass.constants[klass.name][1]][1]
Index: libjava/contrib/aot-compile-rpm.in
===================================================================
--- libjava/contrib/aot-compile-rpm.in	(revision 0)
+++ libjava/contrib/aot-compile-rpm.in	(revision 0)
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import os
+
+def libdir():
+    cmd = "%s -p" % aotcompile.PATHS["dbtool"]
+    dir = os.path.abspath(os.popen(cmd, "r").readline().rstrip())
+    dir, base = os.path.split(dir)
+    if base != "classmap.db":
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    dir, base = os.path.split(dir)
+    if not base.startswith("gcj-"):
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    return dir
+
+def writeSourceList(srcdir, dstpath):
+    def visit(fp, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.isfile(path):
+                print >>fp, path
+    dstdir = os.path.dirname(dstpath)
+    if not os.path.isdir(dstdir):
+        os.makedirs(dstdir)
+    os.path.walk(srcdir, visit, open(dstpath, "w"))
+
+def copy(srcdir, dstdir, suffix):
+    srcdir = os.path.join(srcdir, suffix.lstrip(os.sep))
+    dstdir = os.path.join(dstdir, suffix.lstrip(os.sep))
+    os.makedirs(os.path.dirname(dstdir))
+    aotcompile.system(("/bin/cp", "-a", srcdir, dstdir))
+
+try:
+    name = os.environ.get("RPM_PACKAGE_NAME")
+    if name is None:
+        raise aotcompile.Error, "not for use outside rpm specfiles"
+    arch = os.environ.get("RPM_ARCH")
+    if arch == "noarch":
+        raise aotcompile.Error, "cannot be used on noarch packages"
+    srcdir = os.environ.get("RPM_BUILD_ROOT")
+    if srcdir in (None, "/"):
+        raise aotcompile.Error, "bad $RPM_BUILD_ROOT"
+    tmpdir = os.path.join(os.getcwd(), "aot-compile-rpm")
+    if os.path.exists(tmpdir):
+        raise aotcompile.Error, "%s exists" % tmpdir
+    dstdir = os.path.join(libdir(), "gcj", name)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir, tmpdir)
+    compiler.gcjflags[0:0] = os.environ.get("RPM_OPT_FLAGS", "").split() 
+
+    # XXX: This script should not accept options, because having
+    # them it cannot be integrated into rpm.  But, gcj cannot
+    # build each and every jarfile yet, so we must be able to
+    # exclude until it can.
+    # XXX --exclude is also used in the jonas rpm to stop
+    # everything being made a subset of the mammoth client
+    # jarfile. Should adjust the subset checker's bias to
+    # favour many small jarfiles over one big one.
+    try:
+        options, exclusions = sys.argv[1:], []
+        while options:
+            if options.pop(0) != "--exclude":
+                raise ValueError
+            compiler.exclusions.append(
+                os.path.join(srcdir, options.pop(0).lstrip(os.sep)))
+    except:
+        print >>sys.stderr, "usage: %s [--exclude PATH]..." % (
+            os.path.basename(sys.argv[0]))
+        sys.exit(1)
+
+    sourcelist = os.path.join(tmpdir, "sources.list")
+    writeSourceList(os.getcwd(), sourcelist)
+    compiler.gcjflags.append("-fsource-filename=" + sourcelist)
+
+    compiler.compile()
+    copy(tmpdir, srcdir, dstdir)
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/contrib/classfile.py
===================================================================
--- libjava/contrib/classfile.py	(revision 0)
+++ libjava/contrib/classfile.py	(revision 0)
@@ -0,0 +1,221 @@
+## Copyright (C) 2004, 2005 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+"""Read Java(TM) class files."""
+
+import cStringIO as StringIO
+import struct
+
+class Class:
+    def __init__(self, arg):
+        if hasattr(arg, "read"):
+            self.fp = arg
+        elif type(arg) == type(""):
+            if arg.startswith("\xca\xfe\xba\xbe"):
+                self.fp = StringIO.StringIO(arg)
+            else:
+                self.fp = open(arg, "r")
+        else:
+            raise TypeError, type(arg)
+
+        magic = self._read_int()
+        assert magic == 0xcafebabeL
+        minor, major = self._read(">HH")        
+        self.version = (major, minor)
+
+        self.pool_integrity_checks = None
+        try:
+            assert False
+        except AssertionError:
+            self.pool_integrity_checks = []
+
+        self._read_constants_pool()
+
+        self.access_flags = self._read_short()
+        self.name = self._read_reference_Class()
+        self.super = self._read_reference_Class()
+
+        self.interfaces = self._read_interfaces()
+        self.fields = self._read_fieldsormethods()
+        self.methods = self._read_fieldsormethods()
+        self.attributes = self._read_attributes()
+
+        if self.pool_integrity_checks is not None:
+            for index, tag in self.pool_integrity_checks:
+                assert self.constants[index][0] == tag
+
+        del self.fp, self.pool_integrity_checks
+
+    def __repr__(self):
+        result = []
+        attrs = [attr for attr in dir(self)
+                 if not attr.startswith("_") and attr != "Member"]
+        attrs.sort()
+        for attr in attrs:
+            result.append("%-13s %s" % (
+                attr + ":", attr == "constants" and
+                "<ELIDED>" or repr(getattr(self, attr))))
+        return "\n".join(result)
+
+    def _read_constants_pool(self):
+        self.constants = {}
+        skip = False
+        for i in xrange(1, self._read_short()):
+            if skip:
+                skip = False
+                continue
+            tag = {
+                1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
+                6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
+                10: "Methodref", 11: "InterfaceMethodref",
+                12: "NameAndType"}[self._read_byte()]
+            skip = tag in ("Long", "Double") # crack crack crack!
+            self.constants[i] = (tag, getattr(self, "_read_constant_" + tag)())
+
+    def _read_interfaces(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self._read_reference_Class())
+        return result
+
+    def _read_fieldsormethods(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self.Member(self))
+        return result
+
+    class Member:
+        def __init__(self, source):
+            self.access_flags = source._read_short()
+            self.name = source._read_reference_Utf8()
+            self.descriptor = source._read_reference_Utf8()
+            self.attributes = source._read_attributes()
+
+        def __repr__(self):
+            result = []
+            attrs = [attr for attr in dir(self) if not attr.startswith("_")]
+            attrs.sort()
+            for attr in attrs:
+                value = getattr(self, attr)
+                if attr == "attributes" and value.has_key("Code"):
+                    value = value.copy()
+                    value.update({"Code": "<ELIDED>"})
+                result.append("%-13s %s" % (
+                    attr + ":", repr(value).replace(
+                        "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
+            return ("\n%s" % (15 * " ")).join(result)
+
+    def _read_attributes(self):
+        result = {}
+        for i in xrange(self._read_short()):
+            name = self._read_reference_Utf8()
+            data = self.fp.read(self._read_int())
+            assert not result.has_key(name)
+            result[name] = data
+        return result
+
+    # Constants pool reference reader convenience functions
+
+    def _read_reference_Utf8(self):
+        return self._read_references("Utf8")[0]
+
+    def _read_reference_Class(self):
+        return self._read_references("Class")[0]
+
+    def _read_reference_Class_NameAndType(self):
+        return self._read_references("Class", "NameAndType")
+
+    def _read_references(self, *args):
+        result = []
+        for arg in args:
+            index = self._read_short()
+            if self.pool_integrity_checks is not None:
+                self.pool_integrity_checks.append((index, arg))
+            result.append(index)
+        return result
+
+    # Constants pool constant reader functions
+
+    def _read_constant_Utf8(self):
+        constant = self.fp.read(self._read_short())
+        try:
+            constant = constant.decode("utf-8")
+        except UnicodeError:
+            constant = _bork_utf8_decode(constant)
+        try:
+            constant = constant.encode("us-ascii")
+        except UnicodeError:
+            pass
+        return constant
+
+    def _read_constant_Integer(self):
+        return self._read_int()
+
+    def _read_constant_Float(self):
+        return self._read(">f")[0]
+
+    def _read_constant_Long(self):
+        return self._read(">q")[0]
+
+    def _read_constant_Double(self):
+        return self._read(">d")[0]
+
+    _read_constant_Class = _read_reference_Utf8
+    _read_constant_String = _read_reference_Utf8
+    _read_constant_Fieldref = _read_reference_Class_NameAndType
+    _read_constant_Methodref = _read_reference_Class_NameAndType
+    _read_constant_InterfaceMethodref = _read_reference_Class_NameAndType
+
+    def _read_constant_NameAndType(self):
+        return self._read_reference_Utf8(), self._read_reference_Utf8()
+
+    # Generic reader functions
+
+    def _read_int(self):
+        # XXX how else to read 32 bits on a 64-bit box?
+        h, l = map(long, self._read(">HH"))
+        return (h << 16) + l
+
+    def _read_short(self):
+        return self._read(">H")[0]
+
+    def _read_byte(self):
+        return self._read("B")[0]
+
+    def _read(self, fmt):
+        return struct.unpack(fmt, self.fp.read(struct.calcsize(fmt)))
+
+def _bork_utf8_decode(data):
+    # more crack!
+    bytes, unicode = map(ord, data), ""
+    while bytes:
+        b1 = bytes.pop(0)
+        if b1 & 0x80:
+            assert b1 & 0x40
+            b2 = bytes.pop(0)
+            assert b2 & 0xC0 == 0x80
+            if b1 & 0x20:
+                assert not b1 & 0x10
+                b3 = bytes.pop(0)
+                assert b3 & 0xC0 == 0x80
+                unicode += unichr(
+                    ((b1 & 0x0f) << 12) + ((b2 & 0x3f) << 6) + (b3 & 0x3f))
+            else:
+                unicode += unichr(((b1 & 0x1f) << 6) + (b2 & 0x3f))
+        else:
+            unicode += unichr(b1)
+    return unicode
+
+if __name__ == "__main__":
+    print Class("/usr/share/katana/build/ListDependentClasses.class")
+
Index: libjava/contrib/aot-compile.in
===================================================================
--- libjava/contrib/aot-compile.in	(revision 0)
+++ libjava/contrib/aot-compile.in	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2006 Red Hat, Inc.
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import getopt
+import os
+
+usage = """\
+Usage: %s [OPTION...] SRCDIR DSTDIR
+AOT-compile all Java bytecode in SRCDIR into DSTDIR.
+
+Options:
+  -M, --make=PATH        make executable to use (%s)
+  -C, --gcj=PATH         gcj executable to use (%s)
+  -D, --dbtool=PATH      gcj-dbtool executable to use (%s)
+  -m, --makeflags=FLAGS  flags to pass to make during build
+  -c, --gcjflags=FLAGS   flags to pass to gcj during compilation
+                           in addition to %s
+  -l, --ldflags=FLAGS    flags to pass to gcj during linking
+                           in addition to %s
+  -e, --exclude=PATH     do not compile PATH
+
+Extra flags may also be passed using the AOT_MAKEFLAGS, AOT_GCJFLAGS
+and AOT_LDFLAGS environment variables.""" % (
+    os.path.basename(sys.argv[0]),
+    aotcompile.PATHS["make"],
+    aotcompile.PATHS["gcj"],
+    aotcompile.PATHS["dbtool"],
+    repr(" ".join(aotcompile.GCJFLAGS)),
+    repr(" ".join(aotcompile.LDFLAGS)))
+
+try:
+    if os.environ.has_key("RPM_PACKAGE_NAME"):
+        raise aotcompile.Error, "not for use within rpm specfiles"
+
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            "M:C:D:m:c:l:e:",
+            ["make=", "gcj=", "dbtool=",
+             "makeflags=" "gcjflags=", "ldflags=",
+             "exclude="])
+        srcdir, dstdir = args
+    except:
+        print >>sys.stderr, usage
+        sys.exit(1)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir)
+    for o, a in opts:
+        if o in ("-M", "--make"):
+            aotcompile.PATHS["make"] = a
+        if o in ("-C", "--gcj"):
+            aotcompile.PATHS["gcj"] = a
+        if o in ("-D", "--dbtool"):
+            aotcompile.PATHS["dbtool"] = a
+        if o in ("-m", "--makeflags"):
+            compiler.makeflags[0:0] = a.split()
+        if o in ("-c", "--gcjflags"):
+            compiler.gcjflags[0:0] = a.split()
+        if o in ("-l", "--ldflags"):
+            compiler.ldflags[0:0] = a.split()
+        if o in ("-e", "--exclude"):
+            compiler.exclusions.append(a)
+    
+    compiler.makeflags[0:0] = os.environ.get("AOT_MAKEFLAGS", "").split() 
+    compiler.gcjflags[0:0] = os.environ.get("AOT_GCJFLAGS", "").split() 
+    compiler.ldflags[0:0] = os.environ.get("AOT_LDFLAGS", "").split() 
+
+    compiler.compile()
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/ChangeLog
===================================================================
--- libjava/ChangeLog	(revision 136895)
+++ libjava/ChangeLog	(working copy)
@@ -1,3 +1,31 @@
+2008-06-26  Joshua Sumali  <jsumali@redhat.com>
+
+	* configure.ac (java-home): new AC_ARG_ENABLE.
+	(aot-compile-rpm): Likewise.
+	(CREATE_JAVA_HOME): new AM_CONDITIONAL.
+	(INSTALL_AOT_RPM): Likewise.
+	(gcc-suffix): new AC_ARG_WITH.
+	(arch-directory): Likewise.
+	(os-directory): Likewise.
+	(origin-name): Likewise.
+	(arch-suffix): Likewise.
+	(jvm-root-dir): Likewise.
+	(jvm-jar-dir): Likewise.
+	(python-dir): Likewise.
+	(AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
+	contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
+	* Makefile.am (install-data-local): Install Python modules for
+	aot-compile. Also install an sdk style directory if	--enable-java-home
+	is passed to configure.
+	(bin_SCRIPTS): add contrib/rebuild-gcj-db and contrib/aot-compile.
+	* contrib/aot-compile.in: New file.
+	* contrib/aotcompile.py.in: Likewise.
+	* contrib/aot-compile-rpm.in: Likewise.
+	* contrib/classfile.py: Likewise.
+	* contrib/rebuild-gcj-db.in: Likewise.
+	* configure: Regenerate.
+	* Makefile.in: Regenerate.
+
 2008-06-17  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
 	* configure: Regenerate.
Index: libjava/Makefile.am
===================================================================
--- libjava/Makefile.am	(revision 136895)
+++ libjava/Makefile.am	(working copy)
@@ -85,10 +85,14 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
+endif 
+
+bin_SCRIPTS = addr2name.awk contrib/rebuild-gcj-db contrib/aot-compile
+
+if INSTALL_AOT_RPM
+bin_SCRIPTS += contrib/aot-compile-rpm
 endif
 
-bin_SCRIPTS = addr2name.awk
-
 if BUILD_ECJ1
 ## We build ecjx and not ecj1 because in one mode, ecjx will not work
 ## until after 'make install', and we don't want it to be picked up in
@@ -528,8 +532,141 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
+## Install Python modules for aot-compile.
+	$(mkinstalldirs) $(DESTDIR)$(python_mod_dir); \
+	$(INSTALL_DATA) $(srcdir)/contrib/classfile.py \
+	  $(DESTDIR)$(python_mod_dir)/classfile.py; \
+	$(INSTALL_DATA) contrib/aotcompile.py \
+	  $(DESTDIR)$(python_mod_dir)/aotcompile.py;
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/`echo grmic | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/`echo gjavah | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/`echo gappletviewer | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/`echo gjarsigner | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo gnative2ascii | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/`echo gserialver | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-$(gcc_version).jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	ln -sf $$RELATIVE/libjawt.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$(gcc_version).jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	ln -sf $$RELATIVE/src-$(gcc_version).zip \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip;
+endif
 
-
 ## ################################################################
 
 ##
Index: libjava/configure.ac
===================================================================
--- libjava/configure.ac	(revision 136895)
+++ libjava/configure.ac	(working copy)
@@ -1625,6 +1625,211 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)
 
+AC_ARG_WITH([python-dir],
+            AS_HELP_STRING([--with-python-dir],
+                           [the location to install Python modules. This path should NOT include the prefix.]),
+            [with_python_dir=$withval], [with_python_dir=""])
+
+if test "x${with_python_dir}" = "x"
+then
+  # Needed for installing Python modules during make install.
+  python_mod_dir="\${prefix}/share/python"
+  # Needed for substituting into aot-compile*
+  python_mod_dir_expanded="${prefix}/share/python"
+else
+  python_mod_dir="\${prefix}${with_python_dir}"
+  python_mod_dir_expanded="${prefix}${with_python_dir}"
+fi
+AC_MSG_RESULT(Python modules dir: ${python_mod_dir_expanded});
+AC_SUBST(python_mod_dir)
+AC_SUBST(python_mod_dir_expanded)
+
+# needed for aot-compile-rpm
+MAKE=`which make`
+AC_SUBST(MAKE)
+
+AC_ARG_ENABLE([aot-compile-rpm],
+  [AS_HELP_STRING([--enable-aot-compile-rpm],
+                 [enable installation of aot-compile-rpm [default=no]])],
+  [case "${enableval}" in
+    yes) AOT_RPM_ENABLED=yes ;;
+    no)  AOT_RPM_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable aot-compile-rpm]) ;;
+  esac],
+  [AOT_RPM_ENABLED=no]
+)
+AM_CONDITIONAL(INSTALL_AOT_RPM, test "x${AOT_RPM_ENABLED}" == xyes)
+
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir="\${prefix}/lib/jvm"])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=\${prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
+  AC_SUBST(JAVA_HOME_DIR)
+  AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc
@@ -1633,6 +1838,10 @@
 gcj/Makefile
 include/Makefile
 testsuite/Makefile
+contrib/aotcompile.py
+contrib/aot-compile
+contrib/aot-compile-rpm
+contrib/rebuild-gcj-db
 ])
 
 if test ${multilib} = yes; then

[-- Attachment #3: gcc-install-and-docs-update1.patch --]
[-- Type: text/x-patch, Size: 9678 bytes --]

Index: gcc/ChangeLog
===================================================================
--- gcc/ChangeLog	(revision 137153)
+++ gcc/ChangeLog	(working copy)
@@ -1,3 +1,15 @@
+2008-06-26  Joshua Sumali  <jsumali@redhat.com>
+
+	* doc/install.texi (--enable-java-home): Document.
+	(--enable-aot-compile-rpm): Likewise.
+	(--with-arch-directory): Likewise.
+	(--with-os-directory): Likewise.
+	(--with-origin-name): Likewise.
+	(--with-arch-suffix): Likewise.
+	(--with-jvm-root-dir): Likewise.
+	(--with-jvm-jar-dir): Likewise.
+	(--with-python-dir): Likewise.
+
 2008-06-26  Joseph Myers  <joseph@codesourcery.com>
 
 	* c-decl.c (merge_decls): Use !current_function_decl to check for
Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 137153)
+++ gcc/doc/install.texi	(working copy)
@@ -1607,6 +1607,45 @@
 @item --with-win32-nlsapi=ansi, unicows or unicode
 Indicates how MinGW @samp{libgcj} translates between UNICODE
 characters and the Win32 API@.
+
+@item --enable-java-home
+If enabled, this creates a JPackage compatible SDK environment during install.
+Note that if --enable-java-home is used, --with-arch-directory=ARCH must also
+be specified.
+
+@item --with-arch-directory=ARCH
+Specifies the name to use for the @file{jre/lib/ARCH} directory in the SDK 
+environment created when --enable-java-home is passed. Typical names for this 
+directory include i386, amd64, ia64, etc.
+
+@item --with-os-directory=DIR
+Specifies the OS directory for the SDK include directory. This is set to auto
+detect, and is typically 'linux'.
+
+@item --with-origin-name=NAME
+Specifies the JPackage origin name. This defaults to the 'gcj' in
+java-1.5.0-gcj.
+
+@item --with-arch-suffix=SUFFIX
+Specifies the suffix for the sdk directory. Defaults to the empty string. 
+Examples include '.x86_64' in 'java-1.5.0-gcj-1.5.0.0.x86_64'.
+
+@item --with-jvm-root-dir=DIR
+Specifies where to install the SDK. Default is $(prefix)/lib/jvm.
+
+@item --with-jvm-jar-dir=DIR
+Specifies where to install jars. Default is $(prefix)/lib/jvm-exports.
+
+@item --with-python-dir=DIR
+Specifies where to install the Python modules used for aot-compile. DIR should
+not include the prefix used in installation. For example, if the Python modules
+are to be installed in /usr/lib/python2.5/site-packages, then 
+--with-python-dir=/lib/python2.5/site-packages should be passed. If this is
+not specified, then the Python modules are installed in $(prefix)/share/python.
+
+@item --enable-aot-compile-rpm
+Adds aot-compile-rpm to the list of installed scripts.
+
 @table @code
 @item ansi
 Use the single-byte @code{char} and the Win32 A functions natively,
Index: gcc/java/ChangeLog
===================================================================
--- gcc/java/ChangeLog	(revision 137153)
+++ gcc/java/ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2008-06-26  Joshua Sumali  <jsumali@redhat.com>
+
+	* Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and
+	doc/rebuild-gcj-db.1
+	(java.uninstall): Likewise.
+	(java.maintainer-clean): Likewise.
+	(aot-compile.pod): New rule.
+	(rebuild-gcj-db.pod): New rule.
+	(java.install-man): Install doc/aot-compile.1 and doc/rebuild-gcj-db.1
+	* gcj.texi: Add new sections for aot-compile and rebuild-gcj-db.
+
 2008-06-24  Tom Tromey  <tromey@redhat.com>
 
 	* jcf-path.c (jcf_path_init): Don't name variable 'try'.
Index: gcc/java/gcj.texi
===================================================================
--- gcc/java/gcj.texi	(revision 137153)
+++ gcc/java/gcj.texi	(working copy)
@@ -72,6 +72,11 @@
                             Generate stubs for Remote Method Invocation.
 * gc-analyze: (gcj)Invoking gc-analyze.
                             Analyze Garbage Collector (GC) memory dumps.
+* aot-compile: (gcj)Invoking aot-compile.
+                            Compile bytecode to native and generate databases.
+* rebuild-gcj-db: (gcj)Invoking rebuild-gcj-db.
+                            Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 @end direntry
 @end format
 
@@ -115,6 +120,9 @@
 * Invoking jv-convert:: Converting from one encoding to another
 * Invoking grmic::      Generate stubs for Remote Method Invocation.
 * Invoking gc-analyze:: Analyze Garbage Collector (GC) memory dumps.
+* Invoking aot-compile:: Compile bytecode to native and generate databases.
+* Invoking rebuild-gcj-db:: Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 * About CNI::           Description of the Compiled Native Interface
 * System properties::   Modifying runtime behavior of the libgcj library
 * Resources::           Where to look for more information
@@ -921,7 +929,7 @@
   [@option{-v}] [@option{-m}] [@option{--version}] [@option{--help}]
 
 @c man end
-@c man begin SEEALSO gij
+@c man begin SEEALSO gcj-dbtool
 gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
 and the Info entries for @file{gcj} and @file{gcc}.
 @c man end
@@ -1219,6 +1227,87 @@
 
 @c man end
 
+@node Invoking aot-compile
+@chapter Invoking aot-compile
+
+@c man title aot-compile Compile bytecode to native and generate databases
+
+@ignore
+
+@c man begin SYNOPSIS aot-compile
+aot-compile [@option{OPTION}] @dots{} @var{SRCDIR} @var{DSTDIR}
+
+aot-compile [@option{-M, --make}=@var{PATH}] [@option{-C, --gcj}=@var{PATH}]
+  [@option{-D, --dbtool}=@var{PATH}] [@option{-m, --makeflags}=@var{FLAGS}] 
+  [@option{-c, --gcjflags}=@var{FLAGS}] [@option{-l, --ldflags}=@var{FLAGS}] 
+  [@option{-e, --exclude}=@var{PATH}]
+@c man end
+
+@c man begin SEEALSO aot-compile
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION aot-compile
+@code{aot-compile} is a script that searches a directory for Java bytecode
+(as class files, or in jars) and uses @code{gcj} to compile it to native
+code and generate the databases from it.
+@c man end
+
+@c man begin OPTIONS aot-compile
+@table @gcctabopt
+@item -M, --make=@var{PATH}
+Specify the path to the @code{make} executable to use.
+
+@item -C, --gcj=@var{PATH}
+Specify the path to the @code{gcj} executable to use.
+
+@item -D, --dbtool=@var{PATH}
+Specify the path to the @code{gcj-dbtool} executable to use.
+
+@item -m, --makeflags=@var{FLAGS}
+Specify flags to pass to @code{make} during the build.
+
+@item -c, --gcjflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during compilation, in addition to
+'-fPIC -findirect-dispatch -fjni'.
+
+@item -l, --ldflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during linking, in addition to
+'-Wl,-Bsymbolic'.
+
+@item -e, --exclude=@var{PATH}
+Do not compile @var{PATH}.
+
+@end table
+
+@c man end
+
+@node Invoking rebuild-gcj-db
+@chapter Invoking rebuild-gcj-db
+
+@c man title rebuild-gcj-db Merge the per-solib databases made by aot-compile into one system-wide database.
+@ignore
+
+@c man begin SYNOPSIS rebuild-gcj-db
+rebuild-gcj-db
+@c man end
+
+@c man begin SEEALSO rebuild-gcj-db
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION rebuild-gcj-db
+@code{rebuild-gcj-db} is a script that merges the per-solib databases made by
+@code{aot-compile} into one system-wide database so @code{gij} can find the 
+solibs.
+@c man end
+
 @node About CNI
 @chapter About CNI
 
Index: gcc/java/Make-lang.in
===================================================================
--- gcc/java/Make-lang.in	(revision 137153)
+++ gcc/java/Make-lang.in	(working copy)
@@ -143,8 +143,9 @@
 java.html: $(build_htmldir)/java/index.html
 
 JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
-                doc/jv-convert.1 doc/grmic.1\
-		doc/gcj-dbtool.1 doc/gc-analyze.1
+                doc/jv-convert.1 doc/grmic.1 \
+                doc/gcj-dbtool.1 doc/gc-analyze.1 doc/aot-compile.1 \
+                doc/rebuild-gcj-db.1
 
 java.man: $(JAVA_MANFILES)
 
@@ -189,6 +190,8 @@
 	-rm -rf $(DESTDIR)$(man1dir)/gij$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/jv-convert$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/gcj-dbtool$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/aot-compile$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/rebuild-gcj-db$(man1ext)
 
 java.install-info: $(DESTDIR)$(infodir)/gcj.info
 
@@ -223,6 +226,8 @@
 	-rm -f $(docobjdir)/grmic.1
 	-rm -f $(docobjdir)/gcj-dbtool.1
 	-rm -f $(docobjdir)/gc-analyze.1
+	-rm -f $(docobjdir)/aot-compile.1
+	-rm -f $(docobjdir)/rebuild-gcj-db.1
 #\f
 # Stage hooks:
 # The main makefile has already created stage?/java.
@@ -353,15 +358,21 @@
 	-$(TEXI2POD) -D gcj-dbtool < $< > $@
 gc-analyze.pod: java/gcj.texi
 	-$(TEXI2POD) -D gc-analyze < $< > $@
+aot-compile.pod: java/gcj.texi
+	-$(TEXI2POD) -D aot-compile < $< > $@
+rebuild-gcj-db.pod: java/gcj.texi
+	-$(TEXI2POD) -D rebuild-gcj-db < $< > $@
 
 # Install the man pages.
 java.install-man: installdirs \
                   $(DESTDIR)$(man1dir)/$(JAVA_INSTALL_NAME)$(man1ext) \
 		  $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS:%=doc/%.1) \
 		  doc/gij.1 doc/jv-convert.1 doc/grmic.1 \
-		  doc/gcj-dbtool.1 doc/gc-analyze.1
+		  doc/gcj-dbtool.1 doc/gc-analyze.1 \
+		  doc/aot-compile.1 doc/rebuild-gcj-db.1
 	for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS) \
-		gij jv-convert grmic gcj-dbtool gc-analyze ; do \
+		gij jv-convert grmic gcj-dbtool gc-analyze aot-compile \
+		rebuild-gcj-db; do \
 	  tool_transformed_name=`echo $$tool|sed '$(program_transform_name)'`; \
 	  man_name=$(DESTDIR)$(man1dir)/$${tool_transformed_name}$(man1ext); \
 	  rm -f $$man_name ; \

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-26 18:18           ` Joshua Sumali
@ 2008-06-30 10:20             ` Andrew Haley
  2008-06-30 13:54               ` Joshua Sumali
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Haley @ 2008-06-30 10:20 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches

Joshua Sumali wrote:
> Joshua Sumali wrote:
>> Andrew Haley wrote:
>>> Joshua Sumali wrote:
>>>
>>>  
>>>> Please see the two (updated) patches. The updated patch for the
>>>> "Packager files" thread is now part of the sdk-home patch attached
>>>> here,
>>>> since I had to modify configure.ac to generate those packager files
>>>> this
>>>> time around.
>>>>
>>>> gcc-install-and-docs.patch creates man and info pages for aot-compile
>>>> and rebuild-gcj-db, and also documents the new install options
>>>> (--enable-java-home, --with-arch-directory, --with-python-dir) as
>>>> requested by Matthias.
>>>> gcc-libjava-sdk-home-update.patch is mostly the same as the first patch
>>>> I posted here, except with these main changes:
>>>>
>>>>    - aot-compile and rebuild-gcj-db are now installed in $bindir
>>>>    - if --with-python-dir is not specified (say, in a regular upstream
>>>> build) , classfile.py and aotcompile.py are installed in
>>>> $(prefix)/share/python. Otherwise, those Python modules will be
>>>> installed in the path specified with --with-python-dir. I modified
>>>> aot-compile -> aot-compile.in to append whichever path classfile.py and
>>>> aotcompile.py was installed in, so that it can actually find these
>>>> modules (it wouldn't look in $(prefix)/share/python by default).
>>>>    - the SDK symlinked binaries, as well as aot-compile and
>>>> rebuild-gcj-db are now `transformed' as requested by Matthias.
>>>>     
>>>
>>> OK, thanks.
>>>
>>>  
>>>> Outstanding issues:
>>>> 1. @Matthias, I'm still not sure what you mean by "Same for using
>>>> GIJ_VERSION". Also, the issue about "why using the long version at
>>>> all?"
>>>> 2. rebuild-gcj-db doesn't have a licence header on the top of the
>>>> file... is this required? And if so, what's the right thing to do
>>>> about it?
>>>>     
>>>
>>> Make it GPL.
>>>
>>> Andrew.
>>>   
>> Updated rebuild-gcj-db with license header.
>>
>> Josh
> Hi,
> 
> Updated documentation, and sdk patch attached. I think this one is ready
> to go in.

Nearly there.

Please don't put the ChangeLog files into the diffs.  Post them as plain text.

Please assign all Red Hat copyrights to the FSF.

Do I take it that you don't have commit access to the gcc tree?

Andrew.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-30 10:20             ` Andrew Haley
@ 2008-06-30 13:54               ` Joshua Sumali
  2008-06-30 13:57                 ` Andrew Haley
  0 siblings, 1 reply; 18+ messages in thread
From: Joshua Sumali @ 2008-06-30 13:54 UTC (permalink / raw)
  To: Andrew Haley, java-patches

Andrew Haley wrote:
>
> Nearly there.
>
> Please don't put the ChangeLog files into the diffs.  Post them as plain text.
>   
Will do.
> Please assign all Red Hat copyrights to the FSF.
>   
Is there a special way to do this, or do I simply change "Copyright (C) 
2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free 
Software Foundation" on the appropriate files?
> Do I take it that you don't have commit access to the gcc tree?
>   
I do not. I was hoping someone would be able to commit the patches for me.
> Andrew.
>   
Josh

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-30 13:54               ` Joshua Sumali
@ 2008-06-30 13:57                 ` Andrew Haley
  2008-06-30 14:39                   ` Joshua Sumali
  0 siblings, 1 reply; 18+ messages in thread
From: Andrew Haley @ 2008-06-30 13:57 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches

Joshua Sumali wrote:
> Andrew Haley wrote:

>> Please assign all Red Hat copyrights to the FSF.
>>   
> Is there a special way to do this, or do I simply change "Copyright (C)
> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
> Software Foundation" on the appropriate files?

That's all you have to do.

>> Do I take it that you don't have commit access to the gcc tree?
>>   
> I do not. I was hoping someone would be able to commit the patches for me.

I'll do it.

Andrew.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-30 13:57                 ` Andrew Haley
@ 2008-06-30 14:39                   ` Joshua Sumali
  2008-07-01 13:59                     ` Andrew Haley
  2008-07-02 13:07                     ` Andrew Haley
  0 siblings, 2 replies; 18+ messages in thread
From: Joshua Sumali @ 2008-06-30 14:39 UTC (permalink / raw)
  To: Andrew Haley; +Cc: java-patches

[-- Attachment #1: Type: text/plain, Size: 2630 bytes --]

Andrew Haley wrote:
> Joshua Sumali wrote:
>   
>> Andrew Haley wrote:
>>     
>
>   
>>> Please assign all Red Hat copyrights to the FSF.
>>>   
>>>       
>> Is there a special way to do this, or do I simply change "Copyright (C)
>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
>> Software Foundation" on the appropriate files?
>>     
>
> That's all you have to do.
>
>   
>>> Do I take it that you don't have commit access to the gcc tree?
>>>   
>>>       
>> I do not. I was hoping someone would be able to commit the patches for me.
>>     
>
> I'll do it.
>
> Andrew.
>
>   
Copyrights assigned to FSF. ChangeLogs removed from patches and are 
found below.

libjava/

2008-06-30  Joshua Sumali  <jsumali@redhat.com>

    * configure.ac (java-home): new AC_ARG_ENABLE.
    (aot-compile-rpm): Likewise.
    (CREATE_JAVA_HOME): new AM_CONDITIONAL.
    (INSTALL_AOT_RPM): Likewise.
    (gcc-suffix): new AC_ARG_WITH.
    (arch-directory): Likewise.
    (os-directory): Likewise.
    (origin-name): Likewise.
    (arch-suffix): Likewise.
    (jvm-root-dir): Likewise.
    (jvm-jar-dir): Likewise.
    (python-dir): Likewise.
    (AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
    contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
    * Makefile.am (install-data-local): Install Python modules for
    aot-compile. Also install an sdk style directory if --enable-java-home
    is passed to configure.
    (bin_SCRIPTS): add contrib/rebuild-gcj-db and contrib/aot-compile.
    * contrib/aot-compile.in: New file.
    * contrib/aotcompile.py.in: Likewise.
    * contrib/aot-compile-rpm.in: Likewise.
    * contrib/classfile.py: Likewise.
    * contrib/rebuild-gcj-db.in: Likewise.
    * configure: Regenerate.
    * Makefile.in: Regenerate.

gcc/

2008-06-30  Joshua Sumali  <jsumali@redhat.com>

    * doc/install.texi (--enable-java-home): Document.
    (--enable-aot-compile-rpm): Likewise.
    (--with-arch-directory): Likewise.
    (--with-os-directory): Likewise.
    (--with-origin-name): Likewise.
    (--with-arch-suffix): Likewise.
    (--with-jvm-root-dir): Likewise.
    (--with-jvm-jar-dir): Likewise.
    (--with-python-dir): Likewise.

gcc/java/

2008-06-30  Joshua Sumali  <jsumali@redhat.com>

    * Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and
    doc/rebuild-gcj-db.1
    (java.uninstall): Likewise.
    (java.maintainer-clean): Likewise.
    (aot-compile.pod): New rule.
    (rebuild-gcj-db.pod): New rule.
    (java.install-man): Install doc/aot-compile.1 and doc/rebuild-gcj-db.1
    * gcj.texi: Add new sections for aot-compile and rebuild-gcj-db.



[-- Attachment #2: gcc-libjava-sdk-home-update4.patch --]
[-- Type: text/x-patch, Size: 46246 bytes --]

Index: libjava/contrib/rebuild-gcj-db.in
===================================================================
--- libjava/contrib/rebuild-gcj-db.in	(revision 0)
+++ libjava/contrib/rebuild-gcj-db.in	(revision 0)
@@ -0,0 +1,24 @@
+#!/bin/bash
+# rebuild-gcj-db
+
+## Copyright (C) 2000, 2002, 2003, 2008 Free Software Foundation
+##
+##   This file is part of libgcj.
+##
+## This software is copyrighted work licensed under the terms of the
+## Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+## details.
+
+# Rebuild all the standard databases.
+for base in /usr/lib*; do
+   dbLocation=`@prefix@/bin/gcj-dbtool@gcc_suffix@ -p $base`
+   libdir=$base/gcj
+   if ! test -d $libdir; then
+      # No shared libraries here.
+      continue
+   fi
+   dirname $dbLocation | xargs mkdir -p
+   @prefix@/bin/gcj-dbtool@gcc_suffix@ -n $dbLocation 64
+   find $libdir -follow -name '*.db' -print0 | \
+      xargs -0 @prefix@/bin/gcj-dbtool@gcc_suffix@ -m $dbLocation $dbLocation
+done
Index: libjava/contrib/aotcompile.py.in
===================================================================
--- libjava/contrib/aotcompile.py.in	(revision 0)
+++ libjava/contrib/aotcompile.py.in	(revision 0)
@@ -0,0 +1,412 @@
+# -*- python -*-
+
+## Copyright (C) 2005, 2006, 2008 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import classfile
+import copy
+import md5
+import operator
+import os
+import sys
+import cStringIO as StringIO
+import zipfile
+
+PATHS = {"make":   "@MAKE@",
+         "gcj":    "@prefix@/bin/gcj@gcc_suffix@",
+         "dbtool": "@prefix@/bin/gcj-dbtool@gcc_suffix@"}
+
+MAKEFLAGS = []
+GCJFLAGS = ["-fPIC", "-findirect-dispatch", "-fjni"]
+LDFLAGS = ["-Wl,-Bsymbolic"]
+
+MAX_CLASSES_PER_JAR = 1024
+MAX_BYTES_PER_JAR = 1048576
+
+MAKEFILE = "Makefile"
+
+MAKEFILE_HEADER = '''\
+GCJ = %(gcj)s
+DBTOOL = %(dbtool)s
+GCJFLAGS = %(gcjflags)s
+LDFLAGS = %(ldflags)s
+
+%%.o: %%.jar
+	$(GCJ) -c $(GCJFLAGS) $< -o $@
+
+TARGETS = \\
+%(targets)s
+
+all: $(TARGETS)'''
+
+MAKEFILE_JOB = '''
+%(base)s_SOURCES = \\
+%(jars)s
+
+%(base)s_OBJECTS = \\
+$(%(base)s_SOURCES:.jar=.o)
+
+%(dso)s: $(%(base)s_OBJECTS)
+	$(GCJ) -shared $(GCJFLAGS) $(LDFLAGS) $^ -o $@
+
+%(db)s: $(%(base)s_SOURCES)
+	$(DBTOOL) -n $@ 64
+	for jar in $^; do \\
+            $(DBTOOL) -f $@ $$jar \\
+                %(libdir)s/%(dso)s; \\
+        done'''
+
+ZIPMAGIC, CLASSMAGIC = "PK\x03\x04", "\xca\xfe\xba\xbe"
+
+class Error(Exception):
+    pass
+
+class Compiler:
+    def __init__(self, srcdir, libdir, prefix = None):
+        self.srcdir = os.path.abspath(srcdir)
+        self.libdir = os.path.abspath(libdir)
+        if prefix is None:
+            self.dstdir = self.libdir
+        else:
+            self.dstdir = os.path.join(prefix, self.libdir.lstrip(os.sep))
+
+        # Calling code may modify these parameters
+        self.gcjflags = copy.copy(GCJFLAGS)
+        self.ldflags = copy.copy(LDFLAGS)
+        self.makeflags = copy.copy(MAKEFLAGS)
+        self.exclusions = []
+
+    def compile(self):
+        """Search srcdir for classes and jarfiles, then generate
+        solibs and mappings databases for them all in libdir."""
+        if not os.path.isdir(self.dstdir):
+            os.makedirs(self.dstdir)
+        oldcwd = os.getcwd()
+        os.chdir(self.dstdir)
+        try:            
+            jobs = self.getJobList()
+            if not jobs:
+                raise Error, "nothing to do"
+            self.writeMakefile(MAKEFILE, jobs)
+            for job in jobs:
+                job.writeJars()
+            system([PATHS["make"]] + self.makeflags)
+            for job in jobs:
+                job.clean()
+            os.unlink(MAKEFILE)
+        finally:
+            os.chdir(oldcwd)
+
+    def getJobList(self):
+        """Return all jarfiles and class collections in srcdir."""
+        jobs = weed_jobs(find_jobs(self.srcdir, self.exclusions))
+        set_basenames(jobs)
+        return jobs
+
+    def writeMakefile(self, path, jobs):
+        """Generate a makefile to build the solibs and mappings
+        databases for the specified list of jobs."""
+        fp = open(path, "w")
+        print >>fp, MAKEFILE_HEADER % {
+            "gcj": PATHS["gcj"],
+            "dbtool": PATHS["dbtool"],
+            "gcjflags": " ".join(self.gcjflags),
+            "ldflags": " ".join(self.ldflags),
+            "targets": " \\\n".join(reduce(operator.add, [
+                (job.dsoName(), job.dbName()) for job in jobs]))}
+        for job in jobs:
+            values = job.ruleArguments()
+            values["libdir"] = self.libdir
+            print >>fp, MAKEFILE_JOB % values
+        fp.close()
+
+def find_jobs(dir, exclusions = ()):
+    """Scan a directory and find things to compile: jarfiles (zips,
+    wars, ears, rars, etc: we go by magic rather than file extension)
+    and directories of classes."""
+    def visit((classes, zips), dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            magic = open(path, "r").read(4)
+            if magic == ZIPMAGIC:
+                zips.append(path)
+            elif magic == CLASSMAGIC:
+                classes.append(path)
+    classes, paths = [], []
+    os.path.walk(dir, visit, (classes, paths))
+    # Convert the list of classes into a list of directories
+    while classes:
+        # XXX this requires the class to be correctly located in its heirachy.
+        path = classes[0][:-len(os.sep + classname(classes[0]) + ".class")]
+        paths.append(path)
+        classes = [cls for cls in classes if not cls.startswith(path)]
+    # Handle exclusions.  We're really strict about them because the
+    # option is temporary in aot-compile-rpm and dead options left in
+    # specfiles will hinder its removal.
+    for path in exclusions:
+        if path in paths:
+            paths.remove(path)
+        else:
+            raise Error, "%s: path does not exist or is not a job" % path
+    # Build the list of jobs
+    jobs = []
+    paths.sort()
+    for path in paths:
+        if os.path.isfile(path):
+            job = JarJob(path)
+        else:
+            job = DirJob(path)
+        if len(job.classes):
+            jobs.append(job)
+    return jobs
+
+class Job:
+    """A collection of classes that will be compiled as a unit."""
+    
+    def __init__(self, path):
+        self.path, self.classes, self.blocks = path, {}, None
+
+    def addClass(self, bytes):
+        """Subclasses call this from their __init__ method for
+        every class they find."""
+        self.classes[md5.new(bytes).digest()] = bytes
+
+    def __makeBlocks(self):
+        """Split self.classes into chunks that can be compiled to
+        native code by gcj.  In the majority of cases this is not
+        necessary -- the job will have come from a jarfile which will
+        be equivalent to the one we generate -- but this only happens
+        _if_ the job was a jarfile and _if_ the jarfile isn't too big
+        and _if_ the jarfile has the correct extension and _if_ all
+        classes are correctly named and _if_ the jarfile has no
+        embedded jarfiles.  Fitting a special case around all these
+        conditions is tricky to say the least.
+
+        Note that this could be called at the end of each subclass's
+        __init__ method.  The reason this is not done is because we
+        need to parse every class file.  This is slow, and unnecessary
+        if the job is subsetted."""
+        names = {}
+        for hash, bytes in self.classes.items():
+            name = classname(bytes)
+            if not names.has_key(name):
+                names[name] = []
+            names[name].append(hash)
+        names = names.items()
+        # We have to sort somehow, or the jars we generate 
+        # We sort by name in a simplistic attempt to keep related
+        # classes together so inter-class optimisation can happen.
+        names.sort()
+        self.blocks, bytes = [[]], 0
+        for name, hashes in names:
+            for hash in hashes:
+                if len(self.blocks[-1]) >= MAX_CLASSES_PER_JAR \
+                   or bytes >= MAX_BYTES_PER_JAR:
+                    self.blocks.append([])
+                    bytes = 0
+                self.blocks[-1].append((name, hash))
+                bytes += len(self.classes[hash])
+
+    # From Archit Shah:
+    #   The implementation and the documentation don't seem to match.
+    #  
+    #    [a, b].isSubsetOf([a]) => True
+    #  
+    #   Identical copies of all classes this collection do not exist
+    #   in the other. I think the method should be named isSupersetOf
+    #   and the documentation should swap uses of "this" and "other"
+    #
+    # XXX think about this when I've had more sleep...
+    def isSubsetOf(self, other):
+        """Returns True if identical copies of all classes in this
+        collection exist in the other."""
+        for item in other.classes.keys():
+            if not self.classes.has_key(item):
+                return False
+        return True
+
+    def __targetName(self, ext):
+        return self.basename + ext
+
+    def tempJarName(self, num):
+        return self.__targetName(".%d.jar" % (num + 1))
+
+    def tempObjName(self, num):
+        return self.__targetName(".%d.o" % (num + 1))
+
+    def dsoName(self):
+        """Return the filename of the shared library that will be
+        built from this job."""
+        return self.__targetName(".so")
+
+    def dbName(self):
+        """Return the filename of the mapping database that will be
+        built from this job."""
+        return self.__targetName(".db")
+
+    def ruleArguments(self):
+        """Return a dictionary of values that when substituted
+        into MAKEFILE_JOB will create the rules required to build
+        the shared library and mapping database for this job."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        return {
+            "base": "".join(
+                [c.isalnum() and c or "_" for c in self.dsoName()]),
+            "jars": " \\\n".join(
+                [self.tempJarName(i) for i in xrange(len(self.blocks))]),
+            "dso": self.dsoName(),
+            "db": self.dbName()}
+
+    def writeJars(self):
+        """Generate jarfiles that can be native compiled by gcj."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for block, i in zip(self.blocks, xrange(len(self.blocks))):
+            jar = zipfile.ZipFile(self.tempJarName(i), "w", zipfile.ZIP_STORED)
+            for name, hash in block:
+                jar.writestr(
+                    zipfile.ZipInfo("%s.class" % name), self.classes[hash])
+            jar.close()
+
+    def clean(self):
+        """Delete all temporary files created during this job's build."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for i in xrange(len(self.blocks)):
+            os.unlink(self.tempJarName(i))
+            os.unlink(self.tempObjName(i))
+
+class JarJob(Job):
+    """A Job whose origin was a jarfile."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        self._walk(zipfile.ZipFile(path, "r"))
+
+    def _walk(self, zf):
+        for name in zf.namelist():
+            bytes = zf.read(name)
+            if bytes.startswith(ZIPMAGIC):
+                self._walk(zipfile.ZipFile(StringIO.StringIO(bytes)))
+            elif bytes.startswith(CLASSMAGIC):
+                self.addClass(bytes)
+
+class DirJob(Job):
+    """A Job whose origin was a directory of classfiles."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        os.path.walk(path, DirJob._visit, self)
+
+    def _visit(self, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            fp = open(path, "r")
+            magic = fp.read(4)
+            if magic == CLASSMAGIC:
+                self.addClass(magic + fp.read())
+    
+def weed_jobs(jobs):
+    """Remove any jarfiles that are completely contained within
+    another.  This is more common than you'd think, and we only
+    need one nativified copy of each class after all."""
+    jobs = copy.copy(jobs)
+    while True:
+        for job1 in jobs:
+            for job2 in jobs:
+                if job1 is job2:
+                    continue
+                if job1.isSubsetOf(job2):
+                    msg = "subsetted %s" % job2.path
+                    if job2.isSubsetOf(job1):
+                        if (isinstance(job1, DirJob) and
+                            isinstance(job2, JarJob)):
+                            # In the braindead case where a package
+                            # contains an expanded copy of a jarfile
+                            # the jarfile takes precedence.
+                            continue
+                        msg += " (identical)"
+                    warn(msg)
+                    jobs.remove(job2)
+                    break
+            else:
+                continue
+            break
+        else:
+            break
+        continue
+    return jobs
+
+def set_basenames(jobs):
+    """Ensure that each jarfile has a different basename."""
+    names = {}
+    for job in jobs:
+        name = os.path.basename(job.path)
+        if not names.has_key(name):
+            names[name] = []
+        names[name].append(job)
+    for name, set in names.items():
+        if len(set) == 1:
+            set[0].basename = name
+            continue
+        # prefix the jar filenames to make them unique
+        # XXX will not work in most cases -- needs generalising
+        set = [(job.path.split(os.sep), job) for job in set]
+        minlen = min([len(bits) for bits, job in set])
+        set = [(bits[-minlen:], job) for bits, job in set]
+        bits = apply(zip, [bits for bits, job in set])
+        while True:
+            row = bits[-2]
+            for bit in row[1:]:
+                if bit != row[0]:
+                    break
+            else:
+                del bits[-2]
+                continue
+            break
+        set = zip(
+            ["_".join(name) for name in apply(zip, bits[-2:])],
+            [job for bits, job in set])
+        for name, job in set:
+            warn("building %s as %s" % (job.path, name))
+            job.basename = name
+    # XXX keep this check until we're properly general
+    names = {}
+    for job in jobs:
+        name = job.basename
+        if names.has_key(name):
+            raise Error, "%s: duplicate jobname" % name
+        names[name] = 1
+
+def system(command):
+    """Execute a command."""
+    status = os.spawnv(os.P_WAIT, command[0], command)
+    if status > 0:
+        raise Error, "%s exited with code %d" % (command[0], status)
+    elif status < 0:
+        raise Error, "%s killed by signal %d" % (command[0], -status)
+
+def warn(msg):
+    """Print a warning message."""
+    print >>sys.stderr, "%s: warning: %s" % (
+        os.path.basename(sys.argv[0]), msg)
+
+def classname(bytes):
+    """Extract the class name from the bytes of a class file."""
+    klass = classfile.Class(bytes)
+    return klass.constants[klass.constants[klass.name][1]][1]
Index: libjava/contrib/aot-compile-rpm.in
===================================================================
--- libjava/contrib/aot-compile-rpm.in	(revision 0)
+++ libjava/contrib/aot-compile-rpm.in	(revision 0)
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2005, 2006, 2007 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import os
+
+def libdir():
+    cmd = "%s -p" % aotcompile.PATHS["dbtool"]
+    dir = os.path.abspath(os.popen(cmd, "r").readline().rstrip())
+    dir, base = os.path.split(dir)
+    if base != "classmap.db":
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    dir, base = os.path.split(dir)
+    if not base.startswith("gcj-"):
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    return dir
+
+def writeSourceList(srcdir, dstpath):
+    def visit(fp, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.isfile(path):
+                print >>fp, path
+    dstdir = os.path.dirname(dstpath)
+    if not os.path.isdir(dstdir):
+        os.makedirs(dstdir)
+    os.path.walk(srcdir, visit, open(dstpath, "w"))
+
+def copy(srcdir, dstdir, suffix):
+    srcdir = os.path.join(srcdir, suffix.lstrip(os.sep))
+    dstdir = os.path.join(dstdir, suffix.lstrip(os.sep))
+    os.makedirs(os.path.dirname(dstdir))
+    aotcompile.system(("/bin/cp", "-a", srcdir, dstdir))
+
+try:
+    name = os.environ.get("RPM_PACKAGE_NAME")
+    if name is None:
+        raise aotcompile.Error, "not for use outside rpm specfiles"
+    arch = os.environ.get("RPM_ARCH")
+    if arch == "noarch":
+        raise aotcompile.Error, "cannot be used on noarch packages"
+    srcdir = os.environ.get("RPM_BUILD_ROOT")
+    if srcdir in (None, "/"):
+        raise aotcompile.Error, "bad $RPM_BUILD_ROOT"
+    tmpdir = os.path.join(os.getcwd(), "aot-compile-rpm")
+    if os.path.exists(tmpdir):
+        raise aotcompile.Error, "%s exists" % tmpdir
+    dstdir = os.path.join(libdir(), "gcj", name)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir, tmpdir)
+    compiler.gcjflags[0:0] = os.environ.get("RPM_OPT_FLAGS", "").split() 
+
+    # XXX: This script should not accept options, because having
+    # them it cannot be integrated into rpm.  But, gcj cannot
+    # build each and every jarfile yet, so we must be able to
+    # exclude until it can.
+    # XXX --exclude is also used in the jonas rpm to stop
+    # everything being made a subset of the mammoth client
+    # jarfile. Should adjust the subset checker's bias to
+    # favour many small jarfiles over one big one.
+    try:
+        options, exclusions = sys.argv[1:], []
+        while options:
+            if options.pop(0) != "--exclude":
+                raise ValueError
+            compiler.exclusions.append(
+                os.path.join(srcdir, options.pop(0).lstrip(os.sep)))
+    except:
+        print >>sys.stderr, "usage: %s [--exclude PATH]..." % (
+            os.path.basename(sys.argv[0]))
+        sys.exit(1)
+
+    sourcelist = os.path.join(tmpdir, "sources.list")
+    writeSourceList(os.getcwd(), sourcelist)
+    compiler.gcjflags.append("-fsource-filename=" + sourcelist)
+
+    compiler.compile()
+    copy(tmpdir, srcdir, dstdir)
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/contrib/classfile.py
===================================================================
--- libjava/contrib/classfile.py	(revision 0)
+++ libjava/contrib/classfile.py	(revision 0)
@@ -0,0 +1,221 @@
+## Copyright (C) 2004, 2005 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+"""Read Java(TM) class files."""
+
+import cStringIO as StringIO
+import struct
+
+class Class:
+    def __init__(self, arg):
+        if hasattr(arg, "read"):
+            self.fp = arg
+        elif type(arg) == type(""):
+            if arg.startswith("\xca\xfe\xba\xbe"):
+                self.fp = StringIO.StringIO(arg)
+            else:
+                self.fp = open(arg, "r")
+        else:
+            raise TypeError, type(arg)
+
+        magic = self._read_int()
+        assert magic == 0xcafebabeL
+        minor, major = self._read(">HH")        
+        self.version = (major, minor)
+
+        self.pool_integrity_checks = None
+        try:
+            assert False
+        except AssertionError:
+            self.pool_integrity_checks = []
+
+        self._read_constants_pool()
+
+        self.access_flags = self._read_short()
+        self.name = self._read_reference_Class()
+        self.super = self._read_reference_Class()
+
+        self.interfaces = self._read_interfaces()
+        self.fields = self._read_fieldsormethods()
+        self.methods = self._read_fieldsormethods()
+        self.attributes = self._read_attributes()
+
+        if self.pool_integrity_checks is not None:
+            for index, tag in self.pool_integrity_checks:
+                assert self.constants[index][0] == tag
+
+        del self.fp, self.pool_integrity_checks
+
+    def __repr__(self):
+        result = []
+        attrs = [attr for attr in dir(self)
+                 if not attr.startswith("_") and attr != "Member"]
+        attrs.sort()
+        for attr in attrs:
+            result.append("%-13s %s" % (
+                attr + ":", attr == "constants" and
+                "<ELIDED>" or repr(getattr(self, attr))))
+        return "\n".join(result)
+
+    def _read_constants_pool(self):
+        self.constants = {}
+        skip = False
+        for i in xrange(1, self._read_short()):
+            if skip:
+                skip = False
+                continue
+            tag = {
+                1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
+                6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
+                10: "Methodref", 11: "InterfaceMethodref",
+                12: "NameAndType"}[self._read_byte()]
+            skip = tag in ("Long", "Double") # crack crack crack!
+            self.constants[i] = (tag, getattr(self, "_read_constant_" + tag)())
+
+    def _read_interfaces(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self._read_reference_Class())
+        return result
+
+    def _read_fieldsormethods(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self.Member(self))
+        return result
+
+    class Member:
+        def __init__(self, source):
+            self.access_flags = source._read_short()
+            self.name = source._read_reference_Utf8()
+            self.descriptor = source._read_reference_Utf8()
+            self.attributes = source._read_attributes()
+
+        def __repr__(self):
+            result = []
+            attrs = [attr for attr in dir(self) if not attr.startswith("_")]
+            attrs.sort()
+            for attr in attrs:
+                value = getattr(self, attr)
+                if attr == "attributes" and value.has_key("Code"):
+                    value = value.copy()
+                    value.update({"Code": "<ELIDED>"})
+                result.append("%-13s %s" % (
+                    attr + ":", repr(value).replace(
+                        "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
+            return ("\n%s" % (15 * " ")).join(result)
+
+    def _read_attributes(self):
+        result = {}
+        for i in xrange(self._read_short()):
+            name = self._read_reference_Utf8()
+            data = self.fp.read(self._read_int())
+            assert not result.has_key(name)
+            result[name] = data
+        return result
+
+    # Constants pool reference reader convenience functions
+
+    def _read_reference_Utf8(self):
+        return self._read_references("Utf8")[0]
+
+    def _read_reference_Class(self):
+        return self._read_references("Class")[0]
+
+    def _read_reference_Class_NameAndType(self):
+        return self._read_references("Class", "NameAndType")
+
+    def _read_references(self, *args):
+        result = []
+        for arg in args:
+            index = self._read_short()
+            if self.pool_integrity_checks is not None:
+                self.pool_integrity_checks.append((index, arg))
+            result.append(index)
+        return result
+
+    # Constants pool constant reader functions
+
+    def _read_constant_Utf8(self):
+        constant = self.fp.read(self._read_short())
+        try:
+            constant = constant.decode("utf-8")
+        except UnicodeError:
+            constant = _bork_utf8_decode(constant)
+        try:
+            constant = constant.encode("us-ascii")
+        except UnicodeError:
+            pass
+        return constant
+
+    def _read_constant_Integer(self):
+        return self._read_int()
+
+    def _read_constant_Float(self):
+        return self._read(">f")[0]
+
+    def _read_constant_Long(self):
+        return self._read(">q")[0]
+
+    def _read_constant_Double(self):
+        return self._read(">d")[0]
+
+    _read_constant_Class = _read_reference_Utf8
+    _read_constant_String = _read_reference_Utf8
+    _read_constant_Fieldref = _read_reference_Class_NameAndType
+    _read_constant_Methodref = _read_reference_Class_NameAndType
+    _read_constant_InterfaceMethodref = _read_reference_Class_NameAndType
+
+    def _read_constant_NameAndType(self):
+        return self._read_reference_Utf8(), self._read_reference_Utf8()
+
+    # Generic reader functions
+
+    def _read_int(self):
+        # XXX how else to read 32 bits on a 64-bit box?
+        h, l = map(long, self._read(">HH"))
+        return (h << 16) + l
+
+    def _read_short(self):
+        return self._read(">H")[0]
+
+    def _read_byte(self):
+        return self._read("B")[0]
+
+    def _read(self, fmt):
+        return struct.unpack(fmt, self.fp.read(struct.calcsize(fmt)))
+
+def _bork_utf8_decode(data):
+    # more crack!
+    bytes, unicode = map(ord, data), ""
+    while bytes:
+        b1 = bytes.pop(0)
+        if b1 & 0x80:
+            assert b1 & 0x40
+            b2 = bytes.pop(0)
+            assert b2 & 0xC0 == 0x80
+            if b1 & 0x20:
+                assert not b1 & 0x10
+                b3 = bytes.pop(0)
+                assert b3 & 0xC0 == 0x80
+                unicode += unichr(
+                    ((b1 & 0x0f) << 12) + ((b2 & 0x3f) << 6) + (b3 & 0x3f))
+            else:
+                unicode += unichr(((b1 & 0x1f) << 6) + (b2 & 0x3f))
+        else:
+            unicode += unichr(b1)
+    return unicode
+
+if __name__ == "__main__":
+    print Class("/usr/share/katana/build/ListDependentClasses.class")
+
Index: libjava/contrib/aot-compile.in
===================================================================
--- libjava/contrib/aot-compile.in	(revision 0)
+++ libjava/contrib/aot-compile.in	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2006 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import getopt
+import os
+
+usage = """\
+Usage: %s [OPTION...] SRCDIR DSTDIR
+AOT-compile all Java bytecode in SRCDIR into DSTDIR.
+
+Options:
+  -M, --make=PATH        make executable to use (%s)
+  -C, --gcj=PATH         gcj executable to use (%s)
+  -D, --dbtool=PATH      gcj-dbtool executable to use (%s)
+  -m, --makeflags=FLAGS  flags to pass to make during build
+  -c, --gcjflags=FLAGS   flags to pass to gcj during compilation
+                           in addition to %s
+  -l, --ldflags=FLAGS    flags to pass to gcj during linking
+                           in addition to %s
+  -e, --exclude=PATH     do not compile PATH
+
+Extra flags may also be passed using the AOT_MAKEFLAGS, AOT_GCJFLAGS
+and AOT_LDFLAGS environment variables.""" % (
+    os.path.basename(sys.argv[0]),
+    aotcompile.PATHS["make"],
+    aotcompile.PATHS["gcj"],
+    aotcompile.PATHS["dbtool"],
+    repr(" ".join(aotcompile.GCJFLAGS)),
+    repr(" ".join(aotcompile.LDFLAGS)))
+
+try:
+    if os.environ.has_key("RPM_PACKAGE_NAME"):
+        raise aotcompile.Error, "not for use within rpm specfiles"
+
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            "M:C:D:m:c:l:e:",
+            ["make=", "gcj=", "dbtool=",
+             "makeflags=" "gcjflags=", "ldflags=",
+             "exclude="])
+        srcdir, dstdir = args
+    except:
+        print >>sys.stderr, usage
+        sys.exit(1)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir)
+    for o, a in opts:
+        if o in ("-M", "--make"):
+            aotcompile.PATHS["make"] = a
+        if o in ("-C", "--gcj"):
+            aotcompile.PATHS["gcj"] = a
+        if o in ("-D", "--dbtool"):
+            aotcompile.PATHS["dbtool"] = a
+        if o in ("-m", "--makeflags"):
+            compiler.makeflags[0:0] = a.split()
+        if o in ("-c", "--gcjflags"):
+            compiler.gcjflags[0:0] = a.split()
+        if o in ("-l", "--ldflags"):
+            compiler.ldflags[0:0] = a.split()
+        if o in ("-e", "--exclude"):
+            compiler.exclusions.append(a)
+    
+    compiler.makeflags[0:0] = os.environ.get("AOT_MAKEFLAGS", "").split() 
+    compiler.gcjflags[0:0] = os.environ.get("AOT_GCJFLAGS", "").split() 
+    compiler.ldflags[0:0] = os.environ.get("AOT_LDFLAGS", "").split() 
+
+    compiler.compile()
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/Makefile.am
===================================================================
--- libjava/Makefile.am	(revision 136895)
+++ libjava/Makefile.am	(working copy)
@@ -85,10 +85,14 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
+endif 
+
+bin_SCRIPTS = addr2name.awk contrib/rebuild-gcj-db contrib/aot-compile
+
+if INSTALL_AOT_RPM
+bin_SCRIPTS += contrib/aot-compile-rpm
 endif
 
-bin_SCRIPTS = addr2name.awk
-
 if BUILD_ECJ1
 ## We build ecjx and not ecj1 because in one mode, ecjx will not work
 ## until after 'make install', and we don't want it to be picked up in
@@ -528,8 +532,141 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
+## Install Python modules for aot-compile.
+	$(mkinstalldirs) $(DESTDIR)$(python_mod_dir); \
+	$(INSTALL_DATA) $(srcdir)/contrib/classfile.py \
+	  $(DESTDIR)$(python_mod_dir)/classfile.py; \
+	$(INSTALL_DATA) contrib/aotcompile.py \
+	  $(DESTDIR)$(python_mod_dir)/aotcompile.py;
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/`echo grmic | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/`echo gjavah | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/`echo gappletviewer | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/`echo gjarsigner | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo gnative2ascii | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/`echo gserialver | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-$(gcc_version).jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	ln -sf $$RELATIVE/libjawt.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$(gcc_version).jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	ln -sf $$RELATIVE/src-$(gcc_version).zip \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip;
+endif
 
-
 ## ################################################################
 
 ##
Index: libjava/configure.ac
===================================================================
--- libjava/configure.ac	(revision 136895)
+++ libjava/configure.ac	(working copy)
@@ -1625,6 +1625,211 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)
 
+AC_ARG_WITH([python-dir],
+            AS_HELP_STRING([--with-python-dir],
+                           [the location to install Python modules. This path should NOT include the prefix.]),
+            [with_python_dir=$withval], [with_python_dir=""])
+
+if test "x${with_python_dir}" = "x"
+then
+  # Needed for installing Python modules during make install.
+  python_mod_dir="\${prefix}/share/python"
+  # Needed for substituting into aot-compile*
+  python_mod_dir_expanded="${prefix}/share/python"
+else
+  python_mod_dir="\${prefix}${with_python_dir}"
+  python_mod_dir_expanded="${prefix}${with_python_dir}"
+fi
+AC_MSG_RESULT(Python modules dir: ${python_mod_dir_expanded});
+AC_SUBST(python_mod_dir)
+AC_SUBST(python_mod_dir_expanded)
+
+# needed for aot-compile-rpm
+MAKE=`which make`
+AC_SUBST(MAKE)
+
+AC_ARG_ENABLE([aot-compile-rpm],
+  [AS_HELP_STRING([--enable-aot-compile-rpm],
+                 [enable installation of aot-compile-rpm [default=no]])],
+  [case "${enableval}" in
+    yes) AOT_RPM_ENABLED=yes ;;
+    no)  AOT_RPM_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable aot-compile-rpm]) ;;
+  esac],
+  [AOT_RPM_ENABLED=no]
+)
+AM_CONDITIONAL(INSTALL_AOT_RPM, test "x${AOT_RPM_ENABLED}" == xyes)
+
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir="\${prefix}/lib/jvm"])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=\${prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
+  AC_SUBST(JAVA_HOME_DIR)
+  AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc
@@ -1633,6 +1838,10 @@
 gcj/Makefile
 include/Makefile
 testsuite/Makefile
+contrib/aotcompile.py
+contrib/aot-compile
+contrib/aot-compile-rpm
+contrib/rebuild-gcj-db
 ])
 
 if test ${multilib} = yes; then

[-- Attachment #3: gcc-install-and-docs-update2.patch --]
[-- Type: text/x-patch, Size: 8288 bytes --]

Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 137153)
+++ gcc/doc/install.texi	(working copy)
@@ -1607,6 +1607,45 @@
 @item --with-win32-nlsapi=ansi, unicows or unicode
 Indicates how MinGW @samp{libgcj} translates between UNICODE
 characters and the Win32 API@.
+
+@item --enable-java-home
+If enabled, this creates a JPackage compatible SDK environment during install.
+Note that if --enable-java-home is used, --with-arch-directory=ARCH must also
+be specified.
+
+@item --with-arch-directory=ARCH
+Specifies the name to use for the @file{jre/lib/ARCH} directory in the SDK 
+environment created when --enable-java-home is passed. Typical names for this 
+directory include i386, amd64, ia64, etc.
+
+@item --with-os-directory=DIR
+Specifies the OS directory for the SDK include directory. This is set to auto
+detect, and is typically 'linux'.
+
+@item --with-origin-name=NAME
+Specifies the JPackage origin name. This defaults to the 'gcj' in
+java-1.5.0-gcj.
+
+@item --with-arch-suffix=SUFFIX
+Specifies the suffix for the sdk directory. Defaults to the empty string. 
+Examples include '.x86_64' in 'java-1.5.0-gcj-1.5.0.0.x86_64'.
+
+@item --with-jvm-root-dir=DIR
+Specifies where to install the SDK. Default is $(prefix)/lib/jvm.
+
+@item --with-jvm-jar-dir=DIR
+Specifies where to install jars. Default is $(prefix)/lib/jvm-exports.
+
+@item --with-python-dir=DIR
+Specifies where to install the Python modules used for aot-compile. DIR should
+not include the prefix used in installation. For example, if the Python modules
+are to be installed in /usr/lib/python2.5/site-packages, then 
+--with-python-dir=/lib/python2.5/site-packages should be passed. If this is
+not specified, then the Python modules are installed in $(prefix)/share/python.
+
+@item --enable-aot-compile-rpm
+Adds aot-compile-rpm to the list of installed scripts.
+
 @table @code
 @item ansi
 Use the single-byte @code{char} and the Win32 A functions natively,
Index: gcc/java/gcj.texi
===================================================================
--- gcc/java/gcj.texi	(revision 137153)
+++ gcc/java/gcj.texi	(working copy)
@@ -72,6 +72,11 @@
                             Generate stubs for Remote Method Invocation.
 * gc-analyze: (gcj)Invoking gc-analyze.
                             Analyze Garbage Collector (GC) memory dumps.
+* aot-compile: (gcj)Invoking aot-compile.
+                            Compile bytecode to native and generate databases.
+* rebuild-gcj-db: (gcj)Invoking rebuild-gcj-db.
+                            Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 @end direntry
 @end format
 
@@ -115,6 +120,9 @@
 * Invoking jv-convert:: Converting from one encoding to another
 * Invoking grmic::      Generate stubs for Remote Method Invocation.
 * Invoking gc-analyze:: Analyze Garbage Collector (GC) memory dumps.
+* Invoking aot-compile:: Compile bytecode to native and generate databases.
+* Invoking rebuild-gcj-db:: Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 * About CNI::           Description of the Compiled Native Interface
 * System properties::   Modifying runtime behavior of the libgcj library
 * Resources::           Where to look for more information
@@ -921,7 +929,7 @@
   [@option{-v}] [@option{-m}] [@option{--version}] [@option{--help}]
 
 @c man end
-@c man begin SEEALSO gij
+@c man begin SEEALSO gcj-dbtool
 gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
 and the Info entries for @file{gcj} and @file{gcc}.
 @c man end
@@ -1219,6 +1227,87 @@
 
 @c man end
 
+@node Invoking aot-compile
+@chapter Invoking aot-compile
+
+@c man title aot-compile Compile bytecode to native and generate databases
+
+@ignore
+
+@c man begin SYNOPSIS aot-compile
+aot-compile [@option{OPTION}] @dots{} @var{SRCDIR} @var{DSTDIR}
+
+aot-compile [@option{-M, --make}=@var{PATH}] [@option{-C, --gcj}=@var{PATH}]
+  [@option{-D, --dbtool}=@var{PATH}] [@option{-m, --makeflags}=@var{FLAGS}] 
+  [@option{-c, --gcjflags}=@var{FLAGS}] [@option{-l, --ldflags}=@var{FLAGS}] 
+  [@option{-e, --exclude}=@var{PATH}]
+@c man end
+
+@c man begin SEEALSO aot-compile
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION aot-compile
+@code{aot-compile} is a script that searches a directory for Java bytecode
+(as class files, or in jars) and uses @code{gcj} to compile it to native
+code and generate the databases from it.
+@c man end
+
+@c man begin OPTIONS aot-compile
+@table @gcctabopt
+@item -M, --make=@var{PATH}
+Specify the path to the @code{make} executable to use.
+
+@item -C, --gcj=@var{PATH}
+Specify the path to the @code{gcj} executable to use.
+
+@item -D, --dbtool=@var{PATH}
+Specify the path to the @code{gcj-dbtool} executable to use.
+
+@item -m, --makeflags=@var{FLAGS}
+Specify flags to pass to @code{make} during the build.
+
+@item -c, --gcjflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during compilation, in addition to
+'-fPIC -findirect-dispatch -fjni'.
+
+@item -l, --ldflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during linking, in addition to
+'-Wl,-Bsymbolic'.
+
+@item -e, --exclude=@var{PATH}
+Do not compile @var{PATH}.
+
+@end table
+
+@c man end
+
+@node Invoking rebuild-gcj-db
+@chapter Invoking rebuild-gcj-db
+
+@c man title rebuild-gcj-db Merge the per-solib databases made by aot-compile into one system-wide database.
+@ignore
+
+@c man begin SYNOPSIS rebuild-gcj-db
+rebuild-gcj-db
+@c man end
+
+@c man begin SEEALSO rebuild-gcj-db
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION rebuild-gcj-db
+@code{rebuild-gcj-db} is a script that merges the per-solib databases made by
+@code{aot-compile} into one system-wide database so @code{gij} can find the 
+solibs.
+@c man end
+
 @node About CNI
 @chapter About CNI
 
Index: gcc/java/Make-lang.in
===================================================================
--- gcc/java/Make-lang.in	(revision 137153)
+++ gcc/java/Make-lang.in	(working copy)
@@ -143,8 +143,9 @@
 java.html: $(build_htmldir)/java/index.html
 
 JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
-                doc/jv-convert.1 doc/grmic.1\
-		doc/gcj-dbtool.1 doc/gc-analyze.1
+                doc/jv-convert.1 doc/grmic.1 \
+                doc/gcj-dbtool.1 doc/gc-analyze.1 doc/aot-compile.1 \
+                doc/rebuild-gcj-db.1
 
 java.man: $(JAVA_MANFILES)
 
@@ -189,6 +190,8 @@
 	-rm -rf $(DESTDIR)$(man1dir)/gij$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/jv-convert$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/gcj-dbtool$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/aot-compile$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/rebuild-gcj-db$(man1ext)
 
 java.install-info: $(DESTDIR)$(infodir)/gcj.info
 
@@ -223,6 +226,8 @@
 	-rm -f $(docobjdir)/grmic.1
 	-rm -f $(docobjdir)/gcj-dbtool.1
 	-rm -f $(docobjdir)/gc-analyze.1
+	-rm -f $(docobjdir)/aot-compile.1
+	-rm -f $(docobjdir)/rebuild-gcj-db.1
 #\f
 # Stage hooks:
 # The main makefile has already created stage?/java.
@@ -353,15 +358,21 @@
 	-$(TEXI2POD) -D gcj-dbtool < $< > $@
 gc-analyze.pod: java/gcj.texi
 	-$(TEXI2POD) -D gc-analyze < $< > $@
+aot-compile.pod: java/gcj.texi
+	-$(TEXI2POD) -D aot-compile < $< > $@
+rebuild-gcj-db.pod: java/gcj.texi
+	-$(TEXI2POD) -D rebuild-gcj-db < $< > $@
 
 # Install the man pages.
 java.install-man: installdirs \
                   $(DESTDIR)$(man1dir)/$(JAVA_INSTALL_NAME)$(man1ext) \
 		  $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS:%=doc/%.1) \
 		  doc/gij.1 doc/jv-convert.1 doc/grmic.1 \
-		  doc/gcj-dbtool.1 doc/gc-analyze.1
+		  doc/gcj-dbtool.1 doc/gc-analyze.1 \
+		  doc/aot-compile.1 doc/rebuild-gcj-db.1
 	for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS) \
-		gij jv-convert grmic gcj-dbtool gc-analyze ; do \
+		gij jv-convert grmic gcj-dbtool gc-analyze aot-compile \
+		rebuild-gcj-db; do \
 	  tool_transformed_name=`echo $$tool|sed '$(program_transform_name)'`; \
 	  man_name=$(DESTDIR)$(man1dir)/$${tool_transformed_name}$(man1ext); \
 	  rm -f $$man_name ; \

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-30 14:39                   ` Joshua Sumali
@ 2008-07-01 13:59                     ` Andrew Haley
  2008-07-01 14:53                       ` Joshua Sumali
  2008-07-02 13:07                     ` Andrew Haley
  1 sibling, 1 reply; 18+ messages in thread
From: Andrew Haley @ 2008-07-01 13:59 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches

Joshua Sumali wrote:
> Andrew Haley wrote:
>> Joshua Sumali wrote:
>>  
>>> Andrew Haley wrote:
>>>     
>>
>>  
>>>> Please assign all Red Hat copyrights to the FSF.
>>>>         
>>> Is there a special way to do this, or do I simply change "Copyright (C)
>>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
>>> Software Foundation" on the appropriate files?
>>>     
>>
>> That's all you have to do.
>>
>>  
>>>> Do I take it that you don't have commit access to the gcc tree?
>>>>         
>>> I do not. I was hoping someone would be able to commit the patches
>>> for me.
>>>     
>>
>> I'll do it.
>>
>> Andrew.
>>
>>   
> Copyrights assigned to FSF. ChangeLogs removed from patches and are
> found below.

I get:


 $ automake
Makefile.am:67: JAVA_HOME_DIR was already defined in condition TRUE, which includes condition JAVA_HOME_SET ...
configure.ac:1759: ... `JAVA_HOME_DIR' previously defined here
Makefile.am:70: JAVA_HOME_DIR was already defined in condition TRUE, which includes condition !JAVA_HOME_SET ...


> 
> libjava/
> 
> 2008-06-30  Joshua Sumali  <jsumali@redhat.com>
> 
>    * configure.ac (java-home): new AC_ARG_ENABLE.
>    (aot-compile-rpm): Likewise.
>    (CREATE_JAVA_HOME): new AM_CONDITIONAL.
>    (INSTALL_AOT_RPM): Likewise.
>    (gcc-suffix): new AC_ARG_WITH.
>    (arch-directory): Likewise.
>    (os-directory): Likewise.
>    (origin-name): Likewise.
>    (arch-suffix): Likewise.
>    (jvm-root-dir): Likewise.
>    (jvm-jar-dir): Likewise.
>    (python-dir): Likewise.
>    (AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
>    contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
>    * Makefile.am (install-data-local): Install Python modules for
>    aot-compile. Also install an sdk style directory if --enable-java-home
>    is passed to configure.
>    (bin_SCRIPTS): add contrib/rebuild-gcj-db and contrib/aot-compile.
>    * contrib/aot-compile.in: New file.
>    * contrib/aotcompile.py.in: Likewise.
>    * contrib/aot-compile-rpm.in: Likewise.
>    * contrib/classfile.py: Likewise.
>    * contrib/rebuild-gcj-db.in: Likewise.
>    * configure: Regenerate.
>    * Makefile.in: Regenerate.
> 
> gcc/
> 
> 2008-06-30  Joshua Sumali  <jsumali@redhat.com>
> 
>    * doc/install.texi (--enable-java-home): Document.
>    (--enable-aot-compile-rpm): Likewise.
>    (--with-arch-directory): Likewise.
>    (--with-os-directory): Likewise.
>    (--with-origin-name): Likewise.
>    (--with-arch-suffix): Likewise.
>    (--with-jvm-root-dir): Likewise.
>    (--with-jvm-jar-dir): Likewise.
>    (--with-python-dir): Likewise.
> 
> gcc/java/
> 
> 2008-06-30  Joshua Sumali  <jsumali@redhat.com>
> 
>    * Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and
>    doc/rebuild-gcj-db.1
>    (java.uninstall): Likewise.
>    (java.maintainer-clean): Likewise.
>    (aot-compile.pod): New rule.
>    (rebuild-gcj-db.pod): New rule.
>    (java.install-man): Install doc/aot-compile.1 and doc/rebuild-gcj-db.1
>    * gcj.texi: Add new sections for aot-compile and rebuild-gcj-db.
> 
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-07-01 13:59                     ` Andrew Haley
@ 2008-07-01 14:53                       ` Joshua Sumali
  2008-07-01 15:01                         ` Andrew Haley
  0 siblings, 1 reply; 18+ messages in thread
From: Joshua Sumali @ 2008-07-01 14:53 UTC (permalink / raw)
  To: Andrew Haley; +Cc: java-patches

Andrew Haley wrote:
> Joshua Sumali wrote:
>   
>> Andrew Haley wrote:
>>     
>>> Joshua Sumali wrote:
>>>  
>>>       
>>>> Andrew Haley wrote:
>>>>     
>>>>         
>>>  
>>>       
>>>>> Please assign all Red Hat copyrights to the FSF.
>>>>>         
>>>>>           
>>>> Is there a special way to do this, or do I simply change "Copyright (C)
>>>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
>>>> Software Foundation" on the appropriate files?
>>>>     
>>>>         
>>> That's all you have to do.
>>>
>>>  
>>>       
>>>>> Do I take it that you don't have commit access to the gcc tree?
>>>>>         
>>>>>           
>>>> I do not. I was hoping someone would be able to commit the patches
>>>> for me.
>>>>     
>>>>         
>>> I'll do it.
>>>
>>> Andrew.
>>>
>>>   
>>>       
>> Copyrights assigned to FSF. ChangeLogs removed from patches and are
>> found below.
>>     
>
> I get:
>
>
>  $ automake
> Makefile.am:67: JAVA_HOME_DIR was already defined in condition TRUE, which includes condition JAVA_HOME_SET ...
> configure.ac:1759: ... `JAVA_HOME_DIR' previously defined here
> Makefile.am:70: JAVA_HOME_DIR was already defined in condition TRUE, which includes condition !JAVA_HOME_SET ...
>
>
>   
Sorry, my mistake for leaving that in. To fix that, remove the following 
lines from configure.ac:

JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
AC_SUBST(JAVA_HOME_DIR)
AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})

They should be around line 1759.

(I'd post another patch but I figured that it would be easier to just 
delete those few lines)

Josh

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-07-01 14:53                       ` Joshua Sumali
@ 2008-07-01 15:01                         ` Andrew Haley
  0 siblings, 0 replies; 18+ messages in thread
From: Andrew Haley @ 2008-07-01 15:01 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches

Joshua Sumali wrote:
> Andrew Haley wrote:
>> Joshua Sumali wrote:
>>  
>>> Andrew Haley wrote:
>>>    
>>>> Joshua Sumali wrote:
>>>>  
>>>>      
>>>>> Andrew Haley wrote:
>>>>>             
>>>>  
>>>>      
>>>>>> Please assign all Red Hat copyrights to the FSF.
>>>>>>                   
>>>>> Is there a special way to do this, or do I simply change "Copyright
>>>>> (C)
>>>>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008
>>>>> Free
>>>>> Software Foundation" on the appropriate files?
>>>>>             
>>>> That's all you have to do.
>>>>
>>>>  
>>>>      
>>>>>> Do I take it that you don't have commit access to the gcc tree?
>>>>>>                   
>>>>> I do not. I was hoping someone would be able to commit the patches
>>>>> for me.
>>>>>             
>>>> I'll do it.
>>>>
>>>> Andrew.
>>>>
>>>>         
>>> Copyrights assigned to FSF. ChangeLogs removed from patches and are
>>> found below.
>>>     
>>
>> I get:
>>
>>
>>  $ automake
>> Makefile.am:67: JAVA_HOME_DIR was already defined in condition TRUE,
>> which includes condition JAVA_HOME_SET ...
>> configure.ac:1759: ... `JAVA_HOME_DIR' previously defined here
>> Makefile.am:70: JAVA_HOME_DIR was already defined in condition TRUE,
>> which includes condition !JAVA_HOME_SET ...
>>
>>
>>   
> Sorry, my mistake for leaving that in. To fix that, remove the following
> lines from configure.ac:
> 
> JAVA_HOME_DIR=${jvm_root_dir}/${jre_dir}
> AC_SUBST(JAVA_HOME_DIR)
> AC_MSG_RESULT(JAVA_HOME directory: ${JAVA_HOME_DIR})
> 
> They should be around line 1759.
> 
> (I'd post another patch but I figured that it would be easier to just
> delete those few lines)

OK, TVM.

Andrew.

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-06-30 14:39                   ` Joshua Sumali
  2008-07-01 13:59                     ` Andrew Haley
@ 2008-07-02 13:07                     ` Andrew Haley
  2008-07-02 13:19                       ` Joshua Sumali
  1 sibling, 1 reply; 18+ messages in thread
From: Andrew Haley @ 2008-07-02 13:07 UTC (permalink / raw)
  To: Joshua Sumali; +Cc: java-patches

Joshua Sumali wrote:
> Andrew Haley wrote:
>> Joshua Sumali wrote:
>>  
>>> Andrew Haley wrote:
>>>     
>>
>>  
>>>> Please assign all Red Hat copyrights to the FSF.
>>>>         
>>> Is there a special way to do this, or do I simply change "Copyright (C)
>>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
>>> Software Foundation" on the appropriate files?
>>>     
>>
>> That's all you have to do.
>>
>>  
>>>> Do I take it that you don't have commit access to the gcc tree?
>>>>         
>>> I do not. I was hoping someone would be able to commit the patches
>>> for me.
>>>     
>>
>> I'll do it.

Here's what I committed.  I had partly to rewrite rebuild-gcj-db because it
handled multilibs incorrectly, and in the process discovered a bug in
gcj-dbtool, but otherwise it's the same.

Andrew.


2008-06-30  Joshua Sumali  <jsumali@redhat.com>
        Andrew Haley  <aph@redhat.com>

        * configure.ac (java-home): new AC_ARG_ENABLE.
        (aot-compile-rpm): Likewise.
        (CREATE_JAVA_HOME): new AM_CONDITIONAL.
        (INSTALL_AOT_RPM): Likewise.
        (gcc-suffix): new AC_ARG_WITH.
        (arch-directory): Likewise.
        (os-directory): Likewise.
        (origin-name): Likewise.
        (arch-suffix): Likewise.
        (jvm-root-dir): Likewise.
        (jvm-jar-dir): Likewise.
        (python-dir): Likewise.
        (AC_CONFIG_FILES): Add contrib/aotcompile.py, contrib/aot-compile,
        contrib/aot-compile-rpm, contrib/rebuild-gcj-db.
        (gcjsubdir): New AC_SUBST.
        * Makefile.am (install-data-local): Install Python modules for
        aot-compile. Also install an sdk style directory if
        --enable-java-home is passed to configure.
        (bin_SCRIPTS): Add
        contrib/rebuild-gcj-db and contrib/aot-compile.
        (gcjsubdir): Add.
        (db_pathtail): Redefine in terms of gcjsubdir.
        * contrib/aot-compile.in: New file.
        * contrib/aotcompile.py.in: Likewise.
        * contrib/aot-compile-rpm.in: Likewise.
        * contrib/classfile.py: Likewise.
        * contrib/rebuild-gcj-db.in: Likewise.
        * configure: Regenerate.
        * Makefile.in: Regenerate.

2008-06-30  Joshua Sumali  <jsumali@redhat.com>

        * doc/install.texi (--enable-java-home): Document.
        (--enable-aot-compile-rpm): Likewise.
        (--with-arch-directory): Likewise.
        (--with-os-directory): Likewise.
        (--with-origin-name): Likewise.
        (--with-arch-suffix): Likewise.
        (--with-jvm-root-dir): Likewise.
        (--with-jvm-jar-dir): Likewise.
        (--with-python-dir): Likewise.

Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 137317)
+++ gcc/doc/install.texi	(working copy)
@@ -1607,6 +1607,45 @@
 @item --with-win32-nlsapi=ansi, unicows or unicode
 Indicates how MinGW @samp{libgcj} translates between UNICODE
 characters and the Win32 API@.
+
+@item --enable-java-home
+If enabled, this creates a JPackage compatible SDK environment during install.
+Note that if --enable-java-home is used, --with-arch-directory=ARCH must also
+be specified.
+
+@item --with-arch-directory=ARCH
+Specifies the name to use for the @file{jre/lib/ARCH} directory in the SDK
+environment created when --enable-java-home is passed. Typical names for this
+directory include i386, amd64, ia64, etc.
+
+@item --with-os-directory=DIR
+Specifies the OS directory for the SDK include directory. This is set to auto
+detect, and is typically 'linux'.
+
+@item --with-origin-name=NAME
+Specifies the JPackage origin name. This defaults to the 'gcj' in
+java-1.5.0-gcj.
+
+@item --with-arch-suffix=SUFFIX
+Specifies the suffix for the sdk directory. Defaults to the empty string.
+Examples include '.x86_64' in 'java-1.5.0-gcj-1.5.0.0.x86_64'.
+
+@item --with-jvm-root-dir=DIR
+Specifies where to install the SDK. Default is $(prefix)/lib/jvm.
+
+@item --with-jvm-jar-dir=DIR
+Specifies where to install jars. Default is $(prefix)/lib/jvm-exports.
+
+@item --with-python-dir=DIR
+Specifies where to install the Python modules used for aot-compile. DIR should
+not include the prefix used in installation. For example, if the Python modules
+are to be installed in /usr/lib/python2.5/site-packages, then
+--with-python-dir=/lib/python2.5/site-packages should be passed. If this is
+not specified, then the Python modules are installed in $(prefix)/share/python.
+
+@item --enable-aot-compile-rpm
+Adds aot-compile-rpm to the list of installed scripts.
+
 @table @code
 @item ansi
 Use the single-byte @code{char} and the Win32 A functions natively,
Index: gcc/java/Make-lang.in
===================================================================
--- gcc/java/Make-lang.in	(revision 137317)
+++ gcc/java/Make-lang.in	(working copy)
@@ -146,8 +146,9 @@
 java.html: $(build_htmldir)/java/index.html

 JAVA_MANFILES = doc/gcj.1 doc/jcf-dump.1 doc/gij.1 \
-                doc/jv-convert.1 doc/grmic.1\
-		doc/gcj-dbtool.1 doc/gc-analyze.1
+                doc/jv-convert.1 doc/grmic.1 \
+                doc/gcj-dbtool.1 doc/gc-analyze.1 doc/aot-compile.1 \
+                doc/rebuild-gcj-db.1

 java.man: $(JAVA_MANFILES)

@@ -192,6 +193,8 @@
 	-rm -rf $(DESTDIR)$(man1dir)/gij$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/jv-convert$(man1ext)
 	-rm -rf $(DESTDIR)$(man1dir)/gcj-dbtool$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/aot-compile$(man1ext)
+	-rm -rf $(DESTDIR)$(man1dir)/rebuild-gcj-db$(man1ext)

 java.install-info: $(DESTDIR)$(infodir)/gcj.info

@@ -226,6 +229,8 @@
 	-rm -f $(docobjdir)/grmic.1
 	-rm -f $(docobjdir)/gcj-dbtool.1
 	-rm -f $(docobjdir)/gc-analyze.1
+	-rm -f $(docobjdir)/aot-compile.1
+	-rm -f $(docobjdir)/rebuild-gcj-db.1
 #\f
 # Stage hooks:
 # The main makefile has already created stage?/java.
@@ -356,15 +361,21 @@
 	-$(TEXI2POD) -D gcj-dbtool < $< > $@
 gc-analyze.pod: java/gcj.texi
 	-$(TEXI2POD) -D gc-analyze < $< > $@
+aot-compile.pod: java/gcj.texi
+	-$(TEXI2POD) -D aot-compile < $< > $@
+rebuild-gcj-db.pod: java/gcj.texi
+	-$(TEXI2POD) -D rebuild-gcj-db < $< > $@

 # Install the man pages.
 java.install-man: installdirs \
                   $(DESTDIR)$(man1dir)/$(JAVA_INSTALL_NAME)$(man1ext) \
 		  $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS:%=doc/%.1) \
 		  doc/gij.1 doc/jv-convert.1 doc/grmic.1 \
-		  doc/gcj-dbtool.1 doc/gc-analyze.1
+		  doc/gcj-dbtool.1 doc/gc-analyze.1 \
+		  doc/aot-compile.1 doc/rebuild-gcj-db.1
 	for tool in $(JAVA_TARGET_INDEPENDENT_BIN_TOOLS) \
-		gij jv-convert grmic gcj-dbtool gc-analyze ; do \
+		gij jv-convert grmic gcj-dbtool gc-analyze aot-compile \
+		rebuild-gcj-db; do \
 	  tool_transformed_name=`echo $$tool|sed '$(program_transform_name)'`; \
 	  man_name=$(DESTDIR)$(man1dir)/$${tool_transformed_name}$(man1ext); \
 	  rm -f $$man_name ; \
Index: gcc/java/ChangeLog
===================================================================
--- gcc/java/ChangeLog	(revision 137317)
+++ gcc/java/ChangeLog	(working copy)
@@ -1,3 +1,14 @@
+2008-06-30  Joshua Sumali  <jsumali@redhat.com>
+
+	* Make-lang.in (JAVA_MANFILES): Add doc/aot-compile.1 and
+	doc/rebuild-gcj-db.1
+	(java.uninstall): Likewise.
+	(java.maintainer-clean): Likewise.
+	(aot-compile.pod): New rule.
+	(rebuild-gcj-db.pod): New rule.
+	(java.install-man): Install doc/aot-compile.1 and doc/rebuild-gcj-db.1
+	* gcj.texi: Add new sections for aot-compile and rebuild-gcj-db.
+
 2008-06-29  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>

 	* Make-lang.in (java/jcf-io.o-warn): New.
Index: gcc/java/gcj.texi
===================================================================
--- gcc/java/gcj.texi	(revision 137317)
+++ gcc/java/gcj.texi	(working copy)
@@ -72,6 +72,11 @@
                             Generate stubs for Remote Method Invocation.
 * gc-analyze: (gcj)Invoking gc-analyze.
                             Analyze Garbage Collector (GC) memory dumps.
+* aot-compile: (gcj)Invoking aot-compile.
+                            Compile bytecode to native and generate databases.
+* rebuild-gcj-db: (gcj)Invoking rebuild-gcj-db.
+                            Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 @end direntry
 @end format

@@ -115,6 +120,9 @@
 * Invoking jv-convert:: Converting from one encoding to another
 * Invoking grmic::      Generate stubs for Remote Method Invocation.
 * Invoking gc-analyze:: Analyze Garbage Collector (GC) memory dumps.
+* Invoking aot-compile:: Compile bytecode to native and generate databases.
+* Invoking rebuild-gcj-db:: Merge the per-solib databases made by aot-compile
+                            into one system-wide database.
 * About CNI::           Description of the Compiled Native Interface
 * System properties::   Modifying runtime behavior of the libgcj library
 * Resources::           Where to look for more information
@@ -921,7 +929,7 @@
   [@option{-v}] [@option{-m}] [@option{--version}] [@option{--help}]

 @c man end
-@c man begin SEEALSO gij
+@c man begin SEEALSO gcj-dbtool
 gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
 and the Info entries for @file{gcj} and @file{gcc}.
 @c man end
@@ -1219,6 +1227,87 @@

 @c man end

+@node Invoking aot-compile
+@chapter Invoking aot-compile
+
+@c man title aot-compile Compile bytecode to native and generate databases
+
+@ignore
+
+@c man begin SYNOPSIS aot-compile
+aot-compile [@option{OPTION}] @dots{} @var{SRCDIR} @var{DSTDIR}
+
+aot-compile [@option{-M, --make}=@var{PATH}] [@option{-C, --gcj}=@var{PATH}]
+  [@option{-D, --dbtool}=@var{PATH}] [@option{-m, --makeflags}=@var{FLAGS}]
+  [@option{-c, --gcjflags}=@var{FLAGS}] [@option{-l, --ldflags}=@var{FLAGS}]
+  [@option{-e, --exclude}=@var{PATH}]
+@c man end
+
+@c man begin SEEALSO aot-compile
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION aot-compile
+@code{aot-compile} is a script that searches a directory for Java bytecode
+(as class files, or in jars) and uses @code{gcj} to compile it to native
+code and generate the databases from it.
+@c man end
+
+@c man begin OPTIONS aot-compile
+@table @gcctabopt
+@item -M, --make=@var{PATH}
+Specify the path to the @code{make} executable to use.
+
+@item -C, --gcj=@var{PATH}
+Specify the path to the @code{gcj} executable to use.
+
+@item -D, --dbtool=@var{PATH}
+Specify the path to the @code{gcj-dbtool} executable to use.
+
+@item -m, --makeflags=@var{FLAGS}
+Specify flags to pass to @code{make} during the build.
+
+@item -c, --gcjflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during compilation, in addition to
+'-fPIC -findirect-dispatch -fjni'.
+
+@item -l, --ldflags=@var{FLAGS}
+Specify flags to pass to @code{gcj} during linking, in addition to
+'-Wl,-Bsymbolic'.
+
+@item -e, --exclude=@var{PATH}
+Do not compile @var{PATH}.
+
+@end table
+
+@c man end
+
+@node Invoking rebuild-gcj-db
+@chapter Invoking rebuild-gcj-db
+
+@c man title rebuild-gcj-db Merge the per-solib databases made by aot-compile into one system-wide database.
+@ignore
+
+@c man begin SYNOPSIS rebuild-gcj-db
+rebuild-gcj-db
+@c man end
+
+@c man begin SEEALSO rebuild-gcj-db
+gcc(1), gcj(1), gcjh(1), jcf-dump(1), gfdl(7),
+and the Info entries for @file{gcj} and @file{gcc}.
+@c man end
+
+@end ignore
+
+@c man begin DESCRIPTION rebuild-gcj-db
+@code{rebuild-gcj-db} is a script that merges the per-solib databases made by
+@code{aot-compile} into one system-wide database so @code{gij} can find the
+solibs.
+@c man end
+
 @node About CNI
 @chapter About CNI

Index: libjava/configure.ac
===================================================================
--- libjava/configure.ac	(revision 137317)
+++ libjava/configure.ac	(working copy)
@@ -1416,6 +1416,7 @@
    ;;
 esac
 AC_SUBST(dbexecdir)
+AC_SUBST(gcjsubdir)

 AC_DEFINE(JV_VERSION, "1.5.0", [Compatibility version string])
 AC_DEFINE(JV_API_VERSION, "1.5", [API compatibility version string])
@@ -1628,6 +1629,207 @@
 # We get this from the environment.
 AC_SUBST(GCJFLAGS)

+AC_ARG_WITH([python-dir],
+            AS_HELP_STRING([--with-python-dir],
+                           [the location to install Python modules. This path should NOT include the prefix.]),
+            [with_python_dir=$withval], [with_python_dir=""])
+
+if test "x${with_python_dir}" = "x"
+then
+  # Needed for installing Python modules during make install.
+  python_mod_dir="\${prefix}/share/python"
+  # Needed for substituting into aot-compile*
+  python_mod_dir_expanded="${prefix}/share/python"
+else
+  python_mod_dir="\${prefix}${with_python_dir}"
+  python_mod_dir_expanded="${prefix}${with_python_dir}"
+fi
+AC_MSG_RESULT(Python modules dir: ${python_mod_dir_expanded});
+AC_SUBST(python_mod_dir)
+AC_SUBST(python_mod_dir_expanded)
+
+# needed for aot-compile-rpm
+MAKE=`which make`
+AC_SUBST(MAKE)
+
+AC_ARG_ENABLE([aot-compile-rpm],
+  [AS_HELP_STRING([--enable-aot-compile-rpm],
+                 [enable installation of aot-compile-rpm [default=no]])],
+  [case "${enableval}" in
+    yes) AOT_RPM_ENABLED=yes ;;
+    no)  AOT_RPM_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable aot-compile-rpm]) ;;
+  esac],
+  [AOT_RPM_ENABLED=no]
+)
+AM_CONDITIONAL(INSTALL_AOT_RPM, test "x${AOT_RPM_ENABLED}" == xyes)
+
+AC_ARG_ENABLE([java-home],
+  [AS_HELP_STRING([--enable-java-home],
+                 [create a standard JDK-style directory layout in the install tree [default=no]])],
+  [case "${enableval}" in
+    yes) JAVA_HOME_ENABLED=yes ;;
+    no)  JAVA_HOME_ENABLED=no ;;
+    *)   AC_MSG_ERROR([Unknown argument to enable/disable java-home]) ;;
+  esac],
+  [JAVA_HOME_ENABLED=no]
+)
+AM_CONDITIONAL(CREATE_JAVA_HOME, test "x${JAVA_HOME_ENABLED}" == xyes)
+
+# Only do these checks if java-home above is enabled.
+if test "x${JAVA_HOME_ENABLED}" == xyes
+then
+
+  AC_ARG_WITH([gcc-suffix],
+              AS_HELP_STRING([--with-gcc-suffix],
+                             [the GCC tool suffix (defaults to empty string)]),
+              [gcc_suffix=$withval], [gcc_suffix=""])
+  AC_MSG_RESULT(GCC suffix: ${gcc_suffix})
+  AC_SUBST(gcc_suffix)
+
+  AC_ARG_WITH([arch-directory],
+              AS_HELP_STRING([--with-arch-directory],
+                             [the arch directory under jre/lib (defaults to auto-detect)]),
+              [host_cpu=$withval], [host_cpu=""])
+
+  AC_ARG_WITH([os-directory],
+              AS_HELP_STRING([--with-os-directory],
+                             [the os directory under include (defaults to auto-detect)]),
+              [host_os=$withval], [host_os=""])
+
+  AC_ARG_WITH([origin-name],
+              AS_HELP_STRING([--with-origin-name],
+                             [the JPackage origin name of this package (default is gcj${gcc_suffix}]),
+              [origin_name=$withval], [origin_name=gcj${gcc_suffix}])
+  AC_MSG_RESULT(JPackage origin name: ${origin_name})
+
+  AC_ARG_WITH([arch-suffix],
+              AS_HELP_STRING([--with-arch-suffix],
+                             [the arch directory suffix (default is the empty string]),
+              [arch_suffix=$withval], [arch_suffix=""])
+  AC_MSG_RESULT(arch suffix: ${arch_suffix})
+
+  AC_ARG_WITH([jvm-root-dir],
+              AS_HELP_STRING([--with-jvm-root-dir],
+                             [where to install SDK (default is ${prefix}/lib/jvm)]),
+              [jvm_root_dir=$withval], [jvm_root_dir="\${prefix}/lib/jvm"])
+  AC_MSG_RESULT(JVM root installation directory: ${jvm_root_dir})
+
+  AC_ARG_WITH([jvm-jar-dir],
+              AS_HELP_STRING([--with-jvm-jar-dir],
+			                 [where to install jars (default is ${prefix}/lib/jvm-exports)]),
+              [jvm_jar_dir=$withval], [jvm_jar_dir=\${prefix}/lib/jvm-exports])
+  AC_MSG_RESULT(JAR root installation directory: ${jvm_jar_dir})
+
+  JAVA_VERSION=1.5.0
+  BUILD_VERSION=0
+  AC_SUBST(JAVA_VERSION)
+  AC_SUBST(BUILD_VERSION)
+  AC_MSG_RESULT(Java version: ${JAVA_VERSION})
+
+  jre_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}/jre
+  sdk_dir=java-${JAVA_VERSION}-${origin_name}-${JAVA_VERSION}.${BUILD_VERSION}${arch_suffix}
+  jre_lnk=jre-${JAVA_VERSION}-${origin_name}
+  sdk_lnk=java-${JAVA_VERSION}-${origin_name}
+
+  JVM_ROOT_DIR=${jvm_root_dir}
+  AC_SUBST(JVM_ROOT_DIR)
+  AC_MSG_RESULT(JVM ROOT directory: ${JVM_ROOT_DIR})
+
+  JVM_JAR_ROOT_DIR=${jvm_jar_dir}
+  AC_SUBST(JVM_JAR_ROOT_DIR)
+  AC_MSG_RESULT(JVM JAR ROOT directory: ${JVM_JAR_ROOT_DIR})
+
+  JVM_JAR_DIR=${jvm_jar_dir}/${sdk_dir}
+  AC_SUBST(JVM_JAR_DIR)
+  AC_MSG_RESULT(JVM JAR directory: ${JVM_JAR_DIR})
+
+  JRE_DIR=${jre_dir}
+  AC_SUBST(JRE_DIR)
+
+  SDK_DIR=${sdk_dir}
+  AC_SUBST(SDK_DIR)
+
+  JRE_LNK=${jre_lnk}
+  AC_SUBST(JRE_LNK)
+
+  SDK_LNK=${sdk_lnk}
+  AC_SUBST(SDK_LNK)
+
+  SDK_BIN_DIR=${jvm_root_dir}/${sdk_dir}/bin
+  AC_SUBST(SDK_BIN_DIR)
+  AC_MSG_RESULT(SDK tools directory: ${SDK_BIN_DIR})
+
+  SDK_LIB_DIR=${jvm_root_dir}/${sdk_dir}/lib
+  AC_SUBST(SDK_LIB_DIR)
+  AC_MSG_RESULT(SDK jar directory: ${SDK_LIB_DIR})
+
+  SDK_INCLUDE_DIR=${jvm_root_dir}/${sdk_dir}/include
+  AC_SUBST(SDK_INCLUDE_DIR)
+  AC_MSG_RESULT(SDK include directory: ${SDK_INCLUDE_DIR})
+
+  JRE_BIN_DIR=${jvm_root_dir}/${jre_dir}/bin
+  AC_SUBST(JRE_BIN_DIR)
+  AC_MSG_RESULT(JRE tools directory: ${JRE_BIN_DIR})
+
+  JRE_LIB_DIR=${jvm_root_dir}/${jre_dir}/lib
+  AC_SUBST(JRE_LIB_DIR)
+  AC_MSG_RESULT(JRE lib directory: ${JRE_LIB_DIR})
+
+  # Find gcj prefix using gcj found in PATH.
+  gcj_prefix=`which gcj${gcc_suffix} | sed "s%/bin/gcj${gcc_suffix}%%"`
+
+  # Where do the gcj binaries live?
+  # For jhbuild based builds, they all live in a sibling of bin called
+  # gcj-bin.  Check for gcj-bin first, and use bin otherwise.
+  GCJ_BIN_DIR=`if test -d ${gcj_prefix}/gcj-bin; then echo ${gcj_prefix}/gcj-bin; else echo ${gcj_prefix}/bin; fi`
+  AC_SUBST(GCJ_BIN_DIR)
+  AC_MSG_RESULT(GCJ tools directory: ${GCJ_BIN_DIR})
+
+  echo host is ${host}
+  if test "x${host_cpu}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_cpu=x86;;
+      i486-* | i586-* | i686-*)
+        host_cpu=i386;;
+      *)
+        host_cpu=${host_cpu};;
+    esac
+  fi
+  AC_MSG_RESULT(arch directory: ${host_cpu})
+  CPU=${host_cpu}
+  AC_SUBST(CPU)
+
+  if test "x${host_os}" = "x"
+  then
+    case ${host} in
+      *-mingw* | *-cygwin*)
+        host_os=win32;;
+      *-linux*)
+        host_os=linux;;
+      *)
+        host_os=${host_os};;
+    esac
+  fi
+  echo os directory: ${host_os}
+  OS=${host_os}
+  AC_SUBST(OS)
+
+  # make an expanded $libdir, for substituting into
+  # scripts (and other non-Makefile things).
+  LIBDIR=$libdir
+  if test "x${exec_prefix}" = "xNONE"
+  then
+      lib_exec_prefix=$prefix
+  else
+      lib_exec_prefix=$exec_prefix
+  fi
+  LIBDIR=`echo $libdir | sed "s:\\\${exec_prefix}:$lib_exec_prefix:g"`
+  AC_SUBST(LIBDIR)
+fi
+
 AC_CONFIG_FILES([
 Makefile
 libgcj.pc
@@ -1636,6 +1838,10 @@
 gcj/Makefile
 include/Makefile
 testsuite/Makefile
+contrib/aotcompile.py
+contrib/aot-compile
+contrib/aot-compile-rpm
+contrib/rebuild-gcj-db
 ])

 if test ${multilib} = yes; then
Index: libjava/contrib/rebuild-gcj-db.in
===================================================================
--- libjava/contrib/rebuild-gcj-db.in	(revision 0)
+++ libjava/contrib/rebuild-gcj-db.in	(revision 0)
@@ -0,0 +1,27 @@
+#!/bin/bash
+# rebuild-gcj-db
+
+## Copyright (C) 2000, 2002, 2003, 2008 Free Software Foundation
+##
+##   This file is part of libgcj.
+##
+## This software is copyrighted work licensed under the terms of the
+## Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
+## details.
+
+# Rebuild all the standard databases.
+for i in `@prefix@/bin/gcc --print-multi-lib 2>/dev/null`; do
+   multilib=`echo $i | sed -e 's/^.*;//' | sed -e 's/\@/ -/g'`
+   dirname=`@prefix@/bin/gcc -print-multi-os-directory $multilib 2>/dev/null`
+   base=@prefix@/lib/$dirname
+   dbLocation=`@prefix@/bin/gcj-dbtool -p $base`
+   libdir=$base/gcj
+   if ! test -d $libdir; then
+      # No shared libraries here.
+      continue
+   fi
+   dirname $dbLocation | xargs mkdir -p
+   @prefix@/bin/gcj-dbtool -n $dbLocation 64
+   find $libdir -follow -name '*.db' -print0 | \
+      @prefix@/bin/gcj-dbtool -0 -m $dbLocation $dbLocation
+done
Index: libjava/contrib/aotcompile.py.in
===================================================================
--- libjava/contrib/aotcompile.py.in	(revision 0)
+++ libjava/contrib/aotcompile.py.in	(revision 0)
@@ -0,0 +1,412 @@
+# -*- python -*-
+
+## Copyright (C) 2005, 2006, 2008 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import classfile
+import copy
+import md5
+import operator
+import os
+import sys
+import cStringIO as StringIO
+import zipfile
+
+PATHS = {"make":   "@MAKE@",
+         "gcj":    "@prefix@/bin/gcj@gcc_suffix@",
+         "dbtool": "@prefix@/bin/gcj-dbtool@gcc_suffix@"}
+
+MAKEFLAGS = []
+GCJFLAGS = ["-fPIC", "-findirect-dispatch", "-fjni"]
+LDFLAGS = ["-Wl,-Bsymbolic"]
+
+MAX_CLASSES_PER_JAR = 1024
+MAX_BYTES_PER_JAR = 1048576
+
+MAKEFILE = "Makefile"
+
+MAKEFILE_HEADER = '''\
+GCJ = %(gcj)s
+DBTOOL = %(dbtool)s
+GCJFLAGS = %(gcjflags)s
+LDFLAGS = %(ldflags)s
+
+%%.o: %%.jar
+	$(GCJ) -c $(GCJFLAGS) $< -o $@
+
+TARGETS = \\
+%(targets)s
+
+all: $(TARGETS)'''
+
+MAKEFILE_JOB = '''
+%(base)s_SOURCES = \\
+%(jars)s
+
+%(base)s_OBJECTS = \\
+$(%(base)s_SOURCES:.jar=.o)
+
+%(dso)s: $(%(base)s_OBJECTS)
+	$(GCJ) -shared $(GCJFLAGS) $(LDFLAGS) $^ -o $@
+
+%(db)s: $(%(base)s_SOURCES)
+	$(DBTOOL) -n $@ 64
+	for jar in $^; do \\
+            $(DBTOOL) -f $@ $$jar \\
+                %(libdir)s/%(dso)s; \\
+        done'''
+
+ZIPMAGIC, CLASSMAGIC = "PK\x03\x04", "\xca\xfe\xba\xbe"
+
+class Error(Exception):
+    pass
+
+class Compiler:
+    def __init__(self, srcdir, libdir, prefix = None):
+        self.srcdir = os.path.abspath(srcdir)
+        self.libdir = os.path.abspath(libdir)
+        if prefix is None:
+            self.dstdir = self.libdir
+        else:
+            self.dstdir = os.path.join(prefix, self.libdir.lstrip(os.sep))
+
+        # Calling code may modify these parameters
+        self.gcjflags = copy.copy(GCJFLAGS)
+        self.ldflags = copy.copy(LDFLAGS)
+        self.makeflags = copy.copy(MAKEFLAGS)
+        self.exclusions = []
+
+    def compile(self):
+        """Search srcdir for classes and jarfiles, then generate
+        solibs and mappings databases for them all in libdir."""
+        if not os.path.isdir(self.dstdir):
+            os.makedirs(self.dstdir)
+        oldcwd = os.getcwd()
+        os.chdir(self.dstdir)
+        try:
+            jobs = self.getJobList()
+            if not jobs:
+                raise Error, "nothing to do"
+            self.writeMakefile(MAKEFILE, jobs)
+            for job in jobs:
+                job.writeJars()
+            system([PATHS["make"]] + self.makeflags)
+            for job in jobs:
+                job.clean()
+            os.unlink(MAKEFILE)
+        finally:
+            os.chdir(oldcwd)
+
+    def getJobList(self):
+        """Return all jarfiles and class collections in srcdir."""
+        jobs = weed_jobs(find_jobs(self.srcdir, self.exclusions))
+        set_basenames(jobs)
+        return jobs
+
+    def writeMakefile(self, path, jobs):
+        """Generate a makefile to build the solibs and mappings
+        databases for the specified list of jobs."""
+        fp = open(path, "w")
+        print >>fp, MAKEFILE_HEADER % {
+            "gcj": PATHS["gcj"],
+            "dbtool": PATHS["dbtool"],
+            "gcjflags": " ".join(self.gcjflags),
+            "ldflags": " ".join(self.ldflags),
+            "targets": " \\\n".join(reduce(operator.add, [
+                (job.dsoName(), job.dbName()) for job in jobs]))}
+        for job in jobs:
+            values = job.ruleArguments()
+            values["libdir"] = self.libdir
+            print >>fp, MAKEFILE_JOB % values
+        fp.close()
+
+def find_jobs(dir, exclusions = ()):
+    """Scan a directory and find things to compile: jarfiles (zips,
+    wars, ears, rars, etc: we go by magic rather than file extension)
+    and directories of classes."""
+    def visit((classes, zips), dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            magic = open(path, "r").read(4)
+            if magic == ZIPMAGIC:
+                zips.append(path)
+            elif magic == CLASSMAGIC:
+                classes.append(path)
+    classes, paths = [], []
+    os.path.walk(dir, visit, (classes, paths))
+    # Convert the list of classes into a list of directories
+    while classes:
+        # XXX this requires the class to be correctly located in its heirachy.
+        path = classes[0][:-len(os.sep + classname(classes[0]) + ".class")]
+        paths.append(path)
+        classes = [cls for cls in classes if not cls.startswith(path)]
+    # Handle exclusions.  We're really strict about them because the
+    # option is temporary in aot-compile-rpm and dead options left in
+    # specfiles will hinder its removal.
+    for path in exclusions:
+        if path in paths:
+            paths.remove(path)
+        else:
+            raise Error, "%s: path does not exist or is not a job" % path
+    # Build the list of jobs
+    jobs = []
+    paths.sort()
+    for path in paths:
+        if os.path.isfile(path):
+            job = JarJob(path)
+        else:
+            job = DirJob(path)
+        if len(job.classes):
+            jobs.append(job)
+    return jobs
+
+class Job:
+    """A collection of classes that will be compiled as a unit."""
+
+    def __init__(self, path):
+        self.path, self.classes, self.blocks = path, {}, None
+
+    def addClass(self, bytes):
+        """Subclasses call this from their __init__ method for
+        every class they find."""
+        self.classes[md5.new(bytes).digest()] = bytes
+
+    def __makeBlocks(self):
+        """Split self.classes into chunks that can be compiled to
+        native code by gcj.  In the majority of cases this is not
+        necessary -- the job will have come from a jarfile which will
+        be equivalent to the one we generate -- but this only happens
+        _if_ the job was a jarfile and _if_ the jarfile isn't too big
+        and _if_ the jarfile has the correct extension and _if_ all
+        classes are correctly named and _if_ the jarfile has no
+        embedded jarfiles.  Fitting a special case around all these
+        conditions is tricky to say the least.
+
+        Note that this could be called at the end of each subclass's
+        __init__ method.  The reason this is not done is because we
+        need to parse every class file.  This is slow, and unnecessary
+        if the job is subsetted."""
+        names = {}
+        for hash, bytes in self.classes.items():
+            name = classname(bytes)
+            if not names.has_key(name):
+                names[name] = []
+            names[name].append(hash)
+        names = names.items()
+        # We have to sort somehow, or the jars we generate
+        # We sort by name in a simplistic attempt to keep related
+        # classes together so inter-class optimisation can happen.
+        names.sort()
+        self.blocks, bytes = [[]], 0
+        for name, hashes in names:
+            for hash in hashes:
+                if len(self.blocks[-1]) >= MAX_CLASSES_PER_JAR \
+                   or bytes >= MAX_BYTES_PER_JAR:
+                    self.blocks.append([])
+                    bytes = 0
+                self.blocks[-1].append((name, hash))
+                bytes += len(self.classes[hash])
+
+    # From Archit Shah:
+    #   The implementation and the documentation don't seem to match.
+    #
+    #    [a, b].isSubsetOf([a]) => True
+    #
+    #   Identical copies of all classes this collection do not exist
+    #   in the other. I think the method should be named isSupersetOf
+    #   and the documentation should swap uses of "this" and "other"
+    #
+    # XXX think about this when I've had more sleep...
+    def isSubsetOf(self, other):
+        """Returns True if identical copies of all classes in this
+        collection exist in the other."""
+        for item in other.classes.keys():
+            if not self.classes.has_key(item):
+                return False
+        return True
+
+    def __targetName(self, ext):
+        return self.basename + ext
+
+    def tempJarName(self, num):
+        return self.__targetName(".%d.jar" % (num + 1))
+
+    def tempObjName(self, num):
+        return self.__targetName(".%d.o" % (num + 1))
+
+    def dsoName(self):
+        """Return the filename of the shared library that will be
+        built from this job."""
+        return self.__targetName(".so")
+
+    def dbName(self):
+        """Return the filename of the mapping database that will be
+        built from this job."""
+        return self.__targetName(".db")
+
+    def ruleArguments(self):
+        """Return a dictionary of values that when substituted
+        into MAKEFILE_JOB will create the rules required to build
+        the shared library and mapping database for this job."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        return {
+            "base": "".join(
+                [c.isalnum() and c or "_" for c in self.dsoName()]),
+            "jars": " \\\n".join(
+                [self.tempJarName(i) for i in xrange(len(self.blocks))]),
+            "dso": self.dsoName(),
+            "db": self.dbName()}
+
+    def writeJars(self):
+        """Generate jarfiles that can be native compiled by gcj."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for block, i in zip(self.blocks, xrange(len(self.blocks))):
+            jar = zipfile.ZipFile(self.tempJarName(i), "w", zipfile.ZIP_STORED)
+            for name, hash in block:
+                jar.writestr(
+                    zipfile.ZipInfo("%s.class" % name), self.classes[hash])
+            jar.close()
+
+    def clean(self):
+        """Delete all temporary files created during this job's build."""
+        if self.blocks is None:
+            self.__makeBlocks()
+        for i in xrange(len(self.blocks)):
+            os.unlink(self.tempJarName(i))
+            os.unlink(self.tempObjName(i))
+
+class JarJob(Job):
+    """A Job whose origin was a jarfile."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        self._walk(zipfile.ZipFile(path, "r"))
+
+    def _walk(self, zf):
+        for name in zf.namelist():
+            bytes = zf.read(name)
+            if bytes.startswith(ZIPMAGIC):
+                self._walk(zipfile.ZipFile(StringIO.StringIO(bytes)))
+            elif bytes.startswith(CLASSMAGIC):
+                self.addClass(bytes)
+
+class DirJob(Job):
+    """A Job whose origin was a directory of classfiles."""
+
+    def __init__(self, path):
+        Job.__init__(self, path)
+        os.path.walk(path, DirJob._visit, self)
+
+    def _visit(self, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.islink(path) or not os.path.isfile(path):
+                continue
+            fp = open(path, "r")
+            magic = fp.read(4)
+            if magic == CLASSMAGIC:
+                self.addClass(magic + fp.read())
+
+def weed_jobs(jobs):
+    """Remove any jarfiles that are completely contained within
+    another.  This is more common than you'd think, and we only
+    need one nativified copy of each class after all."""
+    jobs = copy.copy(jobs)
+    while True:
+        for job1 in jobs:
+            for job2 in jobs:
+                if job1 is job2:
+                    continue
+                if job1.isSubsetOf(job2):
+                    msg = "subsetted %s" % job2.path
+                    if job2.isSubsetOf(job1):
+                        if (isinstance(job1, DirJob) and
+                            isinstance(job2, JarJob)):
+                            # In the braindead case where a package
+                            # contains an expanded copy of a jarfile
+                            # the jarfile takes precedence.
+                            continue
+                        msg += " (identical)"
+                    warn(msg)
+                    jobs.remove(job2)
+                    break
+            else:
+                continue
+            break
+        else:
+            break
+        continue
+    return jobs
+
+def set_basenames(jobs):
+    """Ensure that each jarfile has a different basename."""
+    names = {}
+    for job in jobs:
+        name = os.path.basename(job.path)
+        if not names.has_key(name):
+            names[name] = []
+        names[name].append(job)
+    for name, set in names.items():
+        if len(set) == 1:
+            set[0].basename = name
+            continue
+        # prefix the jar filenames to make them unique
+        # XXX will not work in most cases -- needs generalising
+        set = [(job.path.split(os.sep), job) for job in set]
+        minlen = min([len(bits) for bits, job in set])
+        set = [(bits[-minlen:], job) for bits, job in set]
+        bits = apply(zip, [bits for bits, job in set])
+        while True:
+            row = bits[-2]
+            for bit in row[1:]:
+                if bit != row[0]:
+                    break
+            else:
+                del bits[-2]
+                continue
+            break
+        set = zip(
+            ["_".join(name) for name in apply(zip, bits[-2:])],
+            [job for bits, job in set])
+        for name, job in set:
+            warn("building %s as %s" % (job.path, name))
+            job.basename = name
+    # XXX keep this check until we're properly general
+    names = {}
+    for job in jobs:
+        name = job.basename
+        if names.has_key(name):
+            raise Error, "%s: duplicate jobname" % name
+        names[name] = 1
+
+def system(command):
+    """Execute a command."""
+    status = os.spawnv(os.P_WAIT, command[0], command)
+    if status > 0:
+        raise Error, "%s exited with code %d" % (command[0], status)
+    elif status < 0:
+        raise Error, "%s killed by signal %d" % (command[0], -status)
+
+def warn(msg):
+    """Print a warning message."""
+    print >>sys.stderr, "%s: warning: %s" % (
+        os.path.basename(sys.argv[0]), msg)
+
+def classname(bytes):
+    """Extract the class name from the bytes of a class file."""
+    klass = classfile.Class(bytes)
+    return klass.constants[klass.constants[klass.name][1]][1]
Index: libjava/contrib/aot-compile-rpm.in
===================================================================
--- libjava/contrib/aot-compile-rpm.in	(revision 0)
+++ libjava/contrib/aot-compile-rpm.in	(revision 0)
@@ -0,0 +1,97 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2005, 2006, 2007 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import os
+
+def libdir():
+    cmd = "%s -p" % aotcompile.PATHS["dbtool"]
+    dir = os.path.abspath(os.popen(cmd, "r").readline().rstrip())
+    dir, base = os.path.split(dir)
+    if base != "classmap.db":
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    dir, base = os.path.split(dir)
+    if not base.startswith("gcj-"):
+        raise aotcompile.Error, "%s: unexpected output" % cmd
+    return dir
+
+def writeSourceList(srcdir, dstpath):
+    def visit(fp, dir, items):
+        for item in items:
+            path = os.path.join(dir, item)
+            if os.path.isfile(path):
+                print >>fp, path
+    dstdir = os.path.dirname(dstpath)
+    if not os.path.isdir(dstdir):
+        os.makedirs(dstdir)
+    os.path.walk(srcdir, visit, open(dstpath, "w"))
+
+def copy(srcdir, dstdir, suffix):
+    srcdir = os.path.join(srcdir, suffix.lstrip(os.sep))
+    dstdir = os.path.join(dstdir, suffix.lstrip(os.sep))
+    os.makedirs(os.path.dirname(dstdir))
+    aotcompile.system(("/bin/cp", "-a", srcdir, dstdir))
+
+try:
+    name = os.environ.get("RPM_PACKAGE_NAME")
+    if name is None:
+        raise aotcompile.Error, "not for use outside rpm specfiles"
+    arch = os.environ.get("RPM_ARCH")
+    if arch == "noarch":
+        raise aotcompile.Error, "cannot be used on noarch packages"
+    srcdir = os.environ.get("RPM_BUILD_ROOT")
+    if srcdir in (None, "/"):
+        raise aotcompile.Error, "bad $RPM_BUILD_ROOT"
+    tmpdir = os.path.join(os.getcwd(), "aot-compile-rpm")
+    if os.path.exists(tmpdir):
+        raise aotcompile.Error, "%s exists" % tmpdir
+    dstdir = os.path.join(libdir(), "gcj", name)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir, tmpdir)
+    compiler.gcjflags[0:0] = os.environ.get("RPM_OPT_FLAGS", "").split()
+
+    # XXX: This script should not accept options, because having
+    # them it cannot be integrated into rpm.  But, gcj cannot
+    # build each and every jarfile yet, so we must be able to
+    # exclude until it can.
+    # XXX --exclude is also used in the jonas rpm to stop
+    # everything being made a subset of the mammoth client
+    # jarfile. Should adjust the subset checker's bias to
+    # favour many small jarfiles over one big one.
+    try:
+        options, exclusions = sys.argv[1:], []
+        while options:
+            if options.pop(0) != "--exclude":
+                raise ValueError
+            compiler.exclusions.append(
+                os.path.join(srcdir, options.pop(0).lstrip(os.sep)))
+    except:
+        print >>sys.stderr, "usage: %s [--exclude PATH]..." % (
+            os.path.basename(sys.argv[0]))
+        sys.exit(1)
+
+    sourcelist = os.path.join(tmpdir, "sources.list")
+    writeSourceList(os.getcwd(), sourcelist)
+    compiler.gcjflags.append("-fsource-filename=" + sourcelist)
+
+    compiler.compile()
+    copy(tmpdir, srcdir, dstdir)
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/contrib/classfile.py
===================================================================
--- libjava/contrib/classfile.py	(revision 0)
+++ libjava/contrib/classfile.py	(revision 0)
@@ -0,0 +1,221 @@
+## Copyright (C) 2004, 2005 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+"""Read Java(TM) class files."""
+
+import cStringIO as StringIO
+import struct
+
+class Class:
+    def __init__(self, arg):
+        if hasattr(arg, "read"):
+            self.fp = arg
+        elif type(arg) == type(""):
+            if arg.startswith("\xca\xfe\xba\xbe"):
+                self.fp = StringIO.StringIO(arg)
+            else:
+                self.fp = open(arg, "r")
+        else:
+            raise TypeError, type(arg)
+
+        magic = self._read_int()
+        assert magic == 0xcafebabeL
+        minor, major = self._read(">HH")
+        self.version = (major, minor)
+
+        self.pool_integrity_checks = None
+        try:
+            assert False
+        except AssertionError:
+            self.pool_integrity_checks = []
+
+        self._read_constants_pool()
+
+        self.access_flags = self._read_short()
+        self.name = self._read_reference_Class()
+        self.super = self._read_reference_Class()
+
+        self.interfaces = self._read_interfaces()
+        self.fields = self._read_fieldsormethods()
+        self.methods = self._read_fieldsormethods()
+        self.attributes = self._read_attributes()
+
+        if self.pool_integrity_checks is not None:
+            for index, tag in self.pool_integrity_checks:
+                assert self.constants[index][0] == tag
+
+        del self.fp, self.pool_integrity_checks
+
+    def __repr__(self):
+        result = []
+        attrs = [attr for attr in dir(self)
+                 if not attr.startswith("_") and attr != "Member"]
+        attrs.sort()
+        for attr in attrs:
+            result.append("%-13s %s" % (
+                attr + ":", attr == "constants" and
+                "<ELIDED>" or repr(getattr(self, attr))))
+        return "\n".join(result)
+
+    def _read_constants_pool(self):
+        self.constants = {}
+        skip = False
+        for i in xrange(1, self._read_short()):
+            if skip:
+                skip = False
+                continue
+            tag = {
+                1: "Utf8", 3: "Integer", 4: "Float", 5: "Long",
+                6: "Double", 7: "Class", 8: "String", 9: "Fieldref",
+                10: "Methodref", 11: "InterfaceMethodref",
+                12: "NameAndType"}[self._read_byte()]
+            skip = tag in ("Long", "Double") # crack crack crack!
+            self.constants[i] = (tag, getattr(self, "_read_constant_" + tag)())
+
+    def _read_interfaces(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self._read_reference_Class())
+        return result
+
+    def _read_fieldsormethods(self):
+        result = []
+        for i in xrange(self._read_short()):
+            result.append(self.Member(self))
+        return result
+
+    class Member:
+        def __init__(self, source):
+            self.access_flags = source._read_short()
+            self.name = source._read_reference_Utf8()
+            self.descriptor = source._read_reference_Utf8()
+            self.attributes = source._read_attributes()
+
+        def __repr__(self):
+            result = []
+            attrs = [attr for attr in dir(self) if not attr.startswith("_")]
+            attrs.sort()
+            for attr in attrs:
+                value = getattr(self, attr)
+                if attr == "attributes" and value.has_key("Code"):
+                    value = value.copy()
+                    value.update({"Code": "<ELIDED>"})
+                result.append("%-13s %s" % (
+                    attr + ":", repr(value).replace(
+                        "'Code': '<ELIDED>'", "'Code': <ELIDED>")))
+            return ("\n%s" % (15 * " ")).join(result)
+
+    def _read_attributes(self):
+        result = {}
+        for i in xrange(self._read_short()):
+            name = self._read_reference_Utf8()
+            data = self.fp.read(self._read_int())
+            assert not result.has_key(name)
+            result[name] = data
+        return result
+
+    # Constants pool reference reader convenience functions
+
+    def _read_reference_Utf8(self):
+        return self._read_references("Utf8")[0]
+
+    def _read_reference_Class(self):
+        return self._read_references("Class")[0]
+
+    def _read_reference_Class_NameAndType(self):
+        return self._read_references("Class", "NameAndType")
+
+    def _read_references(self, *args):
+        result = []
+        for arg in args:
+            index = self._read_short()
+            if self.pool_integrity_checks is not None:
+                self.pool_integrity_checks.append((index, arg))
+            result.append(index)
+        return result
+
+    # Constants pool constant reader functions
+
+    def _read_constant_Utf8(self):
+        constant = self.fp.read(self._read_short())
+        try:
+            constant = constant.decode("utf-8")
+        except UnicodeError:
+            constant = _bork_utf8_decode(constant)
+        try:
+            constant = constant.encode("us-ascii")
+        except UnicodeError:
+            pass
+        return constant
+
+    def _read_constant_Integer(self):
+        return self._read_int()
+
+    def _read_constant_Float(self):
+        return self._read(">f")[0]
+
+    def _read_constant_Long(self):
+        return self._read(">q")[0]
+
+    def _read_constant_Double(self):
+        return self._read(">d")[0]
+
+    _read_constant_Class = _read_reference_Utf8
+    _read_constant_String = _read_reference_Utf8
+    _read_constant_Fieldref = _read_reference_Class_NameAndType
+    _read_constant_Methodref = _read_reference_Class_NameAndType
+    _read_constant_InterfaceMethodref = _read_reference_Class_NameAndType
+
+    def _read_constant_NameAndType(self):
+        return self._read_reference_Utf8(), self._read_reference_Utf8()
+
+    # Generic reader functions
+
+    def _read_int(self):
+        # XXX how else to read 32 bits on a 64-bit box?
+        h, l = map(long, self._read(">HH"))
+        return (h << 16) + l
+
+    def _read_short(self):
+        return self._read(">H")[0]
+
+    def _read_byte(self):
+        return self._read("B")[0]
+
+    def _read(self, fmt):
+        return struct.unpack(fmt, self.fp.read(struct.calcsize(fmt)))
+
+def _bork_utf8_decode(data):
+    # more crack!
+    bytes, unicode = map(ord, data), ""
+    while bytes:
+        b1 = bytes.pop(0)
+        if b1 & 0x80:
+            assert b1 & 0x40
+            b2 = bytes.pop(0)
+            assert b2 & 0xC0 == 0x80
+            if b1 & 0x20:
+                assert not b1 & 0x10
+                b3 = bytes.pop(0)
+                assert b3 & 0xC0 == 0x80
+                unicode += unichr(
+                    ((b1 & 0x0f) << 12) + ((b2 & 0x3f) << 6) + (b3 & 0x3f))
+            else:
+                unicode += unichr(((b1 & 0x1f) << 6) + (b2 & 0x3f))
+        else:
+            unicode += unichr(b1)
+    return unicode
+
+if __name__ == "__main__":
+    print Class("/usr/share/katana/build/ListDependentClasses.class")
+
Index: libjava/contrib/aot-compile.in
===================================================================
--- libjava/contrib/aot-compile.in	(revision 0)
+++ libjava/contrib/aot-compile.in	(revision 0)
@@ -0,0 +1,88 @@
+#!/usr/bin/env python
+
+## Copyright (C) 2006 Free Software Foundation
+## Written by Gary Benson <gbenson@redhat.com>
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+
+import sys
+sys.path.append("@python_mod_dir_expanded@")
+import aotcompile
+import getopt
+import os
+
+usage = """\
+Usage: %s [OPTION...] SRCDIR DSTDIR
+AOT-compile all Java bytecode in SRCDIR into DSTDIR.
+
+Options:
+  -M, --make=PATH        make executable to use (%s)
+  -C, --gcj=PATH         gcj executable to use (%s)
+  -D, --dbtool=PATH      gcj-dbtool executable to use (%s)
+  -m, --makeflags=FLAGS  flags to pass to make during build
+  -c, --gcjflags=FLAGS   flags to pass to gcj during compilation
+                           in addition to %s
+  -l, --ldflags=FLAGS    flags to pass to gcj during linking
+                           in addition to %s
+  -e, --exclude=PATH     do not compile PATH
+
+Extra flags may also be passed using the AOT_MAKEFLAGS, AOT_GCJFLAGS
+and AOT_LDFLAGS environment variables.""" % (
+    os.path.basename(sys.argv[0]),
+    aotcompile.PATHS["make"],
+    aotcompile.PATHS["gcj"],
+    aotcompile.PATHS["dbtool"],
+    repr(" ".join(aotcompile.GCJFLAGS)),
+    repr(" ".join(aotcompile.LDFLAGS)))
+
+try:
+    if os.environ.has_key("RPM_PACKAGE_NAME"):
+        raise aotcompile.Error, "not for use within rpm specfiles"
+
+    try:
+        opts, args = getopt.getopt(
+            sys.argv[1:],
+            "M:C:D:m:c:l:e:",
+            ["make=", "gcj=", "dbtool=",
+             "makeflags=" "gcjflags=", "ldflags=",
+             "exclude="])
+        srcdir, dstdir = args
+    except:
+        print >>sys.stderr, usage
+        sys.exit(1)
+
+    compiler = aotcompile.Compiler(srcdir, dstdir)
+    for o, a in opts:
+        if o in ("-M", "--make"):
+            aotcompile.PATHS["make"] = a
+        if o in ("-C", "--gcj"):
+            aotcompile.PATHS["gcj"] = a
+        if o in ("-D", "--dbtool"):
+            aotcompile.PATHS["dbtool"] = a
+        if o in ("-m", "--makeflags"):
+            compiler.makeflags[0:0] = a.split()
+        if o in ("-c", "--gcjflags"):
+            compiler.gcjflags[0:0] = a.split()
+        if o in ("-l", "--ldflags"):
+            compiler.ldflags[0:0] = a.split()
+        if o in ("-e", "--exclude"):
+            compiler.exclusions.append(a)
+
+    compiler.makeflags[0:0] = os.environ.get("AOT_MAKEFLAGS", "").split()
+    compiler.gcjflags[0:0] = os.environ.get("AOT_GCJFLAGS", "").split()
+    compiler.ldflags[0:0] = os.environ.get("AOT_LDFLAGS", "").split()
+
+    compiler.compile()
+
+except aotcompile.Error, e:
+    print >>sys.stderr, "%s: error: %s" % (
+        os.path.basename(sys.argv[0]), e)
+    sys.exit(1)
Index: libjava/Makefile.am
===================================================================
--- libjava/Makefile.am	(revision 137317)
+++ libjava/Makefile.am	(working copy)
@@ -74,7 +74,8 @@
 ## Name of the default .db.
 db_name = classmap.db
 ## Compiler specific component of the .db file
-db_pathtail = gcj-$(gcc_version)/$(db_name)
+gcjsubdir = @gcjsubdir@
+db_pathtail = $(gcjsubdir)/$(db_name)

 ## For now, only on native systems.  FIXME.
 if NATIVE
@@ -85,9 +86,13 @@
 ## It is convenient to actually build and install the default database
 ## when gcj-dbtool is available.
 dbexec_DATA = $(db_name)
-endif
+endif

-bin_SCRIPTS = addr2name.awk
+bin_SCRIPTS = addr2name.awk contrib/rebuild-gcj-db contrib/aot-compile
+
+if INSTALL_AOT_RPM
+bin_SCRIPTS += contrib/aot-compile-rpm
+endif

 if BUILD_ECJ1
 ## We build ecjx and not ecj1 because in one mode, ecjx will not work
@@ -528,7 +533,140 @@
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SinkChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 	$(INSTALL_DATA) $(srcdir)/'gnu/java/nio/PipeImpl$$SourceChannelImpl.h' $(DESTDIR)$(gxx_include_dir)/gnu/java/nio/
 ## Don't install java/nio/DirectByteBufferImpl$$ReadWrite.h here. It's for internal use only.
-
+## Install Python modules for aot-compile.
+	$(mkinstalldirs) $(DESTDIR)$(python_mod_dir); \
+	$(INSTALL_DATA) $(srcdir)/contrib/classfile.py \
+	  $(DESTDIR)$(python_mod_dir)/classfile.py; \
+	$(INSTALL_DATA) contrib/aotcompile.py \
+	  $(DESTDIR)$(python_mod_dir)/aotcompile.py;
+if CREATE_JAVA_HOME
+## Create sdk style directories
+	$(mkinstalldirs) $(DESTDIR)$(JRE_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_BIN_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/$(OS)
+	relative() { \
+	  $(PERL) -e 'use File::Spec; \
+	    print File::Spec->abs2rel($$ARGV[0], $$ARGV[1])' $$1 $$2; \
+	}; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(SDK_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gjar | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jar; \
+	ln -sf $$RELATIVE/`echo gjdoc | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javadoc; \
+	ln -sf $$RELATIVE/`echo grmic | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmic; \
+	ln -sf $$RELATIVE/`echo gjavah | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/javah; \
+	ln -sf $$RELATIVE/ecj $(DESTDIR)$(SDK_BIN_DIR)/javac; \
+	ln -sf $$RELATIVE/`echo gappletviewer | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/appletviewer; \
+	ln -sf $$RELATIVE/`echo gjarsigner | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/jarsigner; \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo gnative2ascii | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/native2ascii; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/tnameserv; \
+	ln -sf $$RELATIVE/`echo gserialver | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(SDK_BIN_DIR)/serialver; \
+	RELATIVE=$$(relative $(DESTDIR)$(bindir) $(DESTDIR)$(JRE_BIN_DIR)); \
+	ln -sf $$RELATIVE/`echo grmiregistry | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmiregistry; \
+	ln -sf $$RELATIVE/`echo gkeytool | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/keytool; \
+	ln -sf $$RELATIVE/`echo gij | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/java; \
+	ln -sf $$RELATIVE/`echo gorbd | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/orbd; \
+	ln -sf $$RELATIVE/`echo grmid | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/rmid; \
+	ln -sf $$RELATIVE/`echo gtnameserv | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'` \
+	  $(DESTDIR)$(JRE_BIN_DIR)/tnameserv; \
+	$(mkinstalldirs) $(DESTDIR)$(JVM_JAR_DIR); \
+	version=$(JAVA_VERSION).$(BUILD_VERSION); \
+	working_dir=`pwd`; \
+	cd $(DESTDIR)$(JVM_JAR_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s $$RELATIVE/$$jarname.jar $$jarname-$$version.jar; \
+	  done; \
+	  for jar in *-$$version.jar; \
+	  do \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|-$(JAVA_VERSION).jar|g"); \
+	    ln -sf $$jar $$(echo $$jar | sed "s|-$$version.jar|.jar|g"); \
+	  done; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	RELATIVE=$$(relative $(DESTDIR)$(libdir)/security \
+	  $(DESTDIR)$(JRE_LIB_DIR)/security); \
+	cd $(DESTDIR)$(JRE_LIB_DIR)/security; \
+	  ln -sf $$RELATIVE/classpath.security java.security; \
+	cd $$working_dir; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_INCLUDE_DIR)/linux; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client; \
+	$(mkinstalldirs) $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server; \
+	$(mkinstalldirs) $(DESTDIR)$(SDK_LIB_DIR); \
+	cd $(DESTDIR)$(JRE_LIB_DIR); \
+	  for jarname in jaas jce jdbc-stdext jndi jndi-cos jndi-dns \
+	    jndi-ldap jndi-rmi jsse sasl; \
+	  do \
+	    ln -s rt.jar $$jarname.jar; \
+	  done; \
+	cd $$working_dir; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JRE_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-$(gcc_version).jar \
+	  $(DESTDIR)$(JRE_LIB_DIR)/rt.jar; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)); \
+	ln -sf $$RELATIVE/libjawt.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/libjawt.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/client/libjvm.so; \
+	RELATIVE=$$(relative $(DESTDIR)$(dbexecdir) \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server); \
+	ln -sf $$RELATIVE/libjvm.so \
+	  $(DESTDIR)$(JRE_LIB_DIR)/$(CPU)/server/libjvm.so;	\
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(SDK_LIB_DIR)); \
+	ln -sf $$RELATIVE/libgcj-tools-$(gcc_version).jar \
+	  $(DESTDIR)$(SDK_LIB_DIR)/tools.jar; \
+	for headername in jawt jni; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/$$headername.h; \
+	done; \
+	for headername in jawt_md jni_md; do \
+	  DIRECTORY=$$(dirname $$($(DESTDIR)$(bindir)/gcj \
+	    -print-file-name=include/$$headername.h)); \
+	  RELATIVE=$$(relative $(DESTDIR)$$DIRECTORY \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux); \
+	  ln -sf $$RELATIVE/$$headername.h \
+	    $(DESTDIR)$(SDK_INCLUDE_DIR)/linux/$$headername.h; \
+	done; \
+	RELATIVE=$$(relative $(DESTDIR)$(datarootdir)/java \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)); \
+	ln -sf $$RELATIVE/src-$(gcc_version).zip \
+	  $(DESTDIR)$(JVM_ROOT_DIR)/$(SDK_DIR)/src.zip;
+endif

 ## ################################################################

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [patch] Create sdk style directory on install
  2008-07-02 13:07                     ` Andrew Haley
@ 2008-07-02 13:19                       ` Joshua Sumali
  0 siblings, 0 replies; 18+ messages in thread
From: Joshua Sumali @ 2008-07-02 13:19 UTC (permalink / raw)
  To: Andrew Haley; +Cc: java-patches

Andrew Haley wrote:
> Joshua Sumali wrote:
>   
>> Andrew Haley wrote:
>>     
>>> Joshua Sumali wrote:
>>>  
>>>       
>>>> Andrew Haley wrote:
>>>>     
>>>>         
>>>  
>>>       
>>>>> Please assign all Red Hat copyrights to the FSF.
>>>>>         
>>>>>           
>>>> Is there a special way to do this, or do I simply change "Copyright (C)
>>>> 2005, 2006, 2008 Red Hat, Inc." to "Copyright (C) 2005, 2006, 2008 Free
>>>> Software Foundation" on the appropriate files?
>>>>     
>>>>         
>>> That's all you have to do.
>>>
>>>  
>>>       
>>>>> Do I take it that you don't have commit access to the gcc tree?
>>>>>         
>>>>>           
>>>> I do not. I was hoping someone would be able to commit the patches
>>>> for me.
>>>>     
>>>>         
>>> I'll do it.
>>>       
>
> Here's what I committed.  I had partly to rewrite rebuild-gcj-db because it
> handled multilibs incorrectly, and in the process discovered a bug in
> gcj-dbtool, but otherwise it's the same.
>
> Andrew.
>
>   
TVM for the help with this patch :)

Josh

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2008-07-02 13:19 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-12 20:56 [patch] Create sdk style directory on install Joshua Sumali
2008-06-13 10:42 ` Andrew Haley
2008-06-13 12:42 ` Matthias Klose
2008-06-16 14:37   ` Joshua Sumali
2008-06-18 20:39     ` Joshua Sumali
2008-06-19  9:54       ` Andrew Haley
2008-06-19 14:24         ` Joshua Sumali
2008-06-20  4:13           ` Joshua Sumali
2008-06-26 18:18           ` Joshua Sumali
2008-06-30 10:20             ` Andrew Haley
2008-06-30 13:54               ` Joshua Sumali
2008-06-30 13:57                 ` Andrew Haley
2008-06-30 14:39                   ` Joshua Sumali
2008-07-01 13:59                     ` Andrew Haley
2008-07-01 14:53                       ` Joshua Sumali
2008-07-01 15:01                         ` Andrew Haley
2008-07-02 13:07                     ` Andrew Haley
2008-07-02 13:19                       ` Joshua Sumali

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).