APIs & Docs


  1. Update API status comments
    1. ICU4C
    2. ICU4J
  2. Promote draft APIs to stable
    1. ICU4C
    2. ICU4J
  3. Update the API Change Report
    1. ICU4C
    2. ICU4J
  4. Note that some errors may be shown. This is normal.
    1. Check in API signature data file (ICU4J)
    2. Verify that @draft is surrounded by #ifndef U_HIDE_DRAFT_API etc
      1. Caution
      2. Task
    3. Update udraft.h, usystem.h, uintrnl.h, uobslete.h and udeprctd.h
    4. Compare ICU4J APIs with JDK
    5. Build API documentation
      1. ICU4C
        1. Create the ICU4C docs zip file:
        2. Create a PR for ICU4C docs using the docs zip file
      2. ICU4J
      3. Upload API documentations
        1. Update table of API docs:
      4. Update the Readme.html for GA

Update API status comments


  1. Note: for ICU4C 49m2 or later, will require Doxygen or later ( see ICU-8862 ). On Linux with debian style package management,

    sudo apt-get install doxygen

    Or, to install manually

    1. To update Doxygen, first download binary or source release here
    2. Unpack the release, and run something like
      configure --prefix /usr/local” (to install into /usr/local/bin etc)
      (Note for the binary release, ‘configure’ just builds an installer.)
    3. Run “make install” with appropriate permission (perhaps “sudo make install”.)
    4. Verify that ‘doxygen --version’ gives the correct number.
  2. Update the API documentation in all header files (.h file) to have correct @draft/@stable/@deprecated labels.
  3. Update docmain.h
  4. ./configure
  5. make doc
  6. Follow instructions in tools/release/java/readme.txt to generate the API status change report.
  7. Make sure that ICU headers work with U_HIDE_DRAFT_API and other such switches.
  8. Verify that U_DRAFT and U_STABLE match the @draft and @stable tags (same for other such pairs declaration macro vs. tag).
    1. For example, on Linux:
    2. grep –recursive –include=”*.h” –exclude-dir=”.svn” -e “@deprecated” -A 5 . > at-deprecated.txt
    3. grep –recursive –include=”*.h” –exclude-dir=”.svn” -e “U_DEPRECATED” -B 5 -A 1 . > u_deprecated.txt
    4. Do this for draft, deprecated, obsolete, internal.
    5. For @stable, we either verify by cleaning up all others or we need to write a script.


Update the API documentation to have correct @draft/@stable/@deprecated labels. See the User Guide, ICU Architectural Design, ICU API compatibility.

On ICU4J, run com.ibm.icu.dev.tool.docs.CheckTags (see file for instructions). This requires a JDK with javadoc available, i.e, JDK8. The tool will need to change to reflect the release number to search for.

To check the API status changes, run the script releases_tools/api_reports.sh to generate the report of updates since the previous official release. The resulting file is found in target/icu4j_compare_XX_YY.html.

Make sure @internal APIs are also marked as @deprecated:

* @internal
* @deprecated This API is ICU internal only.

Promote draft APIs to stable

APIs previously introduced as @draft are reviewed for every new release. The current policy is to keep @draft status at least in one release cycle. For example, a new @draft API introduced in ICU 60 will be kept @draft in ICU 61. Then the API will be reviewed by ICU technical committee before ICU 62 release and the API can be promoted to @stable status.


Andy’s method (from email 2019-sep-05):

  • Creation of the promotion spreadsheet was done by hand. It’s something of an iterative process.
  • Start by making a copy of the previous release spread sheet, to get the format, and probable entries for older @draft items that are perpetually being held back.
  • Do the API promotion - search the sources for @draft, and make a best guess at what to promote. Add entries to the spread sheet as you go. Note any items you’re not sure about.
  • Run the API change report tool, see what looks inconsistent, fix up the sources and rerun as needed. Deleted functions will first show up here, and are added to the spread sheet.
  • Cross-check the API change report and the spread sheet.
  • The whole thing takes a bit of time to do.


  1. Create a new GitHub branch.
  2. In directory icu/icu4j, run this script: releases_tools/api_reports.sh
  3. This script generates a tab-separated values file at target/draftAPIs.tsv.
  4. Import the TSV file to Google spread sheet - for example, ICU4J 74 Draft API Promotion.
    • Create the spreadsheet in the shared ICU Projects folder.
  5. Review all APIs introduced in 2 releases ago or older. For example, 72 or older for ICU 74 release.
    • Any API added 2 or more releases ago is a candidate for promotion.
    • Newer APIs should be left in @draft state.
  6. Check each API entry has a corresponding approved API proposal. For example, ICU 72 API proposal status. Note: An API proposal might have been created before the API proposal doc version, so you may need to look at older version of API proposal status doc.
  7. Mark APIs proposed for promotion, and add note in the spread sheet.
  8. Update API comments in ICU4J source code. In this case, @draft is replaced with @stable (do not change ICU version, for example, “@draft ICU 72” will be changed to “@stable ICU 72”).
  9. Now, rerun target to generate an API change report html: releases_tools/api_reports.sh.
  10. Review the report, sent the report file and the link of the spread sheet to ICU technical committee members for review.
  11. Once ICU TC approves the proposed change, create a pull request (PR), wait for review, and merge the branch into the main branch.

Update the API Change Report


This work is done in the root of icu4c:

  1. Update the API documentation in all header files (.h file) to have correct @draft/@stable/@deprecated/@obsolete labels.
  2. Update docmain.h with additions or removals as needed.
  3. source/configure
  4. make doc
  5. Follow instructions in tools/release/java/readme.txt.


This work is done in the root of icu4j:

  1. Make sure JAVA_HOME is set to JDK 8. This report creation fails with JDK 11. For example, in Linux:
    • export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
  2. Now in <icu4j_root>, create a change report:
    • mvn clean
    • releases_tools/api_reports.sh
    • Note that some errors may be shown. This is normal.

  3. Above will produce API change report file <icu4j_root>/<b>target</b>/icu4j_compare_xxx_yyy.html
  4. Make sure there are any new doc tag errors are reported. (As of ICU 4.4, ArabicShaping constants do not have proper tags - otherwise, clean)
  5. Copy generated report file to <icu4j_root>/APIChangeReport.html and check it in.

Once official release version is shipped, we need to keep API signature information file for next iteration. This is not done for milestone releases, only after the final official release.

Check in API signature data file (ICU4J)

Once APIs are frozen for a reference release, we should check in the API signature data file into the repository. The data file will be used for future API change report.

  1. Run releases_tools/api_reports.sh at <icu4j_root>
  2. Resolve any warnings before proceeding.
  3. The output file icu4j<ver>.api3.gz is created in <icu4j_root>/out directory.
  4. Copy the output .gz file to <icu4j_root>/tools/build directory and check in the file to the repository.
  5. You may delete very old versions of the API signature files. Keeping 10 versions to the latest should be good enough.

Note: This task is only necessary for reference releases, because we won’t change public APIs in maintenance releases. The API signature file for an ICU4J version is generated and checked into trunk just before maint-xx branch is created for the major version, so we can keep track of API changes in maintenance releases of the major version (A maintenance release should have no API changes although).

Verify that @draft is surrounded by #ifndef U_HIDE_DRAFT_API etc

In ICU4C, we want every (consecutive group of) @draft API to be surrounded by #ifndef U_HIDE_DRAFT_API. This allows users to -DU_HIDE_DRAFT_API to make sure they don’t use unstable API.

/** @draft ICU 51 */
U_CAPI u_newFunction1();
/** @draft ICU 51 */
U_CAPI u_newFunction2();
#endif  // U_HIDE_DRAFT_API

Same for @deprecated & #ifndef U_HIDE_DEPRECATED_API .. #endif // U_HIDE_DEPRECATED_API

Same for @internal & #ifndef U_HIDE_INTERNAL_API .. #endif // U_HIDE_INTERNAL_API

Same for @system & #ifndef U_HIDE_SYSTEM_API .. #endif // U_HIDE_SYSTEM_API

Same for @obsolete & #ifndef U_HIDE_OBSOLETE_API .. #endif // U_HIDE_OBSOLETE_API


  • We cannot #ifndef-guard virtual methods because that makes the vtable incompatible.
    • // Cannot use #ifndef U_HIDE_DRAFT_API for the following draft method since it is virtual.
  • When you #ifndef-guard enum constants, normally the following unguarded ones (e.g., a _COUNT or _LIMIT) should retain the same numeric values as if the guard was absent.

For more details (and cautions) see the Coding Guidelines section C/C++ Hiding Un-@stable APIs.


a) For each of these API status tags, for each API that is tagged with it, verify that the API is surrounded by the appropriate #ifndef..#endif.

Note: It is best to not use one single guard for APIs with different ICU versions, since they will become stable and thus lose their guards at different times. Use one #ifndef..#endif guard per API status and ICU version.

b) For each of these U_HIDE_…_API guards, verify that it only and exactly surrounds APIs with the corresponding status tag. In particular, make sure that U_HIDE_DRAFT_API does not surround (newly) @stable API.

We don’t have tools for this. One approach is to use “grep” or similar on the public common, i18n, io header files. Use grep options like -A 3, -B 2 and -C 3 for context After, Before, and Around the matching line. A better approach if you have the tools available is to use a programming-oriented text editor that can do (a) powerful regex search across (b) multiple files in several specified directories, and (c) display the matched lines in context such that (d) they or their context can be edited in place; an example of such a tool on macOS is BBEdit. This permits a comprehensive search using an expression such as “(U_HIDE_[A-Z_]+)|(@draft)|(@deprecated)|(@obsolete)|(@system)|(@internal)|(@preview)” which permits relatively easy checking for correct enclosure of status tags in conditionals.

As part of this, you may need to run side searches, for example to verify that no conditionalized type, function or value is used by an unconditionalized portion of a header file.

There is no magic bullet; however you carry out this step, it will require several hours of going through the grep/regex results and manually checking for correct enclosure, checking that conditionalized values are not needed elsewhere, etc.

Update udraft.h, usystem.h, uintrnl.h, uobslete.h and udeprctd.h

Ignore this step for ICU49 and later. In ICU 49 and above, these header files and the gendraft/genheaders.pl tool are gone. (Ticket ICU-8571)

Instructions for ICU4C 4.8.x and earlier:

  1. make doc
  2. cd source/tools/gendraft ; make install-headers
  3. Double check the modified files in /source/common/unicode folder and commit.

Compare ICU4J APIs with JDK

Run the ICU4J versus JDK API comparison tool against the target JDK (anything that will come out before our next release, basically) with the tool com.ibm.icu.dev.tool.docs.ICUJDKCompare and make sure ICU4J adequately covers the JDK API for the classes we replicate.

Build API documentation


Build the API documentation pages for the new release. Run Doxygen to create the javadoc files. Create icu4c-X_X_X-docs.zip

Note: for ICU4C 49m2 or later, requires Doxygen or later ( see ICU-8862 )

Create the ICU4C docs zip file:

  1. Go to …/icu4c/source
  2. Generate the API document pages:
    make doc-searchengine
  3. The generated API docs are in /icu4c/source/doc/html/
    `cd /icu4c/source/doc/html/`
  4. Create a zip file, e.g.,
    `tar cvfz /tmp/icu4c72rc.tar.gz * # Note: label the file apropriately for the release.
  5. Edit README.md in icu-docs.
  6. Update the table under “API docs” at the top of README.md with the new version in column “C” in row “Dev” for the release candidate or “Released” for the final release.
  7. Add the updated README.md to the pull request with the new API documentation.

Create a PR for ICU4C docs using the docs zip file

  1. Follow directions in How to update ICU docs

    a. First, bring the main branch of your icu-docs local copy up to date.

    b. Create and switch to a feature branch based of the latest main. Ex: git checkout -b ICU-<TICKET-NUMBER>.

    c. Go to the directory for the version of interest, either apidoc/dev/icu4c (release candicate) or apidoc/released/icu4c (general release.)

    d. Be sure that you are in the right directory. Then, remove all the files in this directory, e.g., rm -rf *. (Remember “git restore” is a good friend!)

    e. Unzip the tar file from above, replacing all documentation. Ex: tar xvfz /tmp/icu4c72rc.tar.gz

    e. Remove the zip file if it’s in the folder.

    f. git add .. Note that this may remove some old files. That’s correct behavior.

    h. git commit -m "ICU-<TICKET-NUMBER> Update ICU4C API reference docs for XX.Y"
    Example: ICU-21546 Update ICU4C API reference docs for 69.1

    i. git push origin ICU-<TICKET-NUMBER>

    j. Create Pull Request from your personal github fork of icu-docs from your newly-pushed branch ICU-<TICKET-NUMBER> with a destination of the unicode-org/icu-docs repo’s main branch

    k. Request a review and submit the PR when approved.

Note: This is also referenced below Upload API documentations for how to make the API docs public.


Note: JCite must be installed for building ICU4J documentation: https://icu.unicode.org/setup/java/ant#TOC-Building-ICU4J-API-Reference-Document-with-JCite

Build the API documentation pages for the new release:

cd icu4j

The API documentation will be found in targets/github_release/

Next, update the documents for this version:

  • Copy the icu4j-<version>-fulljavadoc.jar to the to icu-docs/apidoc directory, either dev (for release candidates) or released (for public distribution).
  • Unzip the icu4j-<version>-fulljavadoc.jar in that directory.
  • Verify that the documentation is updated, then remove the .jar file.
  • Update the file README.md for either the Released or the Dev line with the new version.
  • Use git add . then create a github commit with the ICU issue for this version, e.g., Pull request #58.
  • Create the pull request, obtain a review, and merge when all is OK.

  • Upload the output files including icu4j-docs.jar to the release page first,
  • Then update the live API docs from the generated docs.jar.

See Upload API documentations below for how to make the API docs public.

Upload API documentations

See https://unicode-org.github.io/icu-docs/HOWTO-Update.html for instructions to upload to https://unicode-org.github.io/icu-docs/

Update table of API docs:

  1. Edit README.md in icu-docs.
  2. Update the table under “API docs” at the top of README.md with the new version in column “J” in row “Dev” for the release candidate or “Released” for the final release.
  3. Add the updated README.md to the pull request with the new API documentation.

Update the Readme.html for GA

If there are any last second changes:

  • Make sure to document especially items that affect software that is currently compiled with the previous version of ICU.
  • Update build/installation instructions as necessary.