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