java -jar javamake.jar [ options ]
[ @files ]
Arguments may be in any order.
javamake.pdb
). If
this file is not found, all of the source (.java
) files are passed
to the underlying Java compiler. After compilation, the tool looks
for .class
files corresponding to the source files.
This lookup is based on source file names, so to make the tool work
correctly, the name of each top-level class should be the same as its
.java
file name. Depending on whether or not the -d
directory option was specified, a .class
file is
looked up in either an appropriate subdirectory of the destination directory,
or in the same directory where its source file resides. In the former case,
Javamake determines the subdir of the destination directory based on the
source file directory name. Thus, to avoid "class file not found"
errors, you should always arrange that the source file directory
reflects the package name of the respective class, You should also place
no more than one top-level class in a single .java
file
(doing the contrary is considered bad practice anyway), since
Javamake currently makes no attempt to find a binary class
whose name does not match the name of its source file. However,
the tool is able to find all of the nested classes for each
top-level or nested class, and keeps track of dependencies between
such classes as well.
The essential information about classes and their sources is
recorded in the project database. It includes the class name, the
source file full path and current timestamp, and the information
about dependencies, i.e. various references to other classes that
each class contains. This information is withdrawn from the .class
file and includes the superclass reference, the implemented interface
list, the constant pool, the declarations of fields and methods, and
some class file attributes. In fact, the dependencies are stored
in the database in the form that largely reflects the class file
structure, i.e. they sound like "class A
extends
class B
, implements interface C
, calls
method m(D,E)
of class F
", and so on.
Javamake keeps track only of the classes explicitly specified to it
at every invocation, either via their .java
files or via the
parameters of the -projclasspath
option (see below). If any
previously specified source file or JAR is omitted, the records for the
respective top-level class(es) and all of its nested classes will be
removed from the project database.
If Javamake finds an existing project database in the current directory, it first synchronizes the project database with the list of source files it is given. Records for missing sources are removed, and new sources are scheduled for recompilation. Then the timestamps of the remaining sources are compared to the timestamps of the respective classes, that are preserved in the database. Sources that are newer than their classes are recompiled, along with newly-added sources.
Next, those binary classes for which timestamps have changed are compared to
their old versions preserved in the database. If any change in the new
version of class C
is source incompatible, for example
the signature of a public method m(boolean b)
is changed
to m(int x)
, Javamake looks for old project classes that call
C.m(boolean)
. You should have updated the sources for all such
classes so that they now call C.m(int)
. However if you haven't
done that for some classes, Javamake will force recompilation of all of them.
If there are any errors, the compiler will report them.
If there are no compilation errors, the project is considered to be in the constistent state, and the project database is updated with the information on the new class versions.
Starting from release 1.3 of Javamake, it is also possible to include in the
project classes that have no .java
sources and are contained in
JAR
files. This is done with the primary goal of supporting
development of hierarchically structured projects, where a top-level project
consumes the output of its subprojects in the form of binary classes packed in
JAR
s. .java
sources are not provided with jarred
classes, but these classes may occasionally be changed in incompatible ways.
Therefore it is desirable to include such classes in the project, be able to
detect incompatible changes to them and treat such changes as usual.
Javamake reads all .class
files from all JAR
s
specified via the -projclasspath
command line option,
adds these classes to the project and saves their dependency information in the
project database as usual. A timestamp of each JAR
is also
saved in the project database, and whenever it changes, each class in this
JAR
is individually checked for updates. If an incompatible
change is detected, all dependent classes are recompiled (note that it is
always assumed that there are no incompatibilities between jarred classes).
Since jarred classes don't have sources that can be recompiled, none of
these classes should depend on any "normal" classes that have
.java
sources. By default, a warning is issued if such a
dependency is detected. You may use several special options
to specify different behaviour.
Also starting from release 1.3, Javamake keeps track of classes that do not
themselves belong to the project, but on which the project depends. These are the
supertypes of project classes, that themselves are Java core classes or, say, third-party
classes that you put on the class path during compilation. To enable Javamake to locate
these classes, -classpath
has been made an explicit Javamake option. For
non-project classes no information is recorded in the project database. The only time
when they are consulted is when some project class C
is changed. In that case,
Javamake verifies if the new version of C
has the same or different set of
direct and indirect superclasses and superinterfaces as the old version. Supertypes
that are not a part of the project are included in this check procedure to increase
its robustness. If this was not done, your code could become inconsistent if,
for example, the new version of C
extended a non-serializable variant of
some Java core class, whereas in some other project class there is still an
assignment like x = (Serializable) C;
com.sun.tools.javac.Main
and static int compile(String args[])
. The classes for
the compiler are physically located in the javahome/lib/tools.jar
archive.
If you have a version of JDK older than 1.3, or a Java Runtime
Environment (JRE) installation which does not include a Java
compiler, or a Java platform implementation from some other vendor,
you have to find out where a Java compiler is located or obtain one.
We support both compilers in the form of native executables and
compilers written in Java, e.g. javac. If you use a compiler
which is a Java application itself, the method of
this application called by our tool should have a single argument of
java.lang.String[]
type corresponding to command line
arguments normally passed to the compiler, and should have int
return type. Zero should be returned if compilation is successful and
any non-zero value if it is not. The class path, and the names for
the main class and method of the compiler can be arbitrary and should
be specified to the tool using -jcpath, -jcmainclass
and -jcmethod options. For example, the default invocation of
our tool is equivalent to:
java -jar javamake.jar -jcpath $JAVA_HOME/lib/tools.jar
-jcmainclass com.sun.tools.javac.Main -jcmethod compile
final, static
and initialized with a
compile-time constant expression, for example:
public static final String LOG_FILE_NAME = "mylog.log";
Unlike other fields, compile-time constants are not symbolically
referenced by classes that use them. Instead, the value of
such a constant is embedded directly into the bytecode of a class
which references it. Thus, if the above LOG_FILE_NAME
constant is defined in A.java
and used (referenced) in
B.java
, B.class
will have only the
"mylog.log"
string in its constant pool, but
not a reference to A.LOG_FILE_NAME
! If you change
LOG_FILE_NAME
in A.java
to, say,
"logfile.log"
and recompile A.java
,
class B
will still use the old vlaue "mylog.log"
.
Due to the above optimization in Java we, in general,
are unable to deduce which classes reference a given non-private
compile-time constant by analyzing class files only. We could have done
that by parsing source files, but this is a complex task, so instead
we currently recompile all of the classes that may reference a given
primitive constant, depending on its access modifiers. In the worst
case, when such a field is public
, the whole project
will be recompiled. We recognize this problem, but hope that changes
to primitive constants are unlikely to be frequent enough to make
this a major inconvenience.
To shorten or simplify the tool invocation command, you may specify one or more files that themselves contain file names and/or options separated by blanks and new lines. On the command line, use the '
- -h
- Print the help message.
- -version
- Print the version of this copy of the tool.
- -pdb project database file name
- Specify the file to be used to store project information (default is
javamake.pdb
).
- -d directory
- Specify the directory to place generated class files. This option is exactly equivalent to the -d option of javac and is passed to the underlying Java compiler unchanged.
- -classpath path
- Set the user class path (note that unlike javac Javamake does not recognize the CLASSPATH environment variable). Javamake uses the user class path (along with the project class path described below, and the bootstrap/extensions class paths) to look up non-project superclasses and superinterfaces of project classes. When Javamake invokes a Java compiler, it is passed the -classpath option with the argument that is the Javamake's user class path and project class path merged.
- -projclasspath path
- Set the project class path (currently only JARs are allowed on this class path). Classes that are contained in JARs on the project class path are considered as special "sourceless" project classes. Javamake keeps track of changes made to them and recompiles the "normal" project classes affected by such changes, but always assumes that all sourceless project classes are mutually compatible. When Javamake invokes a Java compiler, it passes it the -classpath option with the argument that is the Javamake's user class path and project class path merged.
- -Coption
- Pass the specified option to the Java compiler used by the make tool. Note that if this compiler option has arguments, each of them should also be prefixed with
-C
. For example, passing the class path to the compiler will look like:
java -jar javamake.jar -C-classpath -Cmydir/mypackage ...
- -jcpath directory or .jar file
- Specify the class path for the Java compiler (default is javahome
/lib/tools.jar
).
- -jcmainclass class name
- Specify the main class for the Java compiler (default is
com.sun.tools.javac.Main
).
- -jcmetod method name
- Specify the method to call in the main Java compiler class (default is
compile
). The method should accept a single argument ofjava.lang.String[]
type corresponding to the command line arguments and return anint
type value. This value should be0
if compilation is successful, and non-zero if any compilation errors were detected.
- -jcexec executable compiler application
- Specify the Java compiler which is a native executable application. This option is incompatible with -jcpath, -jcmainclass or -jcmethod.
- -failondependentjar
- Specify that Javamake should produce an error message and stop if a class in a
JAR
depends on a class with.java
source (by default, a warning is issued).
- -nowarnondependentjar
- Specify that Javamake should silently ignore a detected dependency of a jarred class on a class with a
.java
source. This option should be used with care, since it effectively allows Javamake to leave the project in an inconsistent state without even notifying you.
- -warnlimit maximum number of warnings
- Specify the maximum number of warnings that the tool can print. The default value is 20.
- -bootclasspath path
- Specify a non-standard location for bootstrap classes (by default, the value of the
sun.boot.class.path
Java property is used). Javamake looks up non-project supertypes of project classes on the boot class path, and also passes it to the Java compiler.
- -extdirs directories
- Specify a non-standard location for extensions (by default, the value of the
java.ext.dirs
Java property is used). Javamake looks up non-project supertypes of project classes in the JAR and ZIP archives in the specified directories, and also passes this option to the Java compiler.
@
' character with the filename to
specify it as a file list. When the tool encounters an
argument beginning with the character '@
', it operates
on the file names and options in that file as if they had been on the
command line. For example, you can list all of the options and source
file names in a file named jmakefile
. This file might
look like:
-d myclasses -classpath myclasses -projclasspath myjars/x.jar
A.java
B.java
C.java
You could then run Javamake as:
java -jar javamake.jar @jmakefile
@
-files are understood by both javac and
javamake.Here is an example which may help to clarify the use of options when switching from javac to our tool. Suppose that you previously used javac as follows:
javac -J-Xmx128m -classpath myclasspath -sourcepath
mysourcepath -d myoutpath @mysourcelist
The first option passed to javac is prefixed with the -J flag
and is thus actually used by the java launcher. It specifies the maximum
size of memory allocation pool. The rest of the options are used by javac.
To change the above command so that javamake is used, you should pass
the first option directly to java, and prefix the rest of them (except
-d and its argument, -classpath and its argument, and
@
mysourcelist) with -C, so that they are passed
correctly to javac. Make sure that there are no spaces between -C
and the actual compiler option. The result will look like:
java -Xmx128m -jar javamake.jar -classpath myclasspath
-C-sourcepath -Cmysourcepath -d myoutpath @mysourcelist