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
javadoctool
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.
--apiname-
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
--labeloption.The option, and the API-specific options that follow, should be provided for each API to be compared.
The order in which the
--apioptions 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-directorydirectory- 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
javadoccommand for the API. --jdk-builddirectory-
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-nameoption when runningsh ./configureto 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-pathor--release.For example,
--jdk-buildrepository/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
--labeltext- 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-pathpath,-classpathpath, or-cppath- Specifies where to find files for the class path for the current API.
--enable-preview- Enables preview language features for the current API.
--module-pathpath or-ppath- Specifies where to find application modules for the current API.
--module-source-pathmodule-source-path- Specifies where to find source files for the current API when comparing code in multiple modules.
--patch-modulemodule=path- Overrides or augments a module in the current API with classes and resources in JAR files or directories.
--releaserelease- Specifies the release version for the current API for any source and class files that may be read.
--sourcerelease or-sourcerelease- Specifies the source version for the current API for any source files that may be read.
--source-pathpath or-sourcepathpath- 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-pathoption instead, possibly using the module-specific form of that option. --systemjdk |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.
--accesspublic|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.
--excludepattern- Specifies the patterns for modules or
packages to be excluded from the comparison. The default is that
none of the elements specified with
--includeoptions are excluded. --includepattern- Specifies the patterns for modules or
packages to be included in the comparison. There must be at least
one
--includeoption. --compare-api-descriptionsboolean- Specifies that the API descriptions (as generated by
javadoc) should be compared for each element being compared. The option defaults totrueif 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 byjavadocthat corresponds to the source and class files being compared. The API directory for an API can be specified explicitly, with the--api-directoryoption, or indirectly, with the--jdk-buildand--jdk-docsoptions. --compare-api-descriptions-as-textboolean- 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-commentsboolean- 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
falseif the API descriptions are to be compared, andtrueotherwise. (See--compare-api-descriptions). --jdk-docsname- In conjunction with the
--jdk-buildoption, 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-buildhave exactly one directory matching the nameimages/*docs*: this is typically the case when building the OpenJDKdocsordocs-jdktargets. For example,docs,javase-docs,reference-docs.
Output Options
--output-directorydirectory or-ddirectory- Specifies the directory in which to write the report about the comparison. The directory will be created if it does not already exist.
--titletext- Specifies a title for the report, to be used in each generated page.
--descriptionhtml- Specifies a short description for the report, to be used on the top level summary page.
--info-textname=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,
--notesfile- Specifies a file containing notes to be added for various elements.
--main-stylesheetfile- Specifies an alternate stylesheet to use in the generated report instead of the system default.
--extra-stylesheetfile- 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-filesfile-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.
--verboseflag[,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 moduleReport on the modules being compared packageReport on the modules and packages being compared typeReport on the modules, packages, and classes and interfaces being compared timeReport the time taken to perform the comparison and generate the reports optionsReport how the command-line options are processed @filename- Reads options from a file. To shorten or simplify the
apidiffcommand, you can specify one or more files that contain arguments for theapidiffcommand. This lets you createapidiffcommands of any length on any operating system. The syntax for the contents of the file is similar to that for other JDK commands, likejavacandjavadoc.
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.niopackages and corresponding subpackages, in thejava.basemodulejava.compiler/**matches all packages and types in thejava.compilermodule
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.basemodule, all packages injava.base, and all types in those packages.java.base/java.lang.*matches thejava.langpackage in thejava.basemodule, 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.Stringjust 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
--apioption to introduce the set of API-specific options that follow - the
--jdk-buildoption 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-buildshould 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-docsoption 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-commentsand--compare-api-descriptionsas needed to indicate the comparisons to be included in the report.
If neither are specified,--compare-api-descriptionsis 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
--apioption to introduce the set of API-specific options that follow - the
--systemoption 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
--apioption to introduce the set of API-specific options that follow - the
--systemoption to point to the instance of JDK - the
--api-directoryoption to point to the corresponding documentation generated by thejavadoctool
- the
-
If you want to compare the declarations and the corresponding documentation comments, it is recommended to use the following:
- the
--apioption to introduce the set of API-specific options that follow - the
--systemoption to point to the instance of JDK - a series of
--patch-moduleoptions 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
javadocfor 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)"