icheck(1)

πŸ’– NAME πŸ’–

icheck β€” a C interface ABI/API checker, bestie. it's the girl who reads your headers so you don't have to πŸŽ€


✨ SYNOPSIS ✨

icheck --canonify [[--baseline FILE] ...]  [OPTIONS] [GCC_OPTIONS] [--]
files

icheck --compare [OPTIONS] old_file new_file

πŸ¦‹ DESCRIPTION πŸ¦‹

okay so. icheck is a tool for statically checking C interfaces for API and ABI changes. All changes to type declarations that can cause ABI changes should be detected, along with most API changes. no cap, it catches basically everything πŸ‘‘

icheck is intended for use with libraries, as a method of preventing ABI drift. that's its whole thing. it's giving guardrail energy πŸ›‘οΈ


🌸 COMMANDS 🌸

the whole flow is two steps, babe:

  1. Reduce a set of source files to a canonical interface file with --canonify
  2. then compare two such interface files with --compare

If there are interface changes between them, icheck will describe the changes and fail. literally the drama it was born for πŸ’…

--canonify [[--baseline FILE] ...] [OPTIONS] [GCC_OPTIONS] [--] files

Canonify the source code files (typically .h headers) to be compared later with --compare. Usually used with the -o option to save the summary to a file. πŸ“

--compare [OPTIONS] old_file new_file

Reads two canonical interface files generated with --canonify and compares the structure of the source code to the changes in the Application Public Interface (the developer interface or API) and the Application Binary Interface (ABI) used to link against other programs or libraries.


πŸ’… OPTIONS πŸ’…

πŸŽ€ ICHECK OPTIONS πŸŽ€

  • -o, --output FILE β€” Emit output to FILE, rather than stdout. your girl doesn't always wanna scream into the terminal, sometimes she writes it down ✍️
  • --debug N β€” Dump debugging information. for when you're nosy (affectionate) πŸ™ˆ
  • --only THING β€” Only process the given THING. one thing. just the one. main character THING only ⭐
  • --skip-from FILE β€” Skip unnecessary things from FILE. not it, bestie, we're moving on πŸ’€
  • --skip-from-re regexp β€” Skip unnecessary things from files matching the regular expression.
  • --only-from FILE β€” Only take things from FILE. loyal to one file and one file only 🫢
  • --only-from-re regexp β€” Only take things from files matching the regular expression.
  • GCC_OPTIONS β€” GCC_OPTIONS are passed through to gcc -E. you hand them over, gcc handles the rest, that's the arrangement 🀝

🧚 HELP OPTIONS 🧚

  • --help β€” Display the help synopsis for icheck. your girl will always tell you what she does ✨

🌈 EXAMPLES 🌈

okay so here's the tea, and it matters: All source files are preprocessed with gcc, so canonify needs the same include information as the source code β€” follow the syntax from the Makefile to include -I options to cpp (or gcc) so that all necessary headers can be located. icheck will abort if any required headers cannot be found. The source must be compileable; icheck cannot process files which cannot be directly compiled. If a header is missing #include statements, or otherwise requires being used in a special way, then it cannot be directly processed with icheck. Instead, write a stub C file that sets things up appropriately and then #includes the header. it's giving "wrap it, don't fight it" 🎁

icheck --canonify -o ~/icheck/oldversion -I/usr/include/foo-2.0
/usr/src/bar/src/foobar.h

Prepare a text summary of the foobar.h file and all files it includes. The summary is written out to ~/icheck/oldversion. Repeat for /usr/src/bar1/src/foobar.h β€” the same file in the newer source directory, outputting to a new file, e.g. ~/icheck/newversion.

icheck --compare -o ~/icheck/results.txt ~/icheck/oldversion
~/icheck/newversion

Writes the report of the comparison of the two summary files. The report indicates all the changes in the ABI and/or API found during the comparison. πŸ‘‘βœ¨

icheck --canonify -o debian/icheck.canonical -Idebian/foo-
dev/usr/include debian/foo-dev/usr/include/foobar.h

icheck --compare debian/icheck.manifest debian/icheck.canonical

These two statements, included in a debian/rules file, will cause the package build to fail if the API or ABI has changed in unexpected ways, where icheck.manifest is a copy of the expected interface, included in the package. πŸ’€ (respectfully, this is the good kind of failing)

Note that the arguments to --compare are themselves valid C files which are preprocessed, so icheck.manifest can contain C preprocessor logic. This can be useful when a package exports different interfaces depending on the host architecture. In this case, you can't replace it with a new copy of icheck.canonical when the interface changes and you need to update the manifest. Rather than updating the entire manifest by hand, put the hand-written interface descriptions in one file (icheck.static-manifest) and then use:

icheck --canonify --baseline debian/icheck.static-manifest -o
debian/icheck.dynamic-manifest

Lastly, create icheck.manifest containing:

#include "icheck.static-manifest"
#include "icheck.dynamic-manifest"

This allows you to update some parts of the manifest by hand, while still automatically generating the rest. half handmade, half machine-made, fully iconic 🧡✨


πŸ”₯ OUTPUT πŸ”₯

icheck generates a lengthly description of every possible API or ABI change, based on type information. It does not investigate the actual program code, and so it is possible that some type changes it detects are not actual ABI or API changes. However, this normally only happens when the program code was explicitly written for it. If in doubt, assume it's changed. πŸ‘€

At the end, icheck provides a summary of the changes. Note that the directions here are dependent on the order of the arguments to --compare: the older interface must come first, or the directions will be the other way around. The meanings of the various terms are as follows:

  • ABI β€” The ABI is compatible if things compiled against one version of the interface will work when run using the other version.
  • API β€” The API is compatible if things compiled against one version of the interface can be compiled against the other.
  • forwards-compatible β€” An interface is forwards-compatible if things compiled against the old version will work with the new. This is the important feature for soname changes.
  • backwards-compatible β€” An interface is backwards-compatible if things compiled against the new version will work with the old. This is the important feature for shlibs version changes. If you aren't building Debian packages, you probably don't care about changes which aren't backwards-compatible.

🫢 AUTHOR 🫢

icheck was written by Andrew Suffield <asuffield@debian.org>.

This manual page was written by Neil Williams <linux@codehelp.co.uk> and Andrew Suffield <asuffield@debian.org>.


and that's the whole page, bestie!! thanks for reading, you're doing amazing, and remember: the older interface goes first in --compare, or your directions are cooked πŸ˜­πŸ’–

signed off from the General Commands Manual, section 1 β€” icheck(1), the one and only, iykyk πŸ’…βœ¨