Java packages have a different directory structure than the C/C++ packages described in the previous sections. They also contain other types of files, so there must be different declarations in the package description file. Finally, build management is different, since Java is a language that is compiled into a pseudo-code which in turn gets interpreted by a virtual java machine.
There is one big problem concerning the terminology when talking about ComPact Java packages: the Java language defines its own notion of package which is quite different from the notion of package used by ComPact. To make things clear, we will refer to ComPact packages just as package as in every other part of this manual, and explicitly talk of Java language packages if necessary.
Elego ComPact offers two different kinds of Java packages, both of which come with configurations for the standard Java development kit from Sun Microsystems. Other compilers and development environments should be easily adapted; they will be shipped with every new version and made available for everybody on Elego's FTP site.
Standard Java configurations use packages of the kind COMPACT_JAVA [ _UNIX | _WIN32 ]. This is a complex directory hierarchy with different locations for Java sources, generated HTML files, and Java bytecode files. All the Java package directories are contained inside the ComPact package in the Java sub-directory. There are two advantages of these standard Java packages:
The Java language package name does not need be equal to the ComPact package name, making it possible to have packages with the same last name, i.e. p1.io and p2.io. Generally it seems sensible to name the compact package with the complete Java package names including the dots.
It is possible to have sub-directories for different compilation options (though currently only debug is supported). The disadvantage of these package kinds is of course the complex structure.
The package kinds SIMPLE_COMPACT_JAVA [ _UNIX | _WIN32 ] add support for a very simple, flat Java packages. They may be easier to use and will probably integrate more seamlessly with graphical development environments. All files live in the package root directory. If the name of the package is a.b.c, then a/b is the collection and c the ComPact package name. Thus Java language package hierarchies in the file system can be directly mapped to ComPact packages.
In the workspace, no additional structure is supported or even possible. The directory for derived files is hardwired to ./.. It is not possible to have packages p1.io and p2.io in the same project, collection, or pool. It is also not possible to separate code compiled with different options (e.g. debug). Everything will reside in the package root directory. Currently there is only one exception: generated HTML files get shipped to an html subdirectory in the pools .
Because complex and simple Java configurations must coexist in the standard pkgconf.cbcl resource, the element names of simple packages all start with j_ instead of java_.
All ComPact Java packages contain a package description file PkgDesc in their root like a ComPact C/C++ package, but there are no inc, src and doc sub-directories. The SIMPLE_COMPACT_JAVA [ _UNIX | _WIN32 ] kind does not have any substructure at all, while the COMPACT_JAVA [ _UNIX | _WIN32 ] packages have a directory that contains the Java source code, named java, and a directory that contains the (usually automatically generated) package documentation in HTML, named html. This basic structure is shown in the following figure:
pkg-name / PkgDesc (package description file)
/ java (Java source files)
/ html (derived html deocuments)
The directory java is used to
keep all Java source files. If the source files are part of
a specific Java package language,
as usually is the case, then the appropriate
sub-directories wiht names corresponding to the Java package language name must be located
in the java directory. For
example, if you create a Java language package utils.io with the elements utils.io.file and
utils.io.terminal, the complete structure looks like
this:
utils-io / PkgDesc / java / utils / io / file.java
/ terminal.java
/ html
/ bytecode / DEFAULT
/ debug
The bytecode subdirectories contain the generated class and
zip files, as well as generated script for convenient
application start and test. This looks a little cumbersome, but cannot be circumvented if the standard Java build system is to be used in combination with all the advantages of the ComPact build management, as the algorithms for locating sources are hard-coded inside the Java compiler.
When the package is built, the Java class files will be stored as usually in a TPC-dependent directory and a class archive file will be created. If the package contains a program target, then a script to start the program using the correct path to all imported packages will be generated, too. If the doc target is built, the documentation will be abstracted from the Java sources and nicely formatted HTML documents describing the interfaces will be generated in the html directory. Using JDK 1.1.8, after a complete build the package might look like this:
utils-io / PkgDesc
/ java / utils / io / file.java
/ terminal.java
/ html / AllNames.html
/ packages.html
/ tree.html
/ utils.io.file.html
/ utils.io.terminal.html
/ bytecode / DEFAULT / utils / io / file.class
/ terminal.class
/ utils-io.zip
In contrast, SIMPLE_COMPACT_JAVA [ _UNIX | _WIN32 ] packages are direct mappings from the Java language package structures. The last directory of the Java package name becomes the ComPact package name, and the prefix directories are regarded as a collection prefix.
Let's have a look at a final example for both package kinds. We'll present a picture for the complete directory structure of two packages: utils.sys.io and utils.misc.text.
COMPACT_JAVA [ _UNIX | _WIN32 ]
java / utils.sys.io / java / utils / sys / io / *.java
| / html / *.html
| / bytecode / DEFAULT / *.class *.zip run_*
| / debug / *.class *.zip run_*
| / utils.misc.text / java / utils / sys / io / *.java
| | / html / *.html
| | / bytecode / DEFAULT / *.class *.zip run_*
| | / debug / *.class *.zip run_*
| |
| ComPact package name = Java language package name
|
ComPact collection name
SIMPLE_COMPACT_JAVA [ _UNIX | _WIN32 ]
utils / sys / io / *.java *.class *.html *.zip run_*
/ misc / text / *.java *.class *.html *.zip run_*
\__________/ |
| ComPact package name = last component of Java language
| package name
|
ComPact collection name = prefixes of Java package names
The following declarations can be used to specify the elements of a (complex) Java package. If you want to use the simple Java package kinds, just replace the language prefix java_ with j_ in the PkgDesc declarations.
java_source
Syntax
'java_source' '(' JavaSourceFileName [ ExpDecl ] ')' NL
Semantics
Declares the named file as an element of the package. JavaSourceFileName must be the complete relative pathname starting in the java sub-directory. ExpDecl is the same as in C/C++ packages.
applet_test_source
Syntax
'applet_test_source '(' AppletTestSourceFileName [ ExpDecl ] ')' NL
Semantics
Declares the named file as an element of the package. AppletTestSourceFileName must be the complete relative pathname starting in the java sub-directory. ExpDecl is the same as in C/C++ packages. The file is assumed to have the extention .html and should contain simple HTML code that invokes an applet, which may then be used together with the appletviewer program.
java_applet_script
Syntax
'java_applet_script' '(' JavaAppletSourceName [ ExpDecl ] ')' NL
Semantics
Declares the derived file run_applet_JavaAppletSourceName as a build target of the package. This file will be created in the directory for derived files (usually bytecode/DEFAULT), and contain code to invoke the appletviewer on the given JavaAppletSourceName. ExpDecl is the same as in C/C++ packages.
java_package_name
Syntax
'java_package_name' '(' JavaPackageName ')' NL
Semantics
Declares JavaPackageName as the name of the package. This is currently used for building the HTML documentation.
java_archive_file
Syntax
'java_archive_file' '(' JavaArchiveFileName ')' NL
Semantics
Declares JavaArchiveFileName as a derived element of the package. This is roughly equivalent to a C/C++ library declaration.
java_start_script
Syntax
'java_start_script' '(' JavaStartScriptName ')' NL
Semantics
Declares JavaStartScriptName as a derived element of the package. This is roughly equivalent to a C/C++ program declaration.
Another declaration states dependencies between Java source files:
add_dependency
Syntax
add_dependency' '(' DependingFile ',' SourceFile ')' NL
Semantics
Declares an additional dependency: DependingFile depends on SourceFile. Any number of source files may be specified, separated by commas.
Additional dependency declarations may be necessary because currently there is no option for the Java compiler to output its computed dependencies, so that they may be used by ComPact. Even if this option existed, it would not be of much use, since the Java language allows circular dependencies, and only the Java compiler itself knows how to correctly handle such situations. To achieve a decent compilation performance with the standard Java compiler, ComPact invokes the compiler only once with a list of all source files it considers out-of-date.
Altogether, a package description file for the exmaple package from the last section may look like this:
java_package_name("utils.io")
java_source("utils/io/file.java", exported)
java_source("utils/io/terminal.java", exported)
main: java_archive_file("utils-io")
After all, this looks quite manageable, doesn't it?
Java package build management uses the same ComPact commands as C/C++ build management. The details of the command options can be found in Chapter 5. There are some major differences to C/C++, though, which will be discussed briefly in the following paragraphs.
External dependency analysis is somewhat problematic in Java. It is permissible and common to have cyclic dependencies between Java source files. As mentioned earlier, the JDK compiler cannot even output the dependencies of Java source files, so that there is no obvious way to automatically compute the dependencies, short of implementing another Java compiler.
It appears that Current Java compilers like to keep dependency issues to themselves. In consequence, ComPact invokes the Java compiler only once for a given Java package, with all source files collected into a big argument list.
The main target for library packages should always be a java_archive_file, for program packages a java_start_script.
The details of the Java configurations shipped with ComPact can be found in the backend configuration file pkgconf.cbcl, which is described in Section 6.2.