rhug

a collection of java packages built with gcj


home

faq

mailing list

source code

hacking howto

So you want to add a package to rhug? Cool. This page explains what you should do. It takes the approach of someone who's not super familiar with automake/autoconf and friends; who already used gcj to build things. If you encounter problems following these steps, read the manuals and/or send mail to the list.

Here's what you should do:

  • Send mail to the mailing list, and tell people what you'd like to do before you start working on it. We need to agree on how useful the package is, it has to be open source, etc... Let's say you proposed and we agreed on adding something called foo

  • Unfortunately, rhug developers require a special hacked version of the auto-tools. Get them from here: ftp://sources.redhat.com/pub/rhug/rhug-maintainer-tools.tar.gz

  • We assume that you already checked out and built rhug. You probably saw that there's one directory per component, with some mandatory items inside the component directory. Along with the relevant bits from the base of the checked out tree, here's what you should care about:
          -+- ChangeLog
           |- configure.in			# (1)
           |- Makefile.am			# (2)
           |- ...
           |- <module> -+- ChangeLog
           |            |- info.rml		# Used for web page generation
           |            |- TODO             # Let people know of what's missing
           |            |- Makefile.am	# (3)
           |            `- upstream/        # where the project original tree resides.
           `- ...
          
    <module>/upstream usually contains a desired snapshot of the module to be added. It's probably better if upstream/src contains the source code (you might notice it not the case with BCEL for instance. Sometimes it's not possible and it's doesn't matter much.)

  • Add (things that you need to add or edit within the added piece are underlined) your package into the AC_OUTPUT section of the top level configure.in (1):

    AC_OUTPUT(Makefile pgsql-jdbc/Makefile ... jasmin/Makefile foo/Makefile)

    And add something to create the beginning of your module source tree in the build directory. Whatever the location of the module sources is, help the creation of an equivalent structure in the build directory by adding something like this (this code will be executed at configuration time:)

    $ac_aux_dir/mkinstalldirs jasmin/upstream/src > /dev/null 2>&1
    ...
    $ac_aux_dir/mkinstalldirs foo/upstream/src > /dev/null 2>&1

  • Add your package into the somedirs section of the top level Makefile.am (2)

    somedirs = pgsql-jdbc gnu.readline rhino gnu.regexp BCEL cup xerces     \
    jakarta-regexp jakarta-oro jakarta-log4j xalan bsf jakarta-servletapi   \
    jakarta-tomcat jython jasmin foo
          

  • Create the directory for foo, create upstream and import a stable version of foo in it, trying to arrange for upstream/scr to contain the sources of your project.

  • Create foo/Makefile.am (3). This is the main task. Let's simplify and say that foo should yield to one library, generate one stand alone binary for testing purposes. For your convenience, a skeleton can be downloaded. In the skeleton file, things to be replaced are between []'s.

    You start by telling automake the libraries, standalone executables and jarfiles that should be created; along with the flags gcj should be using building things natively:

          ## Process this file with automake to produce Makefile.in.
    
          AUTOMAKE_OPTIONS = foreign
    
          ## ################################################################
          ##
          ## What gets installed, and where.
          ##
          lib_LTLIBRARIES = lib-package-that-foo-defines.la
          check_PROGRAMS = test_standalone_executable_name
          JARFILE = package-that-foo-defines.jar
          BUILT_SOURCES = $(JARFILE)
          data_DATA = $(JARFILE)
    
          ## ################################################################
          ##
          ## Compilers and compilation flags.
          ##
          AM_GCJFLAGS = -fassume-compiled -fCLASSPATH=$(srcdir)/upstream/src
          

    AM_GCJFLAGS could contains other flags, like --encoding=... or -fjni, etc... If foo contains native parts, you might have to define AM_CFLAGS.

    package-that-foo-defines means that for example if foo defines and implement org.gnu.foo, you would write it org-gnu-foo (it's an automake convention.) lib_LTLIBRARIES (and subsequently JARFILE) could contain more than one entry.

    Then you need to explain what are the files that you need to consider in order to build the components. There's one entry per entry found in lib_LTLIBRARIES:

          ## ################################################################
          ##
          ## What libraries need in order to be built
          ##
          lib_package_that_foo_defines_la_la_SOURCE = \
          ./upstream/src/<package>/<that>/<foo>/<defines/<file>.java \
          ./upstream/src/<package>/<that>/<foo>/<defines/<other_file>.java \
          ...
          

    package_that_foo_defines means that for example if foo defines and implement org.gnu.foo, you would write it org_gnu_foo (it's an automake convention.)

    If package_that_foo_defines requires other libraries to link properly, then it should be expressed as:

          lib_package_that_foo_defines_la_LIBADD = ...
          

    How would you specify how to build the stand alone test executable? You would add the following section:

          ## ################################################################
          ##
          ## What (test) standalone executables need in order to be build.
          ##
          test_standalone_executable_name_SOURCES = ...
          test_standalone_executable_name_LDFLAGS = --main=<access_to_main> ...
          test_standalone_executable_name_LDADD = -L. -l-package-that-foo-defines
          

    The last thing you have to specify is how the jarfile gets created. It's not super clean yet, maybe future features in automake will simplify things (and maybe they do already:)

          ## ################################################################
          ##
          ## Class file business
          ##
          CLASSFILES = $(lib_package_that_foo_defines_la_SOURCES:.java=.class)
    
          %.class: %.java
            $(GCJ) -C <other_flags> -d upstream/src $<
          

    <other_flags> could be for example --encoding=UTF-8. You could introduce a new variable in order to share as much flags as possible with AM_GCJFLAGS. The there's a rule to add on how to generate the jarfile:

    $(JARFILE): $(CLASSFILES) (cd upstream/src; for x in `find ./ -name \*.class`; do $(GCJH) `echo $$x | sed "s/\.\///g" | sed "s/.class//g"`; done;) (cd upstream/src; jar cf ../../$@ `find ./ -name \*.class`)

    There are a couple of missing things (notably EXTRA_DIST), but with this you should be able to see a build start. You can also read other Makefile.am files for inspirations: gnu.readline/Makefile.am is a good example -- because it's small, handles JNI files, the creation of test executable and jar files.

  • Now you're ready to rebuild everything. The files you created and/or modified are going to be automatically processed at configure time; yielding to further files and eventually a Makefile in <build-dir>/<foo/. This phase is always a bit delicate and unless you're very confortable with automake/autoconf you should probably always wipe things clean before configuring and typing make. Once you generate a Makefile in the added module build directory, you can be a little more localized in your builds.

  • Once you're done, tell the mailing list about it. You can send a patch on the existing file and point to a tarball that contains the new foo/ directory.


Alex Petit-Bianco
apbianco@redhat.com

This page is not maintained in XML and doesn't use the Xalan XSLT processor to generate HTML, :-)~. But that could be fixed.