diff options
Diffstat (limited to 'pkgs/build-support')
72 files changed, 1455 insertions, 786 deletions
diff --git a/pkgs/build-support/appimage/default.nix b/pkgs/build-support/appimage/default.nix index 95dc7ffd1cd66..0d44a5ab23e96 100644 --- a/pkgs/build-support/appimage/default.nix +++ b/pkgs/build-support/appimage/default.nix @@ -40,7 +40,7 @@ rec { wrapAppImage = args@{ src, - extraPkgs, + extraPkgs ? pkgs: [ ], meta ? {}, ... }: buildFHSEnv diff --git a/pkgs/build-support/bintools-wrapper/default.nix b/pkgs/build-support/bintools-wrapper/default.nix index 5ca5bc3f5eb3b..2a1fe1344e205 100644 --- a/pkgs/build-support/bintools-wrapper/default.nix +++ b/pkgs/build-support/bintools-wrapper/default.nix @@ -60,6 +60,7 @@ , postLinkSignHook ? null, signingUtils ? null }: +assert propagateDoc -> bintools ? man; assert nativeTools -> !propagateDoc && nativePrefix != ""; assert !nativeTools -> bintools != null && coreutils != null && gnugrep != null; assert !(nativeLibc && noLibc); @@ -128,7 +129,7 @@ let else if targetPlatform.isRiscV then "${sharedLibraryLoader}/lib/ld-linux-riscv*.so.1" else if targetPlatform.isLoongArch64 then "${sharedLibraryLoader}/lib/ld-linux-loongarch*.so.1" else if targetPlatform.isDarwin then "/usr/lib/dyld" - else if targetPlatform.isFreeBSD then "/libexec/ld-elf.so.1" + else if targetPlatform.isFreeBSD then "${sharedLibraryLoader}/libexec/ld-elf.so.1" else if hasSuffix "pc-gnu" targetPlatform.config then "ld.so.1" else ""; diff --git a/pkgs/build-support/build-fhsenv-bubblewrap/buildFHSEnv.nix b/pkgs/build-support/build-fhsenv-bubblewrap/buildFHSEnv.nix index 1e34ad1e5e448..ffd19cfd4a8a0 100644 --- a/pkgs/build-support/build-fhsenv-bubblewrap/buildFHSEnv.nix +++ b/pkgs/build-support/build-fhsenv-bubblewrap/buildFHSEnv.nix @@ -116,6 +116,10 @@ let export PKG_CONFIG_PATH=/usr/lib/pkgconfig export ACLOCAL_PATH=/usr/share/aclocal + # GStreamer searches for plugins relative to its real binary's location + # https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/bd97973ce0f2c5495bcda5cccd4f7ef7dcb7febc + export GST_PLUGIN_SYSTEM_PATH_1_0=/usr/lib/gstreamer-1.0:/usr/lib32/gstreamer-1.0 + ${profile} ''; diff --git a/pkgs/build-support/build-fhsenv-bubblewrap/default.nix b/pkgs/build-support/build-fhsenv-bubblewrap/default.nix index 12f3e7d585521..398a99e80e8cd 100644 --- a/pkgs/build-support/build-fhsenv-bubblewrap/default.nix +++ b/pkgs/build-support/build-fhsenv-bubblewrap/default.nix @@ -196,8 +196,10 @@ let x11_args+=(--tmpfs /tmp/.X11-unix) # Try to guess X socket path. This doesn't cover _everything_, but it covers some things. - if [[ "$DISPLAY" == :* ]]; then - display_nr=''${DISPLAY#?} + if [[ "$DISPLAY" == *:* ]]; then + # recover display number from $DISPLAY formatted [host]:num[.screen] + display_nr=''${DISPLAY/#*:} # strip host + display_nr=''${display_nr/%.*} # strip screen local_socket=/tmp/.X11-unix/X$display_nr x11_args+=(--ro-bind-try "$local_socket" "$local_socket") fi diff --git a/pkgs/build-support/build-maven.nix b/pkgs/build-support/build-maven.nix deleted file mode 100644 index 7ac8afdde225a..0000000000000 --- a/pkgs/build-support/build-maven.nix +++ /dev/null @@ -1,88 +0,0 @@ -{ stdenv, maven, runCommand, writeText, fetchurl, lib, requireFile, linkFarm }: -# Takes an info file generated by mvn2nix -# (https://github.com/NixOS/mvn2nix-maven-plugin) and builds the maven -# project with it. -# -# repo: A local maven repository with the project's dependencies. -# -# settings: A settings.xml to pass to maven to use the repo. -# -# build: A simple build derivation that uses mvn compile and package to build -# the project. -# -# @example -# project = pkgs.buildMaven ./project-info.json -infoFile: -let - info = lib.importJSON infoFile; - - dependencies = lib.flatten (map (dep: - let - inherit (dep) sha1 groupId artifactId version metadata repository-id; - versionDir = dep.unresolved-version or version; - authenticated = dep.authenticated or false; - url = dep.url or ""; - - fetch = if (url != "") then - ((if authenticated then requireFile else fetchurl) { - inherit url sha1; - }) - else - ""; - - fetchMetadata = (if authenticated then requireFile else fetchurl) { - inherit (metadata) url sha1; - }; - - layout = "${ - builtins.replaceStrings [ "." ] [ "/" ] groupId - }/${artifactId}/${versionDir}"; - in lib.optional (url != "") { - layout = "${layout}/${fetch.name}"; - drv = fetch; - } ++ lib.optionals (dep ? metadata) ([{ - layout = "${layout}/maven-metadata-${repository-id}.xml"; - drv = fetchMetadata; - }] ++ lib.optional (fetch != "") { - layout = "${layout}/${ - builtins.replaceStrings [ version ] [ dep.unresolved-version ] - fetch.name - }"; - drv = fetch; - })) info.dependencies); - - repo = linkFarm "maven-repository" (lib.forEach dependencies (dependency: { - name = dependency.layout; - path = dependency.drv; - })); - - settings = writeText "settings.xml" '' - <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 - http://maven.apache.org/xsd/settings-1.0.0.xsd"> - <localRepository>${repo}</localRepository> - </settings> - ''; - - src = dirOf infoFile; -in { - inherit repo settings info; - - build = stdenv.mkDerivation { - name = "${info.project.artifactId}-${info.project.version}.jar"; - - src = builtins.filterSource (path: type: - (toString path) != (toString (src + "/target")) && (toString path) - != (toString (src + "/.git"))) src; - - buildInputs = [ maven ]; - - buildPhase = "mvn --offline --settings ${settings} compile"; - - installPhase = '' - mvn --offline --settings ${settings} package - mv target/*.jar $out - ''; - }; -} diff --git a/pkgs/build-support/deterministic-uname/default.nix b/pkgs/build-support/deterministic-uname/default.nix index 6d150557aa9d6..9efaa2558bfb6 100644 --- a/pkgs/build-support/deterministic-uname/default.nix +++ b/pkgs/build-support/deterministic-uname/default.nix @@ -5,6 +5,7 @@ , coreutils , getopt , modDirVersion ? "" +, forPlatform ? stdenv.buildPlatform }: substituteAll { @@ -17,8 +18,8 @@ substituteAll { inherit coreutils getopt; - uSystem = if stdenv.buildPlatform.uname.system != null then stdenv.buildPlatform.uname.system else "unknown"; - inherit (stdenv.buildPlatform.uname) processor; + uSystem = if forPlatform.uname.system != null then forPlatform.uname.system else "unknown"; + inherit (forPlatform.uname) processor; # uname -o # maybe add to lib/systems/default.nix uname attrset @@ -26,10 +27,12 @@ substituteAll { # https://stackoverflow.com/questions/61711186/where-does-host-operating-system-in-uname-c-comes-from # https://github.com/coreutils/gnulib/blob/master/m4/host-os.m4 operatingSystem = - if stdenv.buildPlatform.isLinux + if forPlatform.isLinux then "GNU/Linux" - else if stdenv.buildPlatform.isDarwin + else if forPlatform.isDarwin then "Darwin" # darwin isn't in host-os.m4 so where does this come from? + else if stdenv.buildPlatform.isFreeBSD + then "FreeBSD" else "unknown"; # in os-specific/linux module packages @@ -42,11 +45,12 @@ substituteAll { mainProgram = "uname"; longDescription = '' This package provides a replacement for `uname` whose output depends only - on `stdenv.buildPlatform`. It is meant to be used from within derivations. - Many packages' build processes run `uname` at compile time and embed its - output into the result of the build. Since `uname` calls into the kernel, - and the Nix sandbox currently does not intercept these calls, builds made - on different kernels will produce different results. + on `stdenv.buildPlatform`, or a configurable `forPlatform`. It is meant + to be used from within derivations. Many packages' build processes run + `uname` at compile time and embed its output into the result of the build. + Since `uname` calls into the kernel, and the Nix sandbox currently does + not intercept these calls, builds made on different kernels will produce + different results. ''; license = [ licenses.mit ]; maintainers = with maintainers; [ artturin ]; diff --git a/pkgs/build-support/deterministic-uname/deterministic-uname.sh b/pkgs/build-support/deterministic-uname/deterministic-uname.sh index 31772aeee3cc1..cb6f419b03311 100644 --- a/pkgs/build-support/deterministic-uname/deterministic-uname.sh +++ b/pkgs/build-support/deterministic-uname/deterministic-uname.sh @@ -131,6 +131,8 @@ fi # Darwin *nodename* 22.1.0 Darwin Kernel Version 22.1.0: Sun Oct 9 20:14:30 PDT 2022; root:xnu-8792.41.9~2/RELEASE_ARM64_T8103 arm64 arm Darwin # NixOS: # Linux *nodename* 6.0.13 #1-NixOS SMP PREEMPT_DYNAMIC Wed Dec 14 10:41:06 UTC 2022 x86_64 GNU/Linux +# FreeBSD: +# FreeBSD *nodename* 14.0-RELEASE FreeBSD 14.0-RELEASE #0 releng/14.0-n265380-f9716eee8ab4: Fri Nov 10 05:57:23 UTC 2023 root@releng1.nyi.freebsd.org:/usr/obj/usr/src/amd64.amd64/sys/GENERIC amd64 amd64 AMD Ryzen 9 5950X 16-Core Processor FreeBSD output=() if [[ "$all" = "1" ]]; then output+=("$KERNEL_NAME_VAL" "$NODENAME_VAL" "$KERNEL_RELEASE_VAL" "$KERNEL_VERSION_VAL" "$MACHINE_VAL") diff --git a/pkgs/build-support/dlang/builddubpackage/default.nix b/pkgs/build-support/dlang/builddubpackage/default.nix index 9295445b0f7c7..31454d5cd69bf 100644 --- a/pkgs/build-support/dlang/builddubpackage/default.nix +++ b/pkgs/build-support/dlang/builddubpackage/default.nix @@ -2,6 +2,7 @@ lib, stdenv, fetchurl, + fetchgit, linkFarm, dub, ldc, @@ -43,11 +44,27 @@ let }; }; + makeGitDep = + { + pname, + version, + repository, + sha256, + }: + { + inherit pname version; + src = fetchgit { + url = repository; + rev = version; + inherit sha256; + }; + }; + lockJson = if lib.isPath dubLock then lib.importJSON dubLock else dubLock; + depsRaw = lib.mapAttrsToList (pname: args: { inherit pname; } // args) lockJson.dependencies; - lockedDeps = lib.mapAttrsToList ( - pname: { version, sha256 }: makeDubDep { inherit pname version sha256; } - ) lockJson.dependencies; + dubDeps = map makeDubDep (lib.filter (args: !(args ? repository)) depsRaw); + gitDeps = map makeGitDep (lib.filter (args: args ? repository) depsRaw); # a directory with multiple single element registries # one big directory with all .zip files leads to version parsing errors @@ -56,7 +73,7 @@ let map (dep: { name = "${dep.pname}/${dep.pname}-${dep.version}.zip"; path = dep.src; - }) lockedDeps + }) dubDeps ); combinedFlags = "--skip-registry=all --compiler=${lib.getExe compiler} ${toString dubFlags}"; @@ -79,12 +96,18 @@ stdenv.mkDerivation ( runHook preConfigure export DUB_HOME="$NIX_BUILD_TOP/.dub" - mkdir -p $DUB_HOME + mkdir -p "$DUB_HOME" - # register dependencies + # register dub dependencies ${lib.concatMapStringsSep "\n" (dep: '' dub fetch ${dep.pname}@${dep.version} --cache=user --skip-registry=standard --registry=file://${dubRegistryBase}/${dep.pname} - '') lockedDeps} + '') dubDeps} + + # register git dependencies + ${lib.concatMapStringsSep "\n" (dep: '' + mkdir -p "$DUB_HOME/packages/${dep.pname}/${dep.version}" + cp -r --no-preserve=all ${dep.src} "$DUB_HOME/packages/${dep.pname}/${dep.version}/${dep.pname}" + '') gitDeps} runHook postConfigure ''; diff --git a/pkgs/build-support/dlang/dub-to-nix/default.nix b/pkgs/build-support/dlang/dub-to-nix/default.nix index 53a2e99c18df5..87db7eed09331 100644 --- a/pkgs/build-support/dlang/dub-to-nix/default.nix +++ b/pkgs/build-support/dlang/dub-to-nix/default.nix @@ -4,8 +4,15 @@ makeWrapper, python3, nix, + nix-prefetch-git, }: +let + binPath = lib.makeBinPath [ + nix + nix-prefetch-git + ]; +in runCommand "dub-to-nix" { nativeBuildInputs = [ makeWrapper ]; @@ -15,5 +22,5 @@ runCommand "dub-to-nix" install -Dm755 ${./dub-to-nix.py} "$out/bin/dub-to-nix" patchShebangs "$out/bin/dub-to-nix" wrapProgram "$out/bin/dub-to-nix" \ - --prefix PATH : ${lib.makeBinPath [ nix ]} + --prefix PATH : ${binPath} '' diff --git a/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py b/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py index 48a9f241348a4..fbb51960ad7b6 100644 --- a/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py +++ b/pkgs/build-support/dlang/dub-to-nix/dub-to-nix.py @@ -4,10 +4,13 @@ import sys import json import os import subprocess +import string + def eprint(text: str): print(text, file=sys.stderr) + if not os.path.exists("dub.selections.json"): eprint("The file `dub.selections.json` does not exist in the current working directory") eprint("run `dub upgrade --annotate` to generate it") @@ -16,24 +19,53 @@ if not os.path.exists("dub.selections.json"): with open("dub.selections.json") as f: selectionsJson = json.load(f) -versionDict: dict[str, str] = selectionsJson["versions"] +depsDict: dict = selectionsJson["versions"] + +# For each dependency expand non-expanded version into a dict with a "version" key +depsDict = {pname: (versionOrDepDict if isinstance(versionOrDepDict, dict) else {"version": versionOrDepDict}) for (pname, versionOrDepDict) in depsDict.items()} + +# Don't process path-type selections +depsDict = {pname: depDict for (pname, depDict) in depsDict.items() if "path" not in depDict} -for pname in versionDict: - version = versionDict[pname] +# Pre-validate selections before trying to fetch +for pname in depsDict: + depDict = depsDict[pname] + version = depDict["version"] if version.startswith("~"): - eprint(f'Package "{pname}" has a branch-type version "{version}", which doesn\'t point to a fixed version') - eprint("You can resolve it by manually changing the required version to a fixed one inside `dub.selections.json`") - eprint("When packaging, you might need to create a patch for `dub.sdl` or `dub.json` to accept the changed version") + eprint(f'Expected version of "{pname}" to be non-branch type') + eprint(f'Found: "{version}"') + eprint("Please specify a non-branch version inside `dub.selections.json`") + eprint("When packaging, you might also need to patch the version value in the appropriate places (`dub.selections.json`, dub.sdl`, `dub.json`)") sys.exit(1) + if "repository" in depDict: + repository = depDict["repository"] + if not repository.startswith("git+"): + eprint(f'Expected repository field of "{pname}" to begin with "git+"') + eprint(f'Found: "{repository}"') + sys.exit(1) + if (len(version) < 7 or len(version) > 40 or not all(c in string.hexdigits for c in version)): + eprint(f'Expected version field of "{pname}" to begin be a valid git revision') + eprint(f'Found: "{version}"') + sys.exit(1) -lockedDependenciesDict: dict[str, dict[str, str]] = {} +lockedDepsDict: dict[str, dict[str, str]] = {} -for pname in versionDict: - version = versionDict[pname] - eprint(f"Fetching {pname}@{version}") - url = f"https://code.dlang.org/packages/{pname}/{version}.zip" - command = ["nix-prefetch-url", "--type", "sha256", url] - sha256 = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.rstrip() - lockedDependenciesDict[pname] = {"version": version, "sha256": sha256} +for pname in depsDict: + depDict = depsDict[pname] + version = depDict["version"] + if "repository" in depDict: + repository = depDict["repository"] + strippedRepo = repository[4:] + eprint(f"Fetching {pname}@{version} ({strippedRepo})") + command = ["nix-prefetch-git", strippedRepo, version] + rawRes = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout + sha256 = json.loads(rawRes)["sha256"] + lockedDepsDict[pname] = {"version": version, "repository": repository, "sha256": sha256} + else: + eprint(f"Fetching {pname}@{version}") + url = f"https://code.dlang.org/packages/{pname}/{version}.zip" + command = ["nix-prefetch-url", "--type", "sha256", url] + sha256 = subprocess.run(command, check=True, text=True, stdout=subprocess.PIPE, stderr=subprocess.DEVNULL).stdout.rstrip() + lockedDepsDict[pname] = {"version": version, "sha256": sha256} -print(json.dumps({"dependencies": lockedDependenciesDict}, indent=2)) +print(json.dumps({"dependencies": lockedDepsDict}, indent=2)) diff --git a/pkgs/build-support/dotnet/build-dotnet-global-tool/default.nix b/pkgs/build-support/dotnet/build-dotnet-global-tool/default.nix index 16cf029ca3451..7ae9cfc9f6618 100644 --- a/pkgs/build-support/dotnet/build-dotnet-global-tool/default.nix +++ b/pkgs/build-support/dotnet/build-dotnet-global-tool/default.nix @@ -28,7 +28,7 @@ buildDotnetModule (args // { ] ++ (nugetDeps fetchNuGet); }; - projectFile = ""; + dotnetGlobalTool = true; useDotnetFromEnv = true; diff --git a/pkgs/build-support/dotnet/build-dotnet-module/default.nix b/pkgs/build-support/dotnet/build-dotnet-module/default.nix index 15a753df07728..7b88b16064bca 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/default.nix +++ b/pkgs/build-support/dotnet/build-dotnet-module/default.nix @@ -69,7 +69,7 @@ , disabledTests ? [ ] # The project file to run unit tests against. This is usually referenced in the regular project file, but sometimes it needs to be manually set. # It gets restored and build, but not installed. You may need to regenerate your nuget lockfile after setting this. -, testProjectFile ? "" +, testProjectFile ? null # The type of build to perform. This is passed to `dotnet` with the `--configuration` flag. Possible values are `Release`, `Debug`, etc. , buildType ? "Release" @@ -84,23 +84,22 @@ , dotnet-sdk ? dotnetCorePackages.sdk_6_0 # The dotnet runtime to use. , dotnet-runtime ? dotnetCorePackages.runtime_6_0 - # The dotnet SDK to run tests against. This can differentiate from the SDK compiled against. -, dotnet-test-sdk ? dotnet-sdk , ... } @ args: let + projectFiles = + lib.optionals (projectFile != null) (lib.toList projectFile); + testProjectFiles = + lib.optionals (testProjectFile != null) (lib.toList testProjectFile); + platforms = if args ? meta.platforms then lib.intersectLists args.meta.platforms dotnet-sdk.meta.platforms else dotnet-sdk.meta.platforms; inherit (callPackage ./hooks { - inherit dotnet-sdk dotnet-test-sdk disabledTests nuget-source dotnet-runtime runtimeDeps buildType; - runtimeId = - if runtimeId != null - then runtimeId - else dotnetCorePackages.systemToDotnetRid stdenvNoCC.targetPlatform.system; + inherit dotnet-sdk dotnet-runtime; }) dotnetConfigureHook dotnetBuildHook dotnetCheckHook dotnetInstallHook dotnetFixupHook; localDeps = @@ -121,7 +120,7 @@ let # contains the actual package dependencies dependenciesSource = mkNugetSource { name = "${name}-dependencies-source"; - description = "A Nuget source with the dependencies for ${name}"; + description = "Nuget source with the dependencies for ${name}"; deps = [ _nugetDeps ] ++ lib.optional (localDeps != null) localDeps; }; @@ -145,6 +144,19 @@ let nugetDepsFile = _nugetDeps.sourceFile; in stdenvNoCC.mkDerivation (args // { + dotnetInstallPath = installPath; + dotnetExecutables = executables; + dotnetBuildType = buildType; + dotnetProjectFiles = projectFiles; + dotnetTestProjectFiles = testProjectFiles; + dotnetDisabledTests = disabledTests; + dotnetRuntimeId = runtimeId; + nugetSource = nuget-source; + dotnetRuntimeDeps = map lib.getLib runtimeDeps; + dotnetSelfContainedBuild = selfContainedBuild; + dotnetUseAppHost = useAppHost; + inherit useDotnetFromEnv; + nativeBuildInputs = args.nativeBuildInputs or [ ] ++ [ dotnetConfigureHook dotnetBuildHook @@ -174,7 +186,7 @@ stdenvNoCC.mkDerivation (args // { else [ ])); makeWrapperArgs = args.makeWrapperArgs or [ ] ++ [ - "--prefix LD_LIBRARY_PATH : ${dotnet-sdk.icu}/lib" + "--prefix" "LD_LIBRARY_PATH" ":" "${dotnet-sdk.icu}/lib" ]; # Stripping breaks the executable @@ -183,7 +195,9 @@ stdenvNoCC.mkDerivation (args // { # gappsWrapperArgs gets included when wrapping for dotnet, as to avoid double wrapping dontWrapGApps = args.dontWrapGApps or true; - inherit selfContainedBuild useAppHost useDotnetFromEnv; + # propagate the runtime sandbox profile since the contents apply to published + # executables + propagatedSandboxProfile = toString dotnet-runtime.__propagatedSandboxProfile; passthru = { inherit nuget-source; @@ -265,11 +279,11 @@ stdenvNoCC.mkDerivation (args // { --no-cache \ --force \ ${lib.optionalString (!enableParallelBuilding) "--disable-parallel"} \ - ${lib.optionalString (flags != []) (toString flags)} + ${lib.escapeShellArgs flags} } - declare -a projectFiles=( ${toString (lib.toList projectFile)} ) - declare -a testProjectFiles=( ${toString (lib.toList testProjectFile)} ) + declare -a projectFiles=( ${lib.escapeShellArgs projectFiles} ) + declare -a testProjectFiles=( ${lib.escapeShellArgs testProjectFiles} ) export DOTNET_NOLOGO=1 export DOTNET_CLI_TELEMETRY_OPTOUT=1 @@ -316,8 +330,4 @@ stdenvNoCC.mkDerivation (args // { } // args.passthru or { }; meta = (args.meta or { }) // { inherit platforms; }; -} - # ICU tries to unconditionally load files from /usr/share/icu on Darwin, which makes builds fail - # in the sandbox, so disable ICU on Darwin. This, as far as I know, shouldn't cause any built packages - # to behave differently, just the dotnet build tool. - // lib.optionalAttrs stdenvNoCC.isDarwin { DOTNET_SYSTEM_GLOBALIZATION_INVARIANT = 1; }) +}) diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix b/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix index 7012ff36a4a55..b9c51a743c6a6 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/default.nix @@ -4,30 +4,21 @@ , coreutils , zlib , openssl -, callPackage , makeSetupHook -, makeWrapper +, dotnetCorePackages + # Passed from ../default.nix , dotnet-sdk -, dotnet-test-sdk -, disabledTests -, nuget-source , dotnet-runtime -, runtimeDeps -, buildType -, runtimeId }: -assert (builtins.isString runtimeId); - let - libraryPath = lib.makeLibraryPath runtimeDeps; + runtimeId = dotnetCorePackages.systemToDotnetRid stdenv.hostPlatform.system; in { - dotnetConfigureHook = callPackage ({ }: - makeSetupHook { + dotnetConfigureHook = makeSetupHook + { name = "dotnet-configure-hook"; - propagatedBuildInputs = [ dotnet-sdk nuget-source ]; substitutions = { - nugetSource = nuget-source; + runtimeId = lib.escapeShellArg runtimeId; dynamicLinker = "${stdenv.cc}/nix-support/dynamic-linker"; libPath = lib.makeLibraryPath [ stdenv.cc.cc.lib @@ -36,54 +27,44 @@ in zlib openssl ]; - inherit runtimeId; }; - } ./dotnet-configure-hook.sh) { }; + } + ./dotnet-configure-hook.sh; - dotnetBuildHook = callPackage ({ }: - makeSetupHook { + dotnetBuildHook = makeSetupHook + { name = "dotnet-build-hook"; - propagatedBuildInputs = [ dotnet-sdk ]; substitutions = { - inherit buildType runtimeId; + runtimeId = lib.escapeShellArg runtimeId; }; - } ./dotnet-build-hook.sh) { }; + } + ./dotnet-build-hook.sh; - dotnetCheckHook = callPackage ({ }: - makeSetupHook { + dotnetCheckHook = makeSetupHook + { name = "dotnet-check-hook"; - propagatedBuildInputs = [ dotnet-test-sdk ]; substitutions = { - inherit buildType runtimeId libraryPath; - disabledTests = lib.optionalString (disabledTests != []) - (let - escapedNames = lib.lists.map (n: lib.replaceStrings [","] ["%2C"] n) disabledTests; - filters = lib.lists.map (n: "FullyQualifiedName!=${n}") escapedNames; - in - "${lib.concatStringsSep "&" filters}"); + runtimeId = lib.escapeShellArg runtimeId; }; - } ./dotnet-check-hook.sh) { }; + } + ./dotnet-check-hook.sh; - dotnetInstallHook = callPackage ({ }: - makeSetupHook { + dotnetInstallHook = makeSetupHook + { name = "dotnet-install-hook"; - propagatedBuildInputs = [ dotnet-sdk ]; substitutions = { - inherit buildType runtimeId; + runtimeId = lib.escapeShellArg runtimeId; }; - } ./dotnet-install-hook.sh) { }; + } + ./dotnet-install-hook.sh; - dotnetFixupHook = callPackage ({ }: - makeSetupHook { + dotnetFixupHook = makeSetupHook + { name = "dotnet-fixup-hook"; - propagatedBuildInputs = [ dotnet-runtime ]; substitutions = { dotnetRuntime = dotnet-runtime; - runtimeDeps = libraryPath; - shell = stdenv.shell; - which = "${which}/bin/which"; - dirname = "${coreutils}/bin/dirname"; - realpath = "${coreutils}/bin/realpath"; + wrapperPath = lib.makeBinPath [ which coreutils ]; }; - } ./dotnet-fixup-hook.sh) { }; + } + ./dotnet-fixup-hook.sh; } diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-build-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-build-hook.sh index 0acfeced9b169..f209861f79b15 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-build-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-build-hook.sh @@ -1,12 +1,25 @@ -# inherit arguments from derivation -dotnetBuildFlags=( ${dotnetBuildFlags[@]-} ) - dotnetBuildHook() { echo "Executing dotnetBuildHook" runHook preBuild - if [ "${enableParallelBuilding-}" ]; then + local -r hostRuntimeId=@runtimeId@ + local -r dotnetBuildType="${dotnetBuildType-Release}" + local -r dotnetRuntimeId="${dotnetRuntimeId-$hostRuntimeId}" + + if [[ -n $__structuredAttrs ]]; then + local dotnetProjectFilesArray=( "${dotnetProjectFiles[@]}" ) + local dotnetTestProjectFilesArray=( "${dotnetTestProjectFiles[@]}" ) + local dotnetFlagsArray=( "${dotnetFlags[@]}" ) + local dotnetBuildFlagsArray=( "${dotnetBuildFlags[@]}" ) + else + local dotnetProjectFilesArray=($dotnetProjectFiles) + local dotnetTestProjectFilesArray=($dotnetTestProjectFiles) + local dotnetFlagsArray=($dotnetFlags) + local dotnetBuildFlagsArray=($dotnetBuildFlags) + fi + + if [[ -n "${enableParallelBuilding-}" ]]; then local -r maxCpuFlag="$NIX_BUILD_CORES" local -r parallelBuildFlag="true" else @@ -14,50 +27,53 @@ dotnetBuildHook() { local -r parallelBuildFlag="false" fi - if [ "${selfContainedBuild-}" ]; then - dotnetBuildFlags+=("-p:SelfContained=true") + if [[ -n ${dotnetSelfContainedBuild-} ]]; then + dotnetBuildFlagsArray+=("-p:SelfContained=true") else - dotnetBuildFlags+=("-p:SelfContained=false") + dotnetBuildFlagsArray+=("-p:SelfContained=false") fi - if [ "${useAppHost-}" ]; then - dotnetBuildFlags+=("-p:UseAppHost=true") + if [[ -n ${dotnetUseAppHost-} ]]; then + dotnetBuildFlagsArray+=("-p:UseAppHost=true") fi - local versionFlags=() - if [ "${version-}" ]; then - versionFlags+=("-p:InformationalVersion=${version-}") + local versionFlagsArray=() + if [[ -n ${version-} ]]; then + versionFlagsArray+=("-p:InformationalVersion=$version") fi - if [ "${versionForDotnet-}" ]; then - versionFlags+=("-p:Version=${versionForDotnet-}") + if [[ -n ${versionForDotnet-} ]]; then + versionFlagsArray+=("-p:Version=$versionForDotnet") fi dotnetBuild() { - local -r project="${1-}" + local -r projectFile="${1-}" - runtimeIdFlags=() - if [[ "$project" == *.csproj ]] || [ "${selfContainedBuild-}" ]; then - runtimeIdFlags+=("--runtime @runtimeId@") + local runtimeIdFlagsArray=() + if [[ $projectFile == *.csproj || -n ${dotnetSelfContainedBuild-} ]]; then + runtimeIdFlagsArray+=("--runtime" "$dotnetRuntimeId") fi - env dotnet build ${project-} \ - -maxcpucount:$maxCpuFlag \ - -p:BuildInParallel=$parallelBuildFlag \ + dotnet build ${1+"$projectFile"} \ + -maxcpucount:"$maxCpuFlag" \ + -p:BuildInParallel="$parallelBuildFlag" \ -p:ContinuousIntegrationBuild=true \ -p:Deterministic=true \ - --configuration "@buildType@" \ + --configuration "$dotnetBuildType" \ --no-restore \ - ${versionFlags[@]} \ - ${runtimeIdFlags[@]} \ - ${dotnetBuildFlags[@]} \ - ${dotnetFlags[@]} + "${versionFlagsArray[@]}" \ + "${runtimeIdFlagsArray[@]}" \ + "${dotnetBuildFlagsArray[@]}" \ + "${dotnetFlagsArray[@]}" } - (( "${#projectFile[@]}" == 0 )) && dotnetBuild + if (( ${#dotnetProjectFilesArray[@]} == 0 )); then + dotnetBuild + fi - for project in ${projectFile[@]} ${testProjectFile[@]-}; do - dotnetBuild "$project" + local projectFile + for projectFile in "${dotnetProjectFilesArray[@]}" "${dotnetTestProjectFilesArray[@]}"; do + dotnetBuild "$projectFile" done runHook postBuild @@ -65,6 +81,6 @@ dotnetBuildHook() { echo "Finished dotnetBuildHook" } -if [[ -z "${dontDotnetBuild-}" && -z "${buildPhase-}" ]]; then +if [[ -z ${dontDotnetBuild-} && -z ${buildPhase-} ]]; then buildPhase=dotnetBuildHook fi diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-check-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-check-hook.sh index 507721ef98181..c91251f4f1807 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-check-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-check-hook.sh @@ -1,39 +1,65 @@ -# inherit arguments from derivation -dotnetTestFlags=( ${dotnetTestFlags[@]-} ) - dotnetCheckHook() { echo "Executing dotnetCheckHook" runHook preCheck - if [ "${disabledTests-}" ]; then - local -r disabledTestsFlag="--filter @disabledTests@" + local -r hostRuntimeId=@runtimeId@ + local -r dotnetBuildType="${dotnetBuildType-Release}" + local -r dotnetRuntimeId="${dotnetRuntimeId-$hostRuntimeId}" + + if [[ -n $__structuredAttrs ]]; then + local dotnetProjectFilesArray=( "${dotnetProjectFiles[@]}" ) + local dotnetTestProjectFilesArray=( "${dotnetTestProjectFiles[@]}" ) + local dotnetTestFlagsArray=( "${dotnetTestFlags[@]}" ) + local dotnetDisabledTestsArray=( "${dotnetDisabledTests[@]}" ) + local dotnetRuntimeDepsArray=( "${dotnetRuntimeDeps[@]}" ) + else + local dotnetProjectFilesArray=($dotnetProjectFiles) + local dotnetTestProjectFilesArray=($dotnetTestProjectFiles) + local dotnetTestFlagsArray=($dotnetTestFlags) + local dotnetDisabledTestsArray=($dotnetDisabledTests) + local dotnetRuntimeDepsArray=($dotnetRuntimeDeps) + fi + + if (( ${#dotnetDisabledTestsArray[@]} > 0 )); then + local disabledTestsFilters=("${dotnetDisabledTestsArray[@]/#/FullyQualifiedName!=}") + local OLDIFS="$IFS" IFS='&' + dotnetTestFlagsArray+=("--filter:${disabledTestsFilters[*]//,/%2C}") + IFS="$OLDIFS" + fi + + local libraryPath="${LD_LIBRARY_PATH-}" + if (( ${#dotnetRuntimeDepsArray[@]} > 0 )); then + local libraryPathArray=("${dotnetRuntimeDepsArray[@]/%//lib}") + local OLDIFS="$IFS" IFS=':' + libraryPath="${libraryPathArray[*]}${libraryPath:+':'}$libraryPath" + IFS="$OLDIFS" fi - if [ "${enableParallelBuilding-}" ]; then + if [[ -n ${enableParallelBuilding-} ]]; then local -r maxCpuFlag="$NIX_BUILD_CORES" else local -r maxCpuFlag="1" fi - for project in ${testProjectFile[@]-${projectFile[@]}}; do - runtimeIdFlags=() - if [[ "$project" == *.csproj ]]; then - runtimeIdFlags=("--runtime @runtimeId@") + local projectFile + for projectFile in "${dotnetTestProjectFilesArray[@]-${dotnetProjectFilesArray[@]}}"; do + local runtimeIdFlagsArray=() + if [[ $projectFile == *.csproj ]]; then + runtimeIdFlagsArray=("--runtime" "$dotnetRuntimeId") fi - env "LD_LIBRARY_PATH=@libraryPath@" \ - dotnet test "$project" \ - -maxcpucount:$maxCpuFlag \ + LD_LIBRARY_PATH=$libraryPath \ + dotnet test "$projectFile" \ + -maxcpucount:"$maxCpuFlag" \ -p:ContinuousIntegrationBuild=true \ -p:Deterministic=true \ - --configuration "@buildType@" \ + --configuration "$dotnetBuildType" \ --no-build \ --logger "console;verbosity=normal" \ - ${disabledTestsFlag-} \ - ${runtimeIdFlags[@]} \ - "${dotnetTestFlags[@]}" \ - "${dotnetFlags[@]}" + "${runtimeIdFlagsArray[@]}" \ + "${dotnetTestFlagsArray[@]}" \ + "${dotnetFlagsArray[@]}" done runHook postCheck diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-configure-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-configure-hook.sh index c046fc3c306b1..12fa348699865 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-configure-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-configure-hook.sh @@ -1,63 +1,103 @@ -declare -a projectFile testProjectFile - -# Inherit arguments from derivation -dotnetFlags=( ${dotnetFlags[@]-} ) -dotnetRestoreFlags=( ${dotnetRestoreFlags[@]-} ) - dotnetConfigureHook() { echo "Executing dotnetConfigureHook" runHook preConfigure - if [ -z "${enableParallelBuilding-}" ]; then + if [[ -z ${nugetSource-} ]]; then + echo + echo "ERROR: no dependencies were specified" + echo 'Hint: set `nugetSource` if using these hooks individually. If this is happening with `buildDotnetModule`, please open an issue.' + echo + + exit 1 + fi + + local nugetSourceSedQuoted="${nugetSource//[\/\\&$'\n']/\\&}" + local nugetSourceXMLQuoted="$nugetSource" + nugetSourceXMLQuoted="${nugetSource//&/\&}" + nugetSourceXMLQuoted="${nugetSourceXMLQuoted//\"/\"}" + + local -r hostRuntimeId=@runtimeId@ + local -r dynamicLinker=@dynamicLinker@ + local -r libPath=@libPath@ + local -r dotnetRuntimeId="${dotnetRuntimeId-$hostRuntimeId}" + + if [[ -n $__structuredAttrs ]]; then + local dotnetProjectFilesArray=( "${dotnetProjectFiles[@]}" ) + local dotnetTestProjectFilesArray=( "${dotnetTestProjectFiles[@]}" ) + local dotnetFlagsArray=( "${dotnetFlags[@]}" ) + local dotnetRestoreFlagsArray=( "${dotnetRestoreFlags[@]}" ) + else + local dotnetProjectFilesArray=($dotnetProjectFiles) + local dotnetTestProjectFilesArray=($dotnetTestProjectFiles) + local dotnetFlagsArray=($dotnetFlags) + local dotnetRestoreFlagsArray=($dotnetRestoreFlags) + fi + + if [[ -z ${enableParallelBuilding-} ]]; then local -r parallelFlag="--disable-parallel" fi dotnetRestore() { - local -r project="${1-}" - env dotnet restore ${project-} \ + local -r projectFile="${1-}" + dotnet restore ${1+"$projectFile"} \ -p:ContinuousIntegrationBuild=true \ -p:Deterministic=true \ - --runtime "@runtimeId@" \ - --source "@nugetSource@/lib" \ + --runtime "$dotnetRuntimeId" \ + --source "$nugetSource/lib" \ ${parallelFlag-} \ - ${dotnetRestoreFlags[@]} \ - ${dotnetFlags[@]} + "${dotnetRestoreFlagsArray[@]}" \ + "${dotnetFlagsArray[@]}" } # Generate a NuGet.config file to make sure everything, # including things like <Sdk /> dependencies, is restored from the proper source -cat <<EOF > "./NuGet.config" + cat >NuGet.config <<EOF <?xml version="1.0" encoding="utf-8"?> <configuration> <packageSources> <clear /> - <add key="nugetSource" value="@nugetSource@/lib" /> + <add key="nugetSource" value="$nugetSourceXMLQuoted/lib" /> </packageSources> </configuration> EOF - # Patch paket.dependencies and paket.lock (if found) to use the proper source. This ensures - # paket restore works correctly - # We use + instead of / in sed to avoid problems with slashes - find -name paket.dependencies -exec sed -i 's+source .*+source @nugetSource@/lib+g' {} \; - find -name paket.lock -exec sed -i 's+remote:.*+remote: @nugetSource@/lib+g' {} \; - - env dotnet tool restore --add-source "@nugetSource@/lib" - - (( "${#projectFile[@]}" == 0 )) && dotnetRestore + # Patch paket.dependencies and paket.lock (if found) to use the proper + # source. This ensures paket restore works correctly. Note that the + # nugetSourceSedQuoted abomination below safely escapes nugetSource string + # for use as a sed replacement string to avoid issues with slashes and other + # special characters ('&', '\\' and '\n'). + find -name paket.dependencies -exec sed -i "s/source .*/source $nugetSourceSedQuoted\/lib/g" {} \; + find -name paket.lock -exec sed -i "s/remote:.*/remote: $nugetSourceSedQuoted\/lib/g" {} \; + + dotnet tool restore --add-source "$nugetSource/lib" + + # dotnetGlobalTool is set in buildDotnetGlobalTool to patch dependencies but + # avoid other project-specific logic. This is a hack, but the old behavior + # is worse as it relied on a bug: setting projectFile to an empty string + # made the hooks actually skip all project-specific logic. It’s hard to keep + # backwards compatibility with this odd behavior now since we are using + # arrays, so instead we just pass a variable to indicate that we don’t have + # projects. + if [[ -z ${dotnetGlobalTool-} ]]; then + if (( ${#dotnetProjectFilesArray[@]} == 0 )); then + dotnetRestore + fi - for project in ${projectFile[@]} ${testProjectFile[@]-}; do - dotnetRestore "$project" - done + local projectFile + for projectFile in "${dotnetProjectFilesArray[@]}" "${dotnetTestProjectFilesArray[@]}"; do + dotnetRestore "$projectFile" + done + fi echo "Fixing up native binaries..." # Find all native binaries and nuget libraries, and fix them up, # by setting the proper interpreter and rpath to some commonly used libraries + local binary for binary in $(find "$HOME/.nuget/packages/" -type f -executable); do if patchelf --print-interpreter "$binary" >/dev/null 2>/dev/null; then echo "Found binary: $binary, fixing it up..." - patchelf --set-interpreter "$(cat "@dynamicLinker@")" "$binary" + patchelf --set-interpreter "$(cat "$dynamicLinker")" "$binary" # This makes sure that if the binary requires some specific runtime dependencies, it can find it. # This fixes dotnet-built binaries like crossgen2 @@ -68,7 +108,7 @@ EOF --add-needed libssl.so \ "$binary" - patchelf --set-rpath "@libPath@" "$binary" + patchelf --set-rpath "$libPath" "$binary" fi done diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh index e3671728af35e..a9701f2898b27 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh @@ -1,26 +1,60 @@ -# Inherit arguments from the derivation -declare -a derivationMakeWrapperArgs="( ${makeWrapperArgs-} )" -makeWrapperArgs=( "${derivationMakeWrapperArgs[@]}" ) +# For compatibility, convert makeWrapperArgs to an array unless we are using +# structured attributes. That is, we ensure that makeWrapperArgs is always an +# array. +# See https://github.com/NixOS/nixpkgs/blob/858f4db3048c5be3527e183470e93c1a72c5727c/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-fixup-hook.sh#L1-L3 +# and https://github.com/NixOS/nixpkgs/pull/313005#issuecomment-2175482920 +if [[ -z $__structuredAttrs ]]; then + makeWrapperArgs=( ${makeWrapperArgs-} ) +fi # First argument is the executable you want to wrap, # the second is the destination for the wrapper. wrapDotnetProgram() { - local dotnetRootFlags=() + local -r dotnetRuntime=@dotnetRuntime@ + local -r wrapperPath=@wrapperPath@ + + local -r dotnetFromEnvScript='dotnetFromEnv() { + local dotnetPath + if command -v dotnet 2>&1 >/dev/null; then + dotnetPath=$(which dotnet) && \ + dotnetPath=$(realpath "$dotnetPath") && \ + dotnetPath=$(dirname "$dotnetPath") && \ + export DOTNET_ROOT="$dotnetPath" + fi +} +dotnetFromEnv' + + if [[ -n $__structuredAttrs ]]; then + local -r dotnetRuntimeDepsArray=( "${dotnetRuntimeDeps[@]}" ) + else + local -r dotnetRuntimeDepsArray=($dotnetRuntimeDeps) + fi - if [ ! "${selfContainedBuild-}" ]; then - if [ "${useDotnetFromEnv-}" ]; then + local dotnetRuntimeDepsFlags=() + if (( ${#dotnetRuntimeDepsArray[@]} > 0 )); then + local libraryPathArray=("${dotnetRuntimeDepsArray[@]/%//lib}") + local OLDIFS="$IFS" IFS=':' + dotnetRuntimeDepsFlags+=("--suffix" "LD_LIBRARY_PATH" ":" "${libraryPathArray[*]}") + IFS="$OLDIFS" + fi + + local dotnetRootFlagsArray=() + if [[ -z ${dotnetSelfContainedBuild-} ]]; then + if [[ -n ${useDotnetFromEnv-} ]]; then # if dotnet CLI is available, set DOTNET_ROOT based on it. Otherwise set to default .NET runtime - dotnetRootFlags+=("--run" 'command -v dotnet &>/dev/null && export DOTNET_ROOT="$(@dirname@ "$(@realpath@ "$(@which@ dotnet)")")" || export DOTNET_ROOT="@dotnetRuntime@"') - dotnetRootFlags+=("--suffix" "PATH" ":" "@dotnetRuntime@/bin") + dotnetRootFlagsArray+=("--suffix" "PATH" ":" "$wrapperPath") + dotnetRootFlagsArray+=("--run" "$dotnetFromEnvScript") + dotnetRootFlagsArray+=("--set-default" "DOTNET_ROOT" "$dotnetRuntime") + dotnetRootFlagsArray+=("--suffix" "PATH" ":" "$dotnetRuntime/bin") else - dotnetRootFlags+=("--set" "DOTNET_ROOT" "@dotnetRuntime@") - dotnetRootFlags+=("--prefix" "PATH" ":" "@dotnetRuntime@/bin") + dotnetRootFlagsArray+=("--set" "DOTNET_ROOT" "$dotnetRuntime") + dotnetRootFlagsArray+=("--prefix" "PATH" ":" "$dotnetRuntime/bin") fi fi makeWrapper "$1" "$2" \ - --suffix "LD_LIBRARY_PATH" : "@runtimeDeps@" \ - "${dotnetRootFlags[@]}" \ + "${dotnetRuntimeDepsFlags[@]}" \ + "${dotnetRootFlagsArray[@]}" \ "${gappsWrapperArgs[@]}" \ "${makeWrapperArgs[@]}" @@ -30,13 +64,24 @@ wrapDotnetProgram() { dotnetFixupHook() { echo "Executing dotnetFixupPhase" - # check if executables is declared (including empty values, in which case we generate no executables) - if declare -p executables &>/dev/null; then - for executable in ${executables[@]}; do - path="${installPath-$out/lib/$pname}/$executable" + local -r dotnetInstallPath="${dotnetInstallPath-$out/lib/$pname}" + + local executable executableBasename + + # check if dotnetExecutables is declared (including empty values, in which case we generate no executables) + if declare -p dotnetExecutables &>/dev/null; then + if [[ -n $__structuredAttrs ]]; then + local dotnetExecutablesArray=( "${dotnetExecutables[@]}" ) + else + local dotnetExecutablesArray=($dotnetExecutables) + fi + for executable in "${dotnetExecutablesArray[@]}"; do + executableBasename=$(basename "$executable") + + local path="$dotnetInstallPath/$executable" if test -x "$path"; then - wrapDotnetProgram "$path" "$out/bin/$(basename "$executable")" + wrapDotnetProgram "$path" "$out/bin/$executableBasename" else echo "Specified binary \"$executable\" is either not an executable or does not exist!" echo "Looked in $path" @@ -45,8 +90,9 @@ dotnetFixupHook() { done else while IFS= read -d '' executable; do - wrapDotnetProgram "$executable" "$out/bin/$(basename "$executable")" \; - done < <(find "${installPath-$out/lib/$pname}" ! -name "*.dll" -executable -type f -print0) + executableBasename=$(basename "$executable") + wrapDotnetProgram "$executable" "$out/bin/$executableBasename" \; + done < <(find "$dotnetInstallPath" ! -name "*.dll" -executable -type f -print0) fi echo "Finished dotnetFixupPhase" diff --git a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-install-hook.sh b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-install-hook.sh index d832eac288096..4d9b3c502c354 100644 --- a/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-install-hook.sh +++ b/pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-install-hook.sh @@ -1,70 +1,86 @@ -# inherit arguments from derivation -dotnetInstallFlags=( ${dotnetInstallFlags[@]-} ) - dotnetInstallHook() { echo "Executing dotnetInstallHook" runHook preInstall - if [ "${selfContainedBuild-}" ]; then - dotnetInstallFlags+=("--self-contained") + local -r hostRuntimeId=@runtimeId@ + local -r dotnetInstallPath="${dotnetInstallPath-$out/lib/$pname}" + local -r dotnetBuildType="${dotnetBuildType-Release}" + local -r dotnetRuntimeId="${dotnetRuntimeId-$hostRuntimeId}" + + if [[ -n $__structuredAttrs ]]; then + local dotnetProjectFilesArray=( "${dotnetProjectFiles[@]}" ) + local dotnetFlagsArray=( "${dotnetFlags[@]}" ) + local dotnetInstallFlagsArray=( "${dotnetInstallFlags[@]}" ) + local dotnetPackFlagsArray=( "${dotnetPackFlags[@]}" ) + else + local dotnetProjectFilesArray=($dotnetProjectFiles) + local dotnetFlagsArray=($dotnetFlags) + local dotnetInstallFlagsArray=($dotnetInstallFlags) + local dotnetPackFlagsArray=($dotnetPackFlags) + fi + + if [[ -n ${dotnetSelfContainedBuild-} ]]; then + dotnetInstallFlagsArray+=("--self-contained") else - dotnetInstallFlags+=("--no-self-contained") + dotnetInstallFlagsArray+=("--no-self-contained") # https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trim-self-contained # Trimming is only available for self-contained build, so force disable it here - dotnetInstallFlags+=("-p:PublishTrimmed=false") + dotnetInstallFlagsArray+=("-p:PublishTrimmed=false") fi - if [ "${useAppHost-}" ]; then - dotnetInstallFlags+=("-p:UseAppHost=true") + if [[ -n ${dotnetUseAppHost-} ]]; then + dotnetInstallFlagsArray+=("-p:UseAppHost=true") fi dotnetPublish() { - local -r project="${1-}" + local -r projectFile="${1-}" - runtimeIdFlags=() - if [[ "$project" == *.csproj ]] || [ "${selfContainedBuild-}" ]; then - runtimeIdFlags+=("--runtime @runtimeId@") + runtimeIdFlagsArray=() + if [[ $projectFile == *.csproj || -n ${dotnetSelfContainedBuild-} ]]; then + runtimeIdFlagsArray+=("--runtime" "$dotnetRuntimeId") fi - env dotnet publish ${project-} \ + dotnet publish ${1+"$projectFile"} \ -p:ContinuousIntegrationBuild=true \ -p:Deterministic=true \ - --output "${installPath-$out/lib/$pname}" \ - --configuration "@buildType@" \ + --output "$dotnetInstallPath" \ + --configuration "$dotnetBuildType" \ --no-build \ - ${runtimeIdFlags[@]} \ - ${dotnetInstallFlags[@]} \ - ${dotnetFlags[@]} + "${runtimeIdFlagsArray[@]}" \ + "${dotnetInstallFlagsArray[@]}" \ + "${dotnetFlagsArray[@]}" } dotnetPack() { - local -r project="${1-}" - env dotnet pack ${project-} \ + local -r projectFile="${1-}" + dotnet pack ${1+"$projectFile"} \ -p:ContinuousIntegrationBuild=true \ -p:Deterministic=true \ --output "$out/share" \ - --configuration "@buildType@" \ + --configuration "$dotnetBuildType" \ --no-build \ - --runtime "@runtimeId@" \ - ${dotnetPackFlags[@]} \ - ${dotnetFlags[@]} + --runtime "$dotnetRuntimeId" \ + "${dotnetPackFlagsArray[@]}" \ + "${dotnetFlagsArray[@]}" } - if (( "${#projectFile[@]}" == 0 )); then + if (( ${#dotnetProjectFilesArray[@]} == 0 )); then dotnetPublish else - for project in ${projectFile[@]}; do - dotnetPublish "$project" + local projectFile + for projectFile in "${dotnetProjectFilesArray[@]}"; do + dotnetPublish "$projectFile" done fi - if [[ "${packNupkg-}" ]]; then - if (( "${#projectFile[@]}" == 0 )); then + if [[ -n ${packNupkg-} ]]; then + if (( ${#dotnetProjectFilesArray[@]} == 0 )); then dotnetPack else - for project in ${projectFile[@]}; do - dotnetPack "$project" + local projectFile + for projectFile in "${dotnetProjectFilesArray[@]}"; do + dotnetPack "$projectFile" done fi fi diff --git a/pkgs/build-support/emacs/melpa.nix b/pkgs/build-support/emacs/melpa.nix index 323c6e65d9d90..c8f6567049180 100644 --- a/pkgs/build-support/emacs/melpa.nix +++ b/pkgs/build-support/emacs/melpa.nix @@ -35,25 +35,41 @@ in pname /* ename: Original Emacs package name, possibly containing special symbols. + Default: pname */ -, ename ? null +, ename ? pname , version -, recipe + /* + commit: Optional package history commit. + Default: src.rev or "unknown" + This will be written into the generated package but it is not needed during + the build process. + */ +, commit ? (args.src.rev or "unknown") + /* + files: Optional recipe property specifying the files used to build the package. + If null, do not set it in recipe, keeping the default upstream behaviour. + Default: null + */ +, files ? null + /* + recipe: Optional MELPA recipe. + Default: a minimally functional recipe + */ +, recipe ? (writeText "${pname}-recipe" '' + (${ename} :fetcher git :url "" + ${lib.optionalString (files != null) ":files ${files}"}) + '') , meta ? {} , ... }@args: genericBuild ({ - ename = - if ename == null - then pname - else ename; - elpa2nix = ./elpa2nix.el; melpa2nix = ./melpa2nix.el; - inherit packageBuild; + inherit packageBuild commit ename recipe; preUnpack = '' mkdir -p "$NIX_BUILD_TOP/recipes" diff --git a/pkgs/build-support/fetchgit/nix-prefetch-git b/pkgs/build-support/fetchgit/nix-prefetch-git index 7ac3dec91f7f4..0f41cbd6a265d 100755 --- a/pkgs/build-support/fetchgit/nix-prefetch-git +++ b/pkgs/build-support/fetchgit/nix-prefetch-git @@ -166,7 +166,7 @@ checkout_hash(){ clean_git fetch -t ${builder:+--progress} origin || return 1 local object_type=$(git cat-file -t "$hash") - if [[ "$object_type" == "commit" ]]; then + if [[ "$object_type" == "commit" || "$object_type" == "tag" ]]; then clean_git checkout -b "$branchName" "$hash" || return 1 elif [[ "$object_type" == "tree" ]]; then clean_git config user.email "nix-prefetch-git@localhost" diff --git a/pkgs/build-support/fetchgit/tests.nix b/pkgs/build-support/fetchgit/tests.nix index 23e5fa299010d..f3fcd9a578de4 100644 --- a/pkgs/build-support/fetchgit/tests.nix +++ b/pkgs/build-support/fetchgit/tests.nix @@ -72,4 +72,11 @@ leaveDotGit = true; fetchSubmodules = true; }; + + dumb-http-signed-tag = testers.invalidateFetcherByDrvHash fetchgit { + name = "dumb-http-signed-tag-source"; + url = "https://git.scottworley.com/pub/git/pinch"; + rev = "v3.0.14"; + sha256 = "sha256-bd0Lx75Gd1pcBJtwz5WGki7XoYSpqhinCT3a77wpY2c="; + }; } diff --git a/pkgs/build-support/fetchtorrent/default.nix b/pkgs/build-support/fetchtorrent/default.nix index 126748678bf25..041c1b9dcb394 100644 --- a/pkgs/build-support/fetchtorrent/default.nix +++ b/pkgs/build-support/fetchtorrent/default.nix @@ -1,4 +1,4 @@ -{ lib, runCommand, transmission_noSystemd, rqbit, writeShellScript, formats, cacert, rsync }: +{ lib, runCommand, transmission_3_noSystemd, rqbit, writeShellScript, formats, cacert, rsync }: let urlRegexp = ''.*xt=urn:bt[im]h:([^&]{64}|[^&]{40}).*''; in @@ -32,7 +32,7 @@ let in runCommand name { inherit meta; - nativeBuildInputs = [ cacert ] ++ (if (backend == "transmission" ) then [ transmission_noSystemd ] else if (backend == "rqbit") then [ rqbit ] else throw "rqbit or transmission are the only available backends for fetchtorrent"); + nativeBuildInputs = [ cacert ] ++ (if (backend == "transmission" ) then [ transmission_3_noSystemd ] else if (backend == "rqbit") then [ rqbit ] else throw "rqbit or transmission are the only available backends for fetchtorrent"); outputHashAlgo = if hash != "" then null else "sha256"; outputHash = hash; outputHashMode = if recursiveHash then "recursive" else "flat"; diff --git a/pkgs/build-support/flutter/default.nix b/pkgs/build-support/flutter/default.nix index 5d7cd7d984c17..ff6c6b31006f7 100644 --- a/pkgs/build-support/flutter/default.nix +++ b/pkgs/build-support/flutter/default.nix @@ -2,7 +2,7 @@ , callPackage , runCommand , makeWrapper -, wrapGAppsHook +, wrapGAppsHook3 , buildDartApplication , cacert , glib @@ -10,21 +10,32 @@ , pkg-config , jq , yq -, moreutils }: # absolutely no mac support for now -{ pubGetScript ? "flutter pub get" +{ pubGetScript ? null , flutterBuildFlags ? [ ] , targetFlutterPlatform ? "linux" , extraWrapProgramArgs ? "" +, flutterMode ? null , ... }@args: let + hasEngine = flutter ? engine && flutter.engine != null && flutter.engine.meta.available; + flutterMode = args.flutterMode or (if hasEngine then flutter.engine.runtimeMode else "release"); + + flutterFlags = lib.optional hasEngine "--local-engine host_${flutterMode}${lib.optionalString (!flutter.engine.isOptimized) "_unopt"}"; + + flutterBuildFlags = [ + "--${flutterMode}" + ] ++ (args.flutterBuildFlags or []) ++ flutterFlags; + builderArgs = rec { universal = args // { + inherit flutterMode flutterFlags flutterBuildFlags; + sdkSetupScript = '' # Pub needs SSL certificates. Dart normally looks in a hardcoded path. # https://github.com/dart-lang/sdk/blob/3.1.0/runtime/bin/security_context_linux.cc#L48 @@ -47,11 +58,11 @@ let ''}/bin/dart" export HOME="$NIX_BUILD_TOP" - flutter config --no-analytics &>/dev/null # mute first-run - flutter config --enable-linux-desktop >/dev/null + flutter config $flutterFlags --no-analytics &>/dev/null # mute first-run + flutter config $flutterFlags --enable-linux-desktop >/dev/null ''; - inherit pubGetScript; + pubGetScript = args.pubGetScript or "flutter${lib.optionalString hasEngine " --local-engine $flutterMode"} pub get"; sdkSourceBuilders = { # https://github.com/dart-lang/pub/blob/68dc2f547d0a264955c1fa551fa0a0e158046494/lib/src/sdk/flutter.dart#L81 @@ -68,16 +79,34 @@ let exit 1 fi ''; + # https://github.com/dart-lang/pub/blob/e1fbda73d1ac597474b82882ee0bf6ecea5df108/lib/src/sdk/dart.dart#L80 + "dart" = name: runCommand "dart-sdk-${name}" { passthru.packageRoot = "."; } '' + for path in '${flutter.dart}/pkg/${name}'; do + if [ -d "$path" ]; then + ln -s "$path" "$out" + break + fi + done + + if [ ! -e "$out" ]; then + echo 1>&2 'The Dart 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 + export TEMP_PACKAGES=$(mktemp) '${jq}/bin/jq' '.packages |= . + [{ name: "flutter_gen", rootUri: "flutter_gen", languageVersion: "2.12", - }]' "$out" | '${moreutils}/bin/sponge' "$out" + }]' "$out" > "$TEMP_PACKAGES" + cp "$TEMP_PACKAGES" "$out" + rm "$TEMP_PACKAGES" + unset TEMP_PACKAGES fi ''; }; @@ -86,7 +115,7 @@ let outputs = universal.outputs or [ ] ++ [ "debug" ]; nativeBuildInputs = (universal.nativeBuildInputs or [ ]) ++ [ - wrapGAppsHook + wrapGAppsHook3 # Flutter requires pkg-config for Linux desktop support, and many plugins # attempt to use it. @@ -105,7 +134,7 @@ let mkdir -p build/flutter_assets/fonts - flutter build linux -v --release --split-debug-info="$debug" ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)} + flutter build linux -v --split-debug-info="$debug" $flutterBuildFlags runHook postBuild ''; @@ -114,7 +143,7 @@ let installPhase = universal.installPhase or '' runHook preInstall - built=build/linux/*/release/bundle + built=build/linux/*/$flutterMode/bundle mkdir -p $out/bin mv $built $out/app @@ -156,7 +185,7 @@ let mkdir -p build/flutter_assets/fonts - flutter build web -v --release ${builtins.concatStringsSep " " (map (flag: "\"${flag}\"") flutterBuildFlags)} + flutter build web -v $flutterBuildFlags runHook postBuild ''; diff --git a/pkgs/build-support/go/module.nix b/pkgs/build-support/go/module.nix index 6f568c0eb4f95..bc28fbf6fc420 100644 --- a/pkgs/build-support/go/module.nix +++ b/pkgs/build-support/go/module.nix @@ -163,8 +163,10 @@ let inherit (go) GOOS GOARCH; GOFLAGS = GOFLAGS - ++ lib.optional (!proxyVendor) "-mod=vendor" - ++ lib.optional (!allowGoReference) "-trimpath"; + ++ lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS" + (lib.optional (!proxyVendor) "-mod=vendor") + ++ lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true" + (lib.optional (!allowGoReference) "-trimpath"); inherit CGO_ENABLED enableParallelBuilding GO111MODULE GOTOOLCHAIN; # If not set to an explicit value, set the buildid empty for reproducibility. @@ -196,7 +198,12 @@ let runHook postConfigure ''); - buildPhase = args.buildPhase or ('' + buildPhase = args.buildPhase or ( + lib.warnIf (buildFlags != "" || buildFlagsArray != "") + "`buildFlags`/`buildFlagsArray` are deprecated and will be removed in the 24.11 release. Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`" + lib.warnIf (builtins.elem "-buildid=" ldflags) + "`-buildid=` is set by default as ldflag by buildGoModule" + '' runHook preBuild exclude='\(/_\|examples\|Godeps\|testdata' @@ -313,9 +320,4 @@ let } // meta; }); in -lib.warnIf (buildFlags != "" || buildFlagsArray != "") - "Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`" -lib.warnIf (builtins.elem "-buildid=" ldflags) "`-buildid=` is set by default as ldflag by buildGoModule" -lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true" -lib.warnIf (lib.any (lib.hasPrefix "-mod=") GOFLAGS) "use `proxyVendor` to control Go module/vendor behavior instead of setting `-mod=` in GOFLAGS" - package +package diff --git a/pkgs/build-support/go/package.nix b/pkgs/build-support/go/package.nix index 94a459c267f36..58a242a2535c2 100644 --- a/pkgs/build-support/go/package.nix +++ b/pkgs/build-support/go/package.nix @@ -286,7 +286,7 @@ let }); in lib.warnIf (buildFlags != "" || buildFlagsArray != "") - "Use the `ldflags` and/or `tags` attributes instead of `buildFlags`/`buildFlagsArray`" + "`buildFlags`/`buildFlagsArray` are deprecated and will be removed in the 24.11 release. Use the `ldflags` and/or `tags` attributes instead" lib.warnIf (builtins.elem "-buildid=" ldflags) "`-buildid=` is set by default as ldflag by buildGoModule" lib.warnIf (builtins.elem "-trimpath" GOFLAGS) "`-trimpath` is added by default to GOFLAGS by buildGoModule when allowGoReference isn't set to true" package diff --git a/pkgs/build-support/kernel/compress-firmware-xz.nix b/pkgs/build-support/kernel/compress-firmware-xz.nix deleted file mode 100644 index cb9ce7a713389..0000000000000 --- a/pkgs/build-support/kernel/compress-firmware-xz.nix +++ /dev/null @@ -1,29 +0,0 @@ -{ runCommand, lib }: - -firmware: - -let - args = { - allowedRequisites = []; - } // lib.optionalAttrs (firmware ? meta) { inherit (firmware) meta; }; -in - -runCommand "${firmware.name}-xz" args '' - mkdir -p $out/lib - (cd ${firmware} && find lib/firmware -type d -print0) | - (cd $out && xargs -0 mkdir -v --) - (cd ${firmware} && find lib/firmware -type f -print0) | - (cd $out && xargs -0rtP "$NIX_BUILD_CORES" -n1 \ - sh -c 'xz -9c -T1 -C crc32 --lzma2=dict=2MiB "${firmware}/$1" > "$1.xz"' --) - (cd ${firmware} && find lib/firmware -type l) | while read link; do - target="$(readlink "${firmware}/$link")" - if [ -f "${firmware}/$link" ]; then - ln -vs -- "''${target/^${firmware}/$out}.xz" "$out/$link.xz" - else - ln -vs -- "''${target/^${firmware}/$out}" "$out/$link" - fi - done - - echo "Checking for broken symlinks:" - find -L $out -type l -print -execdir false -- '{}' '+' -'' diff --git a/pkgs/build-support/kernel/compress-firmware.nix b/pkgs/build-support/kernel/compress-firmware.nix new file mode 100644 index 0000000000000..0949036d5127f --- /dev/null +++ b/pkgs/build-support/kernel/compress-firmware.nix @@ -0,0 +1,43 @@ +{ runCommand, lib, type ? "zstd", zstd }: + +firmware: + +let + compressor = { + xz = { + ext = "xz"; + nativeBuildInputs = [ ]; + cmd = file: target: ''xz -9c -T1 -C crc32 --lzma2=dict=2MiB "${file}" > "${target}"''; + }; + zstd = { + ext = "zst"; + nativeBuildInputs = [ zstd ]; + cmd = file: target: ''zstd -T1 -19 --long --check -f "${file}" -o "${target}"''; + }; + }.${type} or (throw "Unsupported compressor type for firmware."); + + args = { + allowedRequisites = []; + inherit (compressor) nativeBuildInputs; + } // lib.optionalAttrs (firmware ? meta) { inherit (firmware) meta; }; +in + +runCommand "${firmware.name}-${type}" args '' + mkdir -p $out/lib + (cd ${firmware} && find lib/firmware -type d -print0) | + (cd $out && xargs -0 mkdir -v --) + (cd ${firmware} && find lib/firmware -type f -print0) | + (cd $out && xargs -0rtP "$NIX_BUILD_CORES" -n1 \ + sh -c '${compressor.cmd "${firmware}/$1" "$1.${compressor.ext}"}' --) + (cd ${firmware} && find lib/firmware -type l) | while read link; do + target="$(readlink "${firmware}/$link")" + if [ -f "${firmware}/$link" ]; then + ln -vs -- "''${target/^${firmware}/$out}.${compressor.ext}" "$out/$link.${compressor.ext}" + else + ln -vs -- "''${target/^${firmware}/$out}" "$out/$link" + fi + done + + echo "Checking for broken symlinks:" + find -L $out -type l -print -execdir false -- '{}' '+' +'' diff --git a/pkgs/build-support/kernel/make-initrd-ng-tool.nix b/pkgs/build-support/kernel/make-initrd-ng-tool.nix index 5e08c091c0549..7ffa0bf6813a5 100644 --- a/pkgs/build-support/kernel/make-initrd-ng-tool.nix +++ b/pkgs/build-support/kernel/make-initrd-ng-tool.nix @@ -12,7 +12,7 @@ rustPlatform.buildRustPackage { meta = { description = "Tool for copying binaries and their dependencies"; mainProgram = "make-initrd-ng"; - maintainers = with lib.maintainers; [ das_j elvishjerricco k900 lheckemann ]; + maintainers = with lib.maintainers; [ das_j elvishjerricco k900 ]; license = lib.licenses.mit; }; } diff --git a/pkgs/build-support/kernel/modules-closure.sh b/pkgs/build-support/kernel/modules-closure.sh index 5f61bac751af2..06eb5b0d0de12 100644 --- a/pkgs/build-support/kernel/modules-closure.sh +++ b/pkgs/build-support/kernel/modules-closure.sh @@ -80,7 +80,7 @@ for module in $(< ~-/closure); do # of its output. modinfo -b $kernel --set-version "$version" -F firmware $module | grep -v '^name:' | while read -r i; do echo "firmware for $module: $i" - for name in "$i" "$i.xz" ""; do + for name in "$i" "$i.xz" "$i.zst" ""; do [ -z "$name" ] && echo "WARNING: missing firmware $i for module $module" if cp -v --parents --no-preserve=mode lib/firmware/$name "$out" 2>/dev/null; then break diff --git a/pkgs/build-support/lib/meson.nix b/pkgs/build-support/lib/meson.nix index 456c10fcb8eeb..9ffc5b8c1710f 100644 --- a/pkgs/build-support/lib/meson.nix +++ b/pkgs/build-support/lib/meson.nix @@ -23,6 +23,10 @@ let [binaries] llvm-config = 'llvm-config-native' rust = ['rustc', '--target', '${stdenv.targetPlatform.rust.rustcTargetSpec}'] + # Meson refuses to consider any CMake binary during cross compilation if it's + # not explicitly specified here, in the cross file. + # https://github.com/mesonbuild/meson/blob/0ed78cf6fa6d87c0738f67ae43525e661b50a8a2/mesonbuild/cmake/executor.py#L72 + cmake = 'cmake' ''; crossFlags = optionals (stdenv.hostPlatform != stdenv.buildPlatform) [ "--cross-file=${crossFile}" ]; diff --git a/pkgs/build-support/libredirect/default.nix b/pkgs/build-support/libredirect/default.nix index 1ab4a0db827aa..c4399189b7a21 100644 --- a/pkgs/build-support/libredirect/default.nix +++ b/pkgs/build-support/libredirect/default.nix @@ -112,7 +112,7 @@ else stdenv.mkDerivation rec { meta = with lib; { platforms = platforms.unix; - description = "An LD_PRELOAD library to intercept and rewrite the paths in glibc calls"; + description = "LD_PRELOAD library to intercept and rewrite the paths in glibc calls"; longDescription = '' libredirect is an LD_PRELOAD library to intercept and rewrite the paths in glibc calls based on the value of $NIX_REDIRECTS, a colon-separated list diff --git a/pkgs/build-support/make-pkgconfigitem/default.nix b/pkgs/build-support/make-pkgconfigitem/default.nix index d3bcabbb940f9..e459184b8d7eb 100644 --- a/pkgs/build-support/make-pkgconfigitem/default.nix +++ b/pkgs/build-support/make-pkgconfigitem/default.nix @@ -4,7 +4,7 @@ { name # The name of the pc file # keywords # provide a default description for convenience. it's not important but still required by pkg-config. -, description ? "A pkg-config file for ${name}" +, description ? "Pkg-config file for ${name}" , url ? "" , version ? "" , requires ? [ ] diff --git a/pkgs/build-support/node/fetch-yarn-deps/default.nix b/pkgs/build-support/node/fetch-yarn-deps/default.nix index 7f0e0692f81f6..4ef74c0cab884 100644 --- a/pkgs/build-support/node/fetch-yarn-deps/default.nix +++ b/pkgs/build-support/node/fetch-yarn-deps/default.nix @@ -25,7 +25,8 @@ in { tar --strip-components=1 -xf ${yarnpkg-lockfile-tar} package/index.js mv index.js $out/libexec/yarnpkg-lockfile.js - cp ${./.}/common.js ${./.}/index.js $out/libexec/ + cp ${./common.js} $out/libexec/common.js + cp ${./index.js} $out/libexec/index.js patchShebangs $out/libexec makeWrapper $out/libexec/index.js $out/bin/prefetch-yarn-deps \ @@ -53,7 +54,8 @@ in { tar --strip-components=1 -xf ${yarnpkg-lockfile-tar} package/index.js mv index.js $out/libexec/yarnpkg-lockfile.js - cp ${./.}/common.js ${./.}/fixup.js $out/libexec/ + cp ${./common.js} $out/libexec/common.js + cp ${./fixup.js} $out/libexec/fixup.js patchShebangs $out/libexec makeWrapper $out/libexec/fixup.js $out/bin/fixup-yarn-lock @@ -97,7 +99,7 @@ in { ''; outputHashMode = "recursive"; - } // hash_ // (removeAttrs args ["src" "name" "hash" "sha256"])); + } // hash_ // (removeAttrs args (["name" "hash" "sha256"] ++ (lib.optional (src == null) "src")))); in lib.setFunctionArgs f (lib.functionArgs f) // { inherit tests; diff --git a/pkgs/build-support/ocaml/dune.nix b/pkgs/build-support/ocaml/dune.nix index 972244f80b0a4..e293605cb31d0 100644 --- a/pkgs/build-support/ocaml/dune.nix +++ b/pkgs/build-support/ocaml/dune.nix @@ -7,8 +7,7 @@ let Dune = { "1" = dune_1; "2" = dune_2; "3" = dune_3; }."${dune-version}" ; in -if (args ? minimumOCamlVersion && lib.versionOlder ocaml.version args.minimumOCamlVersion) || - (args ? minimalOCamlVersion && lib.versionOlder ocaml.version args.minimalOCamlVersion) +if args ? minimalOCamlVersion && lib.versionOlder ocaml.version args.minimalOCamlVersion then throw "${pname}-${version} is not available for OCaml ${ocaml.version}" else diff --git a/pkgs/build-support/php/build-composer-project.nix b/pkgs/build-support/php/build-composer-project.nix deleted file mode 100644 index 80c63bcde71b9..0000000000000 --- a/pkgs/build-support/php/build-composer-project.nix +++ /dev/null @@ -1,85 +0,0 @@ -{ callPackage, stdenvNoCC, lib, writeTextDir, php, makeBinaryWrapper, fetchFromGitHub, fetchurl }: - -let - buildComposerProjectOverride = finalAttrs: previousAttrs: - - let - phpDrv = finalAttrs.php or php; - composer = finalAttrs.composer or phpDrv.packages.composer; - composer-local-repo-plugin = callPackage ./pkgs/composer-local-repo-plugin.nix { }; - in - { - composerLock = previousAttrs.composerLock or null; - composerNoDev = previousAttrs.composerNoDev or true; - composerNoPlugins = previousAttrs.composerNoPlugins or true; - composerNoScripts = previousAttrs.composerNoScripts or true; - composerStrictValidation = previousAttrs.composerStrictValidation or true; - - nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [ - composer - composer-local-repo-plugin - phpDrv - phpDrv.composerHooks.composerInstallHook - ]; - - buildInputs = (previousAttrs.buildInputs or [ ]) ++ [ - phpDrv - ]; - - patches = previousAttrs.patches or [ ]; - strictDeps = previousAttrs.strictDeps or true; - - # Should we keep these empty phases? - configurePhase = previousAttrs.configurePhase or '' - runHook preConfigure - - runHook postConfigure - ''; - - buildPhase = previousAttrs.buildPhase or '' - runHook preBuild - - runHook postBuild - ''; - - doCheck = previousAttrs.doCheck or true; - checkPhase = previousAttrs.checkPhase or '' - runHook preCheck - - runHook postCheck - ''; - - installPhase = previousAttrs.installPhase or '' - runHook preInstall - - runHook postInstall - ''; - - doInstallCheck = previousAttrs.doInstallCheck or false; - installCheckPhase = previousAttrs.installCheckPhase or '' - runHook preInstallCheck - - runHook postInstallCheck - ''; - - composerRepository = phpDrv.mkComposerRepository { - inherit composer composer-local-repo-plugin; - inherit (finalAttrs) patches pname src vendorHash version; - - composerLock = previousAttrs.composerLock or null; - composerNoDev = previousAttrs.composerNoDev or true; - composerNoPlugins = previousAttrs.composerNoPlugins or true; - composerNoScripts = previousAttrs.composerNoScripts or true; - composerStrictValidation = previousAttrs.composerStrictValidation or true; - }; - - COMPOSER_CACHE_DIR="/dev/null"; - COMPOSER_DISABLE_NETWORK="1"; - COMPOSER_MIRROR_PATH_REPOS="1"; - - meta = previousAttrs.meta or { } // { - platforms = lib.platforms.all; - }; - }; -in -args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerProjectOverride diff --git a/pkgs/build-support/php/build-pecl.nix b/pkgs/build-support/php/build-pecl.nix index 6f38a668f3a34..16913a85c63de 100644 --- a/pkgs/build-support/php/build-pecl.nix +++ b/pkgs/build-support/php/build-pecl.nix @@ -1,45 +1,69 @@ -{ stdenv, lib, php, autoreconfHook, fetchurl, re2c, nix-update-script }: +{ + stdenv, + lib, + php, + autoreconfHook, + fetchurl, + re2c, + nix-update-script, +}: -{ pname -, version -, internalDeps ? [ ] -, peclDeps ? [ ] -, buildInputs ? [ ] -, nativeBuildInputs ? [ ] -, postPhpize ? "" -, makeFlags ? [ ] -, src ? fetchurl ({ - url = "https://pecl.php.net/get/${pname}-${version}.tgz"; - } // lib.filterAttrs (attrName: _: lib.elem attrName [ "sha256" "hash" ]) args) -, passthru ? { } -, ... +{ + pname, + version, + internalDeps ? [ ], + peclDeps ? [ ], + buildInputs ? [ ], + nativeBuildInputs ? [ ], + postPhpize ? "", + makeFlags ? [ ], + src ? fetchurl ( + { + url = "https://pecl.php.net/get/${pname}-${version}.tgz"; + } + // lib.filterAttrs ( + attrName: _: + lib.elem attrName [ + "sha256" + "hash" + ] + ) args + ), + passthru ? { }, + ... }@args: -stdenv.mkDerivation (args // { - name = "php-${pname}-${version}"; - extensionName = pname; +stdenv.mkDerivation ( + args + // { + name = "php-${pname}-${version}"; + extensionName = pname; - inherit src; + inherit src; - nativeBuildInputs = [ autoreconfHook re2c ] ++ nativeBuildInputs; - buildInputs = [ php ] ++ peclDeps ++ buildInputs; + nativeBuildInputs = [ + autoreconfHook + re2c + ] ++ nativeBuildInputs; + buildInputs = [ php ] ++ peclDeps ++ buildInputs; - makeFlags = [ "EXTENSION_DIR=$(out)/lib/php/extensions" ] ++ makeFlags; + makeFlags = [ "EXTENSION_DIR=$(out)/lib/php/extensions" ] ++ makeFlags; - autoreconfPhase = '' - phpize - ${postPhpize} - ${lib.concatMapStringsSep "\n" - (dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}") - internalDeps} - ''; - checkPhase = "NO_INTERACTON=yes make test"; + autoreconfPhase = '' + phpize + ${postPhpize} + ${lib.concatMapStringsSep "\n" ( + dep: "mkdir -p ext; ln -s ${dep.dev}/include ext/${dep.extensionName}" + ) internalDeps} + ''; + checkPhase = "NO_INTERACTON=yes make test"; - passthru = passthru // { - # Thes flags were introduced for `nix-update` so that it can update - # PHP extensions correctly. - # See the corresponding PR: https://github.com/Mic92/nix-update/pull/123 - isPhpExtension = true; - updateScript = nix-update-script {}; - }; -}) + passthru = passthru // { + # Thes flags were introduced for `nix-update` so that it can update + # PHP extensions correctly. + # See the corresponding PR: https://github.com/Mic92/nix-update/pull/123 + isPhpExtension = true; + updateScript = nix-update-script { }; + }; + } +) diff --git a/pkgs/build-support/php/builders/default.nix b/pkgs/build-support/php/builders/default.nix new file mode 100644 index 0000000000000..ea9bb33504356 --- /dev/null +++ b/pkgs/build-support/php/builders/default.nix @@ -0,0 +1,9 @@ +{ callPackage, callPackages, ... }: +{ + v1 = { + buildComposerProject = callPackage ./v1/build-composer-project.nix { }; + buildComposerWithPlugin = callPackage ./v1/build-composer-with-plugin.nix { }; + mkComposerRepository = callPackage ./v1/build-composer-repository.nix { }; + composerHooks = callPackages ./v1/hooks { }; + }; +} diff --git a/pkgs/build-support/php/builders/v1/build-composer-project.nix b/pkgs/build-support/php/builders/v1/build-composer-project.nix new file mode 100644 index 0000000000000..698391ad1603c --- /dev/null +++ b/pkgs/build-support/php/builders/v1/build-composer-project.nix @@ -0,0 +1,108 @@ +{ + nix-update-script, + stdenvNoCC, + lib, + php, +}: + +let + buildComposerProjectOverride = + finalAttrs: previousAttrs: + + let + phpDrv = finalAttrs.php or php; + composer = finalAttrs.composer or phpDrv.packages.composer-local-repo-plugin; + in + { + composerLock = previousAttrs.composerLock or null; + composerNoDev = previousAttrs.composerNoDev or true; + composerNoPlugins = previousAttrs.composerNoPlugins or true; + composerNoScripts = previousAttrs.composerNoScripts or true; + composerStrictValidation = previousAttrs.composerStrictValidation or true; + + nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [ + composer + phpDrv + phpDrv.composerHooks.composerInstallHook + ]; + + buildInputs = (previousAttrs.buildInputs or [ ]) ++ [ phpDrv ]; + + patches = previousAttrs.patches or [ ]; + strictDeps = previousAttrs.strictDeps or true; + + # Should we keep these empty phases? + configurePhase = + previousAttrs.configurePhase or '' + runHook preConfigure + + runHook postConfigure + ''; + + buildPhase = + previousAttrs.buildPhase or '' + runHook preBuild + + runHook postBuild + ''; + + doCheck = previousAttrs.doCheck or true; + checkPhase = + previousAttrs.checkPhase or '' + runHook preCheck + + runHook postCheck + ''; + + installPhase = + previousAttrs.installPhase or '' + runHook preInstall + + runHook postInstall + ''; + + doInstallCheck = previousAttrs.doInstallCheck or false; + installCheckPhase = + previousAttrs.installCheckPhase or '' + runHook preInstallCheck + + runHook postInstallCheck + ''; + + composerRepository = + previousAttrs.composerRepository or (phpDrv.mkComposerRepository { + inherit composer; + inherit (finalAttrs) + patches + pname + src + vendorHash + version + ; + + composerLock = previousAttrs.composerLock or null; + composerNoDev = previousAttrs.composerNoDev or true; + composerNoPlugins = previousAttrs.composerNoPlugins or true; + composerNoScripts = previousAttrs.composerNoScripts or true; + composerStrictValidation = previousAttrs.composerStrictValidation or true; + }); + + # Projects providing a lockfile from upstream can be automatically updated. + passthru = previousAttrs.passthru or { } // { + updateScript = + previousAttrs.passthru.updateScript + or (if finalAttrs.composerRepository.composerLock == null then nix-update-script { } else null); + }; + + env = { + COMPOSER_CACHE_DIR = "/dev/null"; + COMPOSER_DISABLE_NETWORK = "1"; + COMPOSER_MIRROR_PATH_REPOS = "1"; + }; + + meta = previousAttrs.meta or { } // { + platforms = lib.platforms.all; + }; + }; +in +args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerProjectOverride diff --git a/pkgs/build-support/php/build-composer-repository.nix b/pkgs/build-support/php/builders/v1/build-composer-repository.nix index e359c0829aaf7..037d8bdeb3eb1 100644 --- a/pkgs/build-support/php/build-composer-repository.nix +++ b/pkgs/build-support/php/builders/v1/build-composer-repository.nix @@ -1,4 +1,8 @@ -{ callPackage, stdenvNoCC, lib, writeTextDir, fetchFromGitHub, php }: +{ + stdenvNoCC, + lib, + php, +}: let mkComposerRepositoryOverride = @@ -18,16 +22,27 @@ let let phpDrv = finalAttrs.php or php; - composer = finalAttrs.composer or phpDrv.packages.composer; - composer-local-repo-plugin = callPackage ./pkgs/composer-local-repo-plugin.nix { }; + composer = finalAttrs.composer or phpDrv.packages.composer-local-repo-plugin; in assert (lib.assertMsg (previousAttrs ? src) "mkComposerRepository expects src argument."); - assert (lib.assertMsg (previousAttrs ? vendorHash) "mkComposerRepository expects vendorHash argument."); + assert ( + lib.assertMsg (previousAttrs ? vendorHash) "mkComposerRepository expects vendorHash argument." + ); assert (lib.assertMsg (previousAttrs ? version) "mkComposerRepository expects version argument."); assert (lib.assertMsg (previousAttrs ? pname) "mkComposerRepository expects pname argument."); - assert (lib.assertMsg (previousAttrs ? composerNoDev) "mkComposerRepository expects composerNoDev argument."); - assert (lib.assertMsg (previousAttrs ? composerNoPlugins) "mkComposerRepository expects composerNoPlugins argument."); - assert (lib.assertMsg (previousAttrs ? composerNoScripts) "mkComposerRepository expects composerNoScripts argument."); + assert ( + lib.assertMsg (previousAttrs ? composerNoDev) "mkComposerRepository expects composerNoDev argument." + ); + assert ( + lib.assertMsg ( + previousAttrs ? composerNoPlugins + ) "mkComposerRepository expects composerNoPlugins argument." + ); + assert ( + lib.assertMsg ( + previousAttrs ? composerNoScripts + ) "mkComposerRepository expects composerNoScripts argument." + ); { composerNoDev = previousAttrs.composerNoDev or true; composerNoPlugins = previousAttrs.composerNoPlugins or true; @@ -41,7 +56,6 @@ let nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [ composer - composer-local-repo-plugin phpDrv phpDrv.composerHooks.composerRepositoryHook ]; @@ -51,45 +65,53 @@ let strictDeps = previousAttrs.strictDeps or true; # Should we keep these empty phases? - configurePhase = previousAttrs.configurePhase or '' - runHook preConfigure + configurePhase = + previousAttrs.configurePhase or '' + runHook preConfigure - runHook postConfigure - ''; + runHook postConfigure + ''; - buildPhase = previousAttrs.buildPhase or '' - runHook preBuild + buildPhase = + previousAttrs.buildPhase or '' + runHook preBuild - runHook postBuild - ''; + runHook postBuild + ''; doCheck = previousAttrs.doCheck or true; - checkPhase = previousAttrs.checkPhase or '' - runHook preCheck + checkPhase = + previousAttrs.checkPhase or '' + runHook preCheck - runHook postCheck - ''; + runHook postCheck + ''; - installPhase = previousAttrs.installPhase or '' - runHook preInstall + installPhase = + previousAttrs.installPhase or '' + runHook preInstall - runHook postInstall - ''; + runHook postInstall + ''; doInstallCheck = previousAttrs.doInstallCheck or false; - installCheckPhase = previousAttrs.installCheckPhase or '' - runHook preInstallCheck + installCheckPhase = + previousAttrs.installCheckPhase or '' + runHook preInstallCheck - runHook postInstallCheck - ''; + runHook postInstallCheck + ''; - COMPOSER_CACHE_DIR = "/dev/null"; - COMPOSER_MIRROR_PATH_REPOS = "1"; - COMPOSER_HTACCESS_PROTECT = "0"; - COMPOSER_DISABLE_NETWORK = "0"; + env = { + COMPOSER_CACHE_DIR = "/dev/null"; + COMPOSER_MIRROR_PATH_REPOS = "1"; + COMPOSER_HTACCESS_PROTECT = "0"; + COMPOSER_DISABLE_NETWORK = "0"; + }; outputHashMode = "recursive"; - outputHashAlgo = if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256"; + outputHashAlgo = + if (finalAttrs ? vendorHash && finalAttrs.vendorHash != "") then null else "sha256"; outputHash = finalAttrs.vendorHash or ""; }; in diff --git a/pkgs/build-support/php/builders/v1/build-composer-with-plugin.nix b/pkgs/build-support/php/builders/v1/build-composer-with-plugin.nix new file mode 100644 index 0000000000000..060b51241e6c8 --- /dev/null +++ b/pkgs/build-support/php/builders/v1/build-composer-with-plugin.nix @@ -0,0 +1,161 @@ +{ + stdenvNoCC, + writeText, + lib, + makeBinaryWrapper, + php, + cacert, + nix-update-script, +}: + +let + composerJsonBuilder = + pluginName: pluginVersion: + writeText "composer.json" ( + builtins.toJSON { + name = "nix/plugin"; + description = "Nix Composer plugin"; + license = "MIT"; + require = { + "${pluginName}" = "${pluginVersion}"; + }; + config = { + "allow-plugins" = { + "${pluginName}" = true; + }; + }; + repositories = [ + { + type = "path"; + url = "./src"; + options = { + versions = { + "${pluginName}" = "${pluginVersion}"; + }; + }; + } + ]; + } + ); + + buildComposerWithPluginOverride = + finalAttrs: previousAttrs: + + let + phpDrv = finalAttrs.php or php; + composer = finalAttrs.composer or phpDrv.packages.composer; + in + { + composerLock = previousAttrs.composerLock or null; + composerNoDev = previousAttrs.composerNoDev or true; + composerNoPlugins = previousAttrs.composerNoPlugins or true; + composerNoScripts = previousAttrs.composerNoScripts or true; + composerStrictValidation = previousAttrs.composerStrictValidation or true; + composerGlobal = true; + + nativeBuildInputs = (previousAttrs.nativeBuildInputs or [ ]) ++ [ + composer + phpDrv + makeBinaryWrapper + ]; + + buildInputs = (previousAttrs.buildInputs or [ ]) ++ [ phpDrv ]; + + patches = previousAttrs.patches or [ ]; + strictDeps = previousAttrs.strictDeps or true; + + # Should we keep these empty phases? + configurePhase = + previousAttrs.configurePhase or '' + runHook preConfigure + + runHook postConfigure + ''; + + buildPhase = + previousAttrs.buildPhase or '' + runHook preBuild + + runHook postBuild + ''; + + doCheck = previousAttrs.doCheck or true; + + checkPhase = + previousAttrs.checkPhase or '' + runHook preCheck + + runHook postCheck + ''; + + installPhase = + previousAttrs.installPhase or '' + runHook preInstall + + makeWrapper ${lib.getExe composer} $out/bin/composer \ + --prefix COMPOSER_HOME : ${finalAttrs.vendor} + + runHook postInstall + ''; + + doInstallCheck = previousAttrs.doInstallCheck or false; + installCheckPhase = + previousAttrs.installCheckPhase or '' + runHook preInstallCheck + + composer global show ${finalAttrs.pname} + + runHook postInstallCheck + ''; + + vendor = previousAttrs.vendor or stdenvNoCC.mkDerivation { + pname = "${finalAttrs.pname}-vendor"; + pluginName = finalAttrs.pname; + + inherit (finalAttrs) version src; + + composerLock = previousAttrs.composerLock or null; + composerNoDev = previousAttrs.composerNoDev or true; + composerNoPlugins = previousAttrs.composerNoPlugins or true; + composerNoScripts = previousAttrs.composerNoScripts or true; + composerStrictValidation = previousAttrs.composerStrictValidation or true; + composerGlobal = true; + composerJson = composerJsonBuilder finalAttrs.pname finalAttrs.version; + + nativeBuildInputs = [ + cacert + composer + phpDrv.composerHooks.composerWithPluginVendorHook + ]; + + dontPatchShebangs = true; + doCheck = true; + doInstallCheck = true; + + env = { + COMPOSER_CACHE_DIR = "/dev/null"; + COMPOSER_HTACCESS_PROTECT = "0"; + }; + + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + outputHash = finalAttrs.vendorHash; + }; + + # Projects providing a lockfile from upstream can be automatically updated. + passthru = previousAttrs.passthru or { } // { + updateScript = + previousAttrs.passthru.updateScript + or (if finalAttrs.vendor.composerLock == null then nix-update-script { } else null); + }; + + env = { + COMPOSER_CACHE_DIR = "/dev/null"; + COMPOSER_DISABLE_NETWORK = "1"; + COMPOSER_MIRROR_PATH_REPOS = "1"; + }; + + meta = previousAttrs.meta or composer.meta; + }; +in +args: (stdenvNoCC.mkDerivation args).overrideAttrs buildComposerWithPluginOverride diff --git a/pkgs/build-support/php/hooks/composer-install-hook.sh b/pkgs/build-support/php/builders/v1/hooks/composer-install-hook.sh index a91263422bc84..44e87d06d3a53 100644 --- a/pkgs/build-support/php/hooks/composer-install-hook.sh +++ b/pkgs/build-support/php/builders/v1/hooks/composer-install-hook.sh @@ -83,7 +83,7 @@ composerInstallBuildHook() { # Since this file cannot be generated in the composer-repository-hook.sh # because the file contains hardcoded nix store paths, we generate it here. - composer-local-repo-plugin --no-ansi build-local-repo-lock -m "${composerRepository}" . + composer build-local-repo-lock -m "${composerRepository}" . echo "Finished composerInstallBuildHook" } diff --git a/pkgs/build-support/php/hooks/composer-repository-hook.sh b/pkgs/build-support/php/builders/v1/hooks/composer-repository-hook.sh index c4fa0d52126c1..ec9777541fc0f 100644 --- a/pkgs/build-support/php/hooks/composer-repository-hook.sh +++ b/pkgs/build-support/php/builders/v1/hooks/composer-repository-hook.sh @@ -63,7 +63,7 @@ composerRepositoryBuildHook() { # Build the local composer repository # The command 'build-local-repo' is provided by the Composer plugin # nix-community/composer-local-repo-plugin. - composer-local-repo-plugin --no-ansi build-local-repo-lock ${composerNoDev:+--no-dev} -r repository + composer build-local-repo-lock ${composerNoDev:+--no-dev} -r repository echo "Finished composerRepositoryBuildHook" } diff --git a/pkgs/build-support/php/builders/v1/hooks/composer-with-plugin-vendor-hook.sh b/pkgs/build-support/php/builders/v1/hooks/composer-with-plugin-vendor-hook.sh new file mode 100644 index 0000000000000..0d88d14094ad4 --- /dev/null +++ b/pkgs/build-support/php/builders/v1/hooks/composer-with-plugin-vendor-hook.sh @@ -0,0 +1,93 @@ +declare composerLock +declare version +declare composerNoDev +declare composerNoPlugins +declare composerNoScripts +declare composerStrictValidation + +preConfigureHooks+=(composerWithPluginConfigureHook) +preBuildHooks+=(composerWithPluginBuildHook) +preCheckHooks+=(composerWithPluginCheckHook) +preInstallHooks+=(composerWithPluginInstallHook) +preInstallCheckHooks+=(composerWithPluginInstallCheckHook) + +source @phpScriptUtils@ + +composerWithPluginConfigureHook() { + echo "Executing composerWithPluginConfigureHook" + + mkdir -p $out + + export COMPOSER_HOME=$out + + if [[ -e "$composerLock" ]]; then + cp $composerLock $out/composer.lock + fi + + cp $composerJson $out/composer.json + cp -ar $src $out/src + + if [[ ! -f "$out/composer.lock" ]]; then + setComposeRootVersion + + composer \ + global \ + --no-install \ + --no-interaction \ + --no-progress \ + ${composerNoDev:+--no-dev} \ + ${composerNoPlugins:+--no-plugins} \ + ${composerNoScripts:+--no-scripts} \ + update + + echo + echo -e "\e[31mERROR: No composer.lock found\e[0m" + echo + echo -e '\e[31mNo composer.lock file found, consider adding one to your repository to ensure reproducible builds.\e[0m' + echo -e "\e[31mIn the meantime, a composer.lock file has been generated for you in $out/composer.lock\e[0m" + echo + echo -e '\e[31mTo fix the issue:\e[0m' + echo -e "\e[31m1. Copy the composer.lock file from $out/composer.lock to the project's source:\e[0m" + echo -e "\e[31m cp $out/composer.lock <path>\e[0m" + echo -e '\e[31m2. Add the composerLock attribute, pointing to the copied composer.lock file:\e[0m' + echo -e '\e[31m composerLock = ./composer.lock;\e[0m' + echo + + exit 1 + fi + + echo "Finished composerWithPluginConfigureHook" +} + +composerWithPluginBuildHook() { + echo "Executing composerWithPluginBuildHook" + + echo "Finished composerWithPluginBuildHook" +} + +composerWithPluginCheckHook() { + echo "Executing composerWithPluginCheckHook" + + checkComposerValidate + + echo "Finished composerWithPluginCheckHook" +} + +composerWithPluginInstallHook() { + echo "Executing composerWithPluginInstallHook" + + composer \ + global \ + --no-interaction \ + --no-progress \ + ${composerNoDev:+--no-dev} \ + ${composerNoPlugins:+--no-plugins} \ + ${composerNoScripts:+--no-scripts} \ + install + + echo "Finished composerWithPluginInstallHook" +} + +composerWithPluginInstallCheckHook() { + composer global show $pluginName +} diff --git a/pkgs/build-support/php/builders/v1/hooks/default.nix b/pkgs/build-support/php/builders/v1/hooks/default.nix new file mode 100644 index 0000000000000..d10ff78067278 --- /dev/null +++ b/pkgs/build-support/php/builders/v1/hooks/default.nix @@ -0,0 +1,60 @@ +{ + lib, + makeSetupHook, + jq, + writeShellApplication, + moreutils, + cacert, + buildPackages, +}: + +let + php-script-utils = writeShellApplication { + name = "php-script-utils"; + runtimeInputs = [ jq ]; + text = builtins.readFile ./php-script-utils.bash; + }; +in +{ + composerRepositoryHook = makeSetupHook { + name = "composer-repository-hook.sh"; + propagatedBuildInputs = [ + jq + moreutils + cacert + ]; + substitutions = { + phpScriptUtils = lib.getExe php-script-utils; + }; + } ./composer-repository-hook.sh; + + composerInstallHook = makeSetupHook { + name = "composer-install-hook.sh"; + propagatedBuildInputs = [ + jq + moreutils + cacert + ]; + substitutions = { + # Specify the stdenv's `diff` by abspath to ensure that the user's build + # inputs do not cause us to find the wrong `diff`. + cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp"; + phpScriptUtils = lib.getExe php-script-utils; + }; + } ./composer-install-hook.sh; + + composerWithPluginVendorHook = makeSetupHook { + name = "composer-with-plugin-vendor-hook.sh"; + propagatedBuildInputs = [ + jq + moreutils + cacert + ]; + substitutions = { + # Specify the stdenv's `diff` by abspath to ensure that the user's build + # inputs do not cause us to find the wrong `diff`. + cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp"; + phpScriptUtils = lib.getExe php-script-utils; + }; + } ./composer-with-plugin-vendor-hook.sh; +} diff --git a/pkgs/build-support/php/hooks/php-script-utils.bash b/pkgs/build-support/php/builders/v1/hooks/php-script-utils.bash index bba0242e65d1e..65c0a3b410f69 100644 --- a/pkgs/build-support/php/hooks/php-script-utils.bash +++ b/pkgs/build-support/php/builders/v1/hooks/php-script-utils.bash @@ -1,5 +1,6 @@ declare version declare composerStrictValidation +declare composerGlobal setComposeRootVersion() { set +e # Disable exit on error @@ -13,7 +14,16 @@ setComposeRootVersion() { } checkComposerValidate() { - if ! composer validate --strict --no-ansi --no-interaction --quiet --no-check-all --no-check-lock; then + setComposeRootVersion + + if [ "1" == "${composerGlobal-}" ]; then + global="global"; + else + global=""; + fi + + command="composer ${global} validate --strict --quiet --no-interaction --no-check-all --no-check-lock" + if ! $command; then if [ "1" == "${composerStrictValidation-}" ]; then echo echo -e "\e[31mERROR: composer files validation failed\e[0m" @@ -42,7 +52,8 @@ checkComposerValidate() { fi fi - if ! composer validate --strict --no-ansi --no-interaction --quiet --no-check-all --check-lock; then + command="composer ${global} validate --strict --no-ansi --no-interaction --quiet --no-check-all --check-lock" + if ! $command; then if [ "1" == "${composerStrictValidation-}" ]; then echo echo -e "\e[31mERROR: composer files validation failed\e[0m" diff --git a/pkgs/build-support/php/hooks/default.nix b/pkgs/build-support/php/hooks/default.nix deleted file mode 100644 index ca96b1056db9d..0000000000000 --- a/pkgs/build-support/php/hooks/default.nix +++ /dev/null @@ -1,39 +0,0 @@ -{ lib -, makeSetupHook -, diffutils -, jq -, writeShellApplication -, moreutils -, cacert -, buildPackages -}: - -let - php-script-utils = writeShellApplication { - name = "php-script-utils"; - runtimeInputs = [ jq ]; - text = builtins.readFile ./php-script-utils.bash; - }; -in -{ - composerRepositoryHook = makeSetupHook - { - name = "composer-repository-hook.sh"; - propagatedBuildInputs = [ jq moreutils cacert ]; - substitutions = { - phpScriptUtils = lib.getExe php-script-utils; - }; - } ./composer-repository-hook.sh; - - composerInstallHook = makeSetupHook - { - name = "composer-install-hook.sh"; - propagatedBuildInputs = [ jq moreutils cacert ]; - substitutions = { - # Specify the stdenv's `diff` by abspath to ensure that the user's build - # inputs do not cause us to find the wrong `diff`. - cmp = "${lib.getBin buildPackages.diffutils}/bin/cmp"; - phpScriptUtils = lib.getExe php-script-utils; - }; - } ./composer-install-hook.sh; -} diff --git a/pkgs/build-support/php/pkgs/composer-local-repo-plugin.nix b/pkgs/build-support/php/pkgs/composer-local-repo-plugin.nix deleted file mode 100644 index bfdc3d4f98d1b..0000000000000 --- a/pkgs/build-support/php/pkgs/composer-local-repo-plugin.nix +++ /dev/null @@ -1,113 +0,0 @@ -{ php, callPackage, stdenvNoCC, lib, fetchFromGitHub, makeBinaryWrapper }: - -let - composer = callPackage ./composer-phar.nix { - inherit (php.packages.composer) version pharHash; - }; - - composerKeys = stdenvNoCC.mkDerivation (finalComposerKeysAttrs: { - pname = "composer-keys"; - version = "fa5a62092f33e094073fbda23bbfc7188df3cbc5"; - - src = fetchFromGitHub { - owner = "composer"; - repo = "composer.github.io"; - rev = "${finalComposerKeysAttrs.version}"; - hash = "sha256-3Sfn71LDG1jHwuEIU8iEnV3k6D6QTX7KVIKVaNSuCVE="; - }; - - installPhase = '' - runHook preInstall - - mkdir -p $out - install releases.pub $out/keys.tags.pub - install snapshots.pub $out/keys.dev.pub - - runHook postInstall - ''; - }); -in -stdenvNoCC.mkDerivation (finalAttrs: { - pname = "composer-local-repo-plugin"; - version = "1.1.0"; - - src = fetchFromGitHub { - owner = "nix-community"; - repo = "composer-local-repo-plugin"; - rev = finalAttrs.version; - hash = "sha256-edbn07r/Uc1g0qOuVBZBs6N1bMN5kIfA1b4FCufdw5M="; - }; - - COMPOSER_CACHE_DIR = "/dev/null"; - COMPOSER_MIRROR_PATH_REPOS = "1"; - COMPOSER_HTACCESS_PROTECT = "0"; - COMPOSER_DISABLE_NETWORK = "1"; - - nativeBuildInputs = [ - makeBinaryWrapper - ]; - - buildInputs = [ - composer - ]; - - configurePhase = '' - runHook preConfigure - - export COMPOSER_HOME=${placeholder "out"} - - runHook postConfigure - ''; - - buildPhase = '' - runHook preBuild - - # Configure composer globally - composer global init --quiet --no-interaction --no-ansi \ - --name="nixos/composer" \ - --homepage "https://nixos.org/" \ - --description "Composer with nix-community/composer-local-repo-plugin" \ - --license "MIT" - - composer global config --quiet minimum-stability dev - composer global config --quiet prefer-stable true - composer global config --quiet apcu-autoloader false - composer global config --quiet allow-plugins.nix-community/composer-local-repo-plugin true - composer global config --quiet repo.packagist false - composer global config --quiet repo.plugin path $src - - # Install the local repository plugin - composer global require --quiet --no-ansi --no-interaction nix-community/composer-local-repo-plugin - - runHook postBuild - ''; - - checkPhase = '' - runHook preCheck - - composer global validate --no-ansi - composer global show --no-ansi nix-community/composer-local-repo-plugin - - runHook postCheck - ''; - - installPhase = '' - runHook preInstall - - mkdir -p $out - cp -ar ${composerKeys}/* $out/ - - makeWrapper ${composer}/bin/composer $out/bin/composer-local-repo-plugin \ - --prefix COMPOSER_HOME : $out - - runHook postInstall - ''; - - meta = { - description = "Composer local repo plugin for Composer"; - homepage = "https://github.com/nix-community/composer-local-repo-plugin"; - license = lib.licenses.mit; - maintainers = with lib.maintainers; [ drupol ]; - platforms = lib.platforms.all; - }; -}) diff --git a/pkgs/build-support/php/pkgs/composer-phar.nix b/pkgs/build-support/php/pkgs/composer-phar.nix index f281334ab2d9f..b07c25beec55f 100644 --- a/pkgs/build-support/php/pkgs/composer-phar.nix +++ b/pkgs/build-support/php/pkgs/composer-phar.nix @@ -1,17 +1,16 @@ { - _7zz - , cacert - , curl - , fetchurl - , git - , lib - , makeBinaryWrapper - , php - , stdenvNoCC - , unzip - , xz - , version - , pharHash + _7zz, + curl, + fetchurl, + git, + lib, + makeBinaryWrapper, + php, + stdenvNoCC, + unzip, + xz, + version, + pharHash, }: stdenvNoCC.mkDerivation (finalAttrs: { @@ -32,9 +31,17 @@ stdenvNoCC.mkDerivation (finalAttrs: { mkdir -p $out/bin install -D $src $out/libexec/composer/composer.phar - makeWrapper ${php}/bin/php $out/bin/composer \ + makeWrapper ${lib.getExe php} $out/bin/composer \ --add-flags "$out/libexec/composer/composer.phar" \ - --prefix PATH : ${lib.makeBinPath [ _7zz cacert curl git unzip xz ]} + --prefix PATH : ${ + lib.makeBinPath [ + _7zz + curl + git + unzip + xz + ] + } runHook postInstall ''; @@ -44,6 +51,7 @@ stdenvNoCC.mkDerivation (finalAttrs: { description = "Dependency Manager for PHP, shipped from the PHAR file"; homepage = "https://getcomposer.org/"; license = lib.licenses.mit; + mainProgram = "composer"; maintainers = with lib.maintainers; [ drupol ]; platforms = lib.platforms.all; }; diff --git a/pkgs/build-support/rust/build-rust-crate/build-crate.nix b/pkgs/build-support/rust/build-rust-crate/build-crate.nix index bbb26606a6a4d..7484b3ad0290e 100644 --- a/pkgs/build-support/rust/build-rust-crate/build-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/build-crate.nix @@ -51,7 +51,7 @@ # configure & source common build functions LIB_RUSTC_OPTS="${libRustcOpts}" BIN_RUSTC_OPTS="${binRustcOpts}" - LIB_EXT="${stdenv.hostPlatform.extensions.sharedLibrary or ""}" + LIB_EXT="${stdenv.hostPlatform.extensions.library}" LIB_PATH="${libPath}" LIB_NAME="${libName}" diff --git a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix index 6b88271602623..ab872bac854f8 100644 --- a/pkgs/build-support/rust/build-rust-crate/configure-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/configure-crate.nix @@ -198,13 +198,16 @@ in '' ) set +e - EXTRA_BUILD=$(sed -n "s/^cargo:rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) - EXTRA_FEATURES=$(sed -n "s/^cargo:rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ') - EXTRA_LINK_ARGS=$(sed -n "s/^cargo:rustc-link-arg=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') - EXTRA_LINK_ARGS_BINS=$(sed -n "s/^cargo:rustc-link-arg-bins=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') - EXTRA_LINK_ARGS_LIB=$(sed -n "s/^cargo:rustc-link-arg-lib=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') - EXTRA_LINK_LIBS=$(sed -n "s/^cargo:rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ') - EXTRA_LINK_SEARCH=$(sed -n "s/^cargo:rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) + # We want to support the new prefix invocation syntax which uses two colons + # See https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script + + EXTRA_BUILD=$(sed -n "s/^cargo::\{0,1\}rustc-flags=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) + EXTRA_FEATURES=$(sed -n "s/^cargo::\{0,1\}rustc-cfg=\(.*\)/--cfg \1/p" target/build/${crateName}.opt | tr '\n' ' ') + EXTRA_LINK_ARGS=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') + EXTRA_LINK_ARGS_BINS=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg-bins=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') + EXTRA_LINK_ARGS_LIB=$(sed -n "s/^cargo::\{0,1\}rustc-link-arg-lib=\(.*\)/-C link-arg=\1/p" target/build/${crateName}.opt | tr '\n' ' ') + EXTRA_LINK_LIBS=$(sed -n "s/^cargo::\{0,1\}rustc-link-lib=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ') + EXTRA_LINK_SEARCH=$(sed -n "s/^cargo::\{0,1\}rustc-link-search=\(.*\)/\1/p" target/build/${crateName}.opt | tr '\n' ' ' | sort -u) # We want to read part of every line that has cargo:rustc-env= prefix and # export it as environment variables. This turns out tricky if the lines @@ -217,14 +220,15 @@ in '' # _OLDIFS="$IFS" IFS=$'\n' - for env in $(sed -n "s/^cargo:rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do + for env in $(sed -n "s/^cargo::\{0,1\}rustc-env=\(.*\)/\1/p" target/build/${crateName}.opt); do export "$env" done IFS="$_OLDIFS" CRATENAME=$(echo ${crateName} | sed -e "s/\(.*\)-sys$/\U\1/" -e "s/-/_/g") - grep -P "^cargo:(?!(rustc-|warning=|rerun-if-changed=|rerun-if-env-changed))" target/build/${crateName}.opt \ - | awk -F= "/^cargo:/ { sub(/^cargo:/, \"\", \$1); gsub(/-/, \"_\", \$1); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$1) \"=\" \$2 }" > target/env + grep -P "^cargo:(?!:?(rustc-|warning=|rerun-if-changed=|rerun-if-env-changed))" target/build/${crateName}.opt \ + | awk -F= "/^cargo::metadata=/ { gsub(/-/, \"_\", \$2); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$2) \"=\" \"\\\"\"\$3\"\\\"\"; next } + /^cargo:/ { sub(/^cargo::?/, \"\", \$1); gsub(/-/, \"_\", \$1); print \"export \" toupper(\"DEP_$(echo $CRATENAME)_\" \$1) \"=\" \"\\\"\"\$2\"\\\"\"; next }" > target/env set -e fi runHook postConfigure diff --git a/pkgs/build-support/rust/build-rust-crate/default.nix b/pkgs/build-support/rust/build-rust-crate/default.nix index 4a7fd114829ad..dfe28cc334b5e 100644 --- a/pkgs/build-support/rust/build-rust-crate/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/default.nix @@ -49,7 +49,9 @@ let filename = if lib.any (x: x == "lib" || x == "rlib") dep.crateType then "${dep.metadata}.rlib" - else "${dep.metadata}${stdenv.hostPlatform.extensions.sharedLibrary}"; + # Adjust lib filename for crates of type proc-macro. Proc macros are compiled/run on the build platform architecture. + else if (lib.attrByPath [ "procMacro" ] false dep) then "${dep.metadata}${stdenv.buildPlatform.extensions.library}" + else "${dep.metadata}${stdenv.hostPlatform.extensions.library}"; in " --extern ${opts}${name}=${dep.lib}/lib/lib${extern}-${filename}" ) diff --git a/pkgs/build-support/rust/build-rust-crate/install-crate.nix b/pkgs/build-support/rust/build-rust-crate/install-crate.nix index f4a4dcdb0d945..7c7c102833d85 100644 --- a/pkgs/build-support/rust/build-rust-crate/install-crate.nix +++ b/pkgs/build-support/rust/build-rust-crate/install-crate.nix @@ -41,7 +41,7 @@ if !buildTests then '' fi if [ -e target/lib ]; then find target/lib/ -type f \! -name '*.rlib' \ - -a \! -name '*${stdenv.hostPlatform.extensions.sharedLibrary}' \ + -a \! -name '*${stdenv.hostPlatform.extensions.library}' \ -a \! -name '*.d' \ -executable \ -print0 | xargs --no-run-if-empty --null install --target $out/tests; diff --git a/pkgs/build-support/rust/build-rust-crate/test/default.nix b/pkgs/build-support/rust/build-rust-crate/test/default.nix index 1ecef4c8e3270..d020031a92f93 100644 --- a/pkgs/build-support/rust/build-rust-crate/test/default.nix +++ b/pkgs/build-support/rust/build-rust-crate/test/default.nix @@ -421,6 +421,53 @@ let buildDependencies = [ depCrate ]; dependencies = [ depCrate ]; }; + # Support new invocation prefix for build scripts `cargo::` + # https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script + buildScriptInvocationPrefix = let + depCrate = buildRustCrate: mkCrate buildRustCrate { + crateName = "bar"; + src = mkFile "build.rs" '' + fn main() { + // Old invocation prefix + // We likely won't see be mixing these syntaxes in the same build script in the wild. + println!("cargo:key_old=value_old"); + + // New invocation prefix + println!("cargo::metadata=key=value"); + println!("cargo::metadata=key_complex=complex(value)"); + } + ''; + }; + in { + crateName = "foo"; + src = symlinkJoin { + name = "build-script-and-main-invocation-prefix"; + paths = [ + (mkFile "src/main.rs" '' + const BUILDFOO: &'static str = env!("BUILDFOO"); + + #[test] + fn build_foo_check() { assert!(BUILDFOO == "yes(check)"); } + + fn main() { } + '') + (mkFile "build.rs" '' + use std::env; + fn main() { + assert!(env::var_os("DEP_BAR_KEY_OLD").expect("metadata key 'key_old' not set in dependency") == "value_old"); + assert!(env::var_os("DEP_BAR_KEY").expect("metadata key 'key' not set in dependency") == "value"); + assert!(env::var_os("DEP_BAR_KEY_COMPLEX").expect("metadata key 'key_complex' not set in dependency") == "complex(value)"); + + println!("cargo::rustc-env=BUILDFOO=yes(check)"); + } + '') + ]; + }; + buildDependencies = [ (depCrate buildPackages.buildRustCrate) ]; + dependencies = [ (depCrate buildRustCrate) ]; + buildTests = true; + expectedTestOutputs = [ "test build_foo_check ... ok" ]; + }; # Regression test for https://github.com/NixOS/nixpkgs/issues/74071 # Whenevever a build.rs file is generating files those should not be overlayed onto the actual source dir buildRsOutDirOverlay = { @@ -479,7 +526,7 @@ let # `-undefined dynamic_lookup` as otherwise the compilation fails. $CC -shared \ ${lib.optionalString stdenv.isDarwin "-undefined dynamic_lookup"} \ - -o $out/lib/${name}${stdenv.hostPlatform.extensions.sharedLibrary} ${src} + -o $out/lib/${name}${stdenv.hostPlatform.extensions.library} ${src} ''; b = compile "libb" '' #include <stdio.h> diff --git a/pkgs/build-support/rust/build-rust-package/default.nix b/pkgs/build-support/rust/build-rust-package/default.nix index cd90c68c79303..36e0408cc198a 100644 --- a/pkgs/build-support/rust/build-rust-package/default.nix +++ b/pkgs/build-support/rust/build-rust-package/default.nix @@ -156,9 +156,9 @@ stdenv.mkDerivation ((removeAttrs args [ "depsExtraArgs" "cargoUpdateHook" "carg # Platforms without host tools from # https://doc.rust-lang.org/nightly/rustc/platform-support.html "armv7a-darwin" - "armv5tel-linux" "armv7a-linux" "m68k-linux" "mipsel-linux" - "mips64el-linux" "riscv32-linux" - "armv6l-netbsd" + "armv5tel-linux" "armv7a-linux" "m68k-linux" "mips-linux" + "mips64-linux" "mipsel-linux" "mips64el-linux" "riscv32-linux" + "armv6l-netbsd" "mipsel-netbsd" "riscv64-netbsd" "x86_64-redox" "wasm32-wasi" ]; diff --git a/pkgs/build-support/rust/default-crate-overrides.nix b/pkgs/build-support/rust/default-crate-overrides.nix index 92c71dfc059ce..d8f1bfaf4447b 100644 --- a/pkgs/build-support/rust/default-crate-overrides.nix +++ b/pkgs/build-support/rust/default-crate-overrides.nix @@ -218,6 +218,10 @@ in buildInputs = [ openssl ]; }; + opentelemetry-proto = attrs: { + nativeBuildInputs = [ protobuf ]; + }; + pam-sys = attr: { buildInputs = [ linux-pam ]; }; @@ -236,6 +240,10 @@ in nativeBuildInputs = [ protobuf ]; }; + prost-wkt-types = attr: { + nativeBuildInputs = [ protobuf ]; + }; + rdkafka-sys = attr: { nativeBuildInputs = [ pkg-config ]; buildInputs = [ rdkafka ]; @@ -299,6 +307,10 @@ in buildInputs = [ libsodium ]; }; + tonic-reflection = attrs: { + nativeBuildInputs = [ protobuf ]; + }; + xcb = attrs: { buildInputs = [ python3 ]; }; diff --git a/pkgs/build-support/rust/hooks/cargo-build-hook.sh b/pkgs/build-support/rust/hooks/cargo-build-hook.sh index ed982c7ff30a3..26dde914f22aa 100644 --- a/pkgs/build-support/rust/hooks/cargo-build-hook.sh +++ b/pkgs/build-support/rust/hooks/cargo-build-hook.sh @@ -25,14 +25,21 @@ cargoBuildHook() { fi if [ -n "${cargoBuildFeatures-}" ]; then - cargoBuildFeaturesFlag="--features=${cargoBuildFeatures// /,}" + if [ -n "$__structuredAttrs" ]; then + OLDIFS="$IFS" + IFS=','; cargoBuildFeaturesFlag="--features=${cargoBuildFeatures[*]}" + IFS="$OLDIFS" + unset OLDIFS + else + cargoBuildFeaturesFlag="--features=${cargoBuildFeatures// /,}" + fi fi ( set -x @setEnv@ cargo build -j $NIX_BUILD_CORES \ --target @rustHostPlatformSpec@ \ - --frozen \ + --offline \ ${cargoBuildProfileFlag} \ ${cargoBuildNoDefaultFeaturesFlag} \ ${cargoBuildFeaturesFlag} \ diff --git a/pkgs/build-support/rust/hooks/cargo-check-hook.sh b/pkgs/build-support/rust/hooks/cargo-check-hook.sh index 971a140ec178f..96b87dbf15b45 100644 --- a/pkgs/build-support/rust/hooks/cargo-check-hook.sh +++ b/pkgs/build-support/rust/hooks/cargo-check-hook.sh @@ -29,7 +29,7 @@ cargoCheckHook() { fi argstr="${cargoCheckProfileFlag} ${cargoCheckNoDefaultFeaturesFlag} ${cargoCheckFeaturesFlag} - --target @rustHostPlatformSpec@ --frozen ${cargoTestFlags}" + --target @rustHostPlatformSpec@ --offline ${cargoTestFlags}" ( set -x diff --git a/pkgs/build-support/rust/hooks/cargo-nextest-hook.sh b/pkgs/build-support/rust/hooks/cargo-nextest-hook.sh index 29ba18a6a1e3f..16d32513a0d01 100644 --- a/pkgs/build-support/rust/hooks/cargo-nextest-hook.sh +++ b/pkgs/build-support/rust/hooks/cargo-nextest-hook.sh @@ -29,7 +29,7 @@ cargoNextestHook() { fi argstr="${cargoCheckProfileFlag} ${cargoCheckNoDefaultFeaturesFlag} ${cargoCheckFeaturesFlag} - --target @rustHostPlatformSpec@ --frozen ${cargoTestFlags}" + --target @rustHostPlatformSpec@ --offline ${cargoTestFlags}" ( set -x diff --git a/pkgs/build-support/rust/hooks/maturin-build-hook.sh b/pkgs/build-support/rust/hooks/maturin-build-hook.sh index 028441d18160e..b3cc1ced79647 100644 --- a/pkgs/build-support/rust/hooks/maturin-build-hook.sh +++ b/pkgs/build-support/rust/hooks/maturin-build-hook.sh @@ -11,7 +11,7 @@ maturinBuildHook() { set -x @setEnv@ maturin build \ --jobs=$NIX_BUILD_CORES \ - --frozen \ + --offline \ --target @rustTargetPlatformSpec@ \ --manylinux off \ --strip \ diff --git a/pkgs/build-support/rust/replace-workspace-values.py b/pkgs/build-support/rust/replace-workspace-values.py index 2b88f1fa79bbe..003023ff2560a 100644 --- a/pkgs/build-support/rust/replace-workspace-values.py +++ b/pkgs/build-support/rust/replace-workspace-values.py @@ -15,6 +15,9 @@ def load_file(path: str) -> dict[str, Any]: return tomli.load(f) +# This replicates the dependency merging logic from Cargo. +# See `inner_dependency_inherit_with`: +# https://github.com/rust-lang/cargo/blob/4de0094ac78743d2c8ff682489e35c8a7cafe8e4/src/cargo/util/toml/mod.rs#L982 def replace_key( workspace_manifest: dict[str, Any], table: dict[str, Any], section: str, key: str ) -> bool: @@ -25,28 +28,37 @@ def replace_key( ): print("replacing " + key) - replaced = table[key] - del replaced["workspace"] + local_dep = table[key] + del local_dep["workspace"] - workspace_copy = workspace_manifest[section][key] + workspace_dep = workspace_manifest[section][key] if section == "dependencies": - crate_features = replaced.get("features") + if isinstance(workspace_dep, str): + workspace_dep = {"version": workspace_dep} - if type(workspace_copy) is str: - replaced["version"] = workspace_copy - else: - replaced.update(workspace_copy) + final: dict[str, Any] = workspace_dep.copy() - merged_features = (crate_features or []) + ( - workspace_copy.get("features") or [] - ) + merged_features = local_dep.pop("features", []) + workspace_dep.get("features", []) + if merged_features: + final["features"] = merged_features - if len(merged_features) > 0: - # Dictionaries are guaranteed to be ordered (https://stackoverflow.com/a/7961425) - replaced["features"] = list(dict.fromkeys(merged_features)) + local_default_features = local_dep.pop("default-features", None) + workspace_default_features = workspace_dep.get("default-features") + + if not workspace_default_features and local_default_features: + final["default-features"] = True + + optional = local_dep.pop("optional", False) + if optional: + final["optional"] = True + + if local_dep: + raise Exception(f"Unhandled keys in inherited dependency {key}: {local_dep}") + + table[key] = final elif section == "package": - table[key] = replaced = workspace_copy + table[key] = workspace_dep return True diff --git a/pkgs/build-support/setup-hooks/strip.sh b/pkgs/build-support/setup-hooks/strip.sh index ce41e6ea0562a..49a350af1fa5c 100644 --- a/pkgs/build-support/setup-hooks/strip.sh +++ b/pkgs/build-support/setup-hooks/strip.sh @@ -74,13 +74,17 @@ stripDirs() { echo "stripping (with command $cmd and flags $stripFlags) in $paths" local striperr striperr="$(mktemp --tmpdir="$TMPDIR" 'striperr.XXXXXX')" - # Do not strip lib/debug. This is a directory used by setup-hooks/separate-debug-info.sh. - find $paths -type f "${excludeFlags[@]}" -a '!' -path "$prefix/lib/debug/*" -print0 | - # Make sure we process files under symlinks only once. Otherwise - # 'strip` can corrupt files when writes to them in parallel: - # https://github.com/NixOS/nixpkgs/issues/246147#issuecomment-1657072039 - xargs -r -0 -n1 -- realpath -z | sort -u -z | + # Make sure we process files only once. `strip`ping the same file through different + # links in parallel can corrupt it: + # https://github.com/NixOS/nixpkgs/issues/246147#issuecomment-1657072039 + # Do not strip lib/debug. This is a directory used by setup-hooks/separate-debug-info.sh. + # Print out each file's device and inode (which will be the same if two files are hardlinked + # or are the same file found through different symlinks), followed by its path... + find $paths -type f "${excludeFlags[@]}" -a '!' -path "$prefix/lib/debug/*" -printf '%D-%i,%p\0' | + # ... sort/uniq by device/inode, then cut them out and keep the path, ... + sort -t, -k1,1 -u -z | cut -d, -f2- -z | + # and finally strip each unique path in parallel. xargs -r -0 -n1 -P "$NIX_BUILD_CORES" -- $cmd $stripFlags 2>"$striperr" || exit_code=$? # xargs exits with status code 123 if some but not all of the # processes fail. We don't care if some of the files couldn't diff --git a/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix b/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix index 3c5199be31322..69f9f3b145d7c 100644 --- a/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix +++ b/pkgs/build-support/setup-hooks/wrap-gapps-hook/default.nix @@ -3,12 +3,12 @@ , makeSetupHook , makeWrapper , gobject-introspection -, isGraphical ? true +, isGraphical ? false , gtk3 , librsvg , dconf , callPackage -, wrapGAppsHook +, wrapGAppsHook3 , targetPackages }: @@ -24,9 +24,9 @@ makeSetupHook { librsvg ]; - # depsTargetTargetPropagated will essentially be buildInputs when wrapGAppsHook is placed into nativeBuildInputs + # depsTargetTargetPropagated will essentially be buildInputs when wrapGAppsHook3 is placed into nativeBuildInputs # the librsvg and gtk3 above should be removed but kept to not break anything that implicitly depended on its binaries - depsTargetTargetPropagated = assert (lib.assertMsg (!targetPackages ? raw) "wrapGAppsHook must be in nativeBuildInputs"); lib.optionals isGraphical [ + depsTargetTargetPropagated = assert (lib.assertMsg (!targetPackages ? raw) "wrapGAppsHook3 must be in nativeBuildInputs"); lib.optionals isGraphical [ # librsvg provides a module for gdk-pixbuf to allow rendering # SVG icons. Most icon themes are SVG-based and so are some # graphics in GTK (e.g. cross for closing window in window title bar) @@ -59,7 +59,7 @@ makeSetupHook { src = sample-project; strictDeps = true; - nativeBuildInputs = [ wrapGAppsHook ]; + nativeBuildInputs = [ wrapGAppsHook3 ]; installFlags = [ "bin-foo" "libexec-bar" ]; }; @@ -103,7 +103,7 @@ makeSetupHook { strictDeps = true; nativeBuildInputs = [ gobject-introspection - wrapGAppsHook + wrapGAppsHook3 ]; buildInputs = [ @@ -150,7 +150,7 @@ makeSetupHook { strictDeps = true; nativeBuildInputs = [ gobject-introspection - wrapGAppsHook + wrapGAppsHook3 ]; buildInputs = [ @@ -181,7 +181,7 @@ makeSetupHook { strictDeps = true; nativeBuildInputs = [ gobject-introspection - wrapGAppsHook + wrapGAppsHook3 ]; installFlags = [ "typelib-Cow" "bin-foo" "libexec-bar" ]; diff --git a/pkgs/build-support/singularity-tools/default.nix b/pkgs/build-support/singularity-tools/default.nix index c9e53a4cb706f..cd10a9960421b 100644 --- a/pkgs/build-support/singularity-tools/default.nix +++ b/pkgs/build-support/singularity-tools/default.nix @@ -45,7 +45,7 @@ rec { , diskSize ? 1024 , runScript ? "#!${stdenv.shell}\nexec /bin/sh" , runAsRoot ? null - , memSize ? 512 + , memSize ? 1024 , singularity ? defaultSingularity }: let diff --git a/pkgs/build-support/src-only/default.nix b/pkgs/build-support/src-only/default.nix index 2b0db0e267aa7..cd8572629cad8 100644 --- a/pkgs/build-support/src-only/default.nix +++ b/pkgs/build-support/src-only/default.nix @@ -13,7 +13,7 @@ let in stdenv.mkDerivation (args // { name = "${name}-source"; - installPhase = "cp -r . $out"; + installPhase = "cp -pr --reflink=auto -- . $out"; outputs = [ "out" ]; separateDebugInfo = false; dontUnpack = false; diff --git a/pkgs/build-support/testers/default.nix b/pkgs/build-support/testers/default.nix index 362622d9b7ee8..dbf9a6d6cb05b 100644 --- a/pkgs/build-support/testers/default.nix +++ b/pkgs/build-support/testers/default.nix @@ -1,6 +1,10 @@ { pkgs, pkgsLinux, buildPackages, lib, callPackage, runCommand, stdenv, substituteAll, testers }: # Documentation is in doc/builders/testers.chapter.md { + # See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck + # or doc/builders/testers.chapter.md + inherit (callPackage ./lychee.nix {}) lycheeLinkCheck; + # See https://nixos.org/manual/nixpkgs/unstable/#tester-testBuildFailure # or doc/builders/testers.chapter.md testBuildFailure = drv: drv.overrideAttrs (orig: { diff --git a/pkgs/build-support/testers/hasPkgConfigModules/tester.nix b/pkgs/build-support/testers/hasPkgConfigModules/tester.nix index bbcc4f0c0f710..3d4ded812f75e 100644 --- a/pkgs/build-support/testers/hasPkgConfigModules/tester.nix +++ b/pkgs/build-support/testers/hasPkgConfigModules/tester.nix @@ -5,14 +5,16 @@ { package, moduleNames ? package.meta.pkgConfigModules, testName ? "check-pkg-config-${lib.concatStringsSep "-" moduleNames}", + version ? package.version or null, + versionCheck ? false, }: runCommand testName { nativeBuildInputs = [ pkg-config ]; buildInputs = [ package ]; - inherit moduleNames; + inherit moduleNames version versionCheck; meta = { - description = "Test whether ${package.name} exposes pkg-config modules ${lib.concatStringsSep ", " moduleNames}."; + description = "Test whether ${package.name} exposes pkg-config modules ${lib.concatStringsSep ", " moduleNames}"; } # Make sure licensing info etc is preserved, as this is a concern for e.g. cache.nixos.org, # as hydra can't check this meta info in dependencies. @@ -31,20 +33,38 @@ runCommand testName { package.meta; } '' touch "$out" + notFound=0 + versionMismatch=0 for moduleName in $moduleNames; do echo "checking pkg-config module $moduleName in $buildInputs" set +e - version="$($PKG_CONFIG --modversion $moduleName)" + moduleVersion="$($PKG_CONFIG --modversion $moduleName)" r=$? set -e if [[ $r = 0 ]]; then - echo "✅ pkg-config module $moduleName exists and has version $version" + if [[ "$moduleVersion" == "$version" ]]; then + echo "✅ pkg-config module $moduleName exists and has version $moduleVersion" + else + echo "${if versionCheck then "❌" else "ℹ️"} pkg-config module $moduleName exists at version $moduleVersion != $version (drv version)" + ((versionMismatch+=1)) + fi printf '%s\t%s\n' "$moduleName" "$version" >> "$out" else - echo "These modules were available in the input propagation closure:" - $PKG_CONFIG --list-all echo "❌ pkg-config module $moduleName was not found" - false + ((notFound+=1)) fi done + + if [[ $notFound -eq 0 ]] && ([[ $versionMismatch -eq 0 ]] || [[ -z "$versionCheck" ]]); then + exit 0 + fi + if [[ $notFound -ne 0 ]]; then + echo "$notFound modules not found" + echo "These modules were available in the input propagation closure:" + $PKG_CONFIG --list-all + fi + if [[ $versionMismatch -ne 0 ]]; then + echo "$versionMismatch version mismatches" + fi + exit 1 '' diff --git a/pkgs/build-support/testers/hasPkgConfigModules/tests.nix b/pkgs/build-support/testers/hasPkgConfigModules/tests.nix index 96569498fb152..adad935079849 100644 --- a/pkgs/build-support/testers/hasPkgConfigModules/tests.nix +++ b/pkgs/build-support/testers/hasPkgConfigModules/tests.nix @@ -1,9 +1,25 @@ # cd nixpkgs -# nix-build -A tests.testers.hasPkgConfigModule -{ lib, testers, zlib, openssl, runCommand }: +# nix-build -A tests.testers.hasPkgConfigModules +{ lib, testers, miniz, zlib, openssl, runCommand }: lib.recurseIntoAttrs { + miniz-versions-match = testers.hasPkgConfigModules { + package = miniz; + versionCheck = true; + }; + + miniz-versions-mismatch = testers.testBuildFailure (testers.hasPkgConfigModules { + package = miniz; + version = "1.2.3"; # Deliberately-incorrect version number + versionCheck = true; + }); + + miniz-no-versionCheck = testers.hasPkgConfigModules { + package = miniz; + version = "1.2.3"; # Deliberately-incorrect version number + }; + zlib-has-zlib = testers.hasPkgConfigModules { package = zlib; moduleNames = [ "zlib" ]; diff --git a/pkgs/build-support/testers/lychee.nix b/pkgs/build-support/testers/lychee.nix new file mode 100644 index 0000000000000..80088dc4f9638 --- /dev/null +++ b/pkgs/build-support/testers/lychee.nix @@ -0,0 +1,69 @@ +deps@{ formats, lib, lychee, stdenv, writeShellApplication }: +let + inherit (lib) mapAttrsToList throwIf; + inherit (lib.strings) hasInfix hasPrefix escapeNixString; + + toURL = v: + let s = "${v}"; + in if hasPrefix builtins.storeDir s + then # lychee requires that paths on the file system are prefixed with file:// + "file://${s}" + else s; + + withCheckedName = name: + throwIf (hasInfix " " name) '' + lycheeLinkCheck: remap patterns must not contain spaces. + A space marks the end of the regex in lychee.toml. + + Please change attribute name 'remap.${escapeNixString name}' + ''; + + # See https://nixos.org/manual/nixpkgs/unstable/#tester-lycheeLinkCheck + # or doc/builders/testers.chapter.md + lycheeLinkCheck = { + site, + remap ? { }, + lychee ? deps.lychee, + extraConfig ? { }, + }: + stdenv.mkDerivation (finalAttrs: { + name = "lychee-link-check"; + inherit site; + nativeBuildInputs = [ finalAttrs.passthru.lychee ]; + configFile = (formats.toml {}).generate "lychee.toml" finalAttrs.passthru.config; + + # These can be overriden with overrideAttrs if needed. + passthru = { + inherit lychee remap; + config = { + include_fragments = true; + } // lib.optionalAttrs (finalAttrs.passthru.remap != { }) { + remap = + mapAttrsToList + (name: value: withCheckedName name "${name} ${toURL value}") + finalAttrs.passthru.remap; + } // extraConfig; + online = writeShellApplication { + name = "run-lychee-online"; + runtimeInputs = [ finalAttrs.passthru.lychee ]; + # Comment out to run shellcheck: + checkPhase = ""; + text = '' + site=${finalAttrs.site} + configFile=${finalAttrs.configFile} + echo Checking links on $site + exec lychee --config $configFile $site "$@" + ''; + }; + }; + buildCommand = '' + echo Checking internal links on $site + lychee --offline --config $configFile $site + touch $out + ''; + }); + +in +{ + inherit lycheeLinkCheck; +} diff --git a/pkgs/build-support/testers/test/default.nix b/pkgs/build-support/testers/test/default.nix index da67711156bed..a815fe63e416e 100644 --- a/pkgs/build-support/testers/test/default.nix +++ b/pkgs/build-support/testers/test/default.nix @@ -12,6 +12,8 @@ let in lib.recurseIntoAttrs { + lycheeLinkCheck = lib.recurseIntoAttrs pkgs.lychee.tests; + hasPkgConfigModules = pkgs.callPackage ../hasPkgConfigModules/tests.nix { }; runNixOSTest-example = pkgs-with-overlay.testers.runNixOSTest ({ lib, ... }: { diff --git a/pkgs/build-support/trivial-builders/test/references/default.nix b/pkgs/build-support/trivial-builders/test/references/default.nix index 928cc1d9461f0..85df57ea210c2 100644 --- a/pkgs/build-support/trivial-builders/test/references/default.nix +++ b/pkgs/build-support/trivial-builders/test/references/default.nix @@ -93,21 +93,27 @@ let }; }); in -testers.nixosTest { - name = "nixpkgs-trivial-builders"; - nodes.machine = { ... }: { +testers.runNixOSTest ({ config, lib, ... }: +let + # Use the testScriptBin from guest pkgs. + # The attribute path to access the guest version of testScriptBin is + # tests.trivial-builders.references.config.node.pkgs.tests.trivial-builders.references.testScriptBin + # which is why passthru.guestTestScriptBin is provided. + guestTestScriptBin = config.node.pkgs.tests.trivial-builders.references.testScriptBin; +in +{ + name = "nixpkgs-trivial-builders-references"; + nodes.machine = { config, lib, pkgs, ... }: { virtualisation.writableStore = true; # Test runs without network, so we don't substitute and prepare our deps nix.settings.substituters = lib.mkForce [ ]; - environment.etc."pre-built-paths".source = writeText "pre-built-paths" ( - builtins.toJSON [ testScriptBin ] - ); + system.extraDependencies = [ guestTestScriptBin ]; }; testScript = '' machine.succeed(""" - ${lib.getExe testScriptBin} 2>/dev/console + ${lib.getExe guestTestScriptBin} 2>/dev/console """) ''; passthru = { @@ -118,6 +124,7 @@ testers.nixosTest { samples testScriptBin ; + inherit guestTestScriptBin; }; meta = { maintainers = with lib.maintainers; [ @@ -125,4 +132,4 @@ testers.nixosTest { ShamrockLee ]; }; -} +}) diff --git a/pkgs/build-support/vm/default.nix b/pkgs/build-support/vm/default.nix index 56375851783fb..871f81bb5d69f 100644 --- a/pkgs/build-support/vm/default.nix +++ b/pkgs/build-support/vm/default.nix @@ -40,10 +40,14 @@ rec { ${pkgs.stdenv.cc.libc}/lib/libc.so.* \ ${pkgs.stdenv.cc.libc}/lib/libm.so.* \ ${pkgs.stdenv.cc.libc}/lib/libresolv.so.* \ + ${pkgs.stdenv.cc.libc}/lib/libpthread.so.* \ + ${pkgs.zstd.out}/lib/libzstd.so.* \ + ${pkgs.xz.out}/lib/liblzma.so.* \ $out/lib # Copy BusyBox. cp -pd ${pkgs.busybox}/bin/* $out/bin + cp -pd ${pkgs.kmod}/bin/* $out/bin # Run patchelf to make the programs refer to the copied libraries. for i in $out/bin/* $out/lib/*; do if ! test -L $i; then nuke-refs $i; fi; done @@ -54,6 +58,11 @@ rec { patchelf --set-interpreter $out/lib/ld-*.so.? --set-rpath $out/lib $i || true fi done + + find $out/lib -type f \! -name 'ld*.so.?' | while read i; do + echo "patching $i..." + patchelf --set-rpath $out/lib $i + done ''; # */ diff --git a/pkgs/build-support/writers/scripts.nix b/pkgs/build-support/writers/scripts.nix index 06d763ca9d6af..93fac09c07ba5 100644 --- a/pkgs/build-support/writers/scripts.nix +++ b/pkgs/build-support/writers/scripts.nix @@ -635,7 +635,7 @@ rec { nuget-source = mkNugetSource { name = "${fname}-nuget-source"; - description = "A Nuget source with the dependencies for ${fname}"; + description = "Nuget source with the dependencies for ${fname}"; deps = [ _nugetDeps ]; }; |