Skip to content

Instantly share code, notes, and snippets.

@richlander
Last active March 13, 2023 21:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save richlander/bf7dc697b8702bc63435888b09d421b9 to your computer and use it in GitHub Desktop.
Save richlander/bf7dc697b8702bc63435888b09d421b9 to your computer and use it in GitHub Desktop.
Updating our build

Updating .NET Linux Build

.NET Core started out life as a cross-platform project. We naturally wanted to encourage usage on Linux. Across the first couple versions, we figured out how to build a single set of binaries that worked everywhere (e.g. for Linux x64). A key design point of that project was building on an old Linux so that our choice of build OS didn’t unnecessarily limit where .NET apps could be run. That has worked well, using CentOS 7, but it will soon go out of support. There isn't an obvious replacement for CentOS 7, requiring us to adopt a new approach.

We intend to use a combination of Mariner and a streamlined copy of Ubuntu going forward.

Breadth Targeting

The primary aspect of breadth targeting on Linux is linking with the C standard library (libc). Native code (like the .NET runtime) is compiled with a given libc and then is only able to run on distros with a libc version at least that high.

There are two libc variants (that we support) on Linux: glibc, and musl.

The following technique can be used to determine the glibc version of a given distro.

% docker run --rm ubuntu:16.04 ldd --version 
ldd (Ubuntu GLIBC 2.23-0ubuntu11.3) 2.23 
Copyright (C) 2016 Free Software Foundation, Inc. 

The following technique can be used with Alpine (for musl).

% docker run --rm alpine:3.17 /lib/libc.musl-aarch64.so.1  
musl libc (aarch64) 
Version 1.2.3 

CentOS 7

CentOS 7 has been our workhorse build distro since the early days of .NET Core. We have used it to build the Linux+glibc+x64 product since .NET Core 1.0. We use different methodologies for musl and Arm that already better align with the proposal.

As case in point, the glibc in CentOS 7 is quite old (which is good).

% docker run --rm centos:7 ldd --version  
ldd (GNU libc) 2.17 
Copyright (C) 2012 Free Software Foundation, Inc. 

CentOS was the community (AKA “free”) distro for Red Hat Enterprise Linux (RHEL). We adopted it since it satisfied our need to support both RHEL and Debian distro families. Also, Red Hat was our original Linux distro partner and using CentOS 7 had good alignment with RHEL 7.

CentOS 7 will hit EOL in June 2024, after ten good years of support. CentOS 8 is already EOL. More generally, the CentOS project has been replaced with CentOS Stream, which serves a different market niche than the original project.

Mariner + rootfs

Our plan going forward is to use the newest OS and newest tools to run our build while targeting old Linux. But how?

We intend to switch to Mariner as our build OS (where cmake and the compilers run) and then use the rootfs build technique to target a different distro and to minimize our exposure to it. We will be cross-compiling with the rootfs target, not running the build in the chroot.

We already use the rootfs technique for Arm and musl builds. We will extend that approach to x64. This change will have the advantage that all Linux builds will use the same methodology for breadth targeting.

We plan to use Ubuntu 16.04 for the rootfs target. Ubuntu 16.04 offers us a quite old glibc, offering us significant breadth target compatibility with the Linux ecosystem. For .NET 9, we'd move to Ubuntu 18.04 and for .NET 11 to Ubuntu 20.04. That pattern would continue. Careful readers would realize that we'd be using these Ubuntu versions after they were EOL. We're primarily using them for header files, such that the risk profile is very low.

This approach is roughly similar to manylinux. Our goal is to treat secure supply chain and targeting as high priorities. That's what is motivating the use of the rootfs technique. Similar to manylinux, we will offer our new build environment as a solution for developers that want to build compatible ("breadth targeting") Linux binaries, giving .NET an analogous offering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment