From 9cc1131d962a0008e6ca405deadaf0e7f79f1a19 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Tue, 1 Aug 2023 19:02:10 +0200 Subject: [PATCH] Test multiple Linux distributions for the stdlib The compiler tests can just run on the GitHub runner directly, as these don't involve platform specifics. However, the standard library tests may run into platform specific bits, such as certain distributions requiring additional linker arguments. In addition, standard library tests now only run using Rust 1.68, instead of also testing against Rust stable. As the compiler tests already run against Rust stable, also running the standard library tests using this version is redundant. This commit also includes some fixes for the linker to handle older platforms (e.g. Debian 11) requiring extra libraries to be linked in. Changelog: fixed --- .github/workflows/freebsd.yml | 1 - .github/workflows/lint.yml | 4 +- .github/workflows/linux.yml | 23 +++- .github/workflows/mac.yml | 9 +- compiler/src/linker.rs | 22 ++-- docs/source/getting-started/installation.md | 116 ++++++++++++++------ scripts/deps.sh | 76 +++++++++++++ scripts/llvm.sh | 23 ---- 8 files changed, 198 insertions(+), 76 deletions(-) create mode 100755 scripts/deps.sh delete mode 100755 scripts/llvm.sh diff --git a/.github/workflows/freebsd.yml b/.github/workflows/freebsd.yml index 08b1bdf15..e87f67979 100644 --- a/.github/workflows/freebsd.yml +++ b/.github/workflows/freebsd.yml @@ -49,7 +49,6 @@ jobs: matrix: version: - '1.68' - - stable runs-on: macos-latest needs: - compiler diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e5c9f7c1a..036ba9a92 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -51,8 +51,8 @@ jobs: key: ubuntu-1.68 - name: Installing Rust run: ./scripts/rust.sh 1.68 - - name: Installing LLVM - run: ./scripts/llvm.sh ubuntu + - name: Installing dependencies + run: sudo ./scripts/deps.sh ubuntu:latest - name: Installing clippy run: rustup component add clippy - run: 'cargo clippy -- -D warnings' diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 9c010359e..cc1ab39db 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -6,6 +6,8 @@ on: env: CARGO_HOME: ${{ github.workspace }}/.cargo-home CARGO_REGISTRIES_CRATES_IO_PROTOCOL: sparse + DEBIAN_FRONTEND: noninteractive + TZ: UTC jobs: compiler: @@ -24,10 +26,10 @@ jobs: ${{ env.CARGO_HOME }} target key: ubuntu-${{ matrix.version }} + - name: Installing dependencies + run: sudo ./scripts/deps.sh ubuntu:latest - name: Installing Rust run: ./scripts/rust.sh ${{ matrix.version }} - - name: Installing LLVM - run: ./scripts/llvm.sh ubuntu - name: Running tests run: cargo test @@ -37,8 +39,17 @@ jobs: matrix: version: - '1.68' - - stable + image: + - archlinux:latest + - debian:11 + - debian:latest + - fedora:37 + - fedora:latest + - ubuntu:20.04 + - ubuntu:latest runs-on: ubuntu-latest + container: + image: ${{ matrix.image }} needs: - compiler steps: @@ -48,11 +59,11 @@ jobs: path: | ${{ env.CARGO_HOME }} target - key: ubuntu-${{ matrix.version }} + key: ${{ matrix.image }}-${{ matrix.version }} + - name: Installing dependencies + run: ./scripts/deps.sh ${{ matrix.image }} - name: Installing Rust run: ./scripts/rust.sh ${{ matrix.version }} - - name: Installing LLVM - run: ./scripts/llvm.sh ubuntu - name: Compiling run: cargo build - name: Running tests diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index db6407963..e9fdc9cac 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -24,10 +24,10 @@ jobs: ${{ env.CARGO_HOME }} target key: mac-${{ matrix.version }} + - name: Installing dependencies + run: ./scripts/deps.sh mac - name: Installing Rust run: ./scripts/rust.sh ${{ matrix.version }} - - name: Installing LLVM - run: ./scripts/llvm.sh mac - name: Running tests run: cargo test @@ -37,7 +37,6 @@ jobs: matrix: version: - '1.68' - - stable runs-on: macos-latest needs: - compiler @@ -49,10 +48,10 @@ jobs: ${{ env.CARGO_HOME }} target key: mac-${{ matrix.version }} + - name: Installing dependencies + run: ./scripts/deps.sh mac - name: Installing Rust run: ./scripts/rust.sh ${{ matrix.version }} - - name: Installing LLVM - run: ./scripts/llvm.sh mac - name: Compiling run: cargo build - name: Running tests diff --git a/compiler/src/linker.rs b/compiler/src/linker.rs index c851d7df7..4f5cc0108 100644 --- a/compiler/src/linker.rs +++ b/compiler/src/linker.rs @@ -57,8 +57,15 @@ pub(crate) fn link( cmd.arg(path); } + let rt_path = runtime_library(&state.config).ok_or_else(|| { + format!("No runtime is available for target '{}'", state.config.target) + })?; + + cmd.arg(&rt_path); + // Include any extra platform specific libraries, such as libm on the - // various Unix platforms. + // various Unix platforms. These must come _after_ any object files and + // the runtime library path. // // macOS includes libm in the standard C library, so there's no need to // explicitly include it. @@ -70,7 +77,14 @@ pub(crate) fn link( // details. match state.config.target.os { OperatingSystem::Linux => { + // Certain versions of Linux (e.g. Debian 11) also need libdl and + // libpthread to be linked in explicitly. We use the --as-needed + // flag here (supported by both gcc and clang) to only link these + // libraries if actually needed. + cmd.arg("-Wl,--as-needed"); + cmd.arg("-ldl"); cmd.arg("-lm"); + cmd.arg("-lpthread"); } OperatingSystem::Freebsd => { cmd.arg("-lm"); @@ -130,12 +144,6 @@ pub(crate) fn link( } } - let rt_path = runtime_library(&state.config).ok_or_else(|| { - format!("No runtime is available for target '{}'", state.config.target) - })?; - - cmd.arg(&rt_path); - cmd.stdin(Stdio::null()); cmd.stderr(Stdio::piped()); cmd.stdout(Stdio::null()); diff --git a/docs/source/getting-started/installation.md b/docs/source/getting-started/installation.md index 96f83fb2a..a6659c70f 100644 --- a/docs/source/getting-started/installation.md +++ b/docs/source/getting-started/installation.md @@ -131,8 +131,7 @@ the case. There's no official package for Inko in the Alpine repositories. -When building from source, the compiler requires the following dependencies to -be installed: +The compiler dependencies are installed as follows: ```bash sudo apk add build-base rust cargo llvm15 llvm15-dev llvm15-static git @@ -141,34 +140,59 @@ sudo apk add build-base rust cargo llvm15 llvm15-dev llvm15-static git #### Arch Two AUR packages are provided: `inko` and `inko-git`. These can be installed -using your favourite AUR wrapper: +using your favourite AUR wrapper. For example, using +[yay](https://github.com/Jguer/yay): -=== "yay" - ```bash - yay -S inko - ``` -=== "pacaur" - ```bash - pacaur -S inko - ``` -=== "pikaur" - ```bash - pikaur -S inko - ``` -=== "Manually" - ```bash - git clone https://aur.archlinux.org/inko.git - cd inko - makepkg -si - ``` +```bash +yay -S inko +``` + +Or manually: -When building from source, the compiler requires the following dependencies to -be installed: +```bash +git clone https://aur.archlinux.org/inko.git +cd inko +makepkg -si +``` + +The compiler dependencies are installed as follows: ```bash sudo pacman -Sy llvm rust git base-devel ``` +#### Debian + +There's no official package for Inko in the Debian repositories. + +For Debian 12, the compiler dependencies are installed as follows: + +```bash +sudo apt-get install --yes rustc cargo git build-essential llvm-15 llvm-15-dev \ + libstdc++-11-dev libclang-common-15-dev zlib1g-dev +``` + +For Debian 11, the process is a little different as the provided version of +LLVM is too old. Installing the necessary dependencies is done as follows: + +```bash +curl https://apt.llvm.org/llvm-snapshot.gpg.key | \ + sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc +sudo add-apt-repository \ + "deb http://apt.llvm.org/bullseye/ llvm-toolchain-bullseye-15 main" +sudo apt-get update +``` + +Now we can install the necessary dependencies: + +```bash +sudo apt-get install --yes git build-essential llvm-15 llvm-15-dev \ + libstdc++-10-dev libclang-common-15-dev zlib1g-dev libpolly-15-dev +``` + +The version of Rust provided by Debian 11 is also too old, so you'll need to use +[rustup](https://rustup.rs/) to install the required Rust version. + #### Fedora Inko isn't included in the Fedora repositories, but there's an official @@ -181,24 +205,53 @@ sudo dnf copr enable yorickpeterse/inko sudo dnf install inko ``` -When building from source, the compiler requires the following dependencies to -be installed: +For version 38 and newer, the compiler dependencies are installed as follows: ```bash -sudo dnf install gcc make rust cargo llvm15 llvm15-devel llvm15-static libstdc++-devel libstdc++-static libffi-devel zlib-devel git +sudo dnf install gcc make rust cargo llvm15 llvm15-devel llvm15-static \ + libstdc++-devel libstdc++-static libffi-devel zlib-devel git +``` + +For version 37, the compiler dependencies are instead installed as follows (note +the different LLVM package names): + +```bash +sudo dnf install gcc make rust cargo llvm llvm-devel llvm-static \ + libstdc++-devel libstdc++-static libffi-devel zlib-devel git ``` #### Ubuntu There's no official package for Inko in the Ubuntu repositories. -When building from source, the compiler requires the following dependencies to -be installed: +For Ubuntu 22.04, the compiler dependencies are installed as follows: + +```bash +sudo apt-get install --yes rustc cargo git build-essential llvm-15 llvm-15-dev \ + libstdc++-11-dev libclang-common-15-dev zlib1g-dev +``` + +For Ubuntu 20.04, the process is a little different as the provided version of +LLVM is too old. Installing the necessary dependencies is done as follows: ```bash -sudo apt-get install --yes rustc cargo git build-essential llvm-15 llvm-15-dev libstdc++-11-dev libclang-common-15-dev zlib1g-dev +curl https://apt.llvm.org/llvm-snapshot.gpg.key | \ + sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc +sudo add-apt-repository \ + "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-15 main" +sudo apt-get update ``` +Now we can install the necessary dependencies: + +```bash +sudo apt-get install --yes git build-essential llvm-15 llvm-15-dev \ + libstdc++-10-dev libclang-common-15-dev zlib1g-dev libpolly-15-dev +``` + +The version of Rust provided by 20.04 is also too old, so you'll need to use +[rustup](https://rustup.rs/) to install the required Rust version. + ### macOS Inko is available in [Homebrew](https://brew.sh/): @@ -236,11 +289,10 @@ export LIBRARY_PATH="$(brew --prefix llvm@15)/lib" There's no official package for Inko available on FreeBSD. -When building from source, the compiler requires the following dependencies to -be installed: +The compiler dependencies are installed as follows: ```bash -sudo pkg install llvm15 rust +sudo pkg install llvm15 rust git ``` To build from source, run the following command: diff --git a/scripts/deps.sh b/scripts/deps.sh new file mode 100755 index 000000000..62a219880 --- /dev/null +++ b/scripts/deps.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +set -e + +LLVM_VERSION='15' + +function apt_install_llvm { + curl \ + --retry 10 --retry-connrefused --silent --show-error --fail --location \ + https://apt.llvm.org/llvm-snapshot.gpg.key | \ + tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + + add-apt-repository \ + "deb http://apt.llvm.org/${1}/ llvm-toolchain-${1}-${LLVM_VERSION} main" + apt-get update --yes + apt-get install --yes llvm-${LLVM_VERSION} llvm-${LLVM_VERSION}-dev \ + libclang-common-${LLVM_VERSION}-dev libpolly-${LLVM_VERSION}-dev +} + +echo "::group::Installing dependencies" + +if [ "${1}" = "ubuntu:latest" ] +then + apt-get update --yes + apt-get install --yes llvm-${LLVM_VERSION} llvm-${LLVM_VERSION}-dev \ + libstdc++-11-dev libclang-common-${LLVM_VERSION}-dev zlib1g-dev curl \ + build-essential git + +elif [ "${1}" = "ubuntu:20.04" ] +then + apt-get update --yes + apt-get install --yes libstdc++-10-dev zlib1g-dev curl build-essential \ + software-properties-common git + apt_install_llvm focal + +elif [ "${1}" = "debian:latest" ] +then + apt-get update --yes + apt-get install --yes llvm-${LLVM_VERSION} llvm-${LLVM_VERSION}-dev \ + libstdc++-11-dev libclang-common-${LLVM_VERSION}-dev zlib1g-dev curl \ + build-essential git + +elif [ "${1}" = "debian:11" ] +then + apt-get update --yes + apt-get install --yes libstdc++-10-dev zlib1g-dev curl build-essential \ + software-properties-common git + apt_install_llvm bullseye + +elif [ "${1}" = "fedora:37" ] +then + dnf install --assumeyes gcc make tar git \ + llvm llvm-devel llvm-static libstdc++-devel libstdc++-static \ + libffi-devel zlib-devel + +elif [ "${1}" = "fedora:latest" ] +then + dnf install --assumeyes gcc make tar git \ + llvm${LLVM_VERSION} llvm${LLVM_VERSION}-devel \ + llvm${LLVM_VERSION}-static libstdc++-devel libstdc++-static \ + libffi-devel zlib-devel + +elif [ "${1}" = "archlinux:latest" ] +then + pacman -Syu --noconfirm llvm git base-devel curl + +elif [ "${1}" = "mac" ] +then + brew install llvm@${LLVM_VERSION} + echo "$(brew --prefix llvm@${LLVM_VERSION})/bin" >> $GITHUB_PATH +else + echo 'An OS to install dependencies for must be specified' + exit 1 +fi + +echo "::endgroup::" diff --git a/scripts/llvm.sh b/scripts/llvm.sh deleted file mode 100755 index 5ae7c6d5b..000000000 --- a/scripts/llvm.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -set -e - -echo "::group::Installing LLVM" - -if [ "${1}" = "ubuntu" ] -then - # libclang-common is needed because of - # https://gitlab.com/taricorp/llvm-sys.rs/-/issues/16. - sudo apt-get update - sudo apt-get install --yes llvm-15 llvm-15-dev libstdc++-11-dev \ - libclang-common-15-dev zlib1g-dev -elif [ "${1}" = "mac" ] -then - brew install llvm@15 - echo "$(brew --prefix llvm@15)/bin" >> $GITHUB_PATH -else - echo 'An OS to install LLVM for must be specified' - exit 1 -fi - -echo "::endgroup::"