From 84ada07d731fc43c854d38220e59556d4bddb5af Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Fri, 7 Apr 2023 00:03:43 -0700 Subject: [PATCH 1/6] xdg-utils: mark broken if cross --- pkgs/tools/X11/xdg-utils/default.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/tools/X11/xdg-utils/default.nix b/pkgs/tools/X11/xdg-utils/default.nix index 49a8269b8d4..35557ce447f 100644 --- a/pkgs/tools/X11/xdg-utils/default.nix +++ b/pkgs/tools/X11/xdg-utils/default.nix @@ -83,5 +83,6 @@ stdenv.mkDerivation rec { license = if mimiSupport then licenses.gpl2 else licenses.free; maintainers = [ maintainers.eelco ]; platforms = platforms.all; + broken = !(stdenv.buildPlatform.canExecute stdenv.hostPlatform); }; } From 758bf4cb8a7cf53eb0695e7bc28fc7f8820b2489 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Fri, 7 Apr 2023 00:16:36 -0700 Subject: [PATCH 2/6] chromium: late-bind xdg-utils if broken xdg-utils does not cross-compile. Let's late-bind (using the runtime $PATH) in this scenario so a native-built xdg-utils can be used instead. --- pkgs/applications/networking/browsers/chromium/common.nix | 6 +++++- pkgs/applications/networking/browsers/chromium/default.nix | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/applications/networking/browsers/chromium/common.nix b/pkgs/applications/networking/browsers/chromium/common.nix index 36e25939962..4cd7eb485bc 100644 --- a/pkgs/applications/networking/browsers/chromium/common.nix +++ b/pkgs/applications/networking/browsers/chromium/common.nix @@ -139,7 +139,10 @@ let 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 @@ -225,6 +228,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 diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix index 3b4826930ec..5e65f7f817c 100644 --- a/pkgs/applications/networking/browsers/chromium/default.nix +++ b/pkgs/applications/networking/browsers/chromium/default.nix @@ -213,8 +213,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 From c25897c1f327ebba6f73ef7ed6b9b6c93a2f3101 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Sat, 22 Apr 2023 18:26:11 -0700 Subject: [PATCH 3/6] chromium: take llvmPackages from pkgsBuildTarget `llvmPackages.clang` is used in the `gnFlags` attrset, so we need to indicate explicitly which "on" platform (the build) and which "for" platform (the host) we want. This commit does that. --- pkgs/applications/networking/browsers/chromium/default.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix index 5e65f7f817c..cb77883601c 100644 --- a/pkgs/applications/networking/browsers/chromium/default.nix +++ b/pkgs/applications/networking/browsers/chromium/default.nix @@ -16,10 +16,11 @@ , cupsSupport ? true , pulseSupport ? config.pulseaudio or stdenv.isLinux , commandLineArgs ? "" +, pkgsBuildTarget }: let - llvmPackages = llvmPackages_16; + llvmPackages = pkgsBuildTarget.llvmPackages_16; stdenv = llvmPackages.stdenv; upstream-info = (lib.importJSON ./upstream-info.json).${channel}; From 53af611dd20722f52302fc9efc298eb46684093c Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Sat, 22 Apr 2023 16:22:56 -0700 Subject: [PATCH 4/6] chromium: invoke ungoogled-chromium via buildPackages 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 pkgsBuildBuild, because it contains python scripts which get /nix/store/.../bin/python3 patched into their shebangs. --- .../applications/networking/browsers/chromium/default.nix | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix index cb77883601c..d39b52809ed 100644 --- a/pkgs/applications/networking/browsers/chromium/default.nix +++ b/pkgs/applications/networking/browsers/chromium/default.nix @@ -17,6 +17,7 @@ , pulseSupport ? config.pulseaudio or stdenv.isLinux , commandLineArgs ? "" , pkgsBuildTarget +, pkgsBuildBuild }: let @@ -61,7 +62,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 From 5f3c644b1ad7b73de1888177cea86b44513fb670 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Sun, 23 Apr 2023 16:01:56 -0700 Subject: [PATCH 5/6] chromium: control llvmPackages version selection with a string Sometimes we access `llvmPackages` via `pkgs`, and other times via `pkgsFooBar`, so unfortunately a string (attrname) is the only way to have a single point of control over the LLVM version used for both buildPlatform and hostPlatform. --- .../networking/browsers/chromium/common.nix | 9 ++++++--- .../networking/browsers/chromium/default.nix | 10 +++++++--- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pkgs/applications/networking/browsers/chromium/common.nix b/pkgs/applications/networking/browsers/chromium/common.nix index 4cd7eb485bc..4be1512a6c2 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,7 +11,7 @@ , ninja, pkg-config , python3, perl , which -, llvmPackages +, llvmPackages_attrName , rustc # postPatch: , pkgsBuildHost @@ -130,7 +133,7 @@ let ninja pkg-config python3WithPackages perl which - llvmPackages.bintools + buildPackages.${llvmPackages_attrName}.bintools bison gperf ]; @@ -308,7 +311,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): diff --git a/pkgs/applications/networking/browsers/chromium/default.nix b/pkgs/applications/networking/browsers/chromium/default.nix index d39b52809ed..45327783f0b 100644 --- a/pkgs/applications/networking/browsers/chromium/default.nix +++ b/pkgs/applications/networking/browsers/chromium/default.nix @@ -18,11 +18,15 @@ , commandLineArgs ? "" , pkgsBuildTarget , pkgsBuildBuild +, pkgs }: let - llvmPackages = pkgsBuildTarget.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 = (lib.importJSON ./upstream-info.json).${channel}; @@ -44,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; From 0a05fbb9a010337454b942011bfa92168b2efc17 Mon Sep 17 00:00:00 2001 From: Adam Joseph Date: Sat, 22 Apr 2023 16:18:16 -0700 Subject: [PATCH 6/6] chromium: cross compilation support This commit successfully cross-compiles chromium from buildPlatform=x86_64-linux to hostPlatform=aarch64-linux. Other PRs in this project (can be reviewed/merged independently of this one): - https://github.com/NixOS/nixpkgs/pull/227707 - https://github.com/NixOS/nixpkgs/pull/227708 - https://github.com/NixOS/nixpkgs/pull/227710 - https://github.com/NixOS/nixpkgs/pull/227719 - https://github.com/NixOS/nixpkgs/pull/227720 - https://github.com/NixOS/nixpkgs/pull/227722 - https://github.com/NixOS/nixpkgs/pull/227723 --- .../networking/browsers/chromium/browser.nix | 2 +- .../networking/browsers/chromium/common.nix | 74 ++++++++++++++++++- .../browsers/chromium/cross-compile.patch | 31 ++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) create mode 100644 pkgs/applications/networking/browsers/chromium/cross-compile.patch diff --git a/pkgs/applications/networking/browsers/chromium/browser.nix b/pkgs/applications/networking/browsers/chromium/browser.nix index 7678d87ccff..826d29adeb0 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 4be1512a6c2..13d96f1e295 100644 --- a/pkgs/applications/networking/browsers/chromium/common.nix +++ b/pkgs/applications/networking/browsers/chromium/common.nix @@ -13,6 +13,8 @@ , which , llvmPackages_attrName , rustc +, libuuid +, overrideCC # postPatch: , pkgsBuildHost # configurePhase: @@ -119,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; @@ -137,6 +166,22 @@ let 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 @@ -168,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: @@ -275,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: @@ -321,6 +385,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; @@ -350,6 +417,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 00000000000..7df73299bc4 --- /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 + } + }