Skip to content

The Moving Parts

PlatformIO is a small command driving a storehouse. Five parts do the work; when something surprises you later, it is almost always one of these five behaving exactly as designed.

Core — the command itself

PlatformIO Core is a Python program, the pio command. It parses your platformio.ini, works out what is needed, fetches what is missing, and drives the builds by calling a build engine (SCons, which arrives as one of the packages below). Core itself knows no board and no chip; all of that knowledge lives in the platforms. The lab installed Core 6.2.0, and every transcript in the guide is Core's own output.

Platforms — the knowledge of a chip family

A platform is a downloadable bundle describing one family of chips: which compilers it needs, which boards exist, how uploads work. The guide uses two:

  • atmelavr (5.3.0 in the lab) — Atmel/Microchip AVR chips, the Arduino Uno among them.
  • native (1.2.1) — no chip at all: build for the machine you are sitting at, with its own compiler.

You name a platform in the project file; Core downloads it once and keeps it.

Packages — the tools themselves

Platforms are recipes; packages are the ingredients. Compilers (toolchain-atmelavr, gcc 7.3.0 inside), frameworks (framework-arduino-avr, the Arduino core libraries for AVR), upload tools (tool-avrdude), the test library (Unity), the static checker (cppcheck) — each is a package with a version, fetched on first use. The lab's first Uno build needed four of them; the store that holds them all is measured in chapter 15, because the number surprises everyone the first time: this guide's downloads came to about 300 MB.

The registry and lib_deps — other people's code

The PlatformIO Registry is a public library catalogue: thousands of libraries, each with an owner, a name and versions. Your project declares the ones it uses under lib_deps in platformio.ini:

lib_deps = bblanchon/ArduinoJson@^7.4.3

pio run then fetches exactly those, into the project's own .pio/libdeps/ folder — a per-project shelf, so two projects can use different versions of the same library without quarrelling. Chapter 8 installs one for real.

The LDF — the part that finds your libraries

The Library Dependency Finder reads your source code's #include lines and works out which libraries — registry ones and the private ones in your project's lib/ folder — each environment needs, then compiles exactly those. Its report appears in every build:

Dependency Graph
|-- ArduinoJson @ 7.4.3
|-- RunningAverage @ 1.0.0

When a build complains it cannot find a header, it is the LDF you are arguing with; chapter 16 teaches the argument.

Where everything lives

Part Where it sits
Core your Python environment (the lab used a venv)
Platforms and packages the core directory, ~/.platformio by default; the lab moved it with PLATFORMIO_CORE_DIR
A project's downloads <project>/.pio/ — builds and that project's libraries
Your code src/, lib/, include/, test/ in the project folder

The .pio folder is the one to remember: it is entirely rebuilt from the project file and your sources, so it is safe to delete — and chapter 14's clean-rebuild recipe does exactly that.

Check: name the part

A build fails because the compiler for your new board is missing → a package the platform asked for. A header is not found → the LDF. A library version changed under you → the registry entry in lib_deps. Keep the five parts apart and most error messages read as sentences instead of weather.