apidiff
Name
apidiff - compare different versions of an API
Synopsis
apidiff
[options]
- options
- Command-line options
Description
The apidiff
command reads source, class and HTML
files that provide different versions of an API, compares
corresponding declarations in the different versions and writes out
an HTML report. The comparison includes:
- structural changes, such as whether an element was added, changed or removed, using information in source or class files
- documentation contained in documentation comments, using information in source files
- generated API documentation, using information found in
documentation generated by the
javadoc
tool
Options
apidiff
provides different groups of options, to
specify:
- the APIs to be compared,
- the elements (declarations) in those APIs to be compared,
- the output options for the report to be generated, and
- other options.
All options have a long form, beginning with --
.
Some options may have a single-letter form, beginning with just
-
. For those options that take an argument, the value
may be separated from the option name by either white space or '='.
In general, as is common with most JDK tools, if an option is
repeated, the rule is "last one wins". This rule is modified for
the options that specify the APIs to be compared, such that "last
one wins" only applies within the group of API-specific options
used to define each API.
To see detailed information about how the options are processed,
use --verbose
options
.
The APIs
To specify each of the APIs to be compared, use the
--api
name option followed by a series of
API-specific options that apply to that API.
The API-specific options must at least include options to find the source or class files for the declarations to be compared. The options should also define the location of the generated documentation if that is to be included in the comparison. (When comparing the API documentation, it is not enough to just specify the location of that documentation.)
Note that the API-specific options for each API are separate and distinct from the API-specific options for any other API.
--api
name-
Specifies a name for the API and sets the current API for use by the API-specific options that immediately follow this option. The name will appear in the generated reports when identifying any differences. If the generated report will be publicly shared, it is recommended that the name should be reasonably meaningful to any readers. A longer, more descriptive label may also be given with the
--label
option.The option, and the API-specific options that follow, should be provided for each API to be compared.
The order in which the
--api
options first appear on the command line determines the order in which any differences are reported. It is recommended to specify the options in chronological order, from the oldest version of the API to the most recent version of the API. --api-directory
directory- Specifies where to find the generated API documentation for the
current API. If given, it should be
the top-level directory of the documentation generated by the
javadoc
command for the API. --jdk-build
directory-
Specifies a directory containing a JDK build from which to infer values for various options. The builds can either be for default-named configurations in separate repositories or work areas, or for differently named configurations in the same repository. (To create different configurations within the same JDK repository, use the
--with-conf-name
option when runningsh ./configure
to create the configuration.)It is a matter of personal preference whether to use separate repositories or separate configurations within a single repository for the instances of the API to be compared.
- Using separate repositories uses more disk space, but makes it
more convenient to not have to specify the desired configuration
every time you run
make
. - Using separate configurations in a single repository uses less
disk space, but means that you will have to indicate which
configuration to use every time you run
make
.
When using this option, it should not be necessary to give any additional
javac
-like options, like--module-path
or--release
.For example,
--jdk-build
repository/build/
configuration-name--jdk-build /Users/Duke/jdk-dev/build/macosx-aarch64
--jdk-build /Users/Duke/jdk-dev/build/macosx-aarch64-server-release
--jdk-build $HOME/OpenJDK/build/linux-x86_64-server-fastdebug
- Using separate repositories uses more disk space, but makes it
more convenient to not have to specify the desired configuration
every time you run
--label
text- Specifies a short plain-text label for the API, to be included in the generated reports. For example, the full version string for the instance of the API being compared.
The following API options are similar to the corresponding
javac
option; see the javac
documentation
for more details about the arguments for those options.
--class-path
path,-classpath
path, or-cp
path- Specifies where to find files for the class path for the current API.
--enable-preview
- Enables preview language features for the current API.
--module-path
path or-p
path- Specifies where to find application modules for the current API.
--module-source-path
module-source-path- Specifies where to find source files for the current API when comparing code in multiple modules.
--patch-module
module=
path- Overrides or augments a module in the current API with classes and resources in JAR files or directories.
--release
release- Specifies the release version for the current API for any source and class files that may be read.
--source
release or-source
release- Specifies the source version for the current API for any source files that may be read.
--source-path
path or-sourcepath
path- Specifies where to find source files for the current API. Note that, unlike
javac
, you cannot use this option to specify where to find the source code for a single module. Use the--module-source-path
option instead, possibly using the module-specific form of that option. --system
jdk |none
- Overrides the location of system modules for the current API.
By convention, the APIs should be defined on the command in chronological order: oldest first, newest last. When comparing documentation comments or API descriptions, the APIs will be compared pairwise, with each of the older instances being compared against the newest instance.
The Elements to be Compared
The following options are used to specify the elements
(declarations) to be compared within the APIs, specified by the various --api
options and associated API-specific options.
These options apply equally to all the APIs to be compared: there is no need to repeat these options for each API to be compared.
--access
public|protected|package|private
-
Specifies the access of the declarations to be compared. The default is
protected
.public
: public declarations onlyprotected
: public and protected declarationspackage
: public, protected and package-private declarationsprivate
: all declarations
Note: this option does not apply to the parts of the serialized form of a serializable class, even if those parts are provided by private methods and fields.
--exclude
pattern- Specifies the patterns for modules or
packages to be excluded from the comparison. The default is that
none of the elements specified with
--include
options are excluded. --include
pattern- Specifies the patterns for modules or
packages to be included in the comparison. There must be at least
one
--include
option. --compare-api-descriptions
boolean- Specifies that the API descriptions (as generated by
javadoc
) should be compared for each element being compared. The option defaults totrue
if an API directory is given for each instance of the API to be compared and if documentation comments are not to be compared. (See--compare-doc-comments
). When the option is enabled, either explicitly or by default, the API directory must be specified for each instance of the API to be compared, and set to the location of the files generated byjavadoc
that corresponds to the source and class files being compared. The API directory for an API can be specified explicitly, with the--api-directory
option, or indirectly, with the--jdk-build
and--jdk-docs
options. --compare-api-descriptions-as-text
boolean- Specifies that the HTML for the API descriptions (as generated
by
javadoc
) should be compared as plain text for each element being compared. If the argument istrue
, this option also implies--compare-api-descriptions true
. --compare-doc-comments
boolean- Specifies that the documentation comments should be compared
for each element being compared. This implies that the source files
should be available for each instance of the API being compared; if
they are not available, the documentation comments will not be
compared. The option defaults to
false
if the API descriptions are to be compared, andtrue
otherwise. (See--compare-api-descriptions
). --jdk-docs
name- In conjunction with the
--jdk-build
option, specifies the name of the documentation bundle to use when more than one is available. It need not be specified if all the APIs specified by--jdk-build
have exactly one directory matching the nameimages/*docs*
: this is typically the case when building the OpenJDKdocs
ordocs-jdk
targets. For example,docs
,javase-docs
,reference-docs
.
Output Options
--output-directory
directory or-d
directory- Specifies the directory in which to write the report about the comparison. The directory will be created if it does not already exist.
--title
text- Specifies a title for the report, to be used in each generated page.
--description
html- Specifies a short description for the report, to be used on the top level summary page.
--info-text
name=
html-
Specifies information to be included in different positions on each page. name can be one of:
top
: at the top of each page; this may be used to indicate the status of the pages.header
: in the header bar on each page; if not specified, a default value is generated, based on the names of the APIs being compared.footer
: in the footer bar on each page; if not specified, a default value is generated, based on the names of the APIs being compared.bottom
: at the bottom of each page; this may be used to indicate copyright and license information,
--notes
file- Specifies a file containing notes to be added for various elements.
--main-stylesheet
file- Specifies an alternate stylesheet to use in the generated report instead of the system default.
--extra-stylesheet
file- Specifies an additional stylesheet to use in the generated
report.
This option may be useful when comparing HTML documentation that contains references to custom styles.
--resource-files
file-or-directory- Specifies resource files to be copied from one or more API
directories.
This option may be useful when comparing HTML documentation that depend on some non-HTML resource files.
Other Options
--help
,-help
,-h
,-?
- Displays command-line help.
--version
,-v
- Displays the version of the tool.
--verbose
flag[,
flag]*-
Specifies the kinds of verbose output. flag may be one of
all
,none
, or one of the following, optionally preceded by-
to negate the flag:module
,package
,type
,time
,options
.Flag Description module
Report on the modules being compared package
Report on the modules and packages being compared type
Report on the modules, packages, and classes and interfaces being compared time
Report the time taken to perform the comparison and generate the reports options
Report how the command-line options are processed @
filename- Reads options from a file. To shorten or simplify the
apidiff
command, you can specify one or more files that contain arguments for theapidiff
command. This lets you createapidiff
commands of any length on any operating system. The syntax for the contents of the file is similar to that for other JDK commands, likejavac
andjavadoc
.
Exit Status
apidiff
exits with one of the following values:
Exit status | Description |
---|---|
0 | No differences were found |
1 | Differences were found |
2 | There was an error in the command-line arguments |
3 | An error occurred |
The --help
and --version
options exit
with a status of 0.
The Current API
The current API is the API specified by the most recent
--api
option on the command line, and is the API for
which any subsequent API-specific options will apply.
The "current API" is cancelled when any option is given that is
not specific to any one API. Additional options for an API can be
given by repeating the --api
option to set the API as
the current API again.
Patterns
Patterns provide a way to specify groups of similarly-named modules, packages and types to be included or excluded from the comparison.
A pattern consists of a module-part and/or a type_part.
module-part: : | qualified-identifier
/
| qualified-identifier.* /
type-part: : | **
|
qualified-identifier |
qualified-identifier.*
|
qualified-identifier.**
A module-part that is just a qualified identifier matches the named module. A module-part that ends in a wildcard matches all module names that begin with the given qualified identifier.
A type-part that is just a qualified identifier matches
the named type. A type-part that ends in a single
*
matches all types in the package with the given
qualified identifier. A type-part that ends in
**
matches all types in all packages that begin with
the given qualified identifier. A type-part of
**
can only be used in conjunction with a non-empty
module part.
apidiff
cannot compare a combination of types in
named modules and types in the unnamed module, and so either all
patterns must include a module part, or none must.
For example,
java.base/java.nio.**
matches all types in thejava.nio
packages and corresponding subpackages, in thejava.base
modulejava.compiler/**
matches all packages and types in thejava.compiler
module
Depending on how you invoke apidiff
, you may need
to quote the pattern to prevent the *
characters being
interpreted by a command shell.
Notes
A "notes" file is used to specify links to be injected into the generated report for some elements.
The file is a plain text file. Blank lines and lines beginning
with #
are ignored. The remaining lines are
interpreted as a series of blocks, each of which must start with a
line containing a URL and a short plain-text description, followed
by a series of lines, each containing a signature describing an
element or set of elements. For each block, a link based on the URL
and description, will be added to any element appearing in the
generated report that matches any of the corresponding
signatures.
The following signatures are supported:
- module
- module
/*
- [ module
/
] package - [ module
/
] package.*
- [ module
/
] package.
type - [ module
/
] package.
type.*
- [ module
/
] package.
type#
field - [ module
/
] package.
type#
<init>
(
parameters)
- [ module
/
] package.
type#
method(
parameters)
Signatures should not contain any white-space characters.
Signatures ending in /*
or .*
match the
specified item, and any enclosed elements down to the level of a
type element. For methods and constructors, parameters is
a comma-separated list of parameter types, omitting any type
parameters, and using just the simple name of any declared
types.
For example,
java.base/*
matches thejava.base
module, all packages injava.base
, and all types in those packages.java.base/java.lang.*
matches thejava.lang
package in thejava.base
module, and all types in that package. Note that it does not include subpackages, such asjava.lang.reflect
, or any types in those subpackages.java.base/java.lang.String
just matches the typejava.lang.String
.java.base/java.lang.String#equals(Object)
just matches theequals(Object)
.
Configuring the APIs to be compared
At a minimum, the source or class files must be provided for
each instance of the API to be compared. If the API does not
provide or is not part of a module, use the
--source-path
and --class-path
options.
If the API provides or is part of one or more modules, use the
--source-path
, --module-source-path
,
--module-path
, and related options.
If you want to compare the content of documentation comments, you must provide source files for all the elements to be compared; any dependencies of those source files can be specified as either source or class files.
If you want to compare the API descriptions, you must provide
the locations of the directories generated by the
javadoc
tool for each of the instances of the API
being compared. This is often a directory whose path ends in
api
, although that is not a requirement. To eliminate
any false positive differences being introduced by changes to the
javadoc
tool itself, the same or equivalent versions
of javadoc
should be used for each API to be
compared.
If you want to compare all the exported packages in a module,
use --include <module>/**
. If you want to
compare the contents of specific packages in a module, use
--include <module>/<package>.*
or
--include <module>/<package>.**
. The
.**
form will also include the contents of any
subpackages. You can use multiple --include
options to
include different parts of an API in the comparison.
Configuring instances of JDK to be compared
apidiff
can be used to compare different instances
of JDK, but that can be tricky to set up, depending on the kind of
comparison that is required. That being said, there is a
"convenience" option to specify a JDK build, as generated by the
standard JDK makefiles.
-
If you want to compare the files in two separate JDK builds, for each instance use the following:
- the
--api
option to introduce the set of API-specific options that follow - the
--jdk-build
option to specify the location of the build containing the files to be compared, such asbuild/macosx-x64
,build/linux-x86_64-server-release
, or the path for any directory that is used for a custom configuration.
The directory specified with
--jdk-build
should contain the following files:- the "marker" file
spec.gmk
, - the JDK image, in
images/jdk
, - one or more documentation bundles, in
images/*docs*
, if API descriptions should be compared, and - the source code, in
support/src.zip
, if documentation comments should be compared
In conjunction with this option, use the
jdk-docs
option to specify the name of the docs bundle to be compared, when there is more than one. Note this option applies to all instances to be compared, and need only be given once; it is not specific to the current API. Use the--compare-doc-comments
and--compare-api-descriptions
as needed to indicate the comparisons to be included in the report.
If neither are specified,--compare-api-descriptions
is the default. - the
While the --jdk-build
option provides a convenient
way to have the tool automatically generate the equivalent
underlying options, you can instead specify those options
directly.
-
If you just want to compare some or all of the declarations in different instances of JDK, without comparing the documentation comments or API documentation, for each instance use the following:
- the
--api
option to introduce the set of API-specific options that follow - the
--system
option to point to the instance of JDK
- the
-
If you want to compare the declarations and the corresponding API descriptions generated by
javadoc
, for each instance of JDK use the following:- the
--api
option to introduce the set of API-specific options that follow - the
--system
option to point to the instance of JDK - the
--api-directory
option to point to the corresponding documentation generated by thejavadoc
tool
- the
-
If you want to compare the declarations and the corresponding documentation comments, it is recommended to use the following:
- the
--api
option to introduce the set of API-specific options that follow - the
--system
option to point to the instance of JDK - a series of
--patch-module
options to specify the location of the source for each of the modules to be compared
- the
When using --patch-module
, you do not need to
specify all the source directories for the module: you just need to
specify the source directories containing the classes whose
documentation comments are to be compared. Any supporting
declarations will be found in the JDK specified by the
--system
option.
If the list of --patch-module
options is large, it
may be convenient to place them in a file and use the
@
file option to specify the location of the
file. You might also choose to put all the options for an API in an
API-specific @
file.
If you want to compare the API descriptions as well as the
documentation comments, you can combine the recommended options for
the two modes, specifying both --patch-module
options
for the source files and --api-directory
for the
generated documentation.
If you are using the --jdk-build
option, and the
corresponding images
directory has multiple matches
for images/*docs*
, you will need to use the
--jdk-docs
option to disambiguate which documentation
directory to use. The value that you give should be the name of one
of those subdirectories of the images
directory. The
--jdk-docs
option is not specific to any individual
API, and need only be given once on the command-line. It will be
used as needed to disambiguate the documentation directory to be
used for any API that is defined by using the
--jdk-build
option.
If you want to see or understand how the options are used
internally, you can use --verbose options
, possibly
implicitly as part of --verbose all
.
Comparing different releases of JDK
When comparing any generated API documentation, the comparison
is sensitive to any variations caused by the version of
javadoc
used to generate the documentation. Therefore,
it is highly recommended to use the same version of
javadoc
to generate the documentation for all the
versions to be compared. When building JDK, although the standard
docs
and docs-jdk
targets will use the
version of javadoc
in the same repository, you can
specify the version of JDK to be used for targets like
docs-reference-api
with the
--with-docs-reference-jdk
option to
configure
, allowing you to specify the same version of
JDK and hence the same version of javadoc
to be used
to generate the API documentation for each build to be compared.
Generally, the JDK version used to generate the documentation
should be at least as recent as the latest version to be
compared.
When comparing recent API changes in JDK, such as when creating
a report for a CSR request, when there is no change in
javadoc
in the versions being compared, it is
reasonable to use the standard docs
or
docs-jdk
targets to generate the API documentation to
be compared.
Comparing non-JDK APIs
If the API does not define any modules, use an appropriate
combination of the --source-path
,
--class-path
, and --api-directory
options. You can put either the compiled classes or a JAR file on
the class path. If you want to compare documentation comments, put
the source files on the source path. If you want to compare the API
documentation, use the --api-directory
to specify the
root directory of the documentation.
For example, to set up an API to be able to compare the API documentation associated with a JAR file:
--api before --class-path build/example.jar --api-directory build/docs/api
To set up an API to be able to compare the documentation comments for a project:
--api before --source-path src/main/java
In both cases, you can specify any additional dependencies on the class path.
If the API defines one or more modules, use an appropriate
combination of the --module-source-path
,
--module-path
, and --api-directory
options. You can put either the module or a directory of modules on
the module path, where a module is anything that can be recognized
as such by javac
. If you want to compare documentation
comments, put the source files on the module source path. If you
want to compare the API documentation, use the
--api-directory
to specify the root directory of the
documentation.
For example, to set up an API to be able to compare the API documentation associated with the modules for a project:
--api before --module-path build/modules --api-directory build/docs/api
To set up an API to be able to compare the documentation
comments for a project that defines a module called
com.example
:
--api before --module-source-path com.example=src/main/java
In both cases, you can specify any additional dependencies on the module path.
Comparing documentation comments or API descriptions
As well as comparing the declarations found in source files or
compiled class files, apidiff
can compare
documentation comments and/or the API documentation generated by
javadoc
and the Standard Doclet.
-
Comparing documentation comments is easy, and does not require API documentation to have been generated. However, it is just a simple text comparison of the text of the documentation comments, and so does not take into account any of the analysis and processing that is done by the Standard Doclet. Most notably, it does not take
{@inheritDoc}
into account, and so might miss some differences in any inherited documentation. -
Comparing API descriptions is better for comparing the documentation as generated by the Standard Doclet, and as seen by the end user reading the API specification. However, it does require that API documentation needs to be generated beforehand, and generally using the same version of
javadoc
for all the versions of the API that are being compared.
Operation
The tool operates by creating an instance of the Java compiler
front-end (as found in the
jdk.compiler
module) from which it can obtain the
selected elements to be compared, using the
Java Language Model API and
Compiler Tree API.
Note: Because the compiler is reading the source and class
files for each instance of the API being compared, the release of
the JDK platform used to run apidiff
must be at least
as recent as each of the releases used to compile the instances to
be compared.
When comparing the API descriptions for each selected element,
the tool attempts to find the relevant content in the API
documentation that is provided using the --api-directory
or
--jdk-build
options.
The tool does not attempt to run javadoc
locally to generate the page on the fly.
Examples
To compare APIs in the java.base
module in JDK
builds /local/baseline-jdk
and
/local/updated-jdk
, and place the result in the
directory out
, run the following command:
bin/apidiff \
--api jdk \
--jdk-build /local/baseline-jdk/build/linux-x86_64-server-fastdebug \
--api sv \
--jdk-build /local/updated-jdk/build/linux-x86_64-server-fastdebug \
--jdk-docs docs \
-d out \
--compare-api-descriptions true \
--include 'java.base/**'
To compare the changes for the fix for an issue such as JDK-8330183, using two separate configurations in the same repo, use a command like this:
apidiff \
--api jdk24 --jdk-build build/baseline \
--api 8330183 --jdk-build build/macosx-aarch64-server-release \
--include 'java.compiler/**' \
--output-directory build/apidiff
While the previous example is minimal, it could be augmented by providing additional details to be included in the output, and additional options to be explicit about some of the desired settings.
apidiff \
--api jdk24 --jdk-build build/baseline --label "The baseline for the changes"\
--api 8330183 --jdk-build build/macosx-aarch64-server-release --label "Add SourceVersion.RELEASE_24" \
--include 'java.compiler/**' \
--output-directory build/apidiff \
--compare-api-descriptions true \
--jdk-docs docs \
--info-text top="This proposal is not yet final" \
--title "Diffs for JDK-8330183 CSR" \
--description "Generated by $USER at $(date -u)"