diff --git a/pkgs/applications/networking/browsers/chromium/browser.nix b/pkgs/applications/networking/browsers/chromium/browser.nix index f943e3f12606..1e203fc12e75 100644 --- a/pkgs/applications/networking/browsers/chromium/browser.nix +++ b/pkgs/applications/networking/browsers/chromium/browser.nix @@ -6,7 +6,7 @@ mkChromiumDerivation (base: rec { name = "chromium-browser"; packageName = "chromium"; - buildTargets = [ "mksnapshot" "chrome_sandbox" "chrome" ]; + buildTargets = [ "run_mksnapshot_default" "chrome_sandbox" "chrome" ]; outputs = ["out" "sandbox"]; diff --git a/pkgs/applications/networking/browsers/chromium/common.nix b/pkgs/applications/networking/browsers/chromium/common.nix index 183a83f52e8b..f555ab289391 100644 --- a/pkgs/applications/networking/browsers/chromium/common.nix +++ b/pkgs/applications/networking/browsers/chromium/common.nix @@ -1,4 +1,7 @@ { stdenv, lib, fetchurl, fetchpatch +, buildPackages +, pkgsBuildBuild +, pkgsBuildTarget # Channel data: , channel, upstream-info # Helper functions: @@ -8,8 +11,10 @@ , ninja, pkg-config , python3, perl , which -, llvmPackages +, llvmPackages_attrName , rustc +, libuuid +, overrideCC # postPatch: , pkgsBuildHost # configurePhase: @@ -116,6 +121,33 @@ let inherit (upstream-info.deps.ungoogled-patches) rev sha256; }; + # There currently isn't a (much) more concise way to get a stdenv + # that uses lld as its linker without bootstrapping pkgsLLVM; see + # https://github.com/NixOS/nixpkgs/issues/142901 + buildPlatformLlvmStdenv = + let + llvmPackages = pkgsBuildBuild.${llvmPackages_attrName}; + in + overrideCC llvmPackages.stdenv + (llvmPackages.stdenv.cc.override { + inherit (llvmPackages) bintools; + }); + + chromiumRosettaStone = { + cpu = platform: + let name = platform.parsed.cpu.name; + in ({ "x86_64" = "x64"; + "i686" = "x86"; + "arm" = "arm"; + "aarch64" = "arm64"; + }.${platform.parsed.cpu.name} + or (throw "no chromium Rosetta Stone entry for cpu: ${name}")); + os = platform: + if platform.isLinux + then "linux" + else throw "no chromium Rosetta Stone entry for os: ${platform.config}"; + }; + base = rec { pname = "${packageName}-unwrapped"; inherit (upstream-info) version; @@ -130,16 +162,35 @@ let ninja pkg-config python3WithPackages perl which - llvmPackages.bintools + buildPackages.${llvmPackages_attrName}.bintools bison gperf ]; + depsBuildBuild = [ + buildPlatformLlvmStdenv + buildPlatformLlvmStdenv.cc + pkg-config + libuuid + libpng # needed for "host/generate_colors_info" + ] + # When cross-compiling, chromium builds a huge proportion of its + # components for both the `buildPlatform` (which it calls + # `host`) as well as for the `hostPlatform` -- easily more than + # half of the dependencies are needed here. To avoid having to + # maintain a separate list of buildPlatform-dependencies, we + # simply throw in the kitchen sink. + ++ buildInputs + ; + buildInputs = [ (libpng.override { apngSupport = false; }) # https://bugs.chromium.org/p/chromium/issues/detail?id=752403 bzip2 flac speex opusWithCustomModes libevent expat libjpeg snappy libcap - xdg-utils minizip libwebp + ] ++ lib.optionals (!xdg-utils.meta.broken) [ + xdg-utils + ] ++ [ + minizip libwebp libusb1 re2 ffmpeg libxslt libxml2 nasm @@ -162,6 +213,7 @@ let ++ lib.optional pulseSupport libpulseaudio; patches = [ + ./cross-compile.patch # Optional patch to use SOURCE_DATE_EPOCH in compute_build_timestamp.py (should be upstreamed): ./patches/no-build-timestamps.patch # For bundling Widevine (DRM), might be replaceable via bundle_widevine_cdm=true in gnFlags: @@ -225,6 +277,7 @@ let '/usr/share/locale/' \ '${glibc}/share/locale/' + '' + lib.optionalString (!xdg-utils.meta.broken) '' sed -i -e 's@"\(#!\)\?.*xdg-@"\1${xdg-utils}/bin/xdg-@' \ chrome/browser/shell_integration_linux.cc @@ -268,9 +321,27 @@ let # weaken or disable security measures like sandboxing or ASLR): is_official_build = true; disable_fieldtrial_testing_config = true; + + # note: chromium calls buildPlatform "host" and calls hostPlatform "target" + host_cpu = chromiumRosettaStone.cpu stdenv.buildPlatform; + host_os = chromiumRosettaStone.os stdenv.buildPlatform; + target_cpu = chromiumRosettaStone.cpu stdenv.hostPlatform; + v8_target_cpu = chromiumRosettaStone.cpu stdenv.hostPlatform; + target_os = chromiumRosettaStone.os stdenv.hostPlatform; + # Build Chromium using the system toolchain (for Linux distributions): + # + # What you would expect to be caled "target_toolchain" is + # actually called either "default_toolchain" or "custom_toolchain", + # depending on which part of the codebase you are in; see: + # https://github.com/chromium/chromium/blob/d36462cc9279464395aea5e65d0893d76444a296/build/config/BUILDCONFIG.gn#L17-L44 custom_toolchain = "//build/toolchain/linux/unbundle:default"; - host_toolchain = "//build/toolchain/linux/unbundle:default"; + host_toolchain = "//build/toolchain/linux/unbundle:host"; + v8_snapshot_toolchain = "//build/toolchain/linux/unbundle:host"; + + host_pkg_config = "${pkgsBuildBuild.pkg-config}/bin/pkg-config"; + pkg_config = "${pkgsBuildHost.pkg-config}/bin/${stdenv.cc.targetPrefix}pkg-config"; + # Don't build against a sysroot image downloaded from Cloud Storage: use_sysroot = false; # Because we use a different toolchain / compiler version: @@ -304,7 +375,7 @@ let rtc_use_pipewire = true; # Disable PGO because the profile data requires a newer compiler version (LLVM 14 isn't sufficient): chrome_pgo_phase = 0; - clang_base_path = "${llvmPackages.stdenv.cc}"; + clang_base_path = "${pkgsBuildTarget.${llvmPackages_attrName}.stdenv.cc}"; use_qt = false; # To fix the build as we don't provide libffi_pic.a # (ld.lld: error: unable to find library -l:libffi_pic.a): @@ -313,6 +384,9 @@ let # We do intentionally not set rustc_version as nixpkgs will never do incremental # rebuilds, thus leaving this empty is fine. rust_sysroot_absolute = "${rustc}"; + } // lib.optionalAttrs (!(stdenv.buildPlatform.canExecute stdenv.hostPlatform)) { + # https://www.mail-archive.com/v8-users@googlegroups.com/msg14528.html + arm_control_flow_integrity = "none"; } // lib.optionalAttrs proprietaryCodecs { # enable support for the H.264 codec proprietary_codecs = true; @@ -342,6 +416,11 @@ let # our Clang is always older than Chromium's and the build logs have a size # of approx. 25 MB without this option (and this saves e.g. 66 %). env.NIX_CFLAGS_COMPILE = "-Wno-unknown-warning-option"; + env.BUILD_CC = "$CC_FOR_BUILD"; + env.BUILD_CXX = "$CXX_FOR_BUILD"; + env.BUILD_AR = "$AR_FOR_BUILD"; + env.BUILD_NM = "$NM_FOR_BUILD"; + env.BUILD_READELF = "$READELF_FOR_BUILD"; buildPhase = let buildCommand = target: '' diff --git a/pkgs/applications/networking/browsers/chromium/cross-compile.patch b/pkgs/applications/networking/browsers/chromium/cross-compile.patch new file mode 100644 index 000000000000..7df73299bc43 --- /dev/null +++ b/pkgs/applications/networking/browsers/chromium/cross-compile.patch @@ -0,0 +1,31 @@ +diff --git a/build/toolchain/linux/unbundle/BUILD.gn b/build/toolchain/linux/unbundle/BUILD.gn +index a091491236bb1..d36fd4e652fbf 100644 +--- a/build/toolchain/linux/unbundle/BUILD.gn ++++ b/build/toolchain/linux/unbundle/BUILD.gn +@@ -9,6 +9,7 @@ gcc_toolchain("default") { + cxx = getenv("CXX") + ar = getenv("AR") + nm = getenv("NM") ++ readelf = getenv("READELF") + ld = cxx + + extra_cflags = getenv("CFLAGS") +@@ -27,6 +28,7 @@ gcc_toolchain("host") { + cxx = getenv("BUILD_CXX") + ar = getenv("BUILD_AR") + nm = getenv("BUILD_NM") ++ readelf = getenv("BUILD_READELF") + ld = cxx + + extra_cflags = getenv("BUILD_CFLAGS") +@@ -35,7 +37,8 @@ gcc_toolchain("host") { + extra_ldflags = getenv("BUILD_LDFLAGS") + + toolchain_args = { +- current_cpu = current_cpu +- current_os = current_os ++ current_cpu = host_cpu ++ current_os = host_os ++ v8_current_cpu = target_cpu + } + } diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix index 03b432d19421..6419fa6a14fd 100644 --- a/pkgs/applications/networking/browsers/chromium/default.nix +++ b/pkgs/applications/networking/browsers/chromium/default.nix @@ -16,11 +16,17 @@ , cupsSupport ? true , pulseSupport ? config.pulseaudio or stdenv.isLinux , commandLineArgs ? "" +, pkgsBuildTarget +, pkgsBuildBuild +, pkgs }: let - llvmPackages = llvmPackages_16; - stdenv = llvmPackages.stdenv; + # Sometimes we access `llvmPackages` via `pkgs`, and other times + # via `pkgsFooBar`, so a string (attrname) is the only way to have + # a single point of control over the LLVM version used. + llvmPackages_attrName = "llvmPackages_16"; + stdenv = pkgs.${llvmPackages_attrName}.stdenv; upstream-info = (import ./upstream-info.nix).${channel}; @@ -42,7 +48,7 @@ let callPackage = newScope chromium; chromium = rec { - inherit stdenv llvmPackages upstream-info; + inherit stdenv llvmPackages_attrName upstream-info; mkChromiumDerivation = callPackage ./common.nix ({ inherit channel chromiumVersionAtLeast versionRange; @@ -60,7 +66,12 @@ let inherit channel chromiumVersionAtLeast enableWideVine ungoogled; }; - ungoogled-chromium = callPackage ./ungoogled.nix {}; + # ungoogled-chromium is, contrary to its name, not a build of + # chromium. It is a patched copy of chromium's *source code*. + # Therefore, it needs to come from buildPackages, because it + # contains python scripts which get /nix/store/.../bin/python3 + # patched into their shebangs. + ungoogled-chromium = pkgsBuildBuild.callPackage ./ungoogled.nix {}; }; pkgSuffix = if channel == "dev" then "unstable" else @@ -209,8 +220,10 @@ in stdenv.mkDerivation { export XDG_DATA_DIRS=$XDG_ICON_DIRS:$GSETTINGS_SCHEMAS_PATH\''${XDG_DATA_DIRS:+:}\$XDG_DATA_DIRS + '' + lib.optionalString (!xdg-utils.meta.broken) '' # Mainly for xdg-open but also other xdg-* tools (this is only a fallback; \$PATH is suffixed so that other implementations can be used): export PATH="\$PATH\''${PATH:+:}${xdg-utils}/bin" + '' + '' . w