WiringPi: a C GPIO library for Raspberry Pi that writes straight to the registers
The arguably fastest GPIO Library for the Raspberry Pi
At a glance
- What is it?
- WiringPi is a C library that drives Raspberry Pi GPIO pins by accessing hardware registers directly, with a gpio command-line tool and a CMake target. It is now maintained by GC2, and the Pi 5 GCLK path is still missing.
- Who is it for?
- Adopt WiringPi if you are writing C on a Raspberry Pi and want register-level GPIO access with a small API, a gpio CLI and a CMake target that needs one line. Do not adopt it if you need a maintained Python binding (the README says the wrappers are not updated in sync with version 3 and are unsupported), if you need GCLK on a Pi 5, or if you want a kernel-ABI library such as libgpiod.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 22 days ago.
- What is it written in?
- Mainly C, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What WiringPi solves, and who is actually writing against it
On a Raspberry Pi, blinking an LED is easy; blinking it with low and predictable latency from a C program is where libraries diverge. WiringPi's stated approach is to access the GPIO hardware registers directly, which the README frames as the source of its performance: "By directly accessing the hardware registers, WiringPi ensures minimal latency and maximum performance for your GPIO operations." That design choice is the whole product. It is for people writing C on the Pi who want pinMode, digitalRead, digitalWrite, pullUpDnControl and PWM without pulling in a larger framework, and who are willing to accept a library that knows about Pi hardware generations rather than a generic Linux GPIO abstraction.
The README also positions it historically: this repository continues Gordon's wiringPi 2.5, which was deprecated, and since 2024 GC2 has taken over maintenance, "supporting new OS versions as well as current hardware generations." The last push to the repository was on 2026-09-02, and the most recent release listed is v3.20 on 2026-09-01. That is a live project, not a frozen archive, but the maintenance is a small group's continuation rather than a vendor-backed platform.
The audience is narrower than the download numbers suggest. If you are writing shell scripts, Python or Node, WiringPi is the wrong layer: use it through a wrapper only if you accept that the README calls those wrappers unmaintained.
Register-level access, and the setup call that decides your pin numbering
The mechanism is visible in the README's own example. You include wiringPi.h, call a setup function, then use pin functions. The example uses wiringPiSetupGpio(), and the comment is explicit that this "uses BCM numbering of the GPIOs and directly accesses the GPIO registers." That single call is the fork in the road. WiringPi has more than one numbering scheme, and the gpio readall output in the README shows three columns side by side: BCM, wPi and Physical. Choosing a setup function chooses which of those numbering systems your pin numbers refer to, so a program that works on one scheme will silently drive the wrong pin under another.
After setup, the API is small: pinMode(pin, INPUT) or OUTPUT, PWM_OUTPUT, GPIO_CLOCK; pullUpDnControl(pin, PUD_OFF) or PUD_UP or PUD_DOWN; digitalRead and digitalWrite. The README's snippet reads pin 17 after configuring it as an input with a pull-down, and branches on HIGH. There is no handle, no device object and no error type in the example: state lives in the library after setup, which is why the setup call at the top of main matters more than any other line.
The data flow is therefore short. Your process calls into the library, the library touches registers mapped into the process, and the pin changes. Nothing in the README describes a daemon in the path, so there is no IPC hop to reason about. The flip side is that your process is the thing holding the mapping, and the library's knowledge of which registers exist is per-board.
Installing WiringPi on a Raspberry Pi, then a first build
The README gives two routes: build a Debian package from source, or use prebuilt binaries from the releases page. The source route clones the repository and runs the build script with the debian argument, which produces a .deb that you then install with apt. Note that the README writes the package name with a placeholder version, wiringpi-3.x.deb, so the exact filename depends on the release you build.
sudo apt install git
git clone https://github.com/WiringPi/WiringPi.git
cd WiringPi
./build debian
mv debian-template/wiringpi-3.x.deb .
sudo apt install ./wiringpi-3.x.debIf you prefer the prebuilt path, the README points at the releases page and shows both a portable tarball and the .deb. The tarball is unpacked with tar; the .deb is installed the same way as above.
tar -xfv wiringpi_3.x.tar.gz
sudo apt install ./wiringpi-3.x.debWith the library installed, compiling a program is a single link flag. The README's command is gcc -o myapp myapp.c -l wiringPi, with a space between -l and the library name.
gcc -o myapp myapp.c -l wiringPiFor CMake projects, the README says one target_link_libraries entry is enough once WiringPi is installed, using the wiringPi target name.
add_executable(example
# project sources...
)
target_link_libraries(
example
PRIVATE wiringPi
)To confirm the library sees your board, run the gpio tool's readall subcommand. The README shows a full 40-pin table with BCM, wPi, Name, Mode, V and Physical columns, so on a working install you should see your pins listed with their current modes and levels rather than an error.
The Pi 5 gap, the wrapper gap, and when to pick something else
Two limitations are stated by the project itself, and both are the kind that bite after you have written code. The first is hardware: the README says WiringPi supports all Raspberry Pi boards including Pi 5, but with a caveat, that on the Pi 5 only the GCLK functionality is currently not supported, because the RP1 chip's documentation is missing. If your design clocks an external part from a GPIO clock, the Pi 5 is not a target yet, and no amount of library code fixes a missing datasheet.
The second is language bindings. The README lists Node, Perl, PHP, Python and Ruby wrappers, then says plainly that they are "not updated and maintained in sync with WiringPi version 3+", so functionality cannot be guaranteed and support is not provided for a specific implementation. Anyone arriving from the wiringpi-python search trail should read that sentence twice. The C library is the maintained artifact; the bindings are historical.
A third, quieter constraint is architectural. Because the library talks to registers itself, its board support is a list the maintainers must extend for each new SoC, and the Pi 5 note shows what happens when that knowledge is incomplete. libgpiod takes the opposite approach: it goes through the kernel's GPIO character device interface, so the kernel owns the hardware knowledge and the library stays board-agnostic. The trade is abstraction and syscall overhead against per-board register knowledge. pigpio is the other common comparison, a different daemon-based design; the README does not discuss either project, so treat the choice as one about where you want hardware knowledge to live, not about which library is faster in the abstract.
Maintenance, licence and what upgrades cost you
Maintenance is real but concentrated. The last push was on 2026-09-02, the latest listed release is v3.20 from 2026-09-01, and the previous two releases came in 2026-02 and 2025-06. The README credits GC2 with taking over since 2024 and describes the goal as supporting new OS versions and current hardware generations. That is a maintenance cadence of a few releases a year, not continuous churn, which suits a library whose API has been stable since the 2.x era. It also means a new board or a new OS quirk waits for the next release rather than a patch within days.
On upgrades, the cost is mostly in the packaging story. The README's install instructions build a .deb from source or install one downloaded from the releases page, which means your upgrade path is tied to rebuilding or re-downloading that package, not to a distribution repository. If you install from source on a machine you rebuild often, keep the build script and the version you used, because the README does not document rollback to an earlier version.
The licence is LGPL-3.0, and the repository carries COPYING.LESSER at the top level. The practical implication of the LGPL for a C library is that linking against it does not force your application under the same licence, but modifications to the library itself carry obligations, and static linking raises questions that dynamic linking does not. That is a general property of the licence, not legal advice; check your own distribution model with someone qualified.
What the documentation does and does not cover
The README points to function documentation in English and German, under documentation/english/functions.md and documentation/deutsch/functions.md, and to an examples directory with a Makefile. The examples listing includes blink.c, blink-thread.c, blink8.c, blink12.c, delayTest.c, isr.c, isr_debounce.c, clock.c, lcd.c and ds1302.c, which covers the ground most people need: basic output, threaded blinking, interrupts, a clock example and an LCD. The README's instruction for them is to cd into examples and run make with an example name or really-all.
cd examples
make <example-name | really-all>What the README does not give you is a pin-numbering decision table beyond the readall output, or any guidance on what happens when two programs both map the same registers. It also does not document rollback, version pinning, or how the wrapper projects are versioned. For a library that has been around this long, the thin parts are the operational ones: coexistence, packaging across distributions, and the boundary between the C library and its ports. Plan to read the examples and the function documentation rather than expecting the README to answer those.
Editorial conclusion
Adopt WiringPi if you are writing C on a Raspberry Pi and want register-level GPIO access with a small API, a gpio CLI and a CMake target that needs one line. Do not adopt it if you need a maintained Python binding (the README says the wrappers are not updated in sync with version 3 and are unsupported), if you need GCLK on a Pi 5, or if you want a kernel-ABI library such as libgpiod. Verify first that your board is covered by the current release, that your distribution still packages wiringpi (the README's install path builds the .deb yourself), and whether you depend on any of the wrapper languages, because that dependency is the one the project explicitly disclaims.
Frequently asked questions
How do I install WiringPi on a Raspberry Pi?
The README gives two routes: build a Debian package from source with git clone, ./build debian and sudo apt install ./wiringpi-3.x.deb, or download a prebuilt .deb or tarball from the releases page and install it. There is no distro-repository step documented in the README.
How do I use WiringPi in a C program?
Include wiringPi.h, call a setup function such as wiringPiSetupGpio() for BCM numbering with direct register access, then configure pins with pinMode and pullUpDnControl and read or write them with digitalRead and digitalWrite. Compile with gcc -o myapp myapp.c -l wiringPi, or link the wiringPi target in CMake.
Is WiringPi deprecated?
Gordon's wiringPi 2.5 was deprecated, and this repository is the continuation of it. The README states that since 2024 GC2 has taken over maintenance, supporting new OS versions and current hardware generations, and the most recent release listed is v3.20 from 2026-09-01.
Does WiringPi work on Raspberry Pi 5?
The README says WiringPi supports all Raspberry Pi boards including Pi 5, with one exception: on the Pi 5 only the GCLK functionality is currently not supported, because the RP1 chip's documentation is missing. Other GPIO use is presented as supported.
What is the difference between WiringPi and libgpiod?
WiringPi accesses the GPIO hardware registers directly, which the README ties to minimal latency, and its board support is therefore maintained per hardware generation. libgpiod goes through the kernel's GPIO interface instead, so hardware knowledge lives in the kernel. The README does not compare the two.
Community notes