Unverified Commit 90968171 authored by Maciej Krüger's avatar Maciej Krüger Committed by GitHub
Browse files

Merge pull request #201027 from hacker1024/patch-3

parents 19964a24 f7af9373
Loading
Loading
Loading
Loading
+5 −10
Original line number Diff line number Diff line
@@ -2,19 +2,13 @@
, flutter
, python3
, fetchFromGitHub
, stdenv
, pcre2
, gnome
, makeWrapper
, removeReferencesTo
}:
let
  vendorHashes = {
    x86_64-linux = "sha256-Upe0cEDG02RJD50Ht9VNMwkelsJHX8zOuJZssAhMuMY=";
    aarch64-linux = "sha256-lKER4+gcyFqnCvgBl/qdVBCbUpocWUnXGLXsX82MSy4=";
  };
in
flutter.mkFlutterApp rec {

flutter.buildFlutterApplication rec {
  pname = "yubioath-flutter";
  version = "6.1.0";

@@ -27,7 +21,8 @@ flutter.mkFlutterApp rec {

  passthru.helper = python3.pkgs.callPackage ./helper.nix { inherit src version meta; };

  vendorHash = vendorHashes.${stdenv.system};
  depsListFile = ./deps.json;
  vendorHash = "sha256-WfZiB7MO4wHUg81xm67BMu4zQdC9CfhN5BQol+AI2S8=";

  postPatch = ''
    substituteInPlace linux/CMakeLists.txt \
@@ -89,6 +84,6 @@ flutter.mkFlutterApp rec {
    homepage = "https://github.com/Yubico/yubioath-flutter";
    license = licenses.asl20;
    maintainers = with maintainers; [ lukegb ];
    platforms = builtins.attrNames vendorHashes;
    platforms = [ "x86_64-linux" "aarch64-linux" ];
  };
}
+1319 −0

File added.

Preview size limit exceeded, changes collapsed.

+186 −0
Original line number Diff line number Diff line
{ stdenvNoCC
, lib
, makeSetupHook
, dart
, git
, cacert
, jq
}:

{
  # The output hash of the dependencies for this project.
  vendorHash ? ""
  # Commands to run once before using Dart or pub.
, sdkSetupScript ? ""
  # Commands to run to populate the pub cache.
, pubGetScript ? "dart pub get"
  # A path to a pubspec.lock file to use instead of the one in the source directory.
, pubspecLockFile ? null
  # Arguments used in the derivation that builds the Dart package.
  # Passing these is recommended to ensure that the same steps are made to prepare the sources in both this
  # derivation and the one that builds the Dart package.
, buildDrvArgs ? { }
, ...
}@args:

# This is a fixed-output derivation and setup hook that can be used to fetch dependencies for Dart projects.
# It is designed to be placed in the nativeBuildInputs of a derivation that builds a Dart package.
# Providing the buildDrvArgs argument is highly recommended.
let
  buildDrvInheritArgNames = [
    "name"
    "pname"
    "version"
    "src"
    "sourceRoot"
    "setSourceRoot"
    "preUnpack"
    "unpackPhase"
    "unpackCmd"
    "postUnpack"
    "prePatch"
    "patchPhase"
    "patches"
    "patchFlags"
    "postPatch"
  ];

  buildDrvInheritArgs = builtins.foldl'
    (attrs: arg:
      if buildDrvArgs ? ${arg}
      then attrs // { ${arg} = buildDrvArgs.${arg}; }
      else attrs)
    { }
    buildDrvInheritArgNames;

  drvArgs = buildDrvInheritArgs // (removeAttrs args [ "buildDrvArgs" ]);
  name = (if drvArgs ? name then drvArgs.name else "${drvArgs.pname}-${drvArgs.version}");

  deps =
    stdenvNoCC.mkDerivation ({
      name = "${name}-dart-deps";

      nativeBuildInputs = [
        dart
        git
      ];

      # avoid pub phase
      dontBuild = true;

      configurePhase = ''
        # Configure the package cache
        export PUB_CACHE="$out/cache/.pub-cache"
        mkdir -p "$PUB_CACHE"

        ${sdkSetupScript}
      '';

      installPhase = ''
        _pub_get() {
          ${pubGetScript}
        }

        # so we can use lock, diff yaml
        mkdir -p "$out/pubspec"
        cp "pubspec.yaml" "$out/pubspec"
        ${lib.optionalString (pubspecLockFile != null) "install -m644 ${pubspecLockFile} pubspec.lock"}
        if ! cp "pubspec.lock" "$out/pubspec"; then
          echo 1>&2 -e '\nThe pubspec.lock file is missing. This is a requirement for reproducible builds.' \
                       '\nThe following steps should be taken to fix this issue:' \
                       '\n  1. If you are building an application, contact the developer(s).' \
                       '\n     The pubspec.lock file should be provided with the source code.' \
                       '\n     https://dart.dev/guides/libraries/private-files#pubspeclock' \
                       '\n  2. An attempt to generate and print a compressed pubspec.lock file will be made now.' \
                       '\n     It is compressed with gzip and base64 encoded.' \
                       '\n     Paste it to a file and extract it with `base64 -d pubspec.lock.in | gzip -d > pubspec.lock`.' \
                       '\n     Provide the path to the pubspec.lock file in the pubspecLockFile argument.' \
                       '\n     This must be updated whenever the application is updated.' \
                       '\n'
          _pub_get
          echo ""
          gzip --to-stdout --best pubspec.lock | base64 1>&2
          echo 1>&2 -e '\nA gzipped pubspec.lock file has been printed. Please see the informational message above.'
          exit 1
        fi

        _pub_get

        # nuke nondeterminism

        # Remove Git directories in the Git package cache - these are rarely used by Pub,
        # which instead maintains a corresponsing mirror and clones cached packages through it.
        #
        # An exception is made to keep .git/pub-packages files, which are important.
        # https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L621
        if [ -d "$PUB_CACHE"/git ]; then
          find "$PUB_CACHE"/git -maxdepth 4 -path "*/.git/*" ! -name "pub-packages" -prune -exec rm -rf {} +
        fi

        # Remove continuously updated package metadata caches
        rm -rf "$PUB_CACHE"/hosted/*/.cache # Not pinned by pubspec.lock
        rm -rf "$PUB_CACHE"/git/cache/*/* # Recreate this on the other end. See: https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L531

        # Miscelaneous transient package cache files
        rm -f "$PUB_CACHE"/README.md # May change with different Dart versions
        rm -rf "$PUB_CACHE"/_temp # https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/system_cache.dart#L131
        rm -rf "$PUB_CACHE"/log # https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/command.dart#L348
      '';

      GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
      SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";

      impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
        "GIT_PROXY_COMMAND"
        "NIX_GIT_SSL_CAINFO"
        "SOCKS_SERVER"
      ];

      # Patching shebangs introduces input references to this fixed-output derivation.
      # This triggers a bug in Nix, causing the output path to change unexpectedly.
      # https://github.com/NixOS/nix/issues/6660
      dontPatchShebangs = true;

      # The following operations are not generally useful for this derivation.
      # If a package does contain some native components used at build time,
      # please file an issue.
      dontStrip = true;
      dontMoveSbin = true;
      dontPatchELF = true;

      outputHashAlgo = "sha256";
      outputHashMode = "recursive";
      outputHash = if vendorHash != "" then vendorHash else lib.fakeSha256;
    } // (removeAttrs drvArgs [ "name" "pname" ]));

  depsListDrv = stdenvNoCC.mkDerivation ({
    name = "${name}-dart-deps-list.json";
    nativeBuildInputs = [ hook dart jq ];

    configurePhase = ''
      runHook preConfigure
      dart pub get --offline
      runHook postConfigure
    '';

    buildPhase = ''
      runHook preBuild
      dart pub deps --json | jq .packages > $out
      runHook postBuild
    '';
  } // buildDrvInheritArgs);

  hook = (makeSetupHook {
    # The setup hook should not be part of the fixed-output derivation.
    # Updates to the hook script should not change vendor hashes, and it won't
    # work at all anyway due to https://github.com/NixOS/nix/issues/6660.
    name = "${name}-dart-deps-setup-hook";
    substitutions = { inherit deps; };
    propagatedBuildInputs = [ dart git ];
    passthru = {
      files = deps.outPath;
      depsListFile = depsListDrv.outPath;
    };
  }) ./setup-hook.sh;
in
hook
+41 −0
Original line number Diff line number Diff line
preConfigureHooks+=(_setupPubCache)

_setupPubCache() {
    deps="@deps@"

    # Configure the package cache.
    export PUB_CACHE="$(mktemp -d)"
    mkdir -p "$PUB_CACHE"

    if [ -d "$deps/cache/.pub-cache/git" ]; then
        # Link the Git package cache.
        mkdir -p "$PUB_CACHE/git"
        ln -s "$deps/cache/.pub-cache/git"/* "$PUB_CACHE/git"

        # Recreate the internal Git cache subdirectory.
        # See: https://github.com/dart-lang/pub/blob/c890afa1d65b340fa59308172029680c2f8b0fc6/lib/src/source/git.dart#L339)
        # Blank repositories are created instead of attempting to match the cache mirrors to checkouts.
        # This is not an issue, as pub does not need the mirrors in the Flutter build process.
        rm "$PUB_CACHE/git/cache" && mkdir "$PUB_CACHE/git/cache"
        for mirror in $(ls -A "$deps/cache/.pub-cache/git/cache"); do
            git --git-dir="$PUB_CACHE/git/cache/$mirror" init --bare --quiet
        done
    fi

    # Link the remaining package cache directories.
    # At this point, any subdirectories that must be writable must have been taken care of.
    for file in $(comm -23 <(ls -A "$deps/cache/.pub-cache") <(ls -A "$PUB_CACHE")); do
        ln -s "$deps/cache/.pub-cache/$file" "$PUB_CACHE/$file"
    done

    # ensure we're using a lockfile for the right package version
    if [ ! -e pubspec.lock ]; then
        cp -v "$deps/pubspec/pubspec.lock" .
        # Sometimes the pubspec.lock will get opened in write mode, even when offline.
        chmod u+w pubspec.lock
    elif ! { diff -u pubspec.lock "$deps/pubspec/pubspec.lock" && diff -u pubspec.yaml "$deps/pubspec/pubspec.yaml"; }; then
        echo 1>&2 -e 'The pubspec.lock or pubspec.yaml of the project derivation differs from the one in the dependency derivation.' \
                   '\nYou most likely forgot to update the vendorHash while updating the sources.'
        exit 1
    fi
}
+127 −252
Original line number Diff line number Diff line
{ flutter
, lib
, llvmPackages_13
, cmake
, ninja
, pkg-config
, wrapGAppsHook
, autoPatchelfHook
, util-linux
, libselinux
, libsepol
, libthai
, libdatrie
, libxkbcommon
, at-spi2-core
, libsecret
, jsoncpp
, xorg
, dbus
, gtk3
, glib
, pcre
, libepoxy
{ lib
, callPackage
, stdenvNoCC
, makeWrapper
, llvmPackages_13
, cacert
, git
, dart
, nukeReferences
, bash
, curl
, unzip
, which
, xz
, flutter
, jq
}:

# absolutely no mac support for now

args:
{ pubGetScript ? "flutter pub get"
, flutterBuildFlags ? [ ]
, runtimeDependencies ? [ ]
, customPackageOverrides ? { }
, autoDepsList ? false
, depsListFile ? null
, vendorHash
, pubspecLockFile ? null
, nativeBuildInputs ? [ ]
, preUnpack ? ""
, postFixup ? ""
, ...
}@args:
let
  pl = n: "##FLUTTER_${n}_PLACEHOLDER_MARKER##";
  placeholder_deps = pl "DEPS";
  placeholder_flutter = pl "FLUTTER";
  fetchAttrs = [ "src" "sourceRoot" "setSourceRoot" "unpackPhase" "patches" ];
  getAttrsOrNull = names: attrs: lib.genAttrs names (name: if attrs ? ${name} then attrs.${name} else null);
  flutterDeps = [
    # flutter deps
    flutter.unwrapped
    bash
    curl
    flutter.dart
    git
    unzip
    which
    xz
  ];
  self =
(self: llvmPackages_13.stdenv.mkDerivation (args // {
  deps = stdenvNoCC.mkDerivation (lib.recursiveUpdate (getAttrsOrNull fetchAttrs args) {
    name = "${self.name}-deps-flutter-v${flutter.unwrapped.version}-${stdenvNoCC.targetPlatform.system}.tar.gz";

    nativeBuildInputs = flutterDeps ++ [
      nukeReferences
    ];

    # avoid pub phase
    dontBuild = true;

    installPhase = ''
      . ${../fetchgit/deterministic-git}

      TMP=$(mktemp -d)

      export HOME="$TMP"
      export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
      export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1

  flutterSetupScript = ''
    export HOME="$NIX_BUILD_TOP"
    flutter config --no-analytics &>/dev/null # mute first-run
      flutter config --enable-linux-desktop
      flutter packages get
      flutter build linux || true # so it downloads tools
      ${lib.optionalString (args ? flutterExtraFetchCommands) args.flutterExtraFetchCommands}

      RES="$TMP"

      mkdir -p "$RES/f"

      # so we can use lock, diff yaml
      cp "pubspec.yaml" "$RES"
      cp "pubspec.lock" "$RES"
      [[ -e .packages ]] && mv .packages "$RES/f"
      mv .dart_tool .flutter-plugins .flutter-plugins-dependencies "$RES/f"

      # replace paths with placeholders
      find "$RES" -type f -exec sed -i \
        -e s,$TMP,${placeholder_deps},g \
        -e s,${flutter.unwrapped},${placeholder_flutter},g \
        {} +

      remove_line_matching() {
        replace_line_matching "$1" "$2" ""
      }

      replace_line_matching() {
        sed "s|.*$2.*|$3|g" -r -i "$1"
      }

      # nuke nondeterminism

      # clientId is random
      remove_line_matching "$RES/.flutter" clientId

      # deterministic git repos
      find "$RES" -iname .git -type d | while read -r repoGit; do
        make_deterministic_repo "$(dirname "$repoGit")"
      done

      # dart _fetchedAt, etc
      DART_DATE=$(date --date="@$SOURCE_DATE_EPOCH" -In | sed "s|,|.|g" | sed "s|+.*||g")
      find "$RES/.pub-cache" -iname "*.json" -exec sed -r 's|.*_fetchedAt.*|    "_fetchedAt": "'"$DART_DATE"'",|g' -i {} +
      replace_line_matching "$RES/f/.dart_tool/package_config.json" '"generated"' '"generated": "'"$DART_DATE"'",'
      replace_line_matching "$RES/f/.flutter-plugins-dependencies" '"date_created"' '"date_created": "'"$DART_DATE"'",'
      [[ -e "$RES/f/.packages" ]] && remove_line_matching "$RES/f/.packages" "Generated by pub"

      # nuke refs
      find "$RES" -type f -exec nuke-refs {} +

      # Build a reproducible tar, per instructions at https://reproducible-builds.org/docs/archives/
      tar --owner=0 --group=0 --numeric-owner --format=gnu \
          --sort=name --mtime="@$SOURCE_DATE_EPOCH" \
          -czf "$out" -C "$RES" .
    flutter config --enable-linux-desktop >/dev/null
  '';

    GIT_SSL_CAINFO = "${cacert}/etc/ssl/certs/ca-bundle.crt";
    SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";

    impureEnvVars = lib.fetchers.proxyImpureEnvVars ++ [
      "GIT_PROXY_COMMAND" "NIX_GIT_SSL_CAINFO" "SOCKS_SERVER"
    ];

    # unnecesarry
    dontFixup = true;

    outputHashAlgo = if self ? vendorHash then null else "sha256";
    # outputHashMode = "recursive";
    outputHash = if self ? vendorHash then
      self.vendorHash
    else if self ? vendorSha256 then
      self.vendorSha256
    else
      lib.fakeSha256;

  });

  nativeBuildInputs = flutterDeps ++ [
    # flutter dev tools
    cmake
    ninja
    pkg-config
    wrapGAppsHook
    # flutter likes dynamic linking
    autoPatchelfHook
  ] ++ lib.optionals (args ? nativeBuildInputs) args.nativeBuildInputs;

  buildInputs = [
    # cmake deps
    gtk3
    glib
    pcre
    util-linux
    # also required by cmake, not sure if really needed or dep of all packages
    libselinux
    libsepol
    libthai
    libdatrie
    xorg.libXdmcp
    xorg.libXtst
    libxkbcommon
    dbus
    at-spi2-core
    libsecret
    jsoncpp
    # build deps
    xorg.libX11
    # directly required by build
    libepoxy
  ] ++ lib.optionals (args ? buildInputs) args.buildInputs;
  deps = callPackage ../dart/fetch-dart-deps { dart = flutter; } {
    sdkSetupScript = flutterSetupScript;
    inherit pubGetScript vendorHash pubspecLockFile;
    buildDrvArgs = args;
  };

  baseDerivation = llvmPackages_13.stdenv.mkDerivation (finalAttrs: args // {
    inherit flutterBuildFlags runtimeDependencies;

    outputs = [ "out" "debug" ];

    nativeBuildInputs = [
      makeWrapper
      deps
      flutter
      jq
    ] ++ nativeBuildInputs;

    preUnpack = ''
      ${lib.optionalString (!autoDepsList) ''
        if ! { [ '${lib.boolToString (depsListFile != null)}' = 'true' ] ${lib.optionalString (depsListFile != null) "&& cmp -s <(jq -Sc . '${depsListFile}') <(jq -Sc . '${finalAttrs.passthru.depsListFile}')"}; }; then
          echo 1>&2 -e '\nThe dependency list file was either not given or differs from the expected result.' \
                      '\nPlease choose one of the following solutions:' \
                      '\n - Duplicate the following file and pass it to the depsListFile argument.' \
                      '\n   ${finalAttrs.passthru.depsListFile}' \
                      '\n - Set autoDepsList to true (not supported by Hydra or permitted in Nixpkgs)'.
          exit 1
        fi
      ''}

  # TODO: do we need this?
  NIX_LDFLAGS = "-rpath ${lib.makeLibraryPath self.buildInputs}";
  env.NIX_CFLAGS_COMPILE = "-I${xorg.libX11}/include";
  LD_LIBRARY_PATH = lib.makeLibraryPath self.buildInputs;
      ${preUnpack}
    '';

    configurePhase = ''
      runHook preConfigure

    # for some reason fluffychat build breaks without this - seems file gets overriden by some tool
    cp pubspec.yaml pubspec-backup

    # we get this from $depsFolder so disabled for now, but we might need it again once deps are fetched properly
    # flutter config --no-analytics >/dev/null 2>/dev/null # mute first-run
    # flutter config --enable-linux-desktop

    # extract deps
    depsFolder=$(mktemp -d)
    tar xzf "$deps" -C "$depsFolder"

    # after extracting update paths to point to real paths
    find "$depsFolder" -type f -exec sed -i \
      -e s,${placeholder_deps},$depsFolder,g \
      -e s,${placeholder_flutter},${flutter.unwrapped},g \
      {} +

    # ensure we're using a lockfile for the right package version
    if [ -e pubspec.lock ]; then
      # FIXME: currently this is broken. in theory this should not break, but flutter has it's own way of doing things.
      # diff -u pubspec.lock $depsFolder/pubspec.lock
      true
    else
      cp -v "$depsFolder/pubspec.lock" .
    fi
    diff -u pubspec.yaml $depsFolder/pubspec.yaml

    mv -v $(find $depsFolder/f -type f) .

    # prepare
    export HOME=$depsFolder
    export PUB_CACHE=''${PUB_CACHE:-"$HOME/.pub-cache"}
    export ANDROID_EMULATOR_USE_SYSTEM_LIBS=1

    # binaries need to be patched
    autoPatchelf -- "$depsFolder"
      ${flutterSetupScript}

      runHook postConfigure
    '';
@@ -236,12 +74,10 @@ let
    buildPhase = ''
      runHook preBuild

    # for some reason fluffychat build breaks without this - seems file gets overriden by some tool
    mv pubspec-backup pubspec.yaml
      mkdir -p build/flutter_assets/fonts

      flutter packages get --offline -v
    flutter build linux --release -v
      flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") finalAttrs.flutterBuildFlags)}

      runHook postBuild
    '';
@@ -262,9 +98,6 @@ let
        ln -s $f $out/bin/$(basename $f)
      done

    # this confuses autopatchelf hook otherwise
    rm -rf "$depsFolder"

      # make *.so executable
      find $out/app -iname "*.so" -type f -exec chmod +x {} +

@@ -279,6 +112,48 @@ let

      runHook postInstall
    '';
})) self;

    postFixup = ''
      # Add runtime library dependencies to the LD_LIBRARY_PATH.
      # For some reason, the RUNPATH of the executable is not used to load dynamic libraries in dart:ffi with DynamicLibrary.open().
      #
      # This could alternatively be fixed with patchelf --add-needed, but this would cause all the libraries to be opened immediately,
      # which is not what application authors expect.
      for f in "$out"/bin/*; do
        wrapProgram "$f" \
          --suffix LD_LIBRARY_PATH : '${lib.makeLibraryPath finalAttrs.runtimeDependencies}'
      done

      ${postFixup}
    '';

    passthru = {
      inherit (deps) depsListFile;
    };
  });

  packageOverrideRepository = (callPackage ../../development/compilers/flutter/package-overrides { }) // customPackageOverrides;
  productPackages = builtins.filter (package: package.kind != "dev")
    (if autoDepsList
    then builtins.fromJSON (builtins.readFile deps.depsListFile)
    else
      if depsListFile == null
      then [ ]
      else builtins.fromJSON (builtins.readFile depsListFile));
in
  self
builtins.foldl'
  (prev: package:
  if packageOverrideRepository ? ${package.name}
  then
    prev.overrideAttrs
      (packageOverrideRepository.${package.name} {
        inherit (package)
          name
          version
          kind
          source
          dependencies;
      })
  else prev)
  baseDerivation
  productPackages
Loading