Builds of the ESP8266 compiler, GCC 10.3 for xtensa-lx106-elf, for the host
systems ESPHome supports:
| System | Built on |
|---|---|
linux_x86_64 |
Linux x86_64, in an Ubuntu 20.04 image |
linux_aarch64 |
Linux arm64, in an Ubuntu 20.04 image |
darwin_arm64 |
macOS arm64 |
darwin_x86_64 |
macOS x86_64 |
windows_amd64 |
Linux x86_64 with mingw-w64 |
The compiler generates the same code as the toolchain-xtensa 2.100300.220621
package from the PlatformIO registry. The reason for this repository is that
no build of that package runs on arm64 macOS without Rosetta 2.
ci/prepare-sources.shfetches every source at a fixed commit or checksum and applies the patches. All hosts build from this one tree.ci/build.sh <system> hostbuilds binutils and GCC, the programs that run on the host.ci/build.sh linux_x86_64 devicebuilds newlib, libgcc, libstdc++ and the hal library, the code that ends up in firmware. This happens once, and every package gets the same copy.ci/package.sh <system>combines the two into an archive.ci/verify.shcompiles and links the sources intests/and writes a checksum for every output. Each host must produce the same checksums as the registry package.ci/compare-device.shcompares the device libraries and headers with the registry package.
| Source | Version |
|---|---|
| GCC | 10.3.0, commit f00b5710 |
| binutils | 2.32, commit a9d9a104 |
| newlib | earlephilhower/newlib-xtensa commit d6e3fcdb |
| hal | earlephilhower/lx106-hal commit e4bcc63c |
| gmp, mpfr, mpc, isl | 6.1.0, 3.1.4, 1.0.3, 0.18 |
The hal library is built with mawk. Its build splits some sources into one
object per function using a pattern only GNU awk understands; the registry
package was built with mawk, which skips the split.
The newlib commit is not the newest one. It is the one the libraries and
headers of the registry package match; a newer commit changes 15 objects in
libc and the sys/pgmspace.h header.
Two newlib changes save about 400 bytes of RAM on ESP8266; everything else matches the registry package.
| Change | Symbol | RAM |
|---|---|---|
--enable-newlib-global-atexit moves the 32 entry atexit table out of the reent struct, into an object nothing links |
impure_data |
240 to 96 B |
patches/newlib/newlib-locale-c-only-buffers.patch sizes the locale name buffers for the "C" and "ASCII" that a build without _MB_CAPABLE stores |
__global_locale |
364 to 104 B |
ESPHome's ESP8266 builds take libc and its headers from this toolchain; the Arduino core (3.1.2) ships no newlib headers, and its libc_orig.a is not linked. The prebuilt libraries in the Arduino core only reach the reent struct for stdin, stdout and stderr, which keep their offsets.
Versions are <gcc version>-esphome.<n>, for example 10.3.0-esphome.3; each
release takes the next n.
-
Changes land on
mainthrough pull requests. CI builds all five hosts, compares the device libraries with the registry package (intended differences are listed inci/device-changes.txt) and checks that the compiler output matches the registry compiler. All of it must pass. -
After merging, tag the merge commit (its SHA is on the pull request page) and push the tag:
git fetch origin git tag 10.3.0-esphome.4 <merge commit sha> git push origin 10.3.0-esphome.4
The tag build publishes the five archives and
sha256sums.txtas a release. A tag that containsrc, such as10.3.0-esphome.4-rc1, becomes a prerelease, unless the release was created by hand before the build finished; the build then only uploads the files to it. -
Point ESPHome at it: in the ESPHome repository (
esphome/esphome), inesphome/arduino8266/framework.pysetTOOLCHAIN_VERSIONto the tag and, for every host inTOOLCHAIN_BUILDS, the sha256 and the size in bytes of its archive. This prints both for every host:gh release view 10.3.0-esphome.4 --repo esphome-libs/xtensa-lx106-elf-toolchain \ --json assets --jq '.assets[] | select(.name | endswith(".tar.gz")) | "\(.name) \(.digest | ltrimstr("sha256:")) \(.size)"'ESPHome checks both when it downloads, so build an ESP8266 config before opening the pull request.
The build scripts, workflow and tests are licensed under the Apache License
2.0, see LICENSE. The patches in patches/ and the toolchain archives are
covered by the licenses of the projects they belong to, mainly the GNU General
Public License version 3 or later for GCC and binutils; see
patches/gcc/README.md.