Skip to content

Commit c09b5f7

Browse files
committed
Use Ubuntu 18.10 in Linux build container
Background ========== Shared Library Dependencies --------------------------- The Linux build of Arduino IDE has dynamic linkage against the libstdc++ and glibc shared libraries. This results in it having a dependency on the version of the libraries that happens to be present in the environment it is built in. Although newer versions of the shared libraries are compatible with executables linked against an older version, the reverse is not true. This means that building Arduino IDE on a Linux machine with a recent distro version installed causes the IDE to error on startup for users who have a distro with older versions of the dependencies. For example, if Arduino IDE were built on a machine with version 3.4.33 of libstdc++, then attempting to run it on a machine with an older version of libstdc++ would fail with an error like: ``` Error: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.33' not found (required by /home/foo/arduino-ide/resources/app/lib/backend/native/nsfw.node) ``` Likewise, if Arduino IDE were built on a machine with version 2.39 of glibc, then attempting to run it on a machine with an older version of glibc would fail with an error like: ``` Error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.39' not found (required by /home/foo/arduino-ide/resources/app/node_modules/nsfw/build/Release/nsfw.node) ``` Build Machine Requirements -------------------------- The IDE builds distributed by Arduino should be compatible with a reasonable range of Linux distribution versions. In order to achieve this, the builds must be performed in a machine with an older version of the shared libraries. The shared libraries are part of the Linux distro, and installing a different version is not feasible. So this imposes a maximum limit on the build machine's distro version. The distributed builds are generated via a GitHub Actions workflow. The most simple approach is to run the build in the machine of the GitHub-hosted runners provided for each operating system. However, GitHub provides a limited range of operating system versions in their runners, and removes the older versions as newer versions are added. This means that building in the GitHub-hosted runner machine would not allow for the desired range of Linux distro version compatibility. For this reason, the Linux build is performed in a Docker container that provides an older version of Ubuntu. The same situation of incompatibility with Linux distro versions that have a version of the shared library dependencies older than the version present on the build machine occurs for several of the tools and frameworks used by the build process (e.g., Node.js, Python). In this case, the tables are turned as we are now the user rather than the distributor and so are at the mercy of the Linux distro version compatibility range provided by the distributor. So this imposes a minimum limit on the build machine's distro version. Although several of the dependencies used by the standard build system have dependencies on versions of glibc higher than the version 2.27 present in Ubuntu 18.04, it was possible to use this distro version in the Linux build container by using alternative distributions and/or versions of these dependencies. Workflow Artifacts ------------------ The build workflow uses GitHub actions workflow artifacts to transfer the files generated by the build job to subsequent jobs in the workflow. The "actions/upload-artifact" action is used for this purpose. Problem ======= GitHub is dropping support for the workflow artifacts produced by the version 3.x of the "actions/upload-artifact" action that was previously used by the build job. So the action version used in the build workflow was updated to the current version 4.x. This version of the action uses a newer version of the Node.js runtime (20). Unfortunately the the Node.js 20 runtime used by the action has a dependency on glibc version 2.28, which causes the Linux build job to fail after the update of the "actions/upload-artifact" action: ``` Run actions/upload-artifact@v4 /__e/node20/bin/node: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /__e/node20/bin/node) ``` Unlike the other dependencies of the build process, it is no longer possible to work around this incompatibility by continuing to use the older compatible version of the "actions/upload-artifact" action. It is also impossible to replace the incompatible Node.js 20.x distribution used by the action, since it comes from the read-only file system of the runner image. Likewise, it is not possible to configure or force the action to use a Node.js installation at a different path on the runner machine. Resolution ========== Compatibility with the new version of the "actions/upload-artifact" action is attained by updating the version of Linux in the build container to 18.10, which is the oldest version that has glibc 2.28. The presence of a newer glibc version in the container also makes it compatible with several other dependencies of the build process, meaning the code in the Dockerfile and workflow for working around the incompatibilities of Ubuntu 18.04 can be removed. Consequences ============ Unfortunately this means the loss of compatibility of the Linux Arduino IDE builds with distros that use glibc 2.27 (e.g., Ubuntu 18.04). User of those distros will now find that Arduino IDE fails to start with an error like: ``` Error: node-loader: Error: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.28' not found (required by /home/foo/arduino-ide/resources/app/lib/backend/native/pty.node) at 85467 (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:2766) at __webpack_require__ (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:6663105) at 23571 (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:3374073) at __webpack_require__ (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:6663105) at 55444 (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:3369761) at __webpack_require__ (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:6663105) at 24290 (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:1780542) at __webpack_require__ (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:6663105) at 43416 (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:1770138) at __webpack_require__ (/home/foo/arduino-ide/resources/app/lib/backend/main.js:2:6663105) ```
1 parent dba57b3 commit c09b5f7

File tree

2 files changed

+37
-95
lines changed

2 files changed

+37
-95
lines changed

Diff for: .github/workflows/assets/linux.Dockerfile

+22-71
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,28 @@
11
# The Arduino IDE Linux build workflow job runs in this container.
22
# syntax=docker/dockerfile:1
33

4-
FROM ubuntu:18.04
5-
6-
# See: https://unofficial-builds.nodejs.org/download/release/
7-
ARG node_version="18.17.1"
4+
# See: https://hub.docker.com/_/ubuntu/tags
5+
FROM ubuntu:18.10
86

7+
# This is required in order to use the Ubuntu package repositories for EOL Ubuntu versions:
8+
# https://help.ubuntu.com/community/EOLUpgrades#Update_sources.list
99
RUN \
10-
apt-get \
11-
--yes \
12-
update
10+
sed \
11+
--in-place \
12+
--regexp-extended \
13+
--expression='s/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' \
14+
"/etc/apt/sources.list"
1315

14-
# This is required to get add-apt-repository
1516
RUN \
1617
apt-get \
1718
--yes \
18-
install \
19-
"software-properties-common=0.96.24.32.22"
19+
update
2020

21-
# Install Git
22-
# The PPA is required to get a modern version of Git. The version in the Ubuntu 18.04 package repository is 2.17.1,
23-
# while action/checkout@v3 requires 2.18 or higher.
2421
RUN \
25-
add-apt-repository \
26-
--yes \
27-
"ppa:git-core/ppa" && \
28-
apt-get \
29-
--yes \
30-
update && \
31-
\
3222
apt-get \
3323
--yes \
3424
install \
35-
"git" && \
36-
\
37-
apt-get \
38-
--yes \
39-
purge \
40-
"software-properties-common"
25+
"git"
4126

4227
# The repository path must be added to safe.directory, otherwise any Git operations on it would fail with a
4328
# "dubious ownership" error. actions/checkout configures this, but it is not applied to containers.
@@ -51,62 +36,28 @@ ENV \
5136

5237
# Install Python
5338
# The Python installed by actions/setup-python has dependency on a higher version of glibc than available in the
54-
# ubuntu:18.04 container.
39+
# container.
5540
RUN \
5641
apt-get \
5742
--yes \
5843
install \
59-
"python3.8-minimal=3.8.0-3ubuntu1~18.04.2" && \
60-
\
61-
ln \
62-
--symbolic \
63-
--force \
64-
"$(which python3.8)" \
65-
"/usr/bin/python3"
44+
"python3.7-minimal=3.7.3-2~18.10"
6645

6746
# Install Theia's package dependencies
6847
# These are pre-installed in the GitHub Actions hosted runner machines.
6948
RUN \
7049
apt-get \
7150
--yes \
7251
install \
73-
"libsecret-1-dev=0.18.6-1" \
74-
"libx11-dev=2:1.6.4-3ubuntu0.4" \
52+
"libsecret-1-dev=0.18.6-3" \
53+
"libx11-dev=2:1.6.7-1" \
7554
"libxkbfile-dev=1:1.0.9-2"
7655

77-
# Install Node.js
78-
# It is necessary to use the "unofficial" linux-x64-glibc-217 build because the official Node.js 18.x is dynamically
79-
# linked against glibc 2.28, while Ubuntu 18.04 has glibc 2.27.
80-
ARG node_installation_path="/tmp/node-installation"
81-
ARG artifact_name="node-v${node_version}-linux-x64-glibc-217"
82-
RUN \
83-
mkdir "$node_installation_path" && \
84-
cd "$node_installation_path" && \
85-
\
86-
apt-get \
87-
--yes \
88-
install \
89-
"wget=1.19.4-1ubuntu2.2" && \
90-
\
91-
archive_name="${artifact_name}.tar.xz" && \
92-
wget \
93-
"https://unofficial-builds.nodejs.org/download/release/v${node_version}/${archive_name}" && \
94-
\
95-
apt-get \
96-
--yes \
97-
purge \
98-
"wget" && \
99-
\
100-
tar \
101-
--file="$archive_name" \
102-
--extract && \
103-
rm "$archive_name"
104-
ENV PATH="${PATH}:${node_installation_path}/${artifact_name}/bin"
105-
106-
# Install Yarn
107-
# Yarn is pre-installed in the GitHub Actions hosted runner machines.
56+
# Target python3 symlink to Python 3.7 installation. It would otherwise target version 3.6 due to the installation of
57+
# the `python3` package as a transitive dependency.
10858
RUN \
109-
npm \
110-
install \
111-
--global \
112-
59+
ln \
60+
--symbolic \
61+
--force \
62+
"$(which python3.7)" \
63+
"/usr/bin/python3"

Diff for: .github/workflows/build.yml

+15-24
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ env:
4848
GO_VERSION: '1.21'
4949
# See: https://github.com/actions/setup-node/#readme
5050
NODE_VERSION: '18.17'
51+
YARN_VERSION: '1.22'
5152
JOB_TRANSFER_ARTIFACT_PREFIX: build-artifacts-
5253
CHANGELOG_ARTIFACTS: changelog
5354
STAGED_CHANNEL_FILE_ARTIFACT_PREFIX: staged-channel-file-
@@ -316,21 +317,26 @@ jobs:
316317
if not exist "${{ matrix.config.working-directory }}" mklink /d "${{ matrix.config.working-directory }}" "C:\actions-runner\_work\arduino-ide\arduino-ide"
317318
318319
- name: Checkout
319-
if: fromJSON(matrix.config.container) == null
320320
uses: actions/checkout@v4
321321

322-
- name: Checkout
323-
# actions/checkout@v4 has dependency on a higher version of glibc than available in the Linux container.
324-
if: fromJSON(matrix.config.container) != null
325-
uses: actions/checkout@v3
326322

327323
- name: Install Node.js
328-
if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC'
324+
if: runner.name != 'WINDOWS-SIGN-PC'
329325
uses: actions/setup-node@v4
330326
with:
331327
node-version: ${{ env.NODE_VERSION }}
332328
registry-url: 'https://registry.npmjs.org'
333-
cache: 'yarn'
329+
# Yarn is a prerequisite for the action's cache feature, so caching should be disabled when running in the
330+
# container where Yarn is not pre-installed.
331+
cache: ${{ fromJSON(matrix.config.container) == null && 'yarn' || null }}
332+
333+
- name: Install Yarn
334+
if: runner.name != 'WINDOWS-SIGN-PC'
335+
run: |
336+
npm \
337+
install \
338+
--global \
339+
"yarn@${{ env.YARN_VERSION }}"
334340
335341
- name: Install Python 3.x
336342
if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC'
@@ -339,33 +345,18 @@ jobs:
339345
python-version: '3.11.x'
340346

341347
- name: Install Go
342-
if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC'
348+
if: runner.name != 'WINDOWS-SIGN-PC'
343349
uses: actions/setup-go@v5
344350
with:
345351
go-version: ${{ env.GO_VERSION }}
346352

347-
- name: Install Go
348-
# actions/setup-go@v5 has dependency on a higher version of glibc than available in the Linux container.
349-
if: fromJSON(matrix.config.container) != null && runner.name != 'WINDOWS-SIGN-PC'
350-
uses: actions/setup-go@v4
351-
with:
352-
go-version: ${{ env.GO_VERSION }}
353-
354353
- name: Install Taskfile
355-
if: fromJSON(matrix.config.container) == null && runner.name != 'WINDOWS-SIGN-PC'
354+
if: runner.name != 'WINDOWS-SIGN-PC'
356355
uses: arduino/setup-task@v2
357356
with:
358357
repo-token: ${{ secrets.GITHUB_TOKEN }}
359358
version: 3.x
360359

361-
- name: Install Taskfile
362-
# actions/setup-task@v2 has dependency on a higher version of glibc than available in the Linux container.
363-
if: fromJSON(matrix.config.container) != null && runner.name != 'WINDOWS-SIGN-PC'
364-
uses: arduino/setup-task@v1
365-
with:
366-
repo-token: ${{ secrets.GITHUB_TOKEN }}
367-
version: 3.x
368-
369360
- name: Package
370361
env:
371362
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

0 commit comments

Comments
 (0)