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


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

Re: [patch] Create sdk style directory on install


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.


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
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
 #
 # 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 ; \

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