diff --git a/lib/customisation.nix b/lib/customisation.nix index ce00e364ba76b..e489ecc88a430 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -1050,4 +1050,248 @@ rec { hostTarget = f hostTarget; targetTarget = f targetTarget; }; + + /** + Create a package with multiple variants (versions) managed uniformly. + + `mkPackageVariants` standardizes the pattern of maintaining multiple versions + of a single package (e.g., openssl 1.1/3.0/3.6). It takes variant metadata, + a generic builder, and produces a default derivation with all variants + accessible via passthru attributes. + + The generic builder follows a curried pattern: it first receives variant-specific + arguments (version, hash, patches, plus helper functions like `packageOlder`, + `packageAtLeast`, and `packageBetween`), then package arguments (resolved by + `callPackage`), and returns derivation attributes. + + Each variant's passthru includes references to all other variants, enabling + access patterns like `pkg.v1_1`, `pkg.v3`, etc. A `pkg.variants` attribute + set is also available, containing all built variants as an attrset. + Additionally, each variant exposes `pkg.variantArgs` in passthru, containing + the variant's version, hash, and all helper functions. + + The builder's own passthru (e.g., tests) is preserved and merged with + the variant passthru injected by `mkPackageVariants`. The builder's passthru + has the lowest priority — variant passthru (other variants, `variantArgs`) + is merged on top of it. + + This function is curried in three stages: + + 1. Scope arguments (`callPackage`, `allowAliases`) — typically pre-bound in + the package scope (see `pkgs.mkPackageVariants` in `splice.nix`). + + 2. Override arguments (`outerArgs`) — captured via `@args` in the package's + `default.nix`. Infrastructure args (`mkPackageVariants`, `override`, etc.) + are filtered out; the rest are forwarded to the generic builder via + `callPackage`, enabling `pkg.override { withZlib = true; }` to flow + through without per-package boilerplate. + + 3. Package configuration (`params`) — variant selection, paths, aliases. + + # Inputs + + `scopeArgs` (`AttrSet`) + : Pre-bound scope arguments. Typically provided by `splice.nix`: + + `callPackage` (`Function`) + : The `callPackage` function from the package scope, used to resolve + both variant metadata and the generic builder's package arguments. + + `allowAliases` (`Bool`) + : Whether to include deprecated alias variants. + Typically `config.allowAliases`. + + `outerArgs` (`AttrSet`) + : The full `args` from the outer `callPackage`'d function (captured via + `{ mkPackageVariants, ... }@args`). Infrastructure args + (`mkPackageVariants` and `makeOverridable`-injected attrs) are filtered + out; the remaining args are forwarded to the generic builder via + `callPackage`. This enables `pkg.override { withZlib = true; }` to flow + through to the generic builder without per-package boilerplate. + + Structured function argument (`params`): + + `defaultVariant` (`AttrSet -> AttrSet`) + : A function that selects the default variant from the variants set. + Example: `p: p.v3_6` + + `variants` (`AttrSet | Path | Function`) + : Variant metadata. An attribute set mapping variant names to their + configuration (must include at least `version`). Can be a path to + import or a function to be resolved via `callPackage`. + Each variant may also include an `overrideArgs` attrset that gets + forwarded to `callPackage` as override arguments, merged on top of + the global `outerArgs`. This is how feature variants (e.g., `oqs`, + `legacy`) can inject variant-specific dependencies. + Defaults to `variants.nix` in the caller's directory. + + `genericBuilder` (`Path | Function`) + : The package expression. When given a path, it is imported. The expression + must be a curried function: `variantArgs -> packageArgs -> derivation-attrs`. + The first argument receives variant metadata plus helper functions + (`packageOlder`, `packageAtLeast`, `packageBetween`); + the second is resolved by `callPackage`. + Variant passthru (other variants, `variantArgs`) is automatically + injected by `mkPackageVariants` — the generic builder only needs to + set its own passthru (e.g., tests). + Defaults to `generic.nix` in the caller's directory. + + :::{.note} + Auto-detection of `variants` and `genericBuilder` paths relies on + `builtins.unsafeGetAttrPos` to determine the caller's directory. If + source positions are unavailable (e.g., in `builtins.toFile` or + certain eval contexts), both `variants` and `genericBuilder` must be + provided explicitly. + ::: + + `aliases` (`AttrSet | Path | Function`) + : Optional deprecated variant names. When a function, receives + `{ lib, variants }` and should return an attribute set. + + # Type + + ``` + mkPackageVariants :: { + callPackage :: (AttrSet -> a) -> AttrSet -> a, + allowAliases? :: Bool, + } -> AttrSet -> { + defaultVariant :: AttrSet -> AttrSet, + variants? :: AttrSet | Path | (AttrSet -> AttrSet), + genericBuilder? :: Path | (AttrSet -> AttrSet -> AttrSet), + aliases? :: AttrSet | Path | ({ lib, variants } -> AttrSet), + } -> Derivation + ``` + + # Examples + :::{.example} + ## `lib.customisation.mkPackageVariants` usage example + + ```nix + # variants.nix + { + v1 = { version = "1.0"; hash = "sha256-..."; }; + v2 = { version = "2.0"; hash = "sha256-..."; }; + } + + # generic.nix — curried: variantArgs -> packageArgs -> derivation-attrs + # Variant passthru is injected automatically by mkPackageVariants. + { version, hash, packageOlder, packageAtLeast, ... }: + { lib, stdenv, fetchurl }: + stdenv.mkDerivation { + pname = "my-package"; + inherit version; + src = fetchurl { url = "https://example.com/pkg-${version}.tar.gz"; inherit hash; }; + } + + # default.nix — variants.nix and generic.nix auto-detected in same directory + # mkPackageVariants is pre-bound in the package scope (splice.nix) + { mkPackageVariants, ... }@args: + mkPackageVariants args { + defaultVariant = p: p.v2; + } + + # Result: default derivation (v2) with passthru.v1, passthru.v2, + # passthru.variants (attrset of all variants), passthru.variantArgs + # pkg.override { ... } flows through to the generic builder + ``` + ::: + */ + mkPackageVariants = + { + callPackage, + allowAliases, + }: + outerArgs: + { + defaultVariant, + variants ? null, + genericBuilder ? null, + aliases ? _: { }, + }@params: + assert isFunction defaultVariant; + let + # Detect the caller's directory from source position of `defaultVariant`. + # This allows `variants` and `genericBuilder` to default to files in the + # same directory as the caller without requiring an explicit path. + callerDir = + let + pos = builtins.unsafeGetAttrPos "defaultVariant" params; + in + if pos != null then + /. + dirOf pos.file + else + throw "mkPackageVariants: cannot determine caller directory; provide 'variants' and 'genericBuilder' explicitly"; + + variants' = if variants != null then variants else callerDir + "/variants.nix"; + genericBuilder' = if genericBuilder != null then genericBuilder else callerDir + "/generic.nix"; + + importIfPath = x: if builtins.isPath x then import x else x; + callIfFunction = x: if builtins.isFunction x then callPackage x { } else x; + + # Extract package-level override args from the outer callPackage scope. + # These are args like `providers`, `withZlib`, etc. that were passed via + # .override on the top-level package. Infrastructure args from callPackage + # and makeOverridable are filtered out. + overrideArgs = removeAttrs outerArgs [ + "mkPackageVariants" + "override" + "overrideDerivation" + "overrideAttrs" + ]; + + variantsRaw = callIfFunction (importIfPath variants'); + aliasesExpr = importIfPath aliases; + # Do not use callPackage as the genericExpr should get called from package scope later + genericExpr = importIfPath genericBuilder'; + + resolvedAliases = + if isFunction aliasesExpr then + aliasesExpr { + inherit lib; + variants = variantsRaw; + } + else + aliasesExpr; + + allVariants = if allowAliases then variantsRaw // resolvedAliases else variantsRaw; + + selectedVariant = defaultVariant allVariants; + + mkVariantPassthru = + variantArgs: + let + builtVariants = mapAttrs (_: v: mkPackage (variantArgs // v)) allVariants; + in + builtVariants // { variants = builtVariants; }; + + mkVariantArgs = + { version, ... }@args: + args + // rec { + packageOlder = lib.versionOlder version; + packageAtLeast = lib.versionAtLeast version; + packageBetween = lower: higher: packageAtLeast lower && packageOlder higher; + inherit mkVariantPassthru; + }; + + mkPackage = + variant: + let + variantOverrideArgs = variant.overrideArgs or { }; + cleanVariant = removeAttrs (selectedVariant // variant) [ "overrideArgs" ]; + variantArgs = mkVariantArgs cleanVariant; + pkg = callPackage (genericExpr variantArgs) (overrideArgs // variantOverrideArgs); + in + pkg.overrideAttrs (o: { + passthru = + o.passthru or { } + // mkVariantPassthru variantArgs + // { + inherit variantArgs; + }; + }); + + defaultPackage = defaultVariant (mkVariantPassthru allVariants); + in + defaultPackage; } diff --git a/lib/default.nix b/lib/default.nix index 15949d1cdf367..262f8b0aa9b59 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -415,6 +415,7 @@ let makeScopeWithSplicing makeScopeWithSplicing' extendMkDerivation + mkPackageVariants renameCrossIndexFrom renameCrossIndexTo mapCrossIndex diff --git a/lib/tests/customisation.nix b/lib/tests/customisation.nix new file mode 100644 index 0000000000000..362711551b48c --- /dev/null +++ b/lib/tests/customisation.nix @@ -0,0 +1,430 @@ +/** + Tests for lib.customisation functions (mkPackageVariants, etc.). + + To run these tests: + + [nixpkgs]$ nix-instantiate --eval --strict lib/tests/customisation.nix + + If the resulting list is empty, all tests passed. +*/ + +let + lib = import ../default.nix; + + inherit (lib) + attrNames + callPackageWith + mkPackageVariants + runTests + ; + + testingThrow = expr: { + expr = (builtins.tryEval (builtins.seq expr "didn't throw")); + expected = { + success = false; + value = false; + }; + }; + + # Mock derivation with overrideAttrs support + mkMockDrv = + attrs: + attrs + // { + overrideAttrs = f: mkMockDrv (attrs // (f attrs)); + type = "derivation"; + }; + + # Standard mock scope providing the dependencies that callPackageWith resolves + mockScope = { + inherit lib; + inherit (lib) versionOlder versionAtLeast; + mockDep = "resolved"; + }; + + mockCallPackage = callPackageWith mockScope; + + # Attrs injected by mkPackageVariants into variantArgs (not package-specific) + variantArgsInfra = [ + "mkVariantPassthru" + "packageOlder" + "packageAtLeast" + "packageBetween" + ]; + + # Standard mock generic builder: variantArgs -> packageArgs -> mock derivation + # Extra variant attrs (beyond version/hash/infra) are passed through to passthru. + mockGenericBuilder = + { version, ... }@variantArgs: + { ... }: + mkMockDrv { + name = "test-${version}"; + passthru = builtins.removeAttrs variantArgs ( + [ + "version" + "hash" + ] + ++ variantArgsInfra + ); + }; + + # Pre-bound mkPackageVariants with standard mocks + mkVariants = mkPackageVariants { + callPackage = mockCallPackage; + allowAliases = true; + }; + + mkVariantsNoAliases = mkPackageVariants { + callPackage = mockCallPackage; + allowAliases = false; + }; + + # Standard two-variant test set + testVariants = { + v1 = { + version = "1.0"; + hash = "aaa"; + }; + v2 = { + version = "2.0"; + hash = "bbb"; + }; + }; + + # Standard test package (default = v1) + pkg = mkVariants { } { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = mockGenericBuilder; + }; + + # Shorthand for the default variant's variantArgs + va = pkg.passthru.variantArgs; +in + +runTests { + + # Default variant selection + + testMkPackageVariantsDefaultSelection = { + expr = pkg.name; + expected = "test-1.0"; + }; + + # Passthru: individual variants + + testMkPackageVariantsAllVariantsInPassthru = { + expr = { + hasV1 = pkg.passthru ? v1; + hasV2 = pkg.passthru ? v2; + v1Name = pkg.passthru.v1.name; + v2Name = pkg.passthru.v2.name; + }; + expected = { + hasV1 = true; + hasV2 = true; + v1Name = "test-1.0"; + v2Name = "test-2.0"; + }; + }; + + # Passthru: variants attrset + + testMkPackageVariantsVariantsAttr = { + expr = { + hasVariants = pkg.passthru ? variants; + variantNames = attrNames pkg.passthru.variants; + }; + expected = { + hasVariants = true; + variantNames = [ + "v1" + "v2" + ]; + }; + }; + + # Passthru: variantArgs + + testMkPackageVariantsVariantArgs = { + expr = va.version; + expected = "1.0"; + }; + + # Helper functions + + testMkPackageVariantsPackageOlder = { + expr = { + olderThan2 = va.packageOlder "2.0"; + olderThan1 = va.packageOlder "1.0"; + }; + expected = { + olderThan2 = true; + olderThan1 = false; + }; + }; + + testMkPackageVariantsPackageAtLeast = { + expr = { + atLeast1 = va.packageAtLeast "1.0"; + atLeast2 = va.packageAtLeast "2.0"; + }; + expected = { + atLeast1 = true; + atLeast2 = false; + }; + }; + + testMkPackageVariantsPackageBetween = { + expr = { + between05and15 = va.packageBetween "0.5" "1.5"; + between15and25 = va.packageBetween "1.5" "2.5"; + between05and10 = va.packageBetween "0.5" "1.0"; + }; + expected = { + between05and15 = true; + between15and25 = false; + between05and10 = false; + }; + }; + + # Aliases + + testMkPackageVariantsAliases = + let + aliasPkg = mkVariants { } { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = mockGenericBuilder; + aliases = { + old = testVariants.v1; + }; + }; + in + { + expr = { + hasAlias = aliasPkg.passthru ? old; + aliasName = aliasPkg.passthru.old.name; + }; + expected = { + hasAlias = true; + aliasName = "test-1.0"; + }; + }; + + testMkPackageVariantsNoAliases = + let + noAliasPkg = mkVariantsNoAliases { } { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = mockGenericBuilder; + aliases = { + old = testVariants.v1; + }; + }; + in + { + expr = noAliasPkg.passthru ? old; + expected = false; + }; + + testMkPackageVariantsAliasesFunction = + let + fnAliasPkg = mkVariants { } { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = mockGenericBuilder; + aliases = + { lib, variants }: + { + latest = variants.v2; + }; + }; + in + { + expr = { + hasLatest = fnAliasPkg.passthru ? latest; + latestName = fnAliasPkg.passthru.latest.name; + }; + expected = { + hasLatest = true; + latestName = "test-2.0"; + }; + }; + + # Override args filtering and forwarding + + testMkPackageVariantsOverrideArgsFiltering = + let + filterScope = mockScope // { + mkPackageVariants = "should-be-filtered"; + override = "should-be-filtered"; + overrideDerivation = "should-be-filtered"; + overrideAttrs = "should-be-filtered"; + }; + # Builder accepts infrastructure attr names as optional args; + # if filtering works, they come from scope (strings), not outerArgs. + filterGenericBuilder = + { version, ... }: + { + mkPackageVariants ? "from-scope", + override ? "from-scope", + overrideDerivation ? "from-scope", + overrideAttrs ? "from-scope", + }: + mkMockDrv { + name = "test-${version}"; + passthru = { + receivedMkPV = mkPackageVariants; + receivedOverride = override; + receivedOverrideDerivation = overrideDerivation; + receivedOverrideAttrs = overrideAttrs; + }; + }; + filterMkVariants = lib.mkPackageVariants { + callPackage = callPackageWith filterScope; + allowAliases = true; + }; + # Pass infrastructure args in outerArgs — they should be filtered out + filterPkg = + filterMkVariants + { + mkPackageVariants = "outer-value"; + override = "outer-value"; + overrideDerivation = "outer-value"; + overrideAttrs = "outer-value"; + } + { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = filterGenericBuilder; + }; + in + { + expr = { + inherit (filterPkg.passthru) + receivedMkPV + receivedOverride + receivedOverrideDerivation + receivedOverrideAttrs + ; + }; + expected = { + receivedMkPV = "should-be-filtered"; + receivedOverride = "should-be-filtered"; + receivedOverrideDerivation = "should-be-filtered"; + receivedOverrideAttrs = "should-be-filtered"; + }; + }; + + testMkPackageVariantsOuterArgsForwarding = + let + extraGenericBuilder = + { version, ... }: + { + extraArg ? "default", + ... + }: + mkMockDrv { + name = "test-${version}"; + passthru = { + inherit extraArg; + }; + }; + extraPkg = mkVariants { extraArg = "custom"; } { + defaultVariant = p: p.v1; + variants = testVariants; + genericBuilder = extraGenericBuilder; + }; + in + { + expr = extraPkg.passthru.extraArg; + expected = "custom"; + }; + + testMkPackageVariantsPerVariantOverrideArgs = + let + featureGenericBuilder = + { version, ... }: + { + feature ? "off", + ... + }: + mkMockDrv { + name = "test-${version}"; + passthru = { + inherit feature; + }; + }; + featurePkg = mkVariants { } { + defaultVariant = p: p.v1; + variants = { + v1 = { + version = "1.0"; + hash = "aaa"; + }; + v1_feature = { + version = "1.0"; + hash = "aaa"; + overrideArgs = { + feature = "on"; + }; + }; + }; + genericBuilder = featureGenericBuilder; + }; + in + { + expr = { + v1Feature = featurePkg.passthru.v1.passthru.feature; + v1FeatureVariant = featurePkg.passthru.v1_feature.passthru.feature; + }; + expected = { + v1Feature = "off"; + v1FeatureVariant = "on"; + }; + }; + + # Assertion: defaultVariant must be a function + + testMkPackageVariantsDefaultVariantNotFunction = testingThrow ( + mkVariants { } { + defaultVariant = "not-a-function"; + variants = testVariants; + genericBuilder = mockGenericBuilder; + } + ); + + # Variant-specific fields override selectedVariant defaults + # mockGenericBuilder passes extra variantArgs (like extraField) through to passthru + + testMkPackageVariantsVariantOverridesDefault = + let + overridePkg = mkVariants { } { + defaultVariant = p: p.v1; + variants = { + v1 = { + version = "1.0"; + hash = "aaa"; + extraField = "from-default"; + }; + v2 = { + version = "2.0"; + hash = "bbb"; + extraField = "from-v2"; + }; + }; + genericBuilder = mockGenericBuilder; + }; + in + { + expr = { + v1Extra = overridePkg.passthru.v1.passthru.extraField; + v2Extra = overridePkg.passthru.v2.passthru.extraField; + }; + expected = { + v1Extra = "from-default"; + v2Extra = "from-v2"; + }; + }; +} diff --git a/lib/tests/test-with-nix.nix b/lib/tests/test-with-nix.nix index 7f85db356fdc0..4c4c5bd8c48da 100644 --- a/lib/tests/test-with-nix.nix +++ b/lib/tests/test-with-nix.nix @@ -78,6 +78,9 @@ pkgs.runCommand "nixpkgs-lib-tests-nix-${nix.version}" echo "Running lib/tests/fetchers.nix" [[ $(nix-instantiate --eval --strict lib/tests/fetchers.nix | tee /dev/stderr) == '[ ]' ]]; + echo "Running lib/tests/customisation.nix" + [[ $(nix-instantiate --eval --strict lib/tests/customisation.nix | tee /dev/stderr) == '[ ]' ]]; + mkdir $out echo success > $out/${nix.version} '' diff --git a/pkgs/development/libraries/openssl/1.1/nix-ssl-cert-file.patch b/pkgs/by-name/op/openssl/1.1/nix-ssl-cert-file.patch similarity index 100% rename from pkgs/development/libraries/openssl/1.1/nix-ssl-cert-file.patch rename to pkgs/by-name/op/openssl/1.1/nix-ssl-cert-file.patch diff --git a/pkgs/development/libraries/openssl/1.1/use-etc-ssl-certs-darwin.patch b/pkgs/by-name/op/openssl/1.1/use-etc-ssl-certs-darwin.patch similarity index 100% rename from pkgs/development/libraries/openssl/1.1/use-etc-ssl-certs-darwin.patch rename to pkgs/by-name/op/openssl/1.1/use-etc-ssl-certs-darwin.patch diff --git a/pkgs/development/libraries/openssl/1.1/use-etc-ssl-certs.patch b/pkgs/by-name/op/openssl/1.1/use-etc-ssl-certs.patch similarity index 100% rename from pkgs/development/libraries/openssl/1.1/use-etc-ssl-certs.patch rename to pkgs/by-name/op/openssl/1.1/use-etc-ssl-certs.patch diff --git a/pkgs/development/libraries/openssl/3.0/legacy.cnf b/pkgs/by-name/op/openssl/3.0/legacy.cnf similarity index 100% rename from pkgs/development/libraries/openssl/3.0/legacy.cnf rename to pkgs/by-name/op/openssl/3.0/legacy.cnf diff --git a/pkgs/development/libraries/openssl/3.0/nix-ssl-cert-file.patch b/pkgs/by-name/op/openssl/3.0/nix-ssl-cert-file.patch similarity index 100% rename from pkgs/development/libraries/openssl/3.0/nix-ssl-cert-file.patch rename to pkgs/by-name/op/openssl/3.0/nix-ssl-cert-file.patch diff --git a/pkgs/development/libraries/openssl/3.0/openssl-disable-kernel-detection.patch b/pkgs/by-name/op/openssl/3.0/openssl-disable-kernel-detection.patch similarity index 100% rename from pkgs/development/libraries/openssl/3.0/openssl-disable-kernel-detection.patch rename to pkgs/by-name/op/openssl/3.0/openssl-disable-kernel-detection.patch diff --git a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch b/pkgs/by-name/op/openssl/3.5/use-etc-ssl-certs-darwin.patch similarity index 100% rename from pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs-darwin.patch rename to pkgs/by-name/op/openssl/3.5/use-etc-ssl-certs-darwin.patch diff --git a/pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch b/pkgs/by-name/op/openssl/3.5/use-etc-ssl-certs.patch similarity index 100% rename from pkgs/development/libraries/openssl/3.5/use-etc-ssl-certs.patch rename to pkgs/by-name/op/openssl/3.5/use-etc-ssl-certs.patch diff --git a/pkgs/by-name/op/openssl/3.6/mingw-define-netreset.patch b/pkgs/by-name/op/openssl/3.6/mingw-define-netreset.patch new file mode 100644 index 0000000000000..a228ec407d694 --- /dev/null +++ b/pkgs/by-name/op/openssl/3.6/mingw-define-netreset.patch @@ -0,0 +1,30 @@ +From 3d04d5b678c2f95975d1639dc21398b79308af54 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Alexander=20Hansen=20F=C3=A6r=C3=B8y?= +Date: Wed, 28 Jan 2026 17:55:02 +0100 +Subject: [PATCH] Explicitly define `SIO_UDP_NETRESET` for MinGW builds. + +This patch explicitly defines the value `SIO_UDP_NETRESET` according to +both what Windows and ReactOS does. + +Fixes: #29818. +--- + ssl/quic/quic_reactor.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ssl/quic/quic_reactor.c b/ssl/quic/quic_reactor.c +index a754f285bbe2b..d8ac969d02a69 100644 +--- a/ssl/quic/quic_reactor.c ++++ b/ssl/quic/quic_reactor.c +@@ -76,6 +76,12 @@ void ossl_quic_reactor_cleanup(QUIC_REACTOR *rtor) + } + + #if defined(OPENSSL_SYS_WINDOWS) ++ ++/* Work around for MinGW builds. */ ++#if defined(__MINGW32__) && !defined(SIO_UDP_NETRESET) ++# define SIO_UDP_NETRESET _WSAIOW(IOC_VENDOR, 15) ++#endif ++ + /* + * On Windows recvfrom() may return WSAECONNRESET when destination port + * used in preceding call to sendto() is no longer reachable. The reset diff --git a/pkgs/by-name/op/openssl/generic.nix b/pkgs/by-name/op/openssl/generic.nix new file mode 100644 index 0000000000000..4d4618ff2c8bf --- /dev/null +++ b/pkgs/by-name/op/openssl/generic.nix @@ -0,0 +1,408 @@ +# Curried builder: variantArgs -> packageArgs -> derivation +# +# First argument (variantArgs) is provided by mkPackageVariants and contains: +# version, hash, patches, packageOlder, packageAtLeast, +# packageBetween, mkVariantPassthru +# +# Second argument (packageArgs) is resolved by callPackage. +{ + version, + hash, + patches ? [ ], + packageOlder, + packageAtLeast, + ... +}: + +# Note: this package is used for bootstrapping fetchurl, and thus +# cannot use fetchpatch! All mutable patches (generated by GitHub or +# cgit) that are needed here should be included directly in Nixpkgs as +# files. + +{ + lib, + stdenv, + fetchurl, + buildPackages, + perl, + makeBinaryWrapper, + withCryptodev ? false, + cryptodev, + withZlib ? false, + zlib, + enableSSL2 ? false, + enableSSL3 ? false, + enableMD2 ? false, + enableKTLS ? stdenv.hostPlatform.isLinux, + # change this to a value between 0 and 5 (as of OpenSSL 3.5) + # if null, default is used, changes the permitted algorithms + # and key lengths in the default config + # see: https://docs.openssl.org/3.5/man3/SSL_CTX_set_security_level/ + securityLevel ? null, + static ? stdenv.hostPlatform.isStatic, + # path to openssl.cnf file. will be placed in $etc/etc/ssl/openssl.cnf to replace the default + conf ? null, + removeReferencesTo, + testers, + providers ? [ ], # Each provider in the format { name = "provider-name"; package = ; } + autoloadProviders ? false, + extraINIConfig ? null, # Extra INI config in the format { section_name = { key = "value"}; } +}: + +# check from time to time, if this range is still correct +assert (securityLevel == null) || (securityLevel >= 0 && securityLevel <= 5); + +let + useBinaryWrapper = !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isCygwin); +in + +stdenv.mkDerivation (finalAttrs: { + pname = "openssl"; + inherit version; + + src = fetchurl { + url = + if packageOlder "3.0" then + let + versionFixed = builtins.replaceStrings [ "." ] [ "_" ] version; + in + "https://github.com/openssl/openssl/releases/download/OpenSSL_${versionFixed}/openssl-${version}.tar.gz" + else + "https://github.com/openssl/openssl/releases/download/openssl-${version}/openssl-${version}.tar.gz"; + inherit hash; + }; + + inherit patches; + + postPatch = '' + patchShebangs Configure + '' + + lib.optionalString (packageOlder "1.1.1") '' + patchShebangs test/* + for a in test/t* ; do + substituteInPlace "$a" \ + --replace /bin/rm rm + done + '' + # config is a configure script which is not installed. + + lib.optionalString (packageAtLeast "1.1.1") '' + substituteInPlace config --replace '/usr/bin/env' '${buildPackages.coreutils}/bin/env' + '' + + lib.optionalString (packageAtLeast "1.1.1" && stdenv.hostPlatform.isMusl) '' + substituteInPlace crypto/async/arch/async_posix.h \ + --replace '!defined(__ANDROID__) && !defined(__OpenBSD__)' \ + '!defined(__ANDROID__) && !defined(__OpenBSD__) && 0' + '' + # Move ENGINESDIR into OPENSSLDIR for static builds, in order to move + # it to the separate etc output. + + lib.optionalString static '' + substituteInPlace Configurations/unix-Makefile.tmpl \ + --replace 'ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}' \ + 'ENGINESDIR=$(OPENSSLDIR)/engines-{- $sover_dirname -}' + '' + # This test will fail if the error strings between the build libc and host + # libc mismatch, e.g. when cross-compiling from glibc to musl + + + lib.optionalString + (finalAttrs.finalPackage.doCheck && stdenv.hostPlatform.libc != stdenv.buildPlatform.libc) + '' + rm test/recipes/02-test_errstr.t + '' + + lib.optionalString stdenv.hostPlatform.isCygwin '' + rm test/recipes/01-test_symbol_presence.t + ''; + + outputs = [ + "bin" + "dev" + "out" + "man" + "doc" + ] + # Separate output for the runtime dependencies of the static build. + # Specifically, move OPENSSLDIR into this output, as its path will be + # compiled into 'libcrypto.a'. This makes it a runtime dependency of + # any package that statically links openssl, so we want to keep that + # output minimal. + ++ lib.optional static "etc"; + setOutputFlags = false; + separateDebugInfo = + !stdenv.hostPlatform.isDarwin + && !stdenv.hostPlatform.isAndroid + && !(stdenv.hostPlatform.useLLVM or false) + && stdenv.cc.isGNU; + + nativeBuildInputs = + lib.optional useBinaryWrapper makeBinaryWrapper + ++ [ perl ] + ++ lib.optionals static [ removeReferencesTo ]; + buildInputs = lib.optional withCryptodev cryptodev ++ lib.optional withZlib zlib; + + # TODO(@Ericson2314): Improve with mass rebuild + configurePlatforms = [ ]; + configureScript = + { + armv5tel-linux = "./Configure linux-armv4 -march=armv5te"; + armv6l-linux = "./Configure linux-armv4 -march=armv6"; + armv7l-linux = "./Configure linux-armv4 -march=armv7-a"; + x86_64-darwin = "./Configure darwin64-x86_64-cc"; + aarch64-darwin = "./Configure darwin64-arm64-cc"; + x86_64-linux = "./Configure linux-x86_64"; + x86_64-solaris = "./Configure solaris64-x86_64-gcc"; + powerpc-linux = "./Configure linux-ppc"; + powerpc64-linux = "./Configure linux-ppc64"; + riscv32-linux = "./Configure ${ + if packageAtLeast "3.2" then "linux32-riscv32" else "linux-latomic" + }"; + riscv64-linux = "./Configure linux64-riscv64"; + } + .${stdenv.hostPlatform.system} or ( + if stdenv.hostPlatform == stdenv.buildPlatform then + "./config" + else if stdenv.hostPlatform.isBSD then + if stdenv.hostPlatform.isx86_64 then + "./Configure BSD-x86_64" + else if stdenv.hostPlatform.isx86_32 then + "./Configure BSD-x86" + lib.optionalString stdenv.hostPlatform.isElf "-elf" + else + "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}" + else if stdenv.hostPlatform.isMinGW then + "./Configure mingw${ + lib.optionalString (stdenv.hostPlatform.parsed.cpu.bits != 32) ( + toString stdenv.hostPlatform.parsed.cpu.bits + ) + }" + else if stdenv.hostPlatform.isLinux then + if stdenv.hostPlatform.isx86_64 then + "./Configure linux-x86_64" + else if stdenv.hostPlatform.isMicroBlaze then + "./Configure linux-latomic" + else if stdenv.hostPlatform.isMips32 then + "./Configure linux-mips32" + else if stdenv.hostPlatform.isMips64n32 then + "./Configure linux-mips64" + else if stdenv.hostPlatform.isMips64n64 then + "./Configure linux64-mips64" + else + "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}" + else if stdenv.hostPlatform.isiOS then + "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross" + else if stdenv.hostPlatform.isCygwin then + "./Configure Cygwin-${stdenv.hostPlatform.linuxArch}" + else + throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}" + ); + + # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags. + dontAddStaticConfigureFlags = true; + configureFlags = [ + "shared" # "shared" builds both shared and static libraries + "--libdir=lib" + ( + if !static then + "--openssldir=etc/ssl" + else + # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.' + # to the path to make it appear absolute before variable expansion, + # else the 'prefix' would be prepended to it. + "--openssldir=/.$(etc)/etc/ssl" + ) + ] + ++ lib.optionals withCryptodev [ + "-DHAVE_CRYPTODEV" + "-DUSE_CRYPTODEV_DIGESTS" + ] + # enable optimized EC curve primitives on x86_64, + # can provide a 2x up to 4x speedup at best + # with combined PQC and conventional crypto handshakes + # starting with 3.5 its nice to speed things up for free + ++ lib.optional stdenv.hostPlatform.isx86_64 "enable-ec_nistp_64_gcc_128" + # useful to set e.g. 256 bit security level with setting this to 5 + ++ lib.optional (securityLevel != null) "-DOPENSSL_TLS_SECURITY_LEVEL=${toString securityLevel}" + ++ lib.optional enableMD2 "enable-md2" + ++ lib.optional enableSSL2 "enable-ssl2" + ++ lib.optional enableSSL3 "enable-ssl3" + # We select KTLS here instead of the configure-time detection (which we patch out). + # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it. + ++ lib.optional (packageAtLeast "3.0.0" && enableKTLS) "enable-ktls" + ++ lib.optional (packageAtLeast "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng" + # OpenSSL needs a specific `no-shared` configure flag. + # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options + # for a comprehensive list of configuration options. + ++ lib.optional (packageAtLeast "1.1.1" && static) "no-shared" + ++ lib.optional (packageAtLeast "3.0.0" && static) "no-module" + # This introduces a reference to the CTLOG_FILE which is undesired when + # trying to build binaries statically. + ++ lib.optional static "no-ct" + ++ lib.optional withZlib "zlib" + # /dev/crypto support has been dropped in OpenBSD 5.7. + # + # OpenBSD's ports does this too, + # https://github.com/openbsd/ports/blob/a1147500c76970fea22947648fb92a093a529d7c/security/openssl/3.3/Makefile#L25. + # + # https://github.com/openssl/openssl/pull/10565 indicated the + # intent was that this would be configured properly automatically, + # but that doesn't appear to be the case. + ++ lib.optional stdenv.hostPlatform.isOpenBSD "no-devcryptoeng" + ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [ + # This is necessary in order to avoid openssl adding -march + # flags which ultimately conflict with those added by + # cc-wrapper. Openssl assumes that it can scan CFLAGS to + # detect any -march flags, using this perl code: + # + # && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}}) + # + # The following bogus CFLAGS environment variable triggers the + # the code above, inhibiting `./Configure` from adding the + # conflicting flags. + "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}" + ] + # tests are not being installed, it makes no sense + # to build them if check is disabled, e.g. on cross. + ++ lib.optional (!finalAttrs.finalPackage.doCheck) "disable-tests"; + + makeFlags = [ + "MANDIR=$(man)/share/man" + # This avoids conflicts between man pages of openssl subcommands (for + # example 'ts' and 'err') man pages and their equivalent top-level + # command in other packages (respectively man-pages and moreutils). + # This is done in ubuntu and archlinux, and possibly many other distros. + "MANSUFFIX=ssl" + ]; + + enableParallelBuilding = true; + + doCheck = true; + preCheck = '' + patchShebangs util + ''; + + __darwinAllowLocalNetworking = true; + + postInstall = + ( + if static then + '' + # OPENSSLDIR has a reference to self + remove-references-to -t $out $out/lib/*.a + '' + else + '' + # If we're building dynamic libraries, then don't install static + # libraries. + if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then + rm "$out/lib/"*.a + fi + + # 'etc' is a separate output on static builds only. + etc=$out + '' + ) + + '' + mkdir -p $bin + mv $out/bin $bin/bin + + '' + + + lib.optionalString useBinaryWrapper + # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726) + '' + # c_rehash is a legacy perl script with the same functionality + # as `openssl rehash` + # this wrapper script is created to maintain backwards compatibility without + # depending on perl + makeWrapper $bin/bin/openssl $bin/bin/c_rehash \ + --add-flags "rehash" + '' + + '' + + mkdir $dev + mv $out/include $dev/ + + # remove dependency on Perl at runtime + rm -r $etc/etc/ssl/misc + + rmdir $etc/etc/ssl/{certs,private} + '' + + lib.optionalString (conf != null) '' + cat ${conf} > $etc/etc/ssl/openssl.cnf + '' + + # Replace the config's default provider section with the providers we wish + # to automatically load + + lib.optionalString autoloadProviders '' + sed -i '/^[[:space:]]*#/!s|\[provider_sect\]|${ + let + config-provider-attrset = lib.foldl' (acc: elem: acc // elem) { } ( + map (provider: { "${provider.name}" = "${provider.name}_sect"; }) providers + ); + in + lib.escape [ "\n" ] (lib.generators.toINI { } { provider_sect = config-provider-attrset; }) + }|' $etc/etc/ssl/openssl.cnf + + # Activate the default provider + sed -i '/^[[:space:]]*#/!s/\[default_sect\]/[default_sect]\nactivate = 1/g' $etc/etc/ssl/openssl.cnf + '' + + + lib.concatStringsSep "\n" ( + map + (provider: '' + cp ${provider.package}/lib/ossl-modules/* "$out/lib/ossl-modules" + + ${lib.optionalString autoloadProviders '' + echo '${ + lib.generators.toINI { } { + "${provider.name}_sect" = { + activate = 1; + }; + } + }' >> $etc/etc/ssl/openssl.cnf + ''} + '') + + providers + ) + + lib.optionalString (extraINIConfig != null) '' + echo '${lib.generators.toINI { } extraINIConfig}' >> $etc/etc/ssl/openssl.cnf + ''; + + allowedImpureDLLs = [ "CRYPT32.dll" ]; + + postFixup = + lib.optionalString (!stdenv.hostPlatform.isWindows) '' + # Check to make sure the main output and the static runtime dependencies + # don't depend on perl + if grep -r '${buildPackages.perl}' $out $etc; then + echo "Found an erroneous dependency on perl ^^^" >&2 + exit 1 + fi + '' + + lib.optionalString (packageAtLeast "3.3.0") '' + # cleanup cmake helpers for now (for OpenSSL >= 3.3), only rely on pkg-config. + # pkg-config gets its paths fixed correctly + rm -rf $dev/lib/cmake + ''; + + passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; + + meta = { + homepage = "https://www.openssl.org/"; + changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md"; + description = "Cryptographic library that implements the SSL and TLS protocols"; + license = if packageAtLeast "3.0" then lib.licenses.asl20 else lib.licenses.openssl; + mainProgram = "openssl"; + maintainers = with lib.maintainers; [ thillux ]; + pkgConfigModules = [ + "libcrypto" + "libssl" + "openssl" + ]; + platforms = lib.platforms.all; + identifiers.cpeParts = lib.meta.cpeFullVersionWithVendor "openssl" finalAttrs.version; + } + // lib.optionalAttrs (packageOlder "2.0") { + knownVulnerabilities = [ + "OpenSSL 1.1 is reaching its end of life on 2023/09/11 and cannot be supported through the NixOS 23.11 release cycle. https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/" + ]; + }; +}) diff --git a/pkgs/development/libraries/openssl/openssl-3.0.18-skip-dllmain-detach.patch b/pkgs/by-name/op/openssl/openssl-3.0.18-skip-dllmain-detach.patch similarity index 100% rename from pkgs/development/libraries/openssl/openssl-3.0.18-skip-dllmain-detach.patch rename to pkgs/by-name/op/openssl/openssl-3.0.18-skip-dllmain-detach.patch diff --git a/pkgs/by-name/op/openssl/package.nix b/pkgs/by-name/op/openssl/package.nix new file mode 100644 index 0000000000000..73e41cb7730de --- /dev/null +++ b/pkgs/by-name/op/openssl/package.nix @@ -0,0 +1,17 @@ +{ + mkPackageVariants, + ... +}@args: + +mkPackageVariants args { + # intended version "policy": + # - 1.1 as long as some package exists, which does not build without it + # (tracking issue: https://github.com/NixOS/nixpkgs/issues/269713) + # try to remove in 24.05 for the first time, if possible then + # - latest 3.x LTS + # - latest 3.x non-LTS as preview/for development + # + # - other versions in between only when reasonable need is stated for some package + # - backport every security critical fix release e.g. 3.0.y -> 3.0.y+1 but no new version, e.g. 3.1 -> 3.2 + defaultVariant = p: p.v3_6; +} diff --git a/pkgs/development/libraries/openssl/use-etc-ssl-certs-darwin.patch b/pkgs/by-name/op/openssl/use-etc-ssl-certs-darwin.patch similarity index 100% rename from pkgs/development/libraries/openssl/use-etc-ssl-certs-darwin.patch rename to pkgs/by-name/op/openssl/use-etc-ssl-certs-darwin.patch diff --git a/pkgs/development/libraries/openssl/use-etc-ssl-certs.patch b/pkgs/by-name/op/openssl/use-etc-ssl-certs.patch similarity index 100% rename from pkgs/development/libraries/openssl/use-etc-ssl-certs.patch rename to pkgs/by-name/op/openssl/use-etc-ssl-certs.patch diff --git a/pkgs/by-name/op/openssl/variants.nix b/pkgs/by-name/op/openssl/variants.nix new file mode 100644 index 0000000000000..edac7431d5652 --- /dev/null +++ b/pkgs/by-name/op/openssl/variants.nix @@ -0,0 +1,101 @@ +{ + lib, + stdenv, + oqs-provider, +}: + +let + + + v3_6 = { + version = "3.6.1"; + hash = "sha256-sb/tzVson/Iq7ofJ1gD1FXZ+v0X3cWjLbWTyMfUYqC4="; + patches = [ + ./3.0/nix-ssl-cert-file.patch + ./3.0/openssl-disable-kernel-detection.patch + + ( + if stdenv.hostPlatform.isDarwin then + ./3.5/use-etc-ssl-certs-darwin.patch + else + ./3.5/use-etc-ssl-certs.patch + ) + ] + ++ lib.optionals stdenv.hostPlatform.isMinGW [ + ./3.6/mingw-define-netreset.patch + ] + ++ lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; + }; +in +{ + v1_1 = { + version = "1.1.1w"; + hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg="; + patches = [ + ./1.1/nix-ssl-cert-file.patch + + ( + if stdenv.hostPlatform.isDarwin then + ./1.1/use-etc-ssl-certs-darwin.patch + else + ./1.1/use-etc-ssl-certs.patch + ) + ]; + }; + + v3 = { + version = "3.0.19"; + hash = "sha256-+lpBQ7iq4YvlPvLzyvKaLgdHQwuLx00y2IM1uUq2MHI="; + patches = [ + ./3.0/nix-ssl-cert-file.patch + ./3.0/openssl-disable-kernel-detection.patch + + ( + if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch + ) + ] + ++ lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; + }; + + v3_5 = { + version = "3.5.5"; + hash = "sha256-soyRUyqLZaH5g7TCi3SIF05KAQCOKc6Oab14nyi8Kok="; + patches = [ + ./3.0/nix-ssl-cert-file.patch + ./3.0/openssl-disable-kernel-detection.patch + + ( + if stdenv.hostPlatform.isDarwin then + ./3.5/use-etc-ssl-certs-darwin.patch + else + ./3.5/use-etc-ssl-certs.patch + ) + ] + ++ lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; + }; + + inherit v3_6; + + oqs = v3_6 // { + overrideArgs = { + providers = [ + { + name = "oqsprovider"; + package = oqs-provider; + } + ]; + autoloadProviders = true; + extraINIConfig = { + tls_system_default = { + Groups = "X25519MLKEM768:X25519:P-256:X448:P-521:ffdhe2048:ffdhe3072"; + }; + }; + }; + }; + + legacy = v3_6 // { + overrideArgs = { + conf = ./3.0/legacy.cnf; + }; + }; +} diff --git a/pkgs/development/libraries/openssl/default.nix b/pkgs/development/libraries/openssl/default.nix deleted file mode 100644 index 9bf9df035db20..0000000000000 --- a/pkgs/development/libraries/openssl/default.nix +++ /dev/null @@ -1,539 +0,0 @@ -{ - lib, - stdenv, - fetchurl, - buildPackages, - perl, - coreutils, - writeShellScript, - makeBinaryWrapper, - withCryptodev ? false, - cryptodev, - withZlib ? false, - zlib, - enableSSL2 ? false, - enableSSL3 ? false, - enableMD2 ? false, - enableKTLS ? stdenv.hostPlatform.isLinux, - # change this to a value between 0 and 5 (as of OpenSSL 3.5) - # if null, default is used, changes the permitted algorithms - # and key lengths in the default config - # see: https://docs.openssl.org/3.5/man3/SSL_CTX_set_security_level/ - securityLevel ? null, - static ? stdenv.hostPlatform.isStatic, - # path to openssl.cnf file. will be placed in $etc/etc/ssl/openssl.cnf to replace the default - conf ? null, - removeReferencesTo, - testers, - providers ? [ ], # Each provider in the format { name = "provider-name"; package = ; } - autoloadProviders ? false, - extraINIConfig ? null, # Extra INI config in the format { section_name = { key = "value"}; } -}: - -# Note: this package is used for bootstrapping fetchurl, and thus -# cannot use fetchpatch! All mutable patches (generated by GitHub or -# cgit) that are needed here should be included directly in Nixpkgs as -# files. - -# check from time to time, if this range is still correct -assert (securityLevel == null) || (securityLevel >= 0 && securityLevel <= 5); - -let - useBinaryWrapper = !(stdenv.hostPlatform.isWindows || stdenv.hostPlatform.isCygwin); - - common = - { - version, - hash, - patches ? [ ], - withDocs ? false, - extraMeta ? { }, - }: - stdenv.mkDerivation (finalAttrs: { - pname = "openssl"; - inherit version; - - src = fetchurl { - url = - if lib.versionOlder version "3.0" then - let - versionFixed = builtins.replaceStrings [ "." ] [ "_" ] version; - in - "https://github.com/openssl/openssl/releases/download/OpenSSL_${versionFixed}/openssl-${version}.tar.gz" - else - "https://github.com/openssl/openssl/releases/download/openssl-${version}/openssl-${version}.tar.gz"; - inherit hash; - }; - - inherit patches; - - postPatch = '' - patchShebangs Configure - '' - + lib.optionalString (lib.versionOlder version "1.1.1") '' - patchShebangs test/* - for a in test/t* ; do - substituteInPlace "$a" \ - --replace /bin/rm rm - done - '' - # config is a configure script which is not installed. - + lib.optionalString (lib.versionAtLeast version "1.1.1") '' - substituteInPlace config --replace '/usr/bin/env' '${buildPackages.coreutils}/bin/env' - '' - + lib.optionalString (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isMusl) '' - substituteInPlace crypto/async/arch/async_posix.h \ - --replace '!defined(__ANDROID__) && !defined(__OpenBSD__)' \ - '!defined(__ANDROID__) && !defined(__OpenBSD__) && 0' - '' - # Move ENGINESDIR into OPENSSLDIR for static builds, in order to move - # it to the separate etc output. - + lib.optionalString static '' - substituteInPlace Configurations/unix-Makefile.tmpl \ - --replace 'ENGINESDIR=$(libdir)/engines-{- $sover_dirname -}' \ - 'ENGINESDIR=$(OPENSSLDIR)/engines-{- $sover_dirname -}' - '' - # This test will fail if the error strings between the build libc and host - # libc mismatch, e.g. when cross-compiling from glibc to musl - + - lib.optionalString - (finalAttrs.finalPackage.doCheck && stdenv.hostPlatform.libc != stdenv.buildPlatform.libc) - '' - rm test/recipes/02-test_errstr.t - '' - + lib.optionalString stdenv.hostPlatform.isCygwin '' - rm test/recipes/01-test_symbol_presence.t - ''; - - outputs = [ - "bin" - "dev" - "out" - "man" - ] - ++ lib.optional withDocs "doc" - # Separate output for the runtime dependencies of the static build. - # Specifically, move OPENSSLDIR into this output, as its path will be - # compiled into 'libcrypto.a'. This makes it a runtime dependency of - # any package that statically links openssl, so we want to keep that - # output minimal. - ++ lib.optional static "etc"; - setOutputFlags = false; - separateDebugInfo = - !stdenv.hostPlatform.isDarwin - && !stdenv.hostPlatform.isAndroid - && !(stdenv.hostPlatform.useLLVM or false) - && stdenv.cc.isGNU; - - nativeBuildInputs = - lib.optional useBinaryWrapper makeBinaryWrapper - ++ [ perl ] - ++ lib.optionals static [ removeReferencesTo ]; - buildInputs = lib.optional withCryptodev cryptodev ++ lib.optional withZlib zlib; - - # TODO(@Ericson2314): Improve with mass rebuild - configurePlatforms = [ ]; - configureScript = - { - armv5tel-linux = "./Configure linux-armv4 -march=armv5te"; - armv6l-linux = "./Configure linux-armv4 -march=armv6"; - armv7l-linux = "./Configure linux-armv4 -march=armv7-a"; - x86_64-darwin = "./Configure darwin64-x86_64-cc"; - aarch64-darwin = "./Configure darwin64-arm64-cc"; - x86_64-linux = "./Configure linux-x86_64"; - x86_64-solaris = "./Configure solaris64-x86_64-gcc"; - powerpc-linux = "./Configure linux-ppc"; - powerpc64-linux = "./Configure linux-ppc64"; - riscv32-linux = "./Configure ${ - if lib.versionAtLeast version "3.2" then "linux32-riscv32" else "linux-latomic" - }"; - riscv64-linux = "./Configure linux64-riscv64"; - } - .${stdenv.hostPlatform.system} or ( - if stdenv.hostPlatform == stdenv.buildPlatform then - "./config" - else if stdenv.hostPlatform.isBSD then - if stdenv.hostPlatform.isx86_64 then - "./Configure BSD-x86_64" - else if stdenv.hostPlatform.isx86_32 then - "./Configure BSD-x86" + lib.optionalString stdenv.hostPlatform.isElf "-elf" - else - "./Configure BSD-generic${toString stdenv.hostPlatform.parsed.cpu.bits}" - else if stdenv.hostPlatform.isMinGW then - "./Configure mingw${ - lib.optionalString (stdenv.hostPlatform.parsed.cpu.bits != 32) ( - toString stdenv.hostPlatform.parsed.cpu.bits - ) - }" - else if stdenv.hostPlatform.isLinux then - if stdenv.hostPlatform.isx86_64 then - "./Configure linux-x86_64" - else if stdenv.hostPlatform.isMicroBlaze then - "./Configure linux-latomic" - else if stdenv.hostPlatform.isMips32 then - "./Configure linux-mips32" - else if stdenv.hostPlatform.isMips64n32 then - "./Configure linux-mips64" - else if stdenv.hostPlatform.isMips64n64 then - "./Configure linux64-mips64" - else - "./Configure linux-generic${toString stdenv.hostPlatform.parsed.cpu.bits}" - else if stdenv.hostPlatform.isiOS then - "./Configure ios${toString stdenv.hostPlatform.parsed.cpu.bits}-cross" - else if stdenv.hostPlatform.isCygwin then - "./Configure Cygwin-${stdenv.hostPlatform.linuxArch}" - else - throw "Not sure what configuration to use for ${stdenv.hostPlatform.config}" - ); - - # OpenSSL doesn't like the `--enable-static` / `--disable-shared` flags. - dontAddStaticConfigureFlags = true; - configureFlags = [ - "shared" # "shared" builds both shared and static libraries - "--libdir=lib" - ( - if !static then - "--openssldir=etc/ssl" - else - # Move OPENSSLDIR to the 'etc' output for static builds. Prepend '/.' - # to the path to make it appear absolute before variable expansion, - # else the 'prefix' would be prepended to it. - "--openssldir=/.$(etc)/etc/ssl" - ) - ] - ++ lib.optionals withCryptodev [ - "-DHAVE_CRYPTODEV" - "-DUSE_CRYPTODEV_DIGESTS" - ] - # enable optimized EC curve primitives on x86_64, - # can provide a 2x up to 4x speedup at best - # with combined PQC and conventional crypto handshakes - # starting with 3.5 its nice to speed things up for free - ++ lib.optional stdenv.hostPlatform.isx86_64 "enable-ec_nistp_64_gcc_128" - # useful to set e.g. 256 bit security level with setting this to 5 - ++ lib.optional (securityLevel != null) "-DOPENSSL_TLS_SECURITY_LEVEL=${toString securityLevel}" - ++ lib.optional enableMD2 "enable-md2" - ++ lib.optional enableSSL2 "enable-ssl2" - ++ lib.optional enableSSL3 "enable-ssl3" - # We select KTLS here instead of the configure-time detection (which we patch out). - # KTLS should work on FreeBSD 13+ as well, so we could enable it if someone tests it. - ++ lib.optional (lib.versionAtLeast version "3.0.0" && enableKTLS) "enable-ktls" - ++ lib.optional (lib.versionAtLeast version "1.1.1" && stdenv.hostPlatform.isAarch64) "no-afalgeng" - # OpenSSL needs a specific `no-shared` configure flag. - # See https://wiki.openssl.org/index.php/Compilation_and_Installation#Configure_Options - # for a comprehensive list of configuration options. - ++ lib.optional (lib.versionAtLeast version "1.1.1" && static) "no-shared" - ++ lib.optional (lib.versionAtLeast version "3.0.0" && static) "no-module" - # This introduces a reference to the CTLOG_FILE which is undesired when - # trying to build binaries statically. - ++ lib.optional static "no-ct" - ++ lib.optional withZlib "zlib" - # /dev/crypto support has been dropped in OpenBSD 5.7. - # - # OpenBSD's ports does this too, - # https://github.com/openbsd/ports/blob/a1147500c76970fea22947648fb92a093a529d7c/security/openssl/3.3/Makefile#L25. - # - # https://github.com/openssl/openssl/pull/10565 indicated the - # intent was that this would be configured properly automatically, - # but that doesn't appear to be the case. - ++ lib.optional stdenv.hostPlatform.isOpenBSD "no-devcryptoeng" - ++ lib.optionals (stdenv.hostPlatform.isMips && stdenv.hostPlatform ? gcc.arch) [ - # This is necessary in order to avoid openssl adding -march - # flags which ultimately conflict with those added by - # cc-wrapper. Openssl assumes that it can scan CFLAGS to - # detect any -march flags, using this perl code: - # - # && !grep { $_ =~ /-m(ips|arch=)/ } (@{$config{CFLAGS}}) - # - # The following bogus CFLAGS environment variable triggers the - # the code above, inhibiting `./Configure` from adding the - # conflicting flags. - "CFLAGS=-march=${stdenv.hostPlatform.gcc.arch}" - ] - # tests are not being installed, it makes no sense - # to build them if check is disabled, e.g. on cross. - ++ lib.optional (!finalAttrs.finalPackage.doCheck) "disable-tests"; - - makeFlags = [ - "MANDIR=$(man)/share/man" - # This avoids conflicts between man pages of openssl subcommands (for - # example 'ts' and 'err') man pages and their equivalent top-level - # command in other packages (respectively man-pages and moreutils). - # This is done in ubuntu and archlinux, and possibly many other distros. - "MANSUFFIX=ssl" - ]; - - enableParallelBuilding = true; - - doCheck = true; - preCheck = '' - patchShebangs util - ''; - - __darwinAllowLocalNetworking = true; - - postInstall = - ( - if static then - '' - # OPENSSLDIR has a reference to self - remove-references-to -t $out $out/lib/*.a - '' - else - '' - # If we're building dynamic libraries, then don't install static - # libraries. - if [ -n "$(echo $out/lib/*.so $out/lib/*.dylib $out/lib/*.dll)" ]; then - rm "$out/lib/"*.a - fi - - # 'etc' is a separate output on static builds only. - etc=$out - '' - ) - + '' - mkdir -p $bin - mv $out/bin $bin/bin - - '' - + - lib.optionalString useBinaryWrapper - # makeWrapper is broken for windows cross (https://github.com/NixOS/nixpkgs/issues/120726) - '' - # c_rehash is a legacy perl script with the same functionality - # as `openssl rehash` - # this wrapper script is created to maintain backwards compatibility without - # depending on perl - makeWrapper $bin/bin/openssl $bin/bin/c_rehash \ - --add-flags "rehash" - '' - + '' - - mkdir $dev - mv $out/include $dev/ - - # remove dependency on Perl at runtime - rm -r $etc/etc/ssl/misc - - rmdir $etc/etc/ssl/{certs,private} - '' - + lib.optionalString (conf != null) '' - cat ${conf} > $etc/etc/ssl/openssl.cnf - '' - - # Replace the config's default provider section with the providers we wish - # to automatically load - + lib.optionalString autoloadProviders '' - sed -i '/^[[:space:]]*#/!s|\[provider_sect\]|${ - let - config-provider-attrset = lib.foldl' (acc: elem: acc // elem) { } ( - map (provider: { "${provider.name}" = "${provider.name}_sect"; }) providers - ); - in - lib.escape [ "\n" ] (lib.generators.toINI { } { provider_sect = config-provider-attrset; }) - }|' $etc/etc/ssl/openssl.cnf - - # Activate the default provider - sed -i '/^[[:space:]]*#/!s/\[default_sect\]/[default_sect]\nactivate = 1/g' $etc/etc/ssl/openssl.cnf - '' - - + lib.concatStringsSep "\n" ( - map - (provider: '' - cp ${provider.package}/lib/ossl-modules/* "$out/lib/ossl-modules" - - ${lib.optionalString autoloadProviders '' - echo '${ - lib.generators.toINI { } { - "${provider.name}_sect" = { - activate = 1; - }; - } - }' >> $etc/etc/ssl/openssl.cnf - ''} - '') - - providers - ) - + lib.optionalString (extraINIConfig != null) '' - echo '${lib.generators.toINI { } extraINIConfig}' >> $etc/etc/ssl/openssl.cnf - ''; - - allowedImpureDLLs = [ "CRYPT32.dll" ]; - - postFixup = - lib.optionalString (!stdenv.hostPlatform.isWindows) '' - # Check to make sure the main output and the static runtime dependencies - # don't depend on perl - if grep -r '${buildPackages.perl}' $out $etc; then - echo "Found an erroneous dependency on perl ^^^" >&2 - exit 1 - fi - '' - + lib.optionalString (lib.versionAtLeast version "3.3.0") '' - # cleanup cmake helpers for now (for OpenSSL >= 3.3), only rely on pkg-config. - # pkg-config gets its paths fixed correctly - rm -rf $dev/lib/cmake - ''; - - passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage; - - meta = { - homepage = "https://www.openssl.org/"; - changelog = "https://github.com/openssl/openssl/blob/openssl-${version}/CHANGES.md"; - description = "Cryptographic library that implements the SSL and TLS protocols"; - license = lib.licenses.openssl; - mainProgram = "openssl"; - maintainers = with lib.maintainers; [ thillux ]; - teams = [ lib.teams.security-review ]; - pkgConfigModules = [ - "libcrypto" - "libssl" - "openssl" - ]; - platforms = lib.platforms.all; - identifiers.cpeParts = lib.meta.cpeFullVersionWithVendor "openssl" finalAttrs.version; - } - // extraMeta; - }); - -in -{ - # intended version "policy": - # - 1.1 as long as some package exists, which does not build without it - # (tracking issue: https://github.com/NixOS/nixpkgs/issues/269713) - # try to remove in 24.05 for the first time, if possible then - # - latest 3.x LTS - # - latest 3.x non-LTS as preview/for development - # - # - other versions in between only when reasonable need is stated for some package - # - backport every security critical fix release e.g. 3.0.y -> 3.0.y+1 but no new version, e.g. 3.1 -> 3.2 - - # If you do upgrade here, please update in pkgs/top-level/release.nix - # the permitted insecure version to ensure it gets cached for our users - # and backport this to stable release (at time of writing this 23.11). - openssl_1_1 = common { - version = "1.1.1w"; - hash = "sha256-zzCYlQy02FOtlcCEHx+cbT3BAtzPys1SHZOSUgi3asg="; - patches = [ - ./1.1/nix-ssl-cert-file.patch - - ( - if stdenv.hostPlatform.isDarwin then - ./1.1/use-etc-ssl-certs-darwin.patch - else - ./1.1/use-etc-ssl-certs.patch - ) - ]; - withDocs = true; - extraMeta = { - knownVulnerabilities = [ - "OpenSSL 1.1 is reaching its end of life on 2023/09/11 and cannot be supported through the NixOS 23.11 release cycle. https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/" - ]; - }; - }; - - openssl_3 = common { - version = "3.0.19"; - hash = "sha256-+lpBQ7iq4YvlPvLzyvKaLgdHQwuLx00y2IM1uUq2MHI="; - - patches = [ - # Support for NIX_SSL_CERT_FILE, motivation: - # https://github.com/NixOS/nixpkgs/commit/942dbf89c6120cb5b52fb2ab456855d1fbf2994e - ./3.0/nix-ssl-cert-file.patch - - # openssl will only compile in KTLS if the current kernel supports it. - # This patch disables build-time detection. - ./3.0/openssl-disable-kernel-detection.patch - - # Look up SSL certificates in /etc rather than the immutable installation directory - ( - if stdenv.hostPlatform.isDarwin then ./use-etc-ssl-certs-darwin.patch else ./use-etc-ssl-certs.patch - ) - ] - ++ - # https://cygwin.com/cgit/cygwin-packages/openssl/plain/openssl-3.0.18-skip-dllmain-detach.patch?id=219272d762128451822755e80a61db5557428598 - # and also https://github.com/openssl/openssl/pull/29321 - lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; - - withDocs = true; - - extraMeta = { - license = lib.licenses.asl20; - }; - }; - - openssl_3_5 = common { - version = "3.5.5"; - hash = "sha256-soyRUyqLZaH5g7TCi3SIF05KAQCOKc6Oab14nyi8Kok="; - - patches = [ - # Support for NIX_SSL_CERT_FILE, motivation: - # https://github.com/NixOS/nixpkgs/commit/942dbf89c6120cb5b52fb2ab456855d1fbf2994e - ./3.0/nix-ssl-cert-file.patch - - # openssl will only compile in KTLS if the current kernel supports it. - # This patch disables build-time detection. - ./3.0/openssl-disable-kernel-detection.patch - - # Look up SSL certificates in /etc rather than the immutable installation directory - ( - if stdenv.hostPlatform.isDarwin then - ./3.5/use-etc-ssl-certs-darwin.patch - else - ./3.5/use-etc-ssl-certs.patch - ) - ] - ++ lib.optionals stdenv.hostPlatform.isMinGW [ - ./3.5/fix-mingw-linking.patch - ] - ++ - # https://cygwin.com/cgit/cygwin-packages/openssl/plain/openssl-3.0.18-skip-dllmain-detach.patch?id=219272d762128451822755e80a61db5557428598 - # and also https://github.com/openssl/openssl/pull/29321 - lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; - - withDocs = true; - - extraMeta = { - license = lib.licenses.asl20; - }; - }; - - openssl_3_6 = common { - version = "3.6.1"; - hash = "sha256-sb/tzVson/Iq7ofJ1gD1FXZ+v0X3cWjLbWTyMfUYqC4="; - - patches = [ - # Support for NIX_SSL_CERT_FILE, motivation: - # https://github.com/NixOS/nixpkgs/commit/942dbf89c6120cb5b52fb2ab456855d1fbf2994e - ./3.0/nix-ssl-cert-file.patch - - # openssl will only compile in KTLS if the current kernel supports it. - # This patch disables build-time detection. - ./3.0/openssl-disable-kernel-detection.patch - - # Look up SSL certificates in /etc rather than the immutable installation directory - ( - if stdenv.hostPlatform.isDarwin then - ./3.5/use-etc-ssl-certs-darwin.patch - else - ./3.5/use-etc-ssl-certs.patch - ) - ] - ++ lib.optionals stdenv.hostPlatform.isMinGW [ - # Fix from https://github.com/openssl/openssl/pull/29826 - # Merged, will be in 3.6.2 - ./3.6/mingw-define-netreset.patch - ] - ++ - # https://cygwin.com/cgit/cygwin-packages/openssl/plain/openssl-3.0.18-skip-dllmain-detach.patch?id=219272d762128451822755e80a61db5557428598 - # and also https://github.com/openssl/openssl/pull/29321 - lib.optional stdenv.hostPlatform.isCygwin ./openssl-3.0.18-skip-dllmain-detach.patch; - - withDocs = true; - - extraMeta = { - license = lib.licenses.asl20; - }; - }; -} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index f4513f6b453c3..5bd0a9d100d1f 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -7168,34 +7168,13 @@ with pkgs; libressl_4_2 ; - openssl = openssl_3_6; - - openssl_oqs = openssl.override { - providers = [ - { - name = "oqsprovider"; - package = pkgs.oqs-provider; - } - ]; - autoloadProviders = true; - - extraINIConfig = { - tls_system_default = { - Groups = "X25519MLKEM768:X25519:P-256:X448:P-521:ffdhe2048:ffdhe3072"; - }; - }; - }; - - openssl_legacy = openssl.override { - conf = ../development/libraries/openssl/3.0/legacy.cnf; - }; - - inherit (callPackages ../development/libraries/openssl { }) - openssl_1_1 - openssl_3 - openssl_3_5 - openssl_3_6 - ; + # Backward-compat aliases — prefer openssl.v1_1, openssl.v3, openssl.v3_5, openssl.v3_6, etc. + openssl_1_1 = openssl.v1_1; + openssl_3 = openssl.v3; + openssl_3_5 = openssl.v3_5; + openssl_3_6 = openssl.v3_6; + openssl_oqs = openssl.oqs; + openssl_legacy = openssl.legacy; pcre = callPackage ../development/libraries/pcre { }; # pcre32 seems unused diff --git a/pkgs/top-level/splice.nix b/pkgs/top-level/splice.nix index 2c6f060f23e1f..e57a2c072a2c8 100644 --- a/pkgs/top-level/splice.nix +++ b/pkgs/top-level/splice.nix @@ -14,7 +14,7 @@ # For performance reasons, rather than uniformally splice in all cases, we only # do so when `pkgs` and `buildPackages` are distinct. The `actuallySplice` # parameter there the boolean value of that equality check. -lib: pkgs: actuallySplice: +lib: config: pkgs: actuallySplice: let inherit (lib.customisation) mapCrossIndex renameCrossIndexFrom; @@ -120,6 +120,14 @@ in callPackages = lib.callPackagesWith pkgsForCall; + # Pre-bind callPackage and config into mkPackageVariants so that + # package expressions only need `{ mkPackageVariants, ... }@args:` in + # their formals — no need to declare callPackage or config explicitly. + mkPackageVariants = lib.mkPackageVariants { + callPackage = pkgs.newScope { }; + allowAliases = config.allowAliases; + }; + newScope = extra: lib.callPackageWith (pkgsForCall // extra); pkgs = if actuallySplice then splicedPackages // { recurseForDerivations = false; } else pkgs; diff --git a/pkgs/top-level/stage.nix b/pkgs/top-level/stage.nix index 6c237bc6dd556..b1ac83cc7a1b6 100644 --- a/pkgs/top-level/stage.nix +++ b/pkgs/top-level/stage.nix @@ -142,7 +142,7 @@ let inherit stdenv stdenvNoCC; }; - splice = self: super: import ./splice.nix lib self (adjacentPackages != null); + splice = self: super: import ./splice.nix lib config self (adjacentPackages != null); allPackages = self: super: