Files
camoufox/multibuild.py
T
daijro fb6d475fd3 Drop Linux i686 support for future releases
Firefox 32-bit Linux Support ended in 2026. This change removes it from the workflow
https://blog.mozilla.org/futurereleases/2025/09/05/firefox-32-bit-linux-support-to-end-in-2026/
2026-07-15 14:20:46 -05:00

176 lines
4.9 KiB
Python

"""
Easy build CLI for Camoufox
options:
-h, --help show this help message and exit
--target {linux,windows,macos} [{linux,windows,macos} ...]
Target platforms to build
--arch {x86_64,arm64,i686} [{x86_64,arm64,i686} ...]
Target architectures to build for each platform
--bootstrap Bootstrap the build system
--clean Clean the build directory before starting
Example:
$ python3 multibuild.py --target linux windows macos --arch x86_64 arm64
Since Camoufox is NOT meant to be used as a daily driver, no installers are provided.
"""
import argparse
import glob
import os
from pathlib import Path
import sys
from dataclasses import dataclass
from typing import List
import shutil
# Constants
AVAILABLE_TARGETS = ["linux", "windows", "macos"]
AVAILABLE_ARCHS = ["x86_64", "arm64", "i686"]
def setup_linux_sysroots():
"""
Set up symlinks required for Linux cross-compilation.
The sysroots may be missing the libsqlite3.so symlink needed for linking.
"""
mozbuild = Path.home() / '.mozbuild'
sysroots = [
('sysroot-aarch64-linux-gnu', 'aarch64-linux-gnu'),
('sysroot-x86_64-linux-gnu', 'x86_64-linux-gnu'),
]
for sysroot_name, lib_arch in sysroots:
sysroot_lib = mozbuild / sysroot_name / 'usr' / 'lib' / lib_arch
sqlite_so = sysroot_lib / 'libsqlite3.so'
sqlite_so_0 = sysroot_lib / 'libsqlite3.so.0'
if sysroot_lib.exists() and sqlite_so_0.exists() and not sqlite_so.exists():
print(f"Creating libsqlite3.so symlink in {sysroot_lib}")
sqlite_so.symlink_to('libsqlite3.so.0')
def run(cmd, exit_on_fail=True):
print(f'\n------------\n{cmd}\n------------\n')
retval = os.system(cmd)
if retval != 0 and exit_on_fail:
print(f"fatal error: command '{cmd}' failed")
sys.exit(1)
return retval
@dataclass
class BSYS:
target: str
arch: str
@staticmethod
def bootstrap():
"""Bootstrap the build system"""
run('make bootstrap')
@staticmethod
def generate_assets_car():
"""Generate Assets.car for macOS builds"""
run('make generate-assets-car')
def build(self):
"""Build the Camoufox source code"""
os.environ['BUILD_TARGET'] = f'{self.target},{self.arch}'
run('make build')
def package(self):
"""Package the Camoufox source code"""
run(f'make package-{self.target} arch={self.arch}')
def update_target(self):
"""Change the build target"""
os.environ['BUILD_TARGET'] = f'{self.target},{self.arch}'
run('make set-target')
@property
def assets(self) -> List[str]:
"""Get the list of assets"""
package_pattern = f'camoufox-*-{self.target[:3]}.{self.arch}.zip'
return glob.glob(package_pattern)
@staticmethod
def clean():
"""Clean the Camoufox directory"""
run('make clean')
def run_build(target, arch):
"""
Run the build for the given target and architecture
"""
builder = BSYS(target, arch)
builder.update_target()
# Run build
builder.build()
# Run package
builder.package()
# Move assets to dist
print('Assets:', ', '.join(builder.assets))
for asset in builder.assets:
shutil.move(asset, f'dist/{asset}')
def main():
parser = argparse.ArgumentParser(description="Easy build CLI for Camoufox")
parser.add_argument(
"--target",
choices=AVAILABLE_TARGETS,
nargs='+',
required=True,
help="Target platform for the build",
)
parser.add_argument(
"--arch",
choices=AVAILABLE_ARCHS,
nargs='+',
required=True,
help="Target architecture for the build",
)
parser.add_argument("--bootstrap", action="store_true", help="Bootstrap the build system")
parser.add_argument(
"--clean", action="store_true", help="Clean the build directory before starting"
)
args = parser.parse_args()
# Run bootstrap if requested
if args.bootstrap:
BSYS.bootstrap()
# Clean if requested
if args.clean:
BSYS.clean()
# Generate Assets.car if building for macOS
if 'macos' in args.target:
BSYS.generate_assets_car()
run('make setup-macos-sdk')
# Ensure dist directory exists
os.makedirs('dist', exist_ok=True)
# Set up Linux sysroot symlinks if needed
if 'linux' in args.target:
setup_linux_sysroots()
# Run build
for target in args.target:
for arch in args.arch:
if (target, arch) in [
("windows", "arm64"),
("macos", "i686"),
("linux", "i686"),
]:
print(f"Skipping {target} {arch}: Unsupported architecture.")
continue
run_build(target, arch)
if __name__ == "__main__":
main()