# \`GNAT.Serial\_Communications\` broke on Ubuntu 26.04

**URL:** <https://forum.ada-lang.io/t/gnat-serial-communications-broke-on-ubuntu-26-04/4459>\
**Category:** General\
**Created:** [May 28, 2026, 4:42pm UTC](https://forum.ada-lang.io/t/gnat-serial-communications-broke-on-ubuntu-26-04/4459 "2026-05-28T16:42:18Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Max](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/max/32/21_2.png) [@Max](https://forum.ada-lang.io/u/Max)\
**Post date:** [May 28, 2026, 4:42pm UTC](https://forum.ada-lang.io/t/gnat-serial-communications-broke-on-ubuntu-26-04/4459/1 "2026-05-28T16:42:18Z")

</div>

# `GNAT.Serial_Communications` broke on Ubuntu 26.04 / glibc 2.42+, here is why (and how to fix it)

Hey everyone,

If you’ve recently upgraded your Linux environment (running Ubuntu 26.04 or any distro with **glibc 2.42+** ) and noticed your Ada serial port code suddenly stopped working, you aren’t losing your mind.

If you are using an Alire-provided GNAT toolchain (like GCC 15), there is a subtle breaking change under the hood of `glibc` that directly clashes with how GNAT bakes in OS constants.

* * *

## 🔍 The Problem: Glibc Changed the Rules

In [glibc 2.42](https://lists.gnu.org/archive/html/info-gnu/2025-07/msg00011.html), Linux introduced support for arbitrary baud rates. As part of this change, `speed_t` was redefined to simply match the kernel interface as an unsigned integer representing the actual baud rate.

> **The Catch:** GNAT relies on a file called `System.OS_Constants` (`s-oscons.ads`), which is generated _during the compilation of GNAT itself_ by probing the host OS headers.

Because Alire toolchains are typically compiled on older Linux releases for maximum compatibility, they are baked with the _old_ octal/constant values. When you run that pre-compiled compiler on a brand-new OS, things break. Fortunately, only `GNAT.Serial_Communications` is affected.

### The Proof is in the Headers

Look at the difference in `termios-baud.h` between Ubuntu 22.04 and Ubuntu 26.04:

```shell
ubuntu22.04$ grep 57600 /usr/include/x86_64-linux-gnu/bits/termios-baud.h
#define B57600 0010001

ubuntu26.04$ grep 57600 /usr/include/x86_64-linux-gnu/bits/termios-baud.h
#define B57600 57600U

```

If you regenerate `s-oscons.ads` on the new OS, look at the massive discrepancy:

```diff
- B57600 : constant := 4097; -- 57600 bps
+ B57600 : constant := 57600; -- 57600 bps

```

### The Impact

When your code calls `GNAT.Serial_Communications.Open ("/dev/ttyACM0", B57600);`, your Alire-built compiler passes `4097` to the OS. But the new glibc interprets `4097` literally as **4097 baud** instead of the magic constant for 57600!

_(For more context, check out this [Sourceware Bugzilla ticket](https://sourceware.org/bugzilla/show_bug.cgi?id=33340).)_

* * *

## 🛠 3 Ways to Fix It

If you are hit by this on Ubuntu 26.04 with Alire’s GNAT, here are three ways to get your serial ports working again, ranging from easiest to most advanced:

### 1. Use the System Package Manager (Easiest)

Instead of relying on Alire’s pre-built binary toolchain, switch to the GNAT compiler provided natively by Ubuntu. Because it was compiled directly on and for your current OS version, its `s-oscons.ads` file will perfectly match your system’s `glibc`.

- **How:** Install `gnat` via `apt`, and configure Alire to use the system compiler as an external toolchain.

### 2. Rebuild `gnat_native` via Alire Scripts

If you prefer to keep your toolchains fully managed inside Alire, you can custom-build your own native GNAT compiler right on your machine. This ensures the newly compiled toolchain probes your updated host headers.

- **How:** Use the build scripts provided by the community over at the [Alire GNAT-FSF-builds GitHub repository](https://github.com/alire-project/GNAT-FSF-builds).

### 3. Surgical Strike: Regenerate Just One File & Rebuild Ada RTL (Advanced)

If you don’t want to rebuild the entire compiler and just want to fix the Ada Run-Time Library (RTL), you can regenerate `s-oscons.ads` manually and swap it out.

**How to do it:**

1. Unpack the GCC 15 source code somewhere onto your system.
2. Navigate into the `gcc/ada/` directory.
3. Run the following commands to generate the updated constants file:

```shell
# Preprocess the template with your current OS headers
gcc -DTARGET=\"x86_64-linux-gnu\" -C -E s-oscons-tmplt.c > s-oscons-tmplt.i

# Build the generator utility
gnatmake xoscons.adb

# Run it to output the new s-oscons.ads file
./xoscons s-oscons

```

1. Take the newly created `s-oscons.ads` file from the current directory and **replace the original file** in your Alire toolchain path.
2. Use the scripts from the [my GitHub repository](https://github.com/reznikmm/libada) to cleanly recompile the Ada RTL with the fixed file.

Has anyone else bumped into this yet? Let me know which solution worked best for your workflow!

- **How:** You can automate this specific runtime fix using the scripts available in the [libada GitHub repository](https://github.com/reznikmm/libada) to rebuild your runtime cleanly.

Has anyone else bumped into this yet? Let me know which solution worked best for your workflow!

---

<div class="post-metadata">

**Author:** ![krischik](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/krischik/32/420_2.png) [@krischik](https://forum.ada-lang.io/u/krischik)\
**Post date:** [October 5, 2026, 2:55pm UTC](https://forum.ada-lang.io/t/gnat-serial-communications-broke-on-ubuntu-26-04/4459/2 "2026-10-05T14:55:31Z")

</div>

Ohh dear. I see another way: I could incorporate option 3 into [`adacl_serial`](https://alire.ada.dev/crates/adacl_serial).

1. Add an `xoscons` subcrate to adacl\_serial to generate s-oscons.
2. Generate `s-oscons` in the **pre-build** step.
3. Rename `s-oscons` to avoid naming clashes.
4. Provide fixed `AdaCL.Serial_Communications` for windows, linux and macOS.

Then most user could use **adacl\_serial** as a drop in replacement. No need to build your own runtime.
