EmbCC's own conventions, GCC's as a layer#
Decided 2026-10-14. EmbCC had been drifting into GCC's way of doing
things: it read GCC's spellings, its manual was laid out like GCC's
(Overall options, C and C++ language options, ...) and keyed by
GCC's flags, and its help text said it used "the spellings GCC and Clang
use". On that date the driver tested about 230 option spellings, 114 of
them -f and 134 -m flags taken from GCC, against 44 of EmbCC's own;
the user manual named GCC 293 times.
We read GCC to understand a problem, and then make EmbCC's own answer. We do not copy its names, its structure or its wording.
Three kinds of convention#
| Kind | What | Rule |
|---|---|---|
| Contracts | ABIs and calling conventions; object, archive and debug formats; the runtime helpers' symbol names (__mulsi3, __aeabi_*); __attribute__ and asm syntax in C source; linker-script syntax |
Match exactly. Breaking one means existing objects and sources stop working with EmbCC. |
| Ours | EmbCC's command line, diagnostics, documentation, tool names and output formats; the POSIX c99 utility's letters (-c -o -E -I -D -U -L -l -g -O) |
Designed for EmbCC, in its own words. |
| The compatibility layer | GCC's spellings of options (-fshort-enums, -mcpu=, -Wl,), the arm-none-eabi-gcc-style program names, the binutils names (embcc-ar, embcc-objcopy) |
Accepted, so a build written for GCC keeps working. Kept in one place, and documented on one page (Migrating from GCC), never as how EmbCC names something. |
The redesign's rule still holds: nothing that works today breaks. GCC's spellings stay accepted indefinitely.
The command line#
Every option is a row in src/driver/options.def:
EmbCC's spelling, its value's name, the other spelling it stands for (GCC's,
or EmbCC's own older GCC-style one), a group, and a line of help. embcc --help prints EmbCC's spellings, embcc --help=gcc the other ones, and
embcc --reference=options the option reference that the manual includes.
The rules for EmbCC's spellings:
- POSIX's letters, then words. The
c99utility's options keep their letters. Everything else is a long option made of words, not abbreviations:--freestanding,--stack-usage,--no-common. - A noun and a value, rather than a family of flags.
--opt=size(not-Os),--enums=short,--char=unsigned,--sections=functions,data,--endian=big,--isa=thumb. A value may follow as the next argument (--cpu cortex-m4). --no-turns a thing off:--no-warn=NAME,--no-unwind-tables.- The goal, not the mechanism.
--opt=speedand--opt=sizesay what is wanted; the levels (-O2,-Os) stay as POSIX's-Oletter.
Native spellings are rewritten into the ones the driver's argument loop
reads before it runs (opts_normalize in src/driver/options.c), so a
build gets byte-identical output whichever spelling it uses.
tests/golden/options-table.sh holds the driver to the table:
- every spelling the loop tests is a row in it;
- every native spelling is accepted;
- EmbCC's and GCC's spellings build identical objects, dependency files and diagnostics.
Still to do#
- Move GCC's spellings into one module. Today the argument loop
in
main.creads GCC's spellings, and native ones are translated to them. The loop should read EmbCC's options by id, andsrc/driver/compat_gcc.cshould translate GCC's spellings in. That includes each target's-mlists (src/arch/*/options.c).
Done since:
- A warning ends with the EmbCC option that controls it,
[--warn=conversion](it was GCC's[-Wconversion]). JSON output keeps GCC's"option": "-Wconversion", because tools read that format.--help-warningslists--warn=NAME. - Every message about an option quotes it as the user typed it
(
opt_typedandopt_saidinsrc/driver/util.c), in the driver and in each target's option file, and suggests EmbCC's spelling. An EmbCC option a target has no use for says so instead of "unknown argument". -O1is--opt=basic,-mtune=is--tune=.- A warning named on its own wins over
--warn=alland--warn=extrain either order, as in GCC. embcc --reference=manprintsembcc(1)from the table, andmake installinstalls it.- The manual uses EmbCC's spellings throughout; GCC's appear under each heading, on the Migrating from GCC page, and in what other programs read (embld's own options, the host compiler's flags).
The documentation#
The documentation is generated by EmbCC's own tool, embdoc (C99, no
dependencies). Its sources:
- the handbook in
docs/, written by hand; - the pages generated from the tables in the source, so they cannot
drift from the compiler:
- the option reference (
embcc --reference=options); - the warnings (
embcc --reference=warnings); - the targets (
embcc --reference=targets, fromsrc/targets/*.def); - and, next, the attributes and builtins.
- the option reference (
embdoc renders all of it into a static website and checks every link
and anchor across it; the same tables give --help and the man page
(embcc --reference=man).
The manual's structure is EmbCC's: what a firmware engineer does
(starting, building for a part, fitting in flash, debugging,
simulating), then the references. The GCC comparisons move to
Migrating from GCC. That page is the one place that says "GCC's
-fshort-enums is EmbCC's --enums=short".
The website#
GitHub Pages for this repository (emblinkos.github.io/EmbCC). A
GitHub Actions workflow builds embdoc, checks the links, renders the
site and deploys it on every push to main. The site is never committed. The
generated reference pages are: make reference writes them, and
tests/golden/reference-pages.sh fails when one is stale.