Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
at flake-libs 409 lines 14 kB view raw
1# We have tests for PCRE and PHP-FPM in nixos/tests/php/ or 2# both in the same attribute named nixosTests.php 3 4let 5 generic = 6 { 7 callPackage, 8 lib, 9 stdenv, 10 nixosTests, 11 tests, 12 fetchurl, 13 makeBinaryWrapper, 14 symlinkJoin, 15 writeText, 16 autoconf, 17 automake, 18 bison, 19 flex, 20 libtool, 21 pkg-config, 22 re2c, 23 apacheHttpd, 24 libargon2, 25 libxml2, 26 pcre2, 27 systemd, 28 system-sendmail, 29 valgrind, 30 xcbuild, 31 writeShellScript, 32 common-updater-scripts, 33 curl, 34 jq, 35 36 version, 37 phpSrc ? null, 38 hash ? null, 39 extraPatches ? [ ], 40 packageOverrides ? (final: prev: { }), 41 phpAttrsOverrides ? (final: prev: { }), 42 pearInstallPhar ? (callPackage ./install-pear-nozlib-phar.nix { }), 43 44 # Sapi flags 45 cgiSupport ? true, 46 cliSupport ? true, 47 fpmSupport ? true, 48 pearSupport ? true, 49 pharSupport ? true, 50 phpdbgSupport ? true, 51 52 # Misc flags 53 apxs2Support ? false, 54 argon2Support ? true, 55 cgotoSupport ? false, 56 embedSupport ? false, 57 staticSupport ? false, 58 ipv6Support ? true, 59 zendSignalsSupport ? true, 60 zendMaxExecutionTimersSupport ? false, 61 systemdSupport ? lib.meta.availableOn stdenv.hostPlatform systemd, 62 valgrindSupport ? 63 !stdenv.hostPlatform.isDarwin && lib.meta.availableOn stdenv.hostPlatform valgrind, 64 ztsSupport ? apxs2Support, 65 }@args: 66 67 let 68 # buildEnv wraps php to provide additional extensions and 69 # configuration. Its usage is documented in 70 # doc/languages-frameworks/php.section.md. 71 # 72 # Create a buildEnv with earlier overridden values and 73 # extensions functions in its closure. This is necessary for 74 # consecutive calls to buildEnv and overrides to work as 75 # expected. 76 mkBuildEnv = 77 prevArgs: prevExtensionFunctions: 78 lib.makeOverridable ( 79 { 80 extensions ? ({ enabled, ... }: enabled), 81 extraConfig ? "", 82 ... 83 }@innerArgs: 84 let 85 allArgs = args // prevArgs // innerArgs; 86 filteredArgs = builtins.removeAttrs allArgs [ 87 "extensions" 88 "extraConfig" 89 ]; 90 php = generic filteredArgs; 91 92 php-packages = 93 (callPackage ../../../top-level/php-packages.nix { 94 phpPackage = phpWithExtensions; 95 }).overrideScope 96 packageOverrides; 97 98 allExtensionFunctions = prevExtensionFunctions ++ [ extensions ]; 99 enabledExtensions = builtins.foldl' ( 100 enabled: f: 101 f { 102 inherit enabled; 103 all = php-packages.extensions; 104 } 105 ) [ ] allExtensionFunctions; 106 107 getExtName = ext: ext.extensionName; 108 109 # Recursively get a list of all internal dependencies 110 # for a list of extensions. 111 getDepsRecursively = 112 extensions: 113 let 114 deps = lib.concatMap (ext: (ext.internalDeps or [ ]) ++ (ext.peclDeps or [ ])) extensions; 115 in 116 if !(deps == [ ]) then deps ++ (getDepsRecursively deps) else deps; 117 118 # Generate extension load configuration snippets from the 119 # extension parameter. This is an attrset suitable for use 120 # with textClosureList, which is used to put the strings in 121 # the right order - if a plugin which is dependent on 122 # another plugin is placed before its dependency, it will 123 # fail to load. 124 extensionTexts = lib.listToAttrs ( 125 map ( 126 ext: 127 let 128 extName = getExtName ext; 129 phpDeps = (ext.internalDeps or [ ]) ++ (ext.peclDeps or [ ]); 130 type = "${lib.optionalString (ext.zendExtension or false) "zend_"}extension"; 131 in 132 lib.nameValuePair extName { 133 text = "${type}=${ext}/lib/php/extensions/${extName}.so"; 134 deps = map getExtName phpDeps; 135 } 136 ) (enabledExtensions ++ (getDepsRecursively enabledExtensions)) 137 ); 138 139 extNames = map getExtName enabledExtensions; 140 extraInit = writeText "php-extra-init-${version}.ini" '' 141 ${lib.concatStringsSep "\n" (lib.textClosureList extensionTexts extNames)} 142 ${extraConfig} 143 ''; 144 145 phpWithExtensions = symlinkJoin { 146 name = "php-with-extensions-${version}"; 147 inherit (php) version; 148 nativeBuildInputs = [ makeBinaryWrapper ]; 149 passthru = php.passthru // { 150 buildEnv = mkBuildEnv allArgs allExtensionFunctions; 151 withExtensions = mkWithExtensions allArgs allExtensionFunctions; 152 overrideAttrs = 153 f: 154 let 155 phpAttrsOverrides = filteredArgs.phpAttrsOverrides or (final: prev: { }); 156 newPhpAttrsOverrides = lib.composeExtensions (lib.toExtension phpAttrsOverrides) ( 157 lib.toExtension f 158 ); 159 php = generic (filteredArgs // { phpAttrsOverrides = newPhpAttrsOverrides; }); 160 in 161 php.buildEnv { inherit extensions extraConfig; }; 162 phpIni = "${phpWithExtensions}/lib/php.ini"; 163 unwrapped = php; 164 # Select the right php tests for the php version 165 tests = { 166 nixos = 167 lib.recurseIntoAttrs 168 nixosTests."php${lib.strings.replaceStrings [ "." ] [ "" ] (lib.versions.majorMinor php.version)}"; 169 package = tests.php; 170 }; 171 inherit (php-packages) 172 extensions 173 buildPecl 174 mkComposerRepository 175 mkComposerVendor 176 buildComposerProject 177 buildComposerProject2 178 buildComposerWithPlugin 179 composerHooks 180 composerHooks2 181 mkExtension 182 ; 183 packages = php-packages.tools; 184 meta = php.meta // { 185 outputsToInstall = [ "out" ]; 186 }; 187 }; 188 paths = [ php ]; 189 postBuild = '' 190 ln -s ${extraInit} $out/lib/php.ini 191 192 if test -e $out/bin/php; then 193 wrapProgram $out/bin/php --set-default PHP_INI_SCAN_DIR $out/lib 194 fi 195 196 if test -e $out/bin/php-fpm; then 197 wrapProgram $out/bin/php-fpm --set-default PHP_INI_SCAN_DIR $out/lib 198 fi 199 200 if test -e $out/bin/phpdbg; then 201 wrapProgram $out/bin/phpdbg --set-default PHP_INI_SCAN_DIR $out/lib 202 fi 203 204 if test -e $out/bin/php-cgi; then 205 wrapProgram $out/bin/php-cgi --set-default PHP_INI_SCAN_DIR $out/lib 206 fi 207 ''; 208 }; 209 in 210 phpWithExtensions 211 ); 212 213 mkWithExtensions = 214 prevArgs: prevExtensionFunctions: extensions: 215 mkBuildEnv prevArgs prevExtensionFunctions { inherit extensions; }; 216 217 defaultPhpSrc = fetchurl { 218 url = "https://www.php.net/distributions/php-${version}.tar.bz2"; 219 inherit hash; 220 }; 221 in 222 stdenv.mkDerivation ( 223 let 224 attrs = { 225 pname = "php"; 226 227 inherit version; 228 229 enableParallelBuilding = true; 230 231 nativeBuildInputs = [ 232 autoconf 233 automake 234 bison 235 flex 236 libtool 237 pkg-config 238 re2c 239 ] ++ lib.optional stdenv.hostPlatform.isDarwin xcbuild; 240 241 buildInputs = 242 # PCRE extension 243 [ pcre2 ] 244 245 # Enable sapis 246 ++ lib.optionals pearSupport [ libxml2.dev ] 247 248 # Misc deps 249 ++ lib.optional apxs2Support apacheHttpd 250 ++ lib.optional argon2Support libargon2 251 ++ lib.optional systemdSupport systemd 252 ++ lib.optional valgrindSupport valgrind; 253 254 CXXFLAGS = lib.optionalString stdenv.cc.isClang "-std=c++11"; 255 SKIP_PERF_SENSITIVE = 1; 256 257 configureFlags = 258 # Disable all extensions 259 [ "--disable-all" ] 260 261 # PCRE 262 ++ [ "--with-external-pcre=${pcre2.dev}" ] 263 264 # Enable sapis 265 ++ lib.optional (!cgiSupport) "--disable-cgi" 266 ++ lib.optional (!cliSupport) "--disable-cli" 267 ++ lib.optional fpmSupport "--enable-fpm" 268 ++ lib.optionals pearSupport [ 269 "--with-pear" 270 "--enable-xml" 271 "--with-libxml" 272 ] 273 ++ lib.optional pharSupport "--enable-phar" 274 ++ lib.optional (!phpdbgSupport) "--disable-phpdbg" 275 276 # Misc flags 277 ++ lib.optional apxs2Support "--with-apxs2=${apacheHttpd.dev}/bin/apxs" 278 ++ lib.optional argon2Support "--with-password-argon2=${libargon2}" 279 ++ lib.optional cgotoSupport "--enable-re2c-cgoto" 280 ++ lib.optional embedSupport "--enable-embed${lib.optionalString staticSupport "=static"}" 281 ++ lib.optional (!ipv6Support) "--disable-ipv6" 282 ++ lib.optional systemdSupport "--with-fpm-systemd" 283 ++ lib.optional valgrindSupport "--with-valgrind=${valgrind.dev}" 284 ++ lib.optional ztsSupport "--enable-zts" 285 ++ lib.optional staticSupport "--enable-static" 286 ++ lib.optional (!zendSignalsSupport) [ "--disable-zend-signals" ] 287 ++ lib.optional zendMaxExecutionTimersSupport "--enable-zend-max-execution-timers" 288 289 # Sendmail 290 ++ [ "PROG_SENDMAIL=${system-sendmail}/bin/sendmail" ]; 291 292 hardeningDisable = [ "bindnow" ]; 293 294 preConfigure = 295 # Don't record the configure flags since this causes unnecessary 296 # runtime dependencies 297 '' 298 substituteInPlace main/build-defs.h.in \ 299 --replace-fail '@CONFIGURE_COMMAND@' '(omitted)' 300 substituteInPlace scripts/php-config.in \ 301 --replace-fail '@CONFIGURE_OPTIONS@' "" \ 302 --replace-fail '@PHP_LDFLAGS@' "" 303 304 export EXTENSION_DIR=$out/lib/php/extensions 305 306 ./buildconf --copy --force 307 308 if [ -f "scripts/dev/genfiles" ]; then 309 ./scripts/dev/genfiles 310 fi 311 '' 312 + lib.optionalString stdenv.hostPlatform.isDarwin '' 313 substituteInPlace configure --replace-fail "-lstdc++" "-lc++" 314 ''; 315 316 # When compiling PHP sources from Github, this file is missing and we 317 # need to install it ourselves. 318 # On the other hand, a distribution includes this file by default. 319 preInstall = '' 320 if [[ ! -f ./pear/install-pear-nozlib.phar ]]; then 321 cp ${pearInstallPhar} ./pear/install-pear-nozlib.phar 322 fi 323 ''; 324 325 postInstall = '' 326 test -d $out/etc || mkdir $out/etc 327 cp php.ini-production $out/etc/php.ini 328 ''; 329 330 postFixup = '' 331 mkdir -p $dev/bin $dev/share/man/man1 332 mv $out/bin/phpize $out/bin/php-config $dev/bin/ 333 mv $out/share/man/man1/phpize.1.gz \ 334 $out/share/man/man1/php-config.1.gz \ 335 $dev/share/man/man1/ 336 ''; 337 338 src = if phpSrc == null then defaultPhpSrc else phpSrc; 339 340 patches = 341 lib.optionals (lib.versionOlder version "8.4") [ 342 ./fix-paths-php7.patch 343 ] 344 ++ lib.optionals (lib.versionAtLeast version "8.4") [ 345 ./fix-paths-php84.patch 346 ] 347 ++ extraPatches; 348 349 separateDebugInfo = true; 350 351 outputs = [ 352 "out" 353 "dev" 354 ]; 355 356 passthru = { 357 updateScript = 358 let 359 script = writeShellScript "php${lib.versions.major version}${lib.versions.minor version}-update-script" '' 360 set -o errexit 361 PATH=${ 362 lib.makeBinPath [ 363 common-updater-scripts 364 curl 365 jq 366 ] 367 } 368 new_version=$(curl --silent "https://www.php.net/releases/active" | jq --raw-output '."${lib.versions.major version}"."${lib.versions.majorMinor version}".version') 369 update-source-version "$UPDATE_NIX_ATTR_PATH.unwrapped" "$new_version" "--file=$1" 370 ''; 371 in 372 [ 373 script 374 # Passed as an argument so that update.nix can ensure it does not become a store path. 375 (./. + "/${lib.versions.majorMinor version}.nix") 376 ]; 377 buildEnv = mkBuildEnv { } [ ]; 378 withExtensions = mkWithExtensions { } [ ]; 379 overrideAttrs = 380 f: 381 let 382 newPhpAttrsOverrides = lib.composeExtensions (lib.toExtension phpAttrsOverrides) ( 383 lib.toExtension f 384 ); 385 php = generic (args // { phpAttrsOverrides = newPhpAttrsOverrides; }); 386 in 387 php; 388 inherit ztsSupport; 389 }; 390 391 meta = with lib; { 392 description = "HTML-embedded scripting language"; 393 homepage = "https://www.php.net/"; 394 license = licenses.php301; 395 mainProgram = "php"; 396 teams = [ teams.php ]; 397 platforms = platforms.all; 398 outputsToInstall = [ 399 "out" 400 "dev" 401 ]; 402 }; 403 }; 404 final = attrs // (lib.toExtension phpAttrsOverrides) final attrs; 405 in 406 final 407 ); 408in 409generic