This repository cross-compiles Windows binaries of ungoogled-chromium on Linux.
Download binaries from the Contributor Binaries website.
Or install using winget install --id=eloston.ungoogled-chromium -e.
Use a tag when building a release. The master branch is for development and may be unstable.
This project builds Windows Chromium binaries on Linux. You need a Linux system (Ubuntu 24.04+ recommended) with at least 80GB free disk space. Install the packages listed in System Dependencies first.
# Clone repository
git clone --recurse-submodules https://github.com/vpday/ungoogled-chromium-windows.git
cd ungoogled-chromium-windows
# Checkout a release tag
git checkout --recurse-submodules TAG_OR_BRANCH_HERE
# Build (this will take several hours)
python3 build.py
# Create distribution packages
python3 package.pyA zip archive and installer will be created under build/.
- Recommended distro: Ubuntu 24.04+, or equivalent
- Build machine architecture: x86_64 (for cross-compiling to Windows x64/x86/arm64)
- Minimum 80GB free space (source tree + build artifacts + build cache)
Install these packages before building:
sudo apt-get update
sudo apt-get install -y \
p7zip-full pkg-config libglib2.0-dev libfuse2 libfuse2t64 \
libnss3-dev libcups2-dev libpci-dev libdrm-dev \
libxkbcommon-dev gperf libkrb5-dev python3 gitFor x86 (32-bit) builds, also install:
sudo dpkg --add-architecture i386
sudo apt-get update
sudo apt-get install -y libc6-dev-i386 linux-libc-dev:i386 \
gcc-multilib g++-multilib libglib2.0-0:i386 libnss3:i386 \
libnspr4:i386 libatk1.0-0:i386 libatk-bridge2.0-0:i386 \
libcups2:i386 libdrm2:i386 libdbus-1-3:i386 libexpat1:i386python3 build.py
python3 package.py# 32-bit Windows build
python3 build.py --x86
# ARM64 Windows build
python3 build.py --arm
# Default: 64-bit Windows build
python3 build.py# Use 16 CPU threads
python3 build.py -j 16
# Enable incremental build (skip completed steps)
python3 build.py --ci
# Use pre-packaged Chromium tarball
python3 build.py --tarballThe --ci flag turns on stamp-based step skipping. Most completed steps are
skipped when their stamp file already exists, which is useful when resuming an
interrupted build or continuing a multi-stage CI run.
If the build fails during source download or the git clone phase, run:
rm -rf build/download_cache
python3 build.pyFor most other failures, run:
# Keep download_cache to avoid re-downloading dependencies
rm -rf build/src
python3 build.pyThis removes build/src/.stamps along with the source tree, which resets most
build steps. build/.stamps is separate and only tracks Windows toolchain
extraction state.
For a full clean rebuild, run:
rm -rf build/
python3 build.pyThe build.py script runs these steps in order. In --ci mode, most step
state is stored in build/src/.stamps. Windows toolchain extraction is the
exception: it uses build/.stamps/.vs_toolchain_updated_{target_arch}.stamp.
That split exists to support GitHub Actions multi-stage builds, where the VS
toolchain setup may need to run at the start of each stage while the other
steps usually only need to run once.
- Clone Chromium source or extract a tarball.
- Download Windows-specific dependencies from
downloads.ini. - Remove unnecessary binaries listed in
pruning.list. - Extract downloaded archives into the source tree.
- Create the installer packaging symlink (
7za→7zz). - Apply patches:
- Conditionally add/remove AVX2 optimization patch based on target architecture
- Apply core ungoogled-chromium patches
- Apply Windows-specific patches
- Replace obfuscated Google domains with real ones.
- Configure Rust for the Linux host and the Windows target.
- Combine
ungoogled-chromium/flags.gnandflags.windows.gn. - Configure the Windows SDK and Visual Studio tools.
- Run the remaining toolchain setup:
- Fix domain references in tool download scripts
- Download rc binary for cross-compilation
- Set up LLVM environment variables
- Build the GN build system.
- Generate Ninja build files.
- Compile
chrome,chromedriver, andmini_installer. - In CI mode,
build.pycallspackage.pyautomatically. For local builds, runpython3 package.pyyourself.
Most of these steps can be skipped when their stamp file already exists, which makes recovery much faster after a failed build.
The CI pipeline is split into four workflows:
.github/workflows/build-x64.yml- x64 build.github/workflows/build-x86.yml- x86 build.github/workflows/build-arm.yml- arm64 build.github/workflows/publish-release.yml- release aggregation and publishing
Each architecture workflow keeps the existing 8-stage recovery chain to work around the 6-hour GitHub Actions job timeout. A failed or retried x64/x86/arm build only requires rerunning that architecture's workflow, while the release remains gated on all three architectures being available for the same tag.
The publish workflow listens for successful architecture builds, finds the latest successful x64/x86/arm runs for the same tag, downloads their final chromium, chromium-x86, and chromium-arm artifacts, and publishes a single GitHub Release once all three are present. If one architecture is still missing, the publish workflow exits without creating a partial release.
See .github/workflows/build-x64.yml, .github/workflows/build-x86.yml, .github/workflows/build-arm.yml, .github/workflows/publish-release.yml, and .github/actions/prepare/action.yml for the complete CI setup.
For quilt-based patch development, see ungoogled-chromium's developing.md.
All dependency versions are defined in downloads.ini. Dependencies are organized into three categories:
- Get the version from
build/src/DEPSby searching forsrc/third_party/llvm-build/Release+Asserts - Check LLVM releases for that version
- Download
LLVM-VERSION-Linux-X64.tar.xz - Get the SHA-256 checksum:
sha256sum LLVM-VERSION-Linux-X64.tar.xz - Update
downloads.inisection[llvm]:version = VERSIONsha256 = CHECKSUM
- Check Ninja releases for the latest version
- Download
ninja-linux.zip - Get SHA-256 checksum and update
downloads.inisection[ninja]:version = VERSIONsha256 = CHECKSUM
- Check 7-Zip releases for Linux x64 builds
- Download
7zVERSION-linux-x64.tar.xz - Get SHA-256 checksum and update
downloads.inisection[7zip-linux]:version = VERSION(e.g.,2501for 25.01)sha256 = CHECKSUM
- Get
NODE_VERSIONfrombuild/src/third_party/node/update_node_binaries - Download
node-vVERSION-linux-x64.tar.xzfrom NodeJS website - Update
downloads.ini[nodejs]with version and SHA-256 checksum
- Get
devtools_frontend_revisionfrombuild/src/DEPS - Visit
https://chromium.googlesource.com/devtools/devtools-frontend/+/REVISION/DEPS - Search for
third_party/esbuildto get version (e.g.,version:3@0.25.1.chromium.2→0.25.1) - Download from npm:
https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-VERSION.tgz - Update
downloads.ini[esbuild]with version and SHA-256 checksum
- Get commit hash from
build/src/DEPSby searching forsrc/third_party/microsoft_dxheaders/src - Update
downloads.ini[directx-headers]withversion = COMMIT_HASH
- Get commit hash from
build/src/DEPSby searching forsrc/third_party/microsoft_webauthn/src - Update
downloads.ini[webauthn]withversion = COMMIT_HASH
The Rust toolchain consists of:
- Linux Rust archives:
rust-x64,rust-x86,rust-arm - Windows targets:
rust-std-windows-x64,rust-std-windows-x86,rust-std-windows-arm(for cross-compilation) - Windows crate:
rust-windows-create(system API bindings)
The build does not download all of them for every target:
- Default
x64:rust-x64,rust-std-windows-x64,rust-windows-create --x86:rust-x64,rust-x86,rust-std-windows-x86,rust-windows-create--arm:rust-x64,rust-arm,rust-std-windows-arm,rust-windows-create
- Check
RUST_REVISIONinbuild/src/tools/rust/update_rust.py
grep RUST_REVISION build/src/tools/rust/update_rust.py-
Get commit date from
https://github.com/rust-lang/rust/commit/RUST_REVISION- Example: Revision
abc123...corresponds to date2026-02-28
- Example: Revision
-
Download
https://static.rust-lang.org/dist/2026-02-28/channel-rust-nightly.toml. Use the matchingxz_hashvalue from that manifest as thesha256you put indownloads.ini. That is the SHA-256 for the.tar.xzarchive, so you do not need to download every Rust archive just to runsha256sum.
Linux Rust archives:
rust-nightly-x86_64-unknown-linux-gnu.tar.xz -> [pkg.rust.target.x86_64-unknown-linux-gnu].xz_hash
rust-nightly-i686-unknown-linux-gnu.tar.xz -> [pkg.rust.target.i686-unknown-linux-gnu].xz_hash
rust-nightly-aarch64-unknown-linux-gnu.tar.xz -> [pkg.rust.target.aarch64-unknown-linux-gnu].xz_hash
Windows targets for cross-compilation:
rust-std-nightly-x86_64-pc-windows-msvc.tar.xz -> [pkg.rust-std.target.x86_64-pc-windows-msvc].xz_hash
rust-std-nightly-i686-pc-windows-msvc.tar.xz -> [pkg.rust-std.target.i686-pc-windows-msvc].xz_hash
rust-std-nightly-aarch64-pc-windows-msvc.tar.xz -> [pkg.rust-std.target.aarch64-pc-windows-msvc].xz_hash
- If you want to verify the nightly version string, download one Linux Rust archive and extract it:
wget https://static.rust-lang.org/dist/2026-02-28/rust-nightly-x86_64-unknown-linux-gnu.tar.xz
tar xf rust-nightly-x86_64-unknown-linux-gnu.tar.xz
./rust-nightly-x86_64-unknown-linux-gnu/rustc/bin/rustc -V
# Output: rustc-1.95.0-nightly-
Update
downloads.inisections:[rust-x64],[rust-x86],[rust-arm]: Updateversionandsha256[rust-std-windows-x64],[rust-std-windows-x86],[rust-std-windows-arm]: Updateversionandsha256
-
Update
patches/ungoogled-chromium/windows/windows-fix-building-with-rust.patch:- Replace the
rustc_versionstring with the nightly version string for that toolchain - Example: Change
rustc_version = ""torustc_version = "rustc-1.95.0-nightly"
- Replace the
- Check version in
build/src/third_party/rust/windows_x86_64_msvc/ - Download from GitHub:
https://github.com/microsoft/windows-rs/archive/refs/tags/VERSION.zip - Get SHA-512 checksum:
sha512sum windows-rs-VERSION.zip- Update
downloads.inisection[rust-windows-create]:version = VERSIONsha512 = CHECKSUM
- If version changed, update
patches/ungoogled-chromium/windows/windows-fix-building-with-rust.patchaccordingly
The Windows cross-compilation toolchain configuration lives in win_toolchain.json. It defines the Visual Studio and Windows SDK packages used for cross-compilation.
Update win_toolchain.json when:
- When Chromium version changes (update
chromium_version) - When Visual Studio or Windows SDK version changes in Chromium upstream
win_toolchain.json has the following fields:
{
"variables": {
"chromium_version": "147.0.7727.101",
"sdk_version": "10.0.26100.0",
"vs_version": "2026",
"repo": "vpday/chromium-win-toolchain-builder"
},
"win-toolchain": {
"zip_filename": "dec826221d",
"sha512": "...",
"files": []
},
"win-toolchain-noarm": {
"zip_filename": "89dbc21abe",
"sha512": "...",
"files": []
}
}Field descriptions:
variables.chromium_version: Must matchungoogled-chromium/chromium_version.txtvariables.sdk_version: Windows SDK versionvariables.vs_version: Visual Studio version yearvariables.repo: Toolchain source repositorywin-toolchain: Full toolchain with ARM support (for arm64 builds)- Split into 2 files (.tar.001, .tar.002) due to GitHub release size limits
win-toolchain-noarm: Lightweight toolchain without ARM support (for x64 and x86 builds)- Single .tar file, faster download
- Check the current Chromium version.
cat ungoogled-chromium/chromium_version.txtUpdate variables.chromium_version in win_toolchain.json to match this version.
- Check for new toolchain releases.
Visit: https://github.com/vpday/chromium-win-toolchain-builder/releases/tag/VERSION
From the release page, collect:
- Tar archives:
win_toolchain_chromium-VERSION_vs-YEAR_sdk-SDK.tar.001/002(with ARM) or...noarm.tar(without ARM) - Zip filenames:
dec826221d.zip(with ARM),89dbc21abe.zip(without ARM) - SHA-256 and SHA-512 checksums for both tar and zip files
- Get zip information from the releases page.
From the release page, copy:
- Zip filename (e.g.,
dec826221d.zipfor full toolchain,89dbc21abe.zipfor noarm) - Zip SHA-512 checksum
Use these values for the zip_filename and sha512 fields in win_toolchain.json.
- Get tar file checksums from the releases page.
From the release page, copy SHA-256 checksums for each tar file:
- Full toolchain: checksums for
.tar.001and.tar.002 - Noarm toolchain: checksum for
.tar
Use these values for the sha256 field in the files[] array in win_toolchain.json.
- Update
win_toolchain.json.
Update variables section:
{
"variables": {
"chromium_version": "147.0.7727.101",
"sdk_version": "10.0.26100.0",
"vs_version": "2026"
}
}Make sure chromium_version matches ungoogled-chromium/chromium_version.txt.
Update win-toolchain and win-toolchain-noarm sections:
zip_filename: from step 3sha512: from step 3files[].sha256: from step 4
This project downloads a complete Windows toolchain (LLVM, Windows SDK, Rust) and builds Windows binaries on Linux. The build works like this:
- Downloads Linux-native build tools (LLVM, Ninja, Node.js)
- Downloads Windows cross-compilation toolchain via
win_toolchain.json - Downloads Rust toolchain (Linux host + Windows targets)
- Configures GN with
target_os = "win"andis_clang = true - Builds using the cross-compilation toolchain
The build system supports three Windows target architectures:
- x64 (default): 64-bit Windows, includes AVX2 optimizations
- x86: 32-bit Windows, requires multilib support on build machine
- arm64: ARM64 Windows
The AVX2 optimization patch is based on work from RobRich999/Chromium_Clang.
For x64 builds, the system automatically applies AVX2 optimizations via
patches/ungoogled-chromium/windows/windows-enable-avx2-optimizations.patch.
This patch is conditionally added to patches/series based on the target
architecture.
See LICENSE