Home / Alt manpages / genccode(8)

  • genccode(8)
  • Admin command
  • linux

Turn an ICU Data File into Linkable C Code with genccode

You will finish with a generated C source file containing an ICU data file as a byte array, ready to compile into a program or library. The examples use genccode 74.2 from the Ubuntu icu-devtools package, version 74.2-1ubuntu3.1.

Allow about fifteen minutes. You need a readable binary data file, a writable working directory and a C toolchain if you intend to compile the result. This guide does not install ICU data, replace system files or modify a build; all generated files go into an explicit temporary or build directory.

1. Confirm the installed tool

Check the executable, package version and local option syntax first. These are ordinary read-only commands and do not need elevated privileges:

$ command -v genccode
/usr/sbin/genccode
$ dpkg-query -W icu-devtools
icu-devtools 74.2-1ubuntu3.1
$ genccode --help
usage: genccode [-options] filename1 filename2 ...

The installed help is the most useful reference for this particular build. It includes options not described in every copy of the older manpage, including --object, --revision, --match-arch and --skip-dll-export. Read the full help before using one of those options in a portable build script.

Checkpoint

Confirm that the command resolves to the expected ICU installation and that the package is the version you intend to use.

2. Choose an input and a clean destination

genccode reads one or more binary input files. With no filename it exits without doing useful work, so do not rely on an empty argument list as a validation step. A filename such as mydata.icu normally becomes mydata_icu.c. The output directory defaults to the current directory, but an explicit destination prevents generated files from appearing among your source files by accident.

For a harmless local test, use an input you already have and a new directory. The following example uses an ICU-compatible binary file named INPUT_DATA_FILE; replace that placeholder with the path to your own file:

$ INPUT_DATA_FILE=/path/to/mydata.icu
$ OUT_DIR="$PWD/genccode-output"
$ mkdir -p "$OUT_DIR"
$ test -r "$INPUT_DATA_FILE" && echo readable
readable

Creating a directory in your working tree is a normal user operation. Do not use sudo merely because the executable is under /usr/sbin. You need elevated privileges only if your chosen input or destination is genuinely inaccessible to your account. Prefer copying an input into a workspace over changing its permissions.

3. Generate the default C file

Pass the destination with --destdir and the input as a separate argument. The short form is -d:

$ genccode --destdir "$OUT_DIR" "$INPUT_DATA_FILE"
generating C code for /path/to/mydata.icu
$ find "$OUT_DIR" -maxdepth 1 -type f -printf '%f %s bytes\n'
mydata_icu.c 123456 bytes

The progress line and size depend on the input. The generated file is C source, not an object file. Inspect its first lines before adding it to a build:

$ sed -n '1,12p' "$OUT_DIR/mydata_icu.c"
/* ... generated source ... */
$ grep -n 'const' "$OUT_DIR/mydata_icu.c" | head

Do not hand-edit generated output. Change the command or the input and regenerate it instead. If the command fails, it can leave no usable output or an incomplete file; check the exit status before compiling:

$ genccode --destdir "$OUT_DIR" "$INPUT_DATA_FILE" && echo generation-ok
generating C code for /path/to/mydata.icu
generation-ok

4. Set stable names for a build

Build systems often need names that do not depend on a vendor filename. Use --name to set the symbol prefix and --filename to set the output base name. Use --entrypoint when the data must be exposed through a particular entry point. ICU appends _dat to the entry point name in this installed tool.

$ genccode \
    --destdir "$OUT_DIR" \
    --name application_data \
    --entrypoint application_data \
    --filename application_data \
    "$INPUT_DATA_FILE"
generating C code for /path/to/mydata.icu
$ find "$OUT_DIR" -maxdepth 1 -type f -name 'application_data.c' -printf '%f %s bytes\n'
application_data.c 123456 bytes
$ grep -n 'application_data' "$OUT_DIR/application_data.c" | head

Keep these names stable if another source file or linker rule refers to them. An output filename and a C symbol are separate concerns, so setting only one can leave a build with an unexpected name. Check the generated declarations and update the consuming code only when the change is deliberate.

5. Generate assembly only when the target needs it

The --assembly option selects platform-specific assembly instead of C. It requires a type such as gcc, nasm or another value listed by genccode --help. With ICU 74.2 and gcc, the output uses an .S suffix. Select the type to match the assembler and target ABI used by the rest of your build:

$ genccode --assembly gcc --destdir "$OUT_DIR" \
    --filename application_data "$INPUT_DATA_FILE"
generating assembly code for /path/to/mydata.icu
$ find "$OUT_DIR" -maxdepth 1 -type f -name 'application_data.S' -printf '%f %s bytes\n'
application_data.S 123456 bytes

Do not copy this assembly choice between architectures without checking the help output and compiler toolchain. C is the simpler default when you do not have a specific assembly requirement. Assembly output is source for a later assembler step; it is not already linkable.

6. Compile and verify without overwriting anything

Once the generated C source has the expected symbol and size, compile it into a separate object directory. The command below uses GCC and leaves the generated source untouched:

$ mkdir -p "$OUT_DIR/objects"
$ cc -c "$OUT_DIR/application_data.c" -o "$OUT_DIR/objects/application_data.o"
$ file "$OUT_DIR/objects/application_data.o"
... relocatable ...

The exact file output varies by architecture. If compilation reports an unknown symbol or malformed source, return to the input type and the generated declarations rather than patching the output. If your build already supplies ICU data through a shared library, linking a second copy can create duplicate symbols or unnecessary data. Treat the generated object as an alternative data-linking arrangement, not an automatic replacement.

There is no persistent undo operation for genccode: it reads the input and writes generated files. To recover from a mistaken output, stop using that output and remove only the explicit generated directory after checking it contains no hand-written files. A safer first step is to rename it:

$ mv "$OUT_DIR" "$OUT_DIR.old"
$ mkdir -p "$OUT_DIR"
# Regenerate after correcting the command or input.

Do not run a broad recursive removal command in a source tree. Keep the original binary data file until the compiled program has been tested.

Done means

  • You confirmed the installed ICU 74.2 command and read its local help.
  • The input file was readable and the destination was explicit and writable.
  • A C file was generated and its output name and declarations were checked.
  • Custom symbol, entry point and filename settings are recorded in the build.
  • Assembly was selected only with a target-appropriate type, if it was needed.
  • The generated source compiled into a separate object without changing the original input.