]> granicus.if.org Git - php/commitdiff
Check in the prototype PHP installer for win32.
authorWez Furlong <wez@php.net>
Wed, 5 Feb 2003 07:32:22 +0000 (07:32 +0000)
committerWez Furlong <wez@php.net>
Wed, 5 Feb 2003 07:32:22 +0000 (07:32 +0000)
# Besides looking nice and pretty, the installer is actually smaller
# than the .zip distro:
#   PHP 4.3.0 .zip distro:  5,950,222 bytes
#   PHP 4.3.0 installer:    5,426,242 bytes

win32/installer/README [new file with mode: 0644]
win32/installer/gen-nsis.php [new file with mode: 0644]
win32/installer/setini.php [new file with mode: 0644]

diff --git a/win32/installer/README b/win32/installer/README
new file mode 100644 (file)
index 0000000..107ca7d
--- /dev/null
@@ -0,0 +1,58 @@
+PHP Installer for Win32, by Wez Furlong <wez@thebrainroom.com>
+==============================================================
+$Id$
+
+Here are the supporting scripts for building the win32 PHP installer.
+You need to have the Super-Pimp Installer from Nullsoft (Open Source).
+It is available here:
+       http://nsis.sourceforge.net/
+
+To build an installer, you need:
+
+       o A Source Tree
+       o A win32 snapshot (extracted from the .zip)
+
+       (The source tree and snapshot should have matching versions!)
+
+A Script/Batch file.
+I'm using this (in a .bat file):
+
+----------------------------------------------------------------
+cd <snapshot_root>
+cli\php <source_root>\win32\installer\gen-nsis.php > php.nsi
+"C:\Program Files\NSIS\makensis" /pause /nocd php.nsi
+----------------------------------------------------------------
+  
+  ** It is a good idea to examine the php.nsi file for WARNING
+  ** comments.  These indicate inconsistencies about your source
+  ** tree structure.
+
+This will generate InstallPHP<Version>.exe, where <Version> is the version of
+the php in the snapshot.  The Installer will be placed in the snapshot root.
+
+Installer Concept
+=================
+
+Maintaining installers is a real chore, so we use PHP to generate as much as
+possible.
+
+The gen-nsis.php script will examine the extensions dir from the snapshot and
+then attempt to extract information about the extensions from the source code.
+The sapi dir is subjected to similar treatment.
+
+Throughout the installation, values for php.ini settings are decided; these are
+appended to a temporary file.  After everything has been installed, the
+iniset.php script is run and merges the values from the temporary file into the
+"official" php.ini.
+
+These scripts take advantage of features found in PHP 4.3.0 and later, so you
+can't build a PHP 4.2.x distro with it.
+
+Hacking
+=======
+
+While hacking, it's a good idea to comment out the SetCompressor line; it will
+speed up your installer builds...
+Also, switch the logic for the $SYSDIR define at the top to install vital DLLs
+to a fake system dir.
+
diff --git a/win32/installer/gen-nsis.php b/win32/installer/gen-nsis.php
new file mode 100644 (file)
index 0000000..0907e41
--- /dev/null
@@ -0,0 +1,442 @@
+; PHP Installer for NSIS
+; Based on Welcome/Finish Page Example Script (Written by Joost Verburg)
+; Author: Wez Furlong <wez@thebrainroom.com>
+; $Id$
+<?php
+
+define('PHPVERSION', phpversion());
+define('SOURCEDIR',     dirname(__FILE__) . "\\..\\..\\");
+define('DISTDIR',       getcwd());
+
+/* for testing, install system files in a safe dir */
+
+if (false) {
+       $SYSDIR = "\$INSTDIR\\system";
+} else {
+       $SYSDIR = "\$SYSDIR";
+}
+
+$sections = array(
+       "core" => array(
+               "label" => "-PHP Core (Required)",
+               "files" => array(
+                       "$SYSDIR" => array(
+                               "dlls\\*.dll",
+                               "php4ts.dll",
+                       ),
+                       "\$INSTDIR" => array(
+                               "*.txt",
+                               "php.gif",
+                               "php.ini-*",
+                       ),
+               ),
+               "extras" => "Call CopyPHPIni\nWriteUninstaller \"\$INSTDIR\\Uninstall.exe\""
+       ),
+       "cgi" => array(
+               "group" => "SAPI",
+               "label" => "CGI",
+               "description" => "The most stable SAPI for use to serve PHP scripts in your web server",
+               "files" => array(
+                       "\$INSTDIR" => array(
+                               "php.exe"
+                       ),
+                       "\$INSTDIR\\sapi" => array(
+                               "sapi\\pws-php4cgi.reg"
+                       ),
+               ),
+       ),
+
+       "cli" => array(
+               "group" => "SAPI",
+               "label" => "CLI",
+               "description" => "New Command Line Interface for running PHP scripts as batch files",
+               "files" => array(
+                       "\$INSTDIR\\cli" => array(
+                               "cli\\php.exe"
+                       ),
+               ),
+       ),
+
+    "embed" => array(
+               "group" => "SAPI",
+               "label" => "Embed",
+               "description" => "Libraries for embedding PHP into your own projects",
+               "files" => array(
+                       "\$INSTDIR" => array(
+                               "*.lib"
+                       ),
+               ),
+       ),
+
+       "mibs" => array(
+               "group" => "Extras",
+               "label" => "MIBS for SNMP",
+               "description" => "MIB information for the SNMP extension",
+               "files" => array(
+                       "\$INSTDIR\\mibs" => array(
+                               "mibs\\*"
+                       ),
+               ),
+       ),
+
+       "pdfstuff" => array(
+               "group" => "Extras",
+               "label" => "PDF support files",
+               "description" => "Fonts and codepage data files for the PDF extensions",
+               "files" => array(
+                       "\$INSTDIR\\pdf-related" => array(
+                               "pdf-related\\*"
+                       ),
+               ),
+       ),
+
+       "mimemagic" => array(
+               "group" => "Extras",
+               "label" => "Mime Magic",
+               "description" => "The magic information file for the mimemagic extension",
+               "files" => array(
+                       "\$INSTDIR" => array(
+                               "magic.mime"
+                       ),
+               ),
+       ),
+
+       "openssl" => array(
+               "group" => "Extras",
+               "label" => "OpenSSL",
+               "description" => "OpenSSL configuration information which you must read if you plan to use PHP as a Certificate Authority",
+               "files" => array(
+                       "\$INSTDIR\\openssl" => array(
+                               "openssl\\*"
+                       ),
+               ),
+       ),
+
+          
+
+);
+
+$groups = array(
+       'SAPI'  => array("SAPI", "Select which Server API's to install."),
+       'EXT'   => array("Extensions", "Select which extensions to install."),
+       'XSAPI' => array("Experimental SAPI", "Experimental Server API's - use at your own risk!"),
+       'XEXT'  => array("Experimental Extensions", "Experimental Extensions - use at your own risk!"),
+       'Extras'        => array("Extras", "Supplemental Files"),
+       );
+
+function xglob($pattern)
+{
+       if (strpos($pattern, '*') === false) {
+               return array($pattern);
+       }
+       $dir = dirname($pattern);
+       $pattern = basename($pattern);
+
+       $pattern = str_replace(array('*', '.'), array('.*', '\.'), $pattern);
+
+       $files = array();
+
+       $d = opendir($dir);
+       while ($f = readdir($d)) {
+               if ($f == '.' || $f == '..' || preg_match('/^\..*\.swp$/', $f))
+                       continue;
+               if (preg_match('@' . $pattern . '@i', $f)) {
+                       $files[] = $dir . '\\' . $f;
+               }
+       }
+       
+       return $files;
+}
+
+/* Look for extensions and determine their info based on the source tree.
+ * We can determine the name and author from the CREDITS file.
+ * We can determine experimental status from the EXPERIMENTAL file.
+ * It would be nice to have a standard description line in the CREDITS too.
+ */
+$extension_abbreviations = array(
+       'ifx' => 'informix',
+       'gd2' => 'gd',
+       );
+
+$sapi_abbreviations = array(
+       'apache2'       =>      'apache2filter',
+       'srvlt' =>      'servlet',
+);
+
+function add_sections($pattern, $groupname, $abbrev, &$sections, $sourcedirs, $instdir)
+{
+       $avail = xglob($pattern);
+
+       foreach ($avail as $extname) {
+               /* mangle name */
+               if (preg_match('/(php_|php4|php)([^_].*)\.dll/', basename($extname), $matches)) {
+                       $ext = $matches[2];
+               } else {
+                       $ext = basename($extname);
+               }
+
+               if (isset($abbrev[$ext])) {
+                       $ext = $abbrev[$ext];
+               }
+
+               $extdir = null;
+               
+               foreach ($sourcedirs as $sourcedir) {
+                       // Allow absolute path for separate PECL checkout
+                       if ($sourcedir{0} == '\\' || $sourcedir{1} == ':')
+                               $extdir = $sourcedir;
+                       else
+                               $extdir = SOURCEDIR . $sourcedir . '/' . $ext . '/';
+                               
+                       if (is_dir($extdir))
+                               break;
+
+                       $extdir = null;
+               }
+
+               if ($extdir === null || !is_dir($extdir)) {
+                       echo ";  WARNING: could not find source dir for extension $extname -> $extdir ($ext)\n";
+               }
+
+               $exp = file_exists($extdir . 'EXPERIMENTAL');
+               if (file_exists($extdir . 'CREDITS')) {
+                       list($title, $authors, $description) = file($extdir . 'CREDITS');
+                       $title = trim($title);
+                       $authors = trim($authors);
+                       $description = trim($description);
+
+                       if (strlen($title) == 0)
+                               $title = $ext;
+
+               } else {
+                       $title = $ext;
+                       $authors = "Unknown, or uncredited";
+                       $description = "";
+               }
+
+               /* build list of support files.
+                * in theory, only needed for the srvlt sapi, but useful to keep this
+                * generic */
+               $filepat = preg_replace('/\.[^\.]+$/', '.*', $extname);
+
+               if ($groupname == 'EXT') {
+               }
+
+               $sections['ext_' . $ext] = array(
+                               'group' => ($exp ? 'X' : '') . $groupname,
+                               'label' => $title,
+                               'description' => $title . ".\$\\nAuthors: $authors",
+                               'files' => array(
+                                       "\$INSTDIR\\" . $instdir => array(
+                                               $filepat
+                                               ),
+                                       ),
+                               'extras' => $groupname == 'EXT' ? "Push \"extension=" . basename($extname) . "\"\nCall AddIniSetting\n\n" : ""
+                               );
+
+       }
+
+
+}
+
+add_sections('extensions\\*.dll', 'EXT', $extension_abbreviations, $sections, array('ext'), 'extensions');
+add_sections('sapi\\*.dll', 'SAPI', $sapi_abbreviations, $sections, array('sapi'), 'sapi');
+
+
+
+
+$SECTIONS = "";
+$sections_stage1 = array();
+
+/* list of files to uninstall */
+$uninstall = array();
+$rmdirs = array();
+/* description texts */
+$descriptions = array();
+
+$dirs_no_delete = array("\$SYSDIR", "\$INSTDIR");
+
+foreach ($sections as $sectionid => $sectiondata) {
+       $descriptions[] = "\t!insertmacro MUI_DESCRIPTION_TEXT \${Sec$sectionid} \"" . $sectiondata['description'] . "\"";
+
+       if (isset($sectiondata['group'])) {
+               $sub = "Sub";
+               $group = $sectiondata['group'];
+       } else {
+               $sub = "";
+               $group = '_top_';
+       }
+
+       $body = "Section \"" . $sectiondata['label'] . "\" Sec$sectionid\n";
+
+       foreach ($sectiondata['files'] as $outputdir => $filelist) {
+               $body .= "\tSetOutPath \"$outputdir\"\n";
+               foreach ($filelist as $pattern) {
+                       $files = xglob($pattern);
+                       foreach ($files as $filename) {
+                               $uninstall[] = "\tDelete \"$outputdir\\" . basename($filename) . "\"";
+                               
+                               $body .= "\tFile \"$filename\"\n";
+                       }
+               }
+               if (!in_array($outputdir, $dirs_no_delete) && !isset($rmdirs[$outputdir])) {
+                       $rmdirs[$outputdir] = "\tRMDir \"$outputdir\"";
+               }
+       }
+
+       $body .= $sectiondata['extras'];
+
+       $body .= "\nSectionEnd\n";
+
+       $sections_stage1[$group] .= $body . "\n\n";
+}
+
+foreach ($sections_stage1 as $group => $data)
+{
+       if ($group == '_top_') {
+               $SECTIONS .= $data . "\n";
+       } else {
+               $descriptions[] = "\t!insertmacro MUI_DESCRIPTION_TEXT \${SecGroup$group} \"" . $groups[$group][1] . "\"";
+               $SECTIONS .= "SubSection \"" . $groups[$group][0] . "\" SecGroup$group\n$data\nSubSectionEnd\n\n";
+       }
+}
+
+/* Now build descriptions */
+$DESCRIPTIONS = implode("\n", $descriptions) . "\n";
+
+/* And the uninstallation section */
+$UNINSTALL = implode("\n", $uninstall) . "\n" . implode("\n", $rmdirs) . "\n";
+
+?>
+
+!define MUI_PRODUCT "PHP - Hypertext Preprocessor"
+!define MUI_VERSION "<?= PHPVERSION ?>"
+; The second UI has a wider area for the component names
+!define MUI_UI "${NSISDIR}\Contrib\UIs\modern3.exe"    
+
+!include "${NSISDIR}\Contrib\Modern UI\System.nsh"
+
+;--------------------------------
+;Configuration
+
+!define MUI_WELCOMEPAGE
+!define MUI_LICENSEPAGE
+!define MUI_COMPONENTSPAGE
+!define MUI_DIRECTORYPAGE
+  
+!define MUI_FINISHPAGE
+;!define MUI_FINISHPAGE_RUN "$INSTDIR\modern.exe"
+  
+!define MUI_ABORTWARNING
+  
+!define MUI_UNINSTALLER
+!define MUI_UNCONFIRMPAGE
+    
+;Language
+!insertmacro MUI_LANGUAGE "English"
+
+;General
+OutFile "InstallPHP<?= PHPVERSION ?>.exe"
+
+SetCompressor bzip2
+
+;License page
+LicenseData "license.txt"
+
+;Folder-selection page
+InstallDir "C:\PHP-<?= PHPVERSION ?>"
+  
+;Things that need to be extracted on startup (keep these lines before any File command!)
+;Only useful for BZIP2 compression
+;Use ReserveFile for your own Install Options ini files too!
+!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
+!insertmacro MUI_RESERVEFILE_SPECIALINI
+!insertmacro MUI_RESERVEFILE_SPECIALBITMAP
+  
+;--------------------------------
+;Modern UI System
+
+!insertmacro MUI_SYSTEM
+
+
+;--------------------------------
+;Installer Sections
+
+Function AddIniSetting
+       Pop $R0
+
+       FileOpen $R2 "$INSTDIR\.ini-add" "a"
+       FileSeek $R2 0 END
+       FileWrite $R2 "$R0$\n"
+       FileClose $R2
+
+FunctionEnd
+
+Function CopyPHPIni
+       ; Ensure that we have a working php.ini to reflect the
+       ; installation options.
+       ; Extensions will call a function to activate their entry
+       ; in the ini file as they are installed.
+
+       ifFileExists "<?= $SYSDIR ?>\php.ini" "" +2
+       Rename "<?= $SYSDIR ?>\php.ini" "<?= $SYSDIR ?>\php.ini.old"
+       CopyFiles "$INSTDIR\php.ini-dist" "<?= $SYSDIR ?>\php.ini"
+
+; For editing the ini, put the cli and the php4ts.dll in the same dir
+; these files will be deleted during post-installation
+       CopyFiles "<?= $SYSDIR ?>\php4ts.dll" "$INSTDIR\php4ts.dll"
+       CopyFiles "$INSTDIR\cli\php.exe" "$INSTDIR\strap-php.exe"
+       File "<?= dirname(__FILE__) ?>\setini.php"
+
+; Set the extension_dir setting in the php.ini
+       Push "extension_dir=$\"$INSTDIR\extensions$\""
+       Call AddIniSetting
+
+FunctionEnd
+
+; Generated Section Info
+<?= $SECTIONS ?>
+; ---------
+
+; Perform final actions after everything has been installed
+Section -post
+       ; Merge ini settings
+       nsExec::ExecToLog "$\"$INSTDIR\strap-php.exe$\" $\"$INSTDIR\setini.php$\" $\"<?= $SYSDIR ?>\php.ini$\" $\"$INSTDIR\.ini-add$\""
+
+       Delete "$INSTDIR\.ini-add" ; Created by the AddIniSetting function
+       Delete "$INSTDIR\setini.php"
+       Delete "$INSTDIR\strap-php.exe"
+       Delete "$INSTDIR\php4ts.dll"
+
+       ; Add to Add/Remove programs list
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PHP-<?= PHPVERSION ?>" "UninstallString" "$INSTDIR\Uninstall.exe"
+       WriteRegStr HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PHP-<?= PHPVERSION ?>" "DisplayName" "PHP-<?= PHPVERSION ?> (Uninstall only)"
+
+
+SectionEnd
+
+;--------------------------------
+;Descriptions
+
+!insertmacro MUI_FUNCTIONS_DESCRIPTION_BEGIN
+<?= $DESCRIPTIONS ?>
+!insertmacro MUI_FUNCTIONS_DESCRIPTION_END
+
+;--------------------------------
+;Uninstaller Section
+
+Section "Uninstall"
+<?= $UNINSTALL ?>
+
+       Delete "$INSTDIR\Uninstall.exe"
+       RMDir "$INSTDIR"
+       ; Remove from Add/Remove programs list
+       DeleteRegKey /ifempty HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\PHP-<?= PHPVERSION ?>"
+
+       !insertmacro MUI_UNFINISHHEADER
+
+SectionEnd
+; vim:sw=4:ts=4:
+; vim600:sw=4:ts=4:noet:fdm=marker
diff --git a/win32/installer/setini.php b/win32/installer/setini.php
new file mode 100644 (file)
index 0000000..91d1b1a
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/* $Id$
+ * Wez Furlong <wez@thebrainroom.com>
+ *
+ * Set options in a php.ini file.
+ * This is a support script for the installer.
+ *
+ * $argv[1] is the path to the ini file
+ * $argv[2] is the path to the option file
+ */
+
+$ini_name = $argv[1];
+$option_file = $argv[2];
+
+$options = explode("\n", file_get_contents($option_file));
+$opts = array();
+
+/* Parse the options */
+foreach ($options as $line) {
+       list($name, $value) = explode("=", $line);
+
+       if ($name == "extension") {
+               $pat = "/^;?extension\s*=\s*" . $value . "/i";
+       } else {
+               $pat = "/^;?$name\s*=\s*/i";
+       }
+
+       $opts[] = array('pat' => $pat, 'name' => $name, 'value' => $value);
+}
+
+$new_name = $ini_name . "~";
+$dest = fopen($new_name, "w");
+
+if (!$dest) {
+       die("Cannot create temporary file!");
+}
+
+$lines = file($ini_name);
+
+foreach ($lines as $line) {
+
+       foreach ($opts as $k => $optdata) {
+               extract($optdata);
+               
+               if (preg_match($pat, $line)) {
+                       echo "Found: $line\n";
+                       $line = "$name=$value\r\n";
+                       echo" New value: $line\n";
+
+                       // No need to match again
+                       unset($opts[$k]);
+                       break;
+               }
+       }
+
+       fwrite($dest, $line);
+}
+
+fclose($dest);
+
+unlink($ini_name);
+rename($new_name, $ini_name);
+
+?>