Creating a Rust-Build-Pipeline on Gitlab


GitLab und GitHub bieten eine schöne Möglichkeit seine Projekte gleich zu testen, zu bauen und evtl für den Download zur Verfügung zu stellen.

Da Rust nativen Maschinencode produziert, ist es notwendig für jede unterstützte Plattform zu bauen, die man zum Download anbieten möchte.

In meinem Beispiel habe ich ein Rust Projekt, das ich gerne für X64-Windows und X64-Linux anbieten möchte. Linux ist in dem Fall einfach, da die Build-Container auf den Plattformen meist Linux-Plattformen sind - also man kann einfach mit Bordmitteln bauen.

Der Einfachheit halber habe ich hier mal ein Gitlab-Build-Ci Script:

image: "rust:latest"

before_script:

stages:
- test
- build

build-linux:
  stage: build
  script: cargo build --release
  artifacts:
    paths:
      - "target/release/rust_kontoauszug_importer"
  
test-linux:
  stage: test
  script: cargo test  

Das obige Script führt alle Tests (test Stage) aus und baut anschließend das binary. Leider gibt es hier 2 Probleme

Tests

Die Test-Auswertung von GitLab liest im Normalfall JUnit-Testergebnisse. Daher müssen wir die Test-Reports von Rust/Cargo nach JUnit übersetzen. Bei mir hat cargo2junit am besten funktioniert. Die Testergebnisse werden dann als Artefakte veröffentlicht.

...

test-linux:
  stage: test
  script:
    - cargo install cargo2junit  
    - cargo test -- -Z unstable-options --format json --report-time | cargo2junit > results.xml
  artifacts:
    reports:
      junit: results.xml

Damit werden die Testergebnisse für GitLab lesbar und wir bekommen bessere Auswertungen nach einem Checkin

Windows als Plattform

Dummerweise sind die Anwender der Software meist Windows-Benutzer. Daher ist sogenanntes Cross-Compiling notwendig. Rust bietet von sich aus bereits einen Teil an. rustup target add <plattform> erledigt schon mal einen Teil. Allerdings fehlt meist noch der entsprechende compiler. Für Windows wäre das gcc-mingw-w64-x86-64.

...
build-windows:
  stage: build
  script: 
    - rustup target add x86_64-pc-windows-gnu
    - rustup toolchain install stable-x86_64-pc-windows-gnu
    - apt update
    - apt install gcc-mingw-w64-x86-64 -y
    - cargo build --release --target x86_64-pc-windows-gnu
  artifacts:
    paths:
      - "target/x86_64-pc-windows-gnu/release/rust_kontoauszug_importer.exe"
  

Zusammenfassung

Das gesamte Build-Script sieht dann so aus:

Beispiele für weitere Plattformen wären (alle sieht man rustup target list):

image: "rust:latest"

before_script:

stages:
- test
- build

build-linux:
  stage: build
  script: cargo build --release
  artifacts:
    paths:
      - "target/release/rust_kontoauszug_importer"
  
build-windows:
  stage: build
  script: 
    - rustup target add x86_64-pc-windows-gnu
    - rustup toolchain install stable-x86_64-pc-windows-gnu
    - apt update
    - apt install gcc-mingw-w64-x86-64 -y
    - cargo build --release --target x86_64-pc-windows-gnu
  artifacts:
    paths:
      - "target/x86_64-pc-windows-gnu/release/rust_kontoauszug_importer.exe"
  
test-linux:
  stage: test
  script:
    - cargo install cargo2junit  
    - cargo test -- -Z unstable-options --format json --report-time | cargo2junit > results.xml
  artifacts:
    reports:
      junit: results.xml