Skip to content

Commit

Permalink
WIP: Tooling to cross-compile Chromium for Windows from Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
iskunk committed Jan 4, 2025
1 parent 58e1c24 commit a658551
Show file tree
Hide file tree
Showing 28 changed files with 2,516 additions and 50 deletions.
133 changes: 133 additions & 0 deletions .github/workflows/build-images.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
name: Build container images for cross build

on:
workflow_dispatch:
inputs:
upload:
type: boolean
description: "Upload to registry"
default: false

env:
# used in cross-build/Makefile
APT_MIRROR: azure.archive.ubuntu.com
IMAGE_SOURCE: ${{github.server_url}}/${{github.repository}}

jobs:
main:
runs-on: ubuntu-24.04
permissions:
# needed to upload container images
packages: write
steps:

- name: Clone u-c-w Git repository
uses: actions/checkout@v4

- name: Clone msvc-wine Git repository
uses: actions/checkout@v4
with:
repository: mstorsjo/msvc-wine
ref: 209623ed118aac0121e63a7e86e467c238516f5a # 20240912
path: cross-build/msvc-wine

- name: Free up disk space
run: cd / && sudo $GITHUB_WORKSPACE/cross-build/gh-unburden.sh

- name: Adjust APT config
run: |
sudo tee /etc/apt/apt.conf.d/95custom << END
# Don't install recommended packages
APT::Install-Recommends "0";
# Don't use "Reading database ... X%" progress indicator
Dpkg::Use-Pty "false";
END
- name: Build base container image
run: |
cd cross-build
make build-image-base \
BUILD_UID=$(id -u) \
MULTI_ARCH=1
- name: Install packages required for extracting the MSVC files
run: sudo apt-get -y install msitools

- name: Restore MSVC download cache
id: restore-msvc
uses: actions/cache/restore@v4
with:
key: msvc-download
path: cross-build/msvc-cache

- name: Build MSVC container image
run: |
cd cross-build
make build-image \
MSVC_ACCEPT_LICENSE=--accept-license \
MULTI_ARCH=1
- name: Save MSVC download cache
if: ${{!steps.restore-msvc.outputs.cache-hit}}
uses: actions/cache/save@v4
with:
key: msvc-download
path: cross-build/msvc-cache

- name: Get date-based version tag for images
id: version
run: |
vtag=$(date '+%Y%m%d')
echo "Image version tag: $vtag"
echo "tag=$vtag" >> $GITHUB_OUTPUT
- name: Log in to GitHub Container Registry
if: inputs.upload
env:
GITHUB_ACTOR: ${{github.actor}}
GITHUB_TOKEN: ${{github.token}}
run: docker login ghcr.io --username $GITHUB_ACTOR --password-stdin <<<$GITHUB_TOKEN

# Note: Ensure that the GitHub repo has "Role: Write" access to
# chromium-win-cross{,-base} under "Package settings -> Manage
# Actions access", or else the "docker push" operation will fail.

- name: Upload base container image to registry
if: inputs.upload
run: |
remote_name=ghcr.io/${{github.repository_owner}}/chromium-win-cross-base
set -x
docker tag chromium-win-cross-base $remote_name:${{steps.version.outputs.tag}}
docker tag chromium-win-cross-base $remote_name:latest
docker push $remote_name:${{steps.version.outputs.tag}}
docker push $remote_name:latest
- name: Upload MSVC container image to registry
if: inputs.upload
run: |
remote_name=ghcr.io/${{github.repository_owner}}/chromium-win-cross
set -x
docker tag chromium-win-cross $remote_name:${{steps.version.outputs.tag}}
docker tag chromium-win-cross $remote_name:latest
docker push $remote_name:${{steps.version.outputs.tag}}
docker push $remote_name:latest
docker logout ghcr.io
- name: Prepare image metadata
run: |
mkdir artifact
set -x
cp -p cross-build/MD5SUMS.rootfs artifact/
cp -p cross-build/winsysroot/.vsdownload/MD5SUMS.cache artifact/MD5SUMS.msvc-cache
cp -p cross-build/winsysroot/.vsdownload/*.manifest.xz artifact/
xz -d artifact/*.xz
docker container run --rm chromium-win-cross dpkg-query --show > artifact/dpkg-packages.txt
- name: Archive image metadata
uses: actions/upload-artifact@v4
with:
name: image-info
compression-level: 9
path: artifact/

# EOF
225 changes: 225 additions & 0 deletions .github/workflows/cross-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
---
name: Cross-build ungoogled-chromium

on:
workflow_dispatch:
inputs:
container_image:
description: Container image for build
default: chromium-win-cross:latest
target-cpu:
description: Target CPU
type: choice
options: [x64, x86, arm64]
default: x64

env:
ZSTD_NBTHREADS: 0

jobs:

stage-1:
runs-on: ubuntu-24.04
container:
image: ghcr.io/${{github.repository_owner}}/${{inputs.container_image}}
options: -v /:/HOST
steps:

- name: Free up disk space
run: cd /HOST && sudo /usr/local/sbin/gh-unburden

- name: Clone u-c-w Git repository
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 50
fetch-tags: true

- name: Get Chromium version info
id: chromium
run: |
version=$(cat ungoogled-chromium/chromium_version.txt)
echo "Chromium version: $version"
echo "version=$version" >> $GITHUB_OUTPUT
- name: Restore Chromium source tarball download cache
id: restore-cache
uses: actions/cache/restore@v4
with:
key: chromium-source-${{steps.chromium.outputs.version}}
path: cross-build/build/download_cache

- name: Download and/or verify Chromium source tarball
run: |
cache=cross-build/build/download_cache
mkdir -p $cache
ungoogled-chromium/utils/downloads.py retrieve \
--ini ungoogled-chromium/downloads.ini \
--cache $cache \
--hide-progress-bar
ls -l $cache
- name: Save Chromium source tarball download cache
if: ${{!steps.restore-cache.outputs.cache-hit}}
uses: actions/cache/save@v4
with:
key: chromium-source-${{steps.chromium.outputs.version}}
path: cross-build/build/download_cache

- name: Prepare the build
run: cd cross-build && ./build.sh --ci --${{inputs.target-cpu}}

- name: Prepare GHCI build strategy
run: |
cd cross-build/build/src/out/Default*
targets=$(cat build.targets)
$GITHUB_WORKSPACE/skunk-tmp/ghci-strategy.sh 8 $targets
- name: Delete the download cache
run: rm -r cross-build/build/download_cache

- name: Stage 1 build (${{inputs.target-cpu}})
run: |
cd cross-build/build/src
ninja -C out/Default* -f ghci-stage1.ninja ghci-stage1
- name: Tar up the workspace
# The "touch" prevents a "tar: .: file changed as we read it" error
run: |
touch stage1.tar.zstd
tar cf stage1.tar.zstd --zstd --exclude=stage1.tar.zstd .
ls -lh stage1.tar.zstd
- name: Save the workspace for stage 2
uses: actions/upload-artifact@v4
with:
name: stage1
compression-level: 0
path: stage1.tar.zstd
if-no-files-found: error
retention-days: 1

stage-2:
needs: [stage-1]
runs-on: ubuntu-24.04
strategy:
matrix:
part: [part1, part2, part3, part4, part5, part6, part7, part8]
container:
image: ghcr.io/${{github.repository_owner}}/${{inputs.container_image}}
options: -v /:/HOST
env:
PART: ${{matrix.part}}
steps:

- name: Free up disk space
run: cd /HOST && sudo /usr/local/sbin/gh-unburden

- name: Download workspace tarball from stage 1
uses: actions/download-artifact@v4
with:
name: stage1

# The find/truncate gets rid of the bulk of redundant files under
# obj/, while keeping them as placeholders to avoid recompilation
- name: Unpack workspace tarball
run: |
tar xf stage1.tar.zstd --zstd
rm stage1.tar.zstd
find cross-build/build/src/out/Default*/obj \
-type f -exec truncate -s 0 {} +
- name: Stage 2 build (${{matrix.part}}, ${{inputs.target-cpu}})
run: |
cd cross-build/build/src
ninja -C out/Default* -f ghci-stage2.ninja $PART
- name: Tar up the partial build tree
run: |
tar cf stage2-$PART.tar.zstd --zstd cross-build/build/src/out/Default*/obj
ls -lh stage2-$PART.tar.zstd
- name: Save the partial tree for stage 3
uses: actions/upload-artifact@v4
with:
name: stage2-${{matrix.part}}
compression-level: 0
path: stage2-${{matrix.part}}.tar.zstd
if-no-files-found: error
retention-days: 1

stage-3:
needs: [stage-2]
runs-on: ubuntu-24.04
container:
image: ghcr.io/${{github.repository_owner}}/${{inputs.container_image}}
options: -v /:/HOST
steps:

- name: Free up disk space
run: cd /HOST && sudo /usr/local/sbin/gh-unburden

- name: Download the workspace and partial build tree tarballs
uses: actions/download-artifact@v4

- name: Unpack the tarballs
run: |
for tarball in \
stage1/stage1.tar.zstd \
stage2-part*/stage2-part*.tar.zstd
do
echo "Unpacking $tarball ..."
tar xf $tarball --zstd --skip-old-files
rm $tarball
done
rmdir stage1 stage2-part*
- name: Stage 3 build (${{inputs.target-cpu}})
run: cd cross-build && ./build.sh --${{inputs.target-cpu}}

- name: Archive build outputs
uses: actions/upload-artifact@v4
with:
name: packages
compression-level: 0
path: cross-build/build/ungoogled-chromium_*
if-no-files-found: error

- name: Archive reproducibility info
uses: actions/upload-artifact@v4
with:
name: reproduce
compression-level: 9
path: cross-build/build/MD5SUMS.repro
if-no-files-found: error

cleanup:
if: always()
needs: [stage-3]
runs-on: ubuntu-24.04
permissions:
actions: write
steps:
- name: Delete temporary artifacts
env:
GH_TOKEN: ${{github.token}}
run: |
gh_api_call()
{
gh api $2 $3 \
-H 'Accept: application/vnd.github+json' \
-H 'X-GitHub-Api-Version: 2022-11-28' \
"/repos/$GITHUB_REPOSITORY/actions/$1"
}
gh_api_call "runs/$GITHUB_RUN_ID/artifacts" \
| jq -r '.artifacts[] | (.id|tostring)+"\t"+.name' \
| grep stage \
> artifacts.txt || true
echo "Found $(wc -l < artifacts.txt) artifact(s) to delete."
while read id name
do
echo "Deleting artifact \"$name\" (id=$id)"
gh_api_call "artifacts/$id" --method DELETE
done < artifacts.txt
# EOF
33 changes: 33 additions & 0 deletions cross-build/Dockerfile.base
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Dockerfile.base

FROM ubuntu:noble

LABEL org.opencontainers.image.description="Base image for building chromium-win-cross"

ARG APT_MIRROR=mirrors.wikimedia.org
ARG BUILD_UID=1024
ARG MULTI_ARCH=

ADD ccache.conf /etc/
ADD gh-unburden.sh /usr/local/sbin/gh-unburden
ADD rootfs-sums.sh /usr/local/sbin/rootfs-sums
ADD rc.cc /usr/local/src/

ADD llvm /opt/llvm

ADD rust /opt/rust

# Most setup is performed in this script
RUN --mount=type=bind,source=base-setup.sh,target=/tmp/base-setup.sh \
sh /tmp/base-setup.sh

# Prevents "error: the option `Z` is only accepted on the nightly compiler"
ENV RUSTC_BOOTSTRAP=1

WORKDIR /home/build
USER build

# Avoid .pyc files as they don't help reproducibility
ENV PYTHONDONTWRITEBYTECODE=y

# end Dockerfile.base
Loading

0 comments on commit a658551

Please sign in to comment.