diff options
author | Alyssa Ross <hi@alyssa.is> | 2024-01-07 14:58:29 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2024-01-07 14:58:29 +0100 |
commit | ad899504860973e98351c922ecb934595f2c0f19 (patch) | |
tree | b1260cc90947e834af941c6cb6aed51dc68f50b5 /nixpkgs/pkgs/build-support | |
parent | f34a1b70eb86e4a63cfb88ea460345bb1aed88e3 (diff) | |
parent | dc676e1b5014069a2b06e236242e2f0990384934 (diff) | |
download | nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar.gz nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar.bz2 nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar.lz nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar.xz nixlib-ad899504860973e98351c922ecb934595f2c0f19.tar.zst nixlib-ad899504860973e98351c922ecb934595f2c0f19.zip |
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/pkgs/build-support')
13 files changed, 452 insertions, 372 deletions
diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/default.nix b/nixpkgs/pkgs/build-support/dart/build-dart-application/default.nix index 2cb193ac6f16..e8e6bd16b168 100644 --- a/nixpkgs/pkgs/build-support/dart/build-dart-application/default.nix +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/default.nix @@ -1,7 +1,25 @@ -{ lib, stdenv, callPackage, fetchDartDeps, runCommand, symlinkJoin, writeText, dartHooks, makeWrapper, dart, cacert, nodejs, darwin, jq }: +{ lib +, stdenv +, callPackage +, writeText +, pub2nix +, dartHooks +, makeWrapper +, dart +, nodejs +, darwin +, jq +}: -{ sdkSetupScript ? "" -, pubGetScript ? "dart pub get" +{ src +, sourceRoot ? "source" +, packageRoot ? (lib.removePrefix "/" (lib.removePrefix "source" sourceRoot)) +, gitHashes ? { } +, sdkSourceBuilders ? { } +, customSourceBuilders ? { } + +, sdkSetupScript ? "" +, extraPackageConfigSetup ? "" # Output type to produce. Can be any kind supported by dart # https://dart.dev/tools/dart-compile#types-of-output @@ -26,47 +44,52 @@ , runtimeDependencies ? [ ] , extraWrapProgramArgs ? "" -, customPackageOverrides ? { } -, autoDepsList ? false -, depsListFile ? null -, pubspecLockFile ? null -, vendorHash ? "" +, pubspecLock , ... }@args: let - dartDeps = (fetchDartDeps.override { - dart = symlinkJoin { - name = "dart-sdk-fod"; - paths = [ - (runCommand "dart-fod" { nativeBuildInputs = [ makeWrapper ]; } '' - mkdir -p "$out/bin" - makeWrapper "${dart}/bin/dart" "$out/bin/dart" \ - --add-flags "--root-certs-file=${cacert}/etc/ssl/certs/ca-bundle.crt" - '') - dart - ]; + generators = callPackage ./generators.nix { inherit dart; } { buildDrvArgs = args; }; + + pubspecLockFile = builtins.toJSON pubspecLock; + pubspecLockData = pub2nix.readPubspecLock { inherit src packageRoot pubspecLock gitHashes sdkSourceBuilders customSourceBuilders; }; + packageConfig = generators.linkPackageConfig { + packageConfig = pub2nix.generatePackageConfig { + pname = if args.pname != null then "${args.pname}-${args.version}" else null; + + dependencies = + # Ideally, we'd only include the main dependencies and their transitive + # dependencies. + # + # The pubspec.lock file does not contain information about where + # transitive dependencies come from, though, and it would be weird to + # include the transitive dependencies of dev and override dependencies + # without including the dev and override dependencies themselves. + builtins.concatLists (builtins.attrValues pubspecLockData.dependencies); + + inherit (pubspecLockData) dependencySources; }; - }) { - buildDrvArgs = args; - inherit sdkSetupScript pubGetScript vendorHash pubspecLockFile; + extraSetupCommands = extraPackageConfigSetup; }; + inherit (dartHooks.override { inherit dart; }) dartConfigHook dartBuildHook dartInstallHook dartFixupHook; - baseDerivation = stdenv.mkDerivation (finalAttrs: args // { - inherit sdkSetupScript pubGetScript dartCompileCommand dartOutputType - dartRuntimeCommand dartCompileFlags dartJitFlags runtimeDependencies; + baseDerivation = stdenv.mkDerivation (finalAttrs: (builtins.removeAttrs args [ "gitHashes" "sdkSourceBuilders" "pubspecLock" "customSourceBuilders" ]) // { + inherit pubspecLockFile packageConfig sdkSetupScript + dartCompileCommand dartOutputType dartRuntimeCommand dartCompileFlags + dartJitFlags; + + outputs = args.outputs or [ ] ++ [ "out" "pubcache" ]; dartEntryPoints = if (dartEntryPoints != null) then writeText "entrypoints.json" (builtins.toJSON dartEntryPoints) else null; - runtimeDependencyLibraryPath = lib.makeLibraryPath finalAttrs.runtimeDependencies; + runtimeDependencies = map lib.getLib runtimeDependencies; nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ dart - dartDeps dartConfigHook dartBuildHook dartInstallHook @@ -75,55 +98,27 @@ let jq ] ++ lib.optionals stdenv.isDarwin [ darwin.sigtool - ]; - - preUnpack = '' - ${lib.optionalString (!autoDepsList) '' - if ! { [ '${lib.boolToString (depsListFile != null)}' = 'true' ] ${lib.optionalString (depsListFile != null) "&& cmp -s <(jq -Sc . '${depsListFile}') <(jq -Sc . '${finalAttrs.passthru.dartDeps.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.dartDeps.depsListFile}' \ - '\n - Set autoDepsList to true (not supported by Hydra or permitted in Nixpkgs)'. - exit 1 - fi - ''} - ${args.preUnpack or ""} + ] ++ + # Ensure that we inherit the propagated build inputs from the dependencies. + builtins.attrValues pubspecLockData.dependencySources; + + preConfigure = args.preConfigure or "" + '' + ln -sf "$pubspecLockFilePath" pubspec.lock ''; # When stripping, it seems some ELF information is lost and the dart VM cli # runs instead of the expected program. Don't strip if it's an exe output. dontStrip = args.dontStrip or (dartOutputType == "exe"); - passthru = { inherit dartDeps; } // (args.passthru or { }); + passAsFile = [ "pubspecLockFile" ]; + + passthru = { + pubspecLock = pubspecLockData; + } // (args.passthru or { }); meta = (args.meta or { }) // { platforms = args.meta.platforms or dart.meta.platforms; }; }); - - packageOverrideRepository = (callPackage ../../../development/compilers/dart/package-overrides { }) // customPackageOverrides; - productPackages = builtins.filter (package: package.kind != "dev") - (if autoDepsList - then lib.importJSON dartDeps.depsListFile - else - if depsListFile == null - then [ ] - else lib.importJSON depsListFile); in assert !(builtins.isString dartOutputType && dartOutputType != "") -> throw "dartOutputType must be a non-empty string"; -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 +baseDerivation diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/generators.nix b/nixpkgs/pkgs/build-support/dart/build-dart-application/generators.nix new file mode 100644 index 000000000000..f01a09305dba --- /dev/null +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/generators.nix @@ -0,0 +1,74 @@ +{ lib +, stdenvNoCC +, dart +, dartHooks +, jq +, yq +, cacert +}: + +{ + # 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 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}"); + + # Adds the root package to a dependency package_config.json file from pub2nix. + linkPackageConfig = { packageConfig, extraSetupCommands ? "" }: stdenvNoCC.mkDerivation (drvArgs // { + name = "${name}-package-config-with-root.json"; + + nativeBuildInputs = drvArgs.nativeBuildInputs or [ ] ++ args.nativeBuildInputs or [ ] ++ [ jq yq ]; + + dontBuild = true; + + installPhase = '' + runHook preInstall + + packageName="$(yq --raw-output .name pubspec.yaml)" + jq --arg name "$packageName" '.packages |= . + [{ name: $name, rootUri: "../", packageUri: "lib/" }]' '${packageConfig}' > "$out" + ${extraSetupCommands} + + runHook postInstall + ''; + }); +in +{ + inherit + linkPackageConfig; +} diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-config-hook.sh b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-config-hook.sh index f22d7d2ce64d..50754a7b56d4 100644 --- a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-config-hook.sh +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-config-hook.sh @@ -7,7 +7,62 @@ dartConfigHook() { eval "$sdkSetupScript" echo "Installing dependencies" - eval doPubGet "$pubGetScript" --offline + mkdir -p .dart_tool + cp "$packageConfig" .dart_tool/package_config.json + + packagePath() { + jq --raw-output --arg name "$1" '.packages.[] | select(.name == $name) .rootUri | sub("file://"; "")' .dart_tool/package_config.json + } + + # Runs a Dart executable from a package with a custom path. + # + # Usage: + # packageRunCustom <package> [executable] [bin_dir] + # + # By default, [bin_dir] is "bin", and [executable] is <package>. + # i.e. `packageRunCustom build_runner` is equivalent to `packageRunCustom build_runner build_runner bin`, which runs `bin/build_runner.dart` from the build_runner package. + packageRunCustom() { + local args=() + local passthrough=() + + while [ $# -gt 0 ]; do + if [ "$1" != "--" ]; then + args+=("$1") + shift + else + shift + passthrough=("$@") + break + fi + done + + local name="${args[0]}" + local path="${args[1]:-$name}" + local prefix="${args[2]:-bin}" + + dart --packages=.dart_tool/package_config.json "$(packagePath "$name")/$prefix/$path.dart" "${passthrough[@]}" + } + + # Runs a Dart executable from a package. + # + # Usage: + # packageRun <package> [-e executable] [...] + # + # To run an executable from an unconventional location, use packageRunCustom. + packageRun() { + local name="$1" + shift + + local executableName="$name" + if [ "$1" = "-e" ]; then + shift + executableName="$1" + shift + fi + + fileName="$(@yq@ --raw-output --arg name "$executableName" '.executables.[$name] // $name' "$(packagePath "$name")/pubspec.yaml")" + packageRunCustom "$name" "$fileName" -- "$@" + } echo "Finished dartConfigHook" } diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-fixup-hook.sh b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-fixup-hook.sh index c5a9bedd0665..60bd74871c92 100644 --- a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-fixup-hook.sh +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-fixup-hook.sh @@ -10,9 +10,12 @@ dartFixupHook() { # # 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. - echo "$runtimeDependencyLibraryPath" - if [[ ! -z "$runtimeDependencyLibraryPath" ]]; then - wrapProgramArgs+=(--suffix LD_LIBRARY_PATH : \"$runtimeDependencyLibraryPath\") + APPLICATION_LD_LIBRARY_PATH="" + for runtimeDependency in "${runtimeDependencies[@]}"; do + addToSearchPath APPLICATION_LD_LIBRARY_PATH "${runtimeDependency}/lib" + done + if [[ ! -z "$APPLICATION_LD_LIBRARY_PATH" ]]; then + wrapProgramArgs+=(--suffix LD_LIBRARY_PATH : \"$APPLICATION_LD_LIBRARY_PATH\") fi if [[ ! -z "$extraWrapProgramArgs" ]]; then diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-install-hook.sh b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-install-hook.sh index 1906bcfbca4c..888e12a07d83 100644 --- a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-install-hook.sh +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/dart-install-hook.sh @@ -5,8 +5,8 @@ dartInstallHook() { runHook preInstall + # Install snapshots and executables. mkdir -p "$out" - while IFS=$'\t' read -ra target; do dest="${target[0]}" # Wrap with runtime command, if it's defined @@ -19,6 +19,10 @@ dartInstallHook() { fi done < <(_getDartEntryPoints) + # Install the package_config.json file. + mkdir -p "$pubcache" + cp .dart_tool/package_config.json "$pubcache/package_config.json" + runHook postInstall echo "Finished dartInstallHook" diff --git a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/default.nix b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/default.nix index 134989426d96..253d3132ad02 100644 --- a/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/default.nix +++ b/nixpkgs/pkgs/build-support/dart/build-dart-application/hooks/default.nix @@ -3,6 +3,8 @@ { dartConfigHook = makeSetupHook { name = "dart-config-hook"; + substitutions.yq = "${yq}/bin/yq"; + substitutions.jq = "${jq}/bin/jq"; } ./dart-config-hook.sh; dartBuildHook = makeSetupHook { name = "dart-build-hook"; diff --git a/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/default.nix b/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/default.nix deleted file mode 100644 index 29e5209a2877..000000000000 --- a/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/default.nix +++ /dev/null @@ -1,248 +0,0 @@ -{ stdenvNoCC -, lib -, makeSetupHook -, writeShellScriptBin -, 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" ])); - - mkDepsDrv = args: stdenvNoCC.mkDerivation (args // { - nativeBuildInputs = args.nativeBuildInputs or [ ] ++ [ hook dart ]; - - configurePhase = args.configurePhase or '' - runHook preConfigure - - ${sdkSetupScript} - - _pub_get() { - ${pubGetScript} --offline - } - doPubGet _pub_get - - runHook postConfigure - ''; - } // (removeAttrs buildDrvInheritArgs [ "name" "pname" ])); - - depsListDrv = mkDepsDrv { - name = "${name}-dart-deps-list.json"; - - nativeBuildInputs = [ jq ]; - - buildPhase = '' - runHook preBuild - if [ -e ${dart}/bin/flutter ]; then - flutter pub deps --json | jq .packages > $out - else - dart pub deps --json | jq .packages > $out - fi - runHook postBuild - ''; - - dontInstall = true; - }; - - packageConfigDrv = mkDepsDrv { - name = "${name}-package-config.json"; - - nativeBuildInputs = [ jq ]; - - buildPhase = '' - runHook preBuild - - # Canonicalise the package_config.json, and replace references to the - # reconstructed package cache with the original FOD. - # - # The reconstructed package cache is not reproducible. The intended - # use-case of this derivation is for use with tools that use a - # package_config.json to load assets from packages, and not for use with - # Pub directly, which requires the setup performed by the hook before - # usage. - jq -S ' - .packages[] |= . + { rootUri: .rootUri | gsub("'"$PUB_CACHE"'"; "${hook.deps}/cache/.pub-cache") } - | .generated |= "1970-01-01T00:00:00.000Z" - ' .dart_tool/package_config.json > $out - - runHook postBuild - ''; - - dontInstall = true; - }; - - # As of Dart 3.0.0, Pub checks the revision of cached Git-sourced packages. - # Git must be wrapped to return a positive result, as the real .git directory is wiped - # to produce a deteministic dependency derivation output. - # https://github.com/dart-lang/pub/pull/3791/files#diff-1639c4669c428c26e68cfebd5039a33f87ba568795f2c058c303ca8528f62b77R631 - gitSourceWrapper = writeShellScriptBin "git" '' - args=("$@") - if [[ "''${args[0]}" == "rev-list" && "''${args[1]}" == "--max-count=1" ]]; then - revision="''${args[''${#args[@]}-1]}" - echo "$revision" - else - ${git}/bin/git "''${args[@]}" - fi - ''; - - 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 gitSourceWrapper deps; }; - propagatedBuildInputs = [ dart git ]; - passthru = { - inherit deps; - files = deps.outPath; - depsListFile = depsListDrv.outPath; - packageConfig = packageConfigDrv; - }; - }) ./setup-hook.sh; -in -hook diff --git a/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/setup-hook.sh b/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/setup-hook.sh deleted file mode 100644 index 689e0e8c5b5f..000000000000 --- a/nixpkgs/pkgs/build-support/dart/fetch-dart-deps/setup-hook.sh +++ /dev/null @@ -1,46 +0,0 @@ -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 -} - -# Performs the given pub get command with an appropriate environment. -doPubGet() { - PATH="@gitSourceWrapper@/bin:$PATH" "$@" -} diff --git a/nixpkgs/pkgs/build-support/dart/pub2nix/default.nix b/nixpkgs/pkgs/build-support/dart/pub2nix/default.nix new file mode 100644 index 000000000000..ace2cc5a1e0c --- /dev/null +++ b/nixpkgs/pkgs/build-support/dart/pub2nix/default.nix @@ -0,0 +1,6 @@ +{ callPackage }: + +{ + readPubspecLock = callPackage ./pubspec-lock.nix { }; + generatePackageConfig = callPackage ./package-config.nix { }; +} diff --git a/nixpkgs/pkgs/build-support/dart/pub2nix/package-config.nix b/nixpkgs/pkgs/build-support/dart/pub2nix/package-config.nix new file mode 100644 index 000000000000..309e51ec84a1 --- /dev/null +++ b/nixpkgs/pkgs/build-support/dart/pub2nix/package-config.nix @@ -0,0 +1,68 @@ +{ lib +, runCommand +, jq +, yq +}: + +{ pname ? null + + # A list of dependency package names. +, dependencies + + # An attribute set of package names to sources. +, dependencySources +}: + +let + packages = lib.genAttrs dependencies (dependency: rec { + src = dependencySources.${dependency}; + inherit (src) packageRoot; + }); +in +(runCommand "${lib.optionalString (pname != null) "${pname}-"}package-config.json" { + inherit packages; + + nativeBuildInputs = [ jq yq ]; + + __structuredAttrs = true; +}) '' + declare -A packageSources + declare -A packageRoots + while IFS=',' read -r name src packageRoot; do + packageSources["$name"]="$src" + packageRoots["$name"]="$packageRoot" + done < <(jq -r '.packages | to_entries | map("\(.key),\(.value.src),\(.value.packageRoot)") | .[]' "$NIX_ATTRS_JSON_FILE") + + for package in "''${!packageSources[@]}"; do + if [ ! -e "''${packageSources["$package"]}/''${packageRoots["$package"]}/pubspec.yaml" ]; then + echo >&2 "The package sources for $package are missing. Is the following path inside the source derivation?" + echo >&2 "Source path: ''${packageSources["$package"]}/''${packageRoots["$package"]}/pubspec.yaml" + exit 1 + fi + + languageConstraint="$(yq -r .environment.sdk "''${packageSources["$package"]}/''${packageRoots["$package"]}/pubspec.yaml")" + if [[ "$languageConstraint" =~ ^[[:space:]]*(\^|>=|>|)[[:space:]]*([[:digit:]]+\.[[:digit:]]+)\.[[:digit:]]+.*$ ]]; then + languageVersionJson="\"''${BASH_REMATCH[2]}\"" + elif [ "$languageConstraint" = 'any' ]; then + languageVersionJson='null' + else + # https://github.com/dart-lang/pub/blob/68dc2f547d0a264955c1fa551fa0a0e158046494/lib/src/language_version.dart#L106C35-L106C35 + languageVersionJson='"2.7"' + fi + + jq --null-input \ + --arg name "$package" \ + --arg path "''${packageSources["$package"]}/''${packageRoots["$package"]}" \ + --argjson languageVersion "$languageVersionJson" \ + '{ + name: $name, + rootUri: "file://\($path)", + packageUri: "lib/", + languageVersion: $languageVersion, + }' + done | jq > "$out" --slurp '{ + configVersion: 2, + generator: "nixpkgs", + packages: ., + }' +'' diff --git a/nixpkgs/pkgs/build-support/dart/pub2nix/pubspec-lock.nix b/nixpkgs/pkgs/build-support/dart/pub2nix/pubspec-lock.nix new file mode 100644 index 000000000000..e1ab4d7d2359 --- /dev/null +++ b/nixpkgs/pkgs/build-support/dart/pub2nix/pubspec-lock.nix @@ -0,0 +1,119 @@ +{ lib +, callPackage +, fetchurl +, fetchgit +, runCommand +}: + +{ + # The source directory of the package. + src + + # The package subdirectory within src. + # Useful if the package references sibling packages with relative paths. +, packageRoot ? "." + + # The pubspec.lock file, in attribute set form. +, pubspecLock + + # Hashes for Git dependencies. + # Pub does not record these itself, so they must be manually provided. +, gitHashes ? { } + + # Functions to generate SDK package sources. + # The function names should match the SDK names, and the package name is given as an argument. +, sdkSourceBuilders ? { } + + # Functions that create custom package source derivations. + # + # The function names should match the package names, and the package version, + # source, and source files are given in an attribute set argument. + # + # The passthru of the source derivation should be propagated. +, customSourceBuilders ? { } +}: + +let + dependencyVersions = builtins.mapAttrs (name: details: details.version) pubspecLock.packages; + + dependencyTypes = { + "direct main" = "main"; + "direct dev" = "dev"; + "direct overridden" = "overridden"; + "transitive" = "transitive"; + }; + + dependencies = lib.foldlAttrs + (dependencies: name: details: dependencies // { ${dependencyTypes.${details.dependency}} = dependencies.${dependencyTypes.${details.dependency}} ++ [ name ]; }) + (lib.genAttrs (builtins.attrValues dependencyTypes) (dependencyType: [ ])) + pubspecLock.packages; + + # fetchTarball fails with "tarball contains an unexpected number of top-level files". This is a workaround. + # https://discourse.nixos.org/t/fetchtarball-with-multiple-top-level-directories-fails/20556 + mkHostedDependencySource = name: details: + let + archive = fetchurl { + name = "pub-${name}-${details.version}.tar.gz"; + url = "${details.description.url}/packages/${details.description.name}/versions/${details.version}.tar.gz"; + sha256 = details.description.sha256; + }; + in + runCommand "pub-${name}-${details.version}" { passthru.packageRoot = "."; } '' + mkdir -p "$out" + tar xf '${archive}' -C "$out" + ''; + + mkGitDependencySource = name: details: (fetchgit { + name = "pub-${name}-${details.version}"; + url = details.description.url; + rev = details.description.resolved-ref; + hash = gitHashes.${name} or (throw "A Git hash is required for ${name}! Set to an empty string to obtain it."); + }).overrideAttrs ({ passthru ? { }, ... }: { + passthru = passthru // { + packageRoot = details.description.path; + }; + }); + + mkPathDependencySource = name: details: + assert lib.assertMsg details.description.relative "Only relative paths are supported - ${name} has an absolue path!"; + (if lib.isDerivation src then src else (runCommand "pub-${name}-${details.version}" { } ''cp -r '${src}' "$out"'')).overrideAttrs ({ passthru ? { }, ... }: { + passthru = passthru // { + packageRoot = "${packageRoot}/${details.description.path}"; + }; + }); + + mkSdkDependencySource = name: details: + (sdkSourceBuilders.${details.description} or (throw "No SDK source builder has been given for ${details.description}!")) name; + + addDependencySourceUtils = dependencySource: details: dependencySource.overrideAttrs ({ passthru, ... }: { + passthru = passthru // { + inherit (details) version; + }; + }); + + sourceBuilders = callPackage ../../../development/compilers/dart/package-source-builders { } // customSourceBuilders; + + dependencySources = lib.filterAttrs (name: src: src != null) (builtins.mapAttrs + (name: details: + (sourceBuilders.${name} or ({ src, ... }: src)) { + inherit (details) version source; + src = ((addDependencySourceUtils (({ + "hosted" = mkHostedDependencySource; + "git" = mkGitDependencySource; + "path" = mkPathDependencySource; + "sdk" = mkSdkDependencySource; + }.${details.source} name) details)) details); + }) + pubspecLock.packages); +in +{ + inherit + # An attribute set of dependency categories to package name lists. + dependencies + + # An attribute set of package names to their versions. + dependencyVersions + + # An attribute set of package names to their sources. + dependencySources; +} diff --git a/nixpkgs/pkgs/build-support/fetchpijul/default.nix b/nixpkgs/pkgs/build-support/fetchpijul/default.nix index ca7e1a7926e8..fd41cfa55355 100644 --- a/nixpkgs/pkgs/build-support/fetchpijul/default.nix +++ b/nixpkgs/pkgs/build-support/fetchpijul/default.nix @@ -1,4 +1,4 @@ -{ lib, stdenvNoCC, pijul }: +{ lib, stdenvNoCC, pijul, cacert }: lib.makeOverridable ( { url @@ -17,7 +17,8 @@ if change != null && state != null then else stdenvNoCC.mkDerivation { inherit name; - nativeBuildInputs = [ pijul ]; + nativeBuildInputs = [ pijul cacert ]; + strictDeps = true; dontUnpack = true; dontConfigure = true; @@ -52,5 +53,7 @@ else lib.fakeSha256; inherit url change state channel; + + impureEnvVars = lib.fetchers.proxyImpureEnvVars; } ) diff --git a/nixpkgs/pkgs/build-support/flutter/default.nix b/nixpkgs/pkgs/build-support/flutter/default.nix index bcee31506df1..4d00e177370e 100644 --- a/nixpkgs/pkgs/build-support/flutter/default.nix +++ b/nixpkgs/pkgs/build-support/flutter/default.nix @@ -3,11 +3,14 @@ , runCommand , makeWrapper , wrapGAppsHook -, fetchDartDeps , buildDartApplication , cacert , glib , flutter +, pkg-config +, jq +, yq +, moreutils }: # absolutely no mac support for now @@ -20,7 +23,6 @@ (buildDartApplication.override { dart = flutter; - fetchDartDeps = fetchDartDeps.override { dart = flutter; }; }) (args // { sdkSetupScript = '' # Pub needs SSL certificates. Dart normally looks in a hardcoded path. @@ -50,7 +52,46 @@ inherit pubGetScript; - nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ wrapGAppsHook ]; + sdkSourceBuilders = { + # https://github.com/dart-lang/pub/blob/68dc2f547d0a264955c1fa551fa0a0e158046494/lib/src/sdk/flutter.dart#L81 + "flutter" = name: runCommand "flutter-sdk-${name}" { passthru.packageRoot = "."; } '' + for path in '${flutter}/packages/${name}' '${flutter}/bin/cache/pkg/${name}'; do + if [ -d "$path" ]; then + ln -s "$path" "$out" + break + fi + done + + if [ ! -e "$out" ]; then + echo 1>&2 'The Flutter SDK does not contain the requested package: ${name}!' + exit 1 + fi + ''; + }; + + extraPackageConfigSetup = '' + # https://github.com/flutter/flutter/blob/3.13.8/packages/flutter_tools/lib/src/dart/pub.dart#L755 + if [ "$('${yq}/bin/yq' '.flutter.generate // false' pubspec.yaml)" = "true" ]; then + '${jq}/bin/jq' '.packages |= . + [{ + name: "flutter_gen", + rootUri: "flutter_gen", + languageVersion: "2.12", + }]' "$out" | '${moreutils}/bin/sponge' "$out" + fi + ''; + + nativeBuildInputs = (args.nativeBuildInputs or [ ]) ++ [ + wrapGAppsHook + + # Flutter requires pkg-config for Linux desktop support, and many plugins + # attempt to use it. + # + # It is available to the `flutter` tool through its wrapper, but it must be + # added here as well so the setup hook adds plugin dependencies to the + # pkg-config search paths. + pkg-config + ]; + buildInputs = (args.buildInputs or [ ]) ++ [ glib ]; dontDartBuild = true; @@ -59,7 +100,6 @@ mkdir -p build/flutter_assets/fonts - doPubGet flutter pub get --offline -v flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)} runHook postBuild @@ -94,6 +134,11 @@ fi done + # Install the package_config.json file. + # This is normally done by dartInstallHook, but we disable it. + mkdir -p "$pubcache" + cp .dart_tool/package_config.json "$pubcache/package_config.json" + runHook postInstall ''; |