Improve the OS X installer
authorIan Lynagh <igloo@earth.li>
Fri, 22 Oct 2010 22:31:04 +0000 (22:31 +0000)
committerIan Lynagh <igloo@earth.li>
Fri, 22 Oct 2010 22:31:04 +0000 (22:31 +0000)
Major changes are:
* Version number now includes full GHC version and arch
* Uninstaller copes with multiple versions

configure.ac
distrib/MacOS/GHC-relocatable.pmdoc/01ghc.xml
distrib/MacOS/GHC-system.pmdoc/01ghc.xml
distrib/MacOS/GHC-system.pmdoc/index.xml.in [moved from distrib/MacOS/GHC-system.pmdoc/index.xml with 90% similarity]
distrib/MacOS/GHC.xcodeproj/project.pbxproj
distrib/MacOS/Makefile
distrib/MacOS/installer-scripts/Uninstaller [deleted file]
distrib/MacOS/installer-scripts/Uninstaller.in [new file with mode: 0644]
distrib/MacOS/installer-scripts/create-links.in

index b281cd8..7d1cdf2 100644 (file)
@@ -950,7 +950,7 @@ if grep '   ' compiler/ghc.cabal.in 2>&1 >/dev/null; then
    AC_MSG_ERROR([compiler/ghc.cabal.in contains tab characters; please remove them])
 fi
 
-AC_CONFIG_FILES([mk/config.mk mk/install.mk mk/project.mk compiler/ghc.cabal ghc/ghc-bin.cabal utils/runghc/runghc.cabal ghc.spec extra-gcc-opts docs/users_guide/ug-book.xml docs/users_guide/ug-ent.xml docs/index.html libraries/prologue.txt distrib/ghc.iss distrib/configure.ac distrib/MacOS/installer-scripts/create-links])
+AC_CONFIG_FILES([mk/config.mk mk/install.mk mk/project.mk compiler/ghc.cabal ghc/ghc-bin.cabal utils/runghc/runghc.cabal ghc.spec extra-gcc-opts docs/users_guide/ug-book.xml docs/users_guide/ug-ent.xml docs/index.html libraries/prologue.txt distrib/ghc.iss distrib/configure.ac distrib/MacOS/installer-scripts/create-links distrib/MacOS/installer-scripts/Uninstaller distrib/MacOS/GHC-system.pmdoc/index.xml])
 AC_CONFIG_COMMANDS([mk/stamp-h],[echo timestamp > mk/stamp-h])
 AC_OUTPUT
 
index a414253..6ad037d 100644 (file)
@@ -1 +1 @@
-<pkgref spec="1.12" uuid="FD3688D8-0443-4DCE-A3BB-F4A8EF12A4AB"><config><identifier>org.haskell.ghc.pkg</identifier><version>1</version><description></description><post-install type="none"/><installFrom relative="true" mod="true" includeRoot="true">build/Release/GHC.framework</installFrom><installTo relocatable="true">/Library/Frameworks</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>scripts.postinstall.path</mod><mod>requireAuthorization</mod><mod>scripts.scriptsDirectoryPath.isRelativeType</mod><mod>scripts.postinstall.isRelativeType</mod><mod>installTo.isRelativeType</mod><mod>scripts.postinstall.isAbsoluteType</mod><mod>relocatable</mod><mod>installFrom.isRelativeType</mod><mod>installFrom.path</mod><mod>installTo</mod></config><scripts><postinstall relative="true" mod="true">installer-scripts/relocate</postinstall><scripts-dir relative="true" mod="true">installer-scripts</scripts-dir></scripts><contents><component id="org.haskell.GHC" path="/Users/chak/Code/ghc/distrib/MacOS/build/Release/GHC.framework" version="609.20071208"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>\r
\ No newline at end of file
+<pkgref spec="1.12" uuid="FD3688D8-0443-4DCE-A3BB-F4A8EF12A4AB"><config><identifier>org.haskell.ghc.pkg</identifier><version>1</version><description></description><post-install type="none"/><installFrom relative="true" mod="true" includeRoot="true">build/Release/GHC.framework</installFrom><installTo relocatable="true">/Library/Frameworks</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"></packageStore><mod>parent</mod><mod>scripts.postinstall.path</mod><mod>requireAuthorization</mod><mod>scripts.scriptsDirectoryPath.isRelativeType</mod><mod>scripts.postinstall.isRelativeType</mod><mod>installTo.isRelativeType</mod><mod>scripts.postinstall.isAbsoluteType</mod><mod>relocatable</mod><mod>installFrom.isRelativeType</mod><mod>installFrom.path</mod><mod>installTo</mod></config><scripts><postinstall relative="true" mod="true">installer-scripts/relocate</postinstall><scripts-dir relative="true" mod="true">installer-scripts</scripts-dir></scripts><contents><component id="org.haskell.ghc" path="/Users/chak/Code/ghc/distrib/MacOS/build/Release/GHC.framework" version="609.20071208"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>\r
\ No newline at end of file
index 9963fb1..4eb91c3 100644 (file)
@@ -1 +1 @@
-<pkgref spec="1.12" uuid="24EEBBE7-7B79-47C9-839B-A5407A419948"><config><identifier>org.haskell.ghc.pkg</identifier><version>1.0</version><description/><post-install type="none"/><requireAuthorization/><installFrom includeRoot="true">/tmp/GHC.dst/Library/Frameworks/GHC.framework</installFrom><installTo>/Library/Frameworks</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>scripts.scriptsDirectoryPath.path</mod><mod>parent</mod><mod>identifier</mod><mod>scripts.postinstall.path</mod></config><scripts><postinstall relative="true" mod="true">installer-scripts/create-links</postinstall><scripts-dir relative="true" mod="true">installer-scripts</scripts-dir></scripts><contents><file-list>01ghc-contents.xml</file-list><component id="org.haskell.GHC" path="/tmp/GHC.dst/Library/Frameworks/GHC.framework" version="612.220100521"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>\r
\ No newline at end of file
+<pkgref spec="1.12" uuid="24EEBBE7-7B79-47C9-839B-A5407A419948"><config><identifier>org.haskell.ghc.pkg</identifier><version>1.0</version><description/><post-install type="none"/><requireAuthorization/><installFrom includeRoot="true">/tmp/GHC.dst/Library/Frameworks/GHC.framework</installFrom><installTo>/Library/Frameworks</installTo><flags><followSymbolicLinks/></flags><packageStore type="internal"/><mod>scripts.scriptsDirectoryPath.path</mod><mod>parent</mod><mod>identifier</mod><mod>scripts.postinstall.path</mod></config><scripts><postinstall relative="true" mod="true">installer-scripts/create-links</postinstall><scripts-dir relative="true" mod="true">installer-scripts</scripts-dir></scripts><contents><file-list>01ghc-contents.xml</file-list><component id="org.haskell.ghc" path="/tmp/GHC.dst/Library/Frameworks/GHC.framework" version="612.220100521"/><filter>/CVS$</filter><filter>/\.svn$</filter><filter>/\.cvsignore$</filter><filter>/\.cvspass$</filter><filter>/\.DS_Store$</filter></contents></pkgref>\r
\ No newline at end of file
similarity index 90%
rename from distrib/MacOS/GHC-system.pmdoc/index.xml
rename to distrib/MacOS/GHC-system.pmdoc/index.xml.in
index ba5f836..2e90ba6 100644 (file)
@@ -28,4 +28,4 @@ in a web browser. More documentation is available online at\
 \
 To uninstall, execute\
 \
-  /Library/Frameworks/GHC.framework/Tools/Uninstaller}]]></resource></locale></resources><flags/><item type="file">01ghc.xml</item><mod>properties.systemDomain</mod><mod>properties.title</mod><mod>properties.userDomain</mod><mod>properties.anywhereDomain</mod><mod>description</mod></pkmkdoc>
+  /Library/Frameworks/GHC.framework/Versions/@ProjectVersion@-@TargetArch_CPP@/Tools/Uninstaller}]]></resource></locale></resources><flags/><item type="file">01ghc.xml</item><mod>properties.systemDomain</mod><mod>properties.title</mod><mod>properties.userDomain</mod><mod>properties.anywhereDomain</mod><mod>description</mod></pkmkdoc>
index 0b2e480..6cd8658 100644 (file)
@@ -74,7 +74,7 @@
                        );
                        buildRules = (
                        );
-                       comments = "Supported targets: build\n\nPrecondition: Fully compiled tree (i.e., \"perl boot; ./configure; make\" was already executed)\n\nThis project creates a Mac OS X framework that encapsulates a *relocatable* *binary* GHC distribution.\n\n*  The framework is versioned using GHC's ProjectVersionInt. and we call the current version directory in the following CONTENTS_FOLDER_BUILD.\n\n* This target installs into CONTENTS_FOLDER_BUILD/ghc/ the same contents that is in a binary-dist tar ball.\n\n* The idea is that at framework installation time, a post install script will perform \n\n    ./configure --prefix=CONTENTS_FOLDER_INSTALL/usr; make install \n\n   in that ghc/ directory, where CONTENTS_FOLDER_INSTALL is the path that CONTENTS_FOLDER_BUILD has after the package containing the framework was installed by the package installer.  This effectively rellocates the ghc installation to its final destination.";
+                       comments = "Supported targets: build\n\nPrecondition: Fully compiled tree (i.e., \"perl boot; ./configure; make\" was already executed)\n\nThis project creates a Mac OS X framework that encapsulates a *relocatable* *binary* GHC distribution.\n\n*  The framework is versioned using GHC's version and platform, and we call the current version directory in the following CONTENTS_FOLDER_BUILD.\n\n* This target installs into CONTENTS_FOLDER_BUILD/ghc/ the same contents that is in a binary-dist tar ball.\n\n* The idea is that at framework installation time, a post install script will perform \n\n    ./configure --prefix=CONTENTS_FOLDER_INSTALL/usr; make install \n\n   in that ghc/ directory, where CONTENTS_FOLDER_INSTALL is the path that CONTENTS_FOLDER_BUILD has after the package containing the framework was installed by the package installer.  This effectively rellocates the ghc installation to its final destination.";
                        dependencies = (
                        );
                        name = "GHC-relocatable";
@@ -92,7 +92,7 @@
                        );
                        buildRules = (
                        );
-                       comments = "Supported targets: build, install\n\nPrecondition: We are in a distribution tree, not a vanilla tree from darcs - i.e., \"perl boot; ./configure\" was already executed.\n\nAs part of the build target, ./configure will be executed again (setting a --prefix).  Additional arguments to ./configure can be specified by way of the environment variable XCODE_EXTRA_CONFIGURE_ARGS.\n\nThis project creates a Mac OS X framework at /Library/Frameworks.\n\n*  The framework is versioned using GHC's ProjectVersionInt.\n\n* The target configures the tree for the deployment location and builds the tree.\n\n* This target installs the framework not into its final destination, but into a build directory using the DESTDIR feature of GHC build system (unless the deployment flag in the build rules is set).\n\n* The idea is that the framework at the build location is being turned into a package and the package installer eventually puts its at its final destination. \n";
+                       comments = "Supported targets: build, install\n\nPrecondition: We are in a distribution tree, not a vanilla tree from darcs - i.e., \"perl boot; ./configure\" was already executed.\n\nAs part of the build target, ./configure will be executed again (setting a --prefix).  Additional arguments to ./configure can be specified by way of the environment variable XCODE_EXTRA_CONFIGURE_ARGS.\n\nThis project creates a Mac OS X framework at /Library/Frameworks.\n\n*  The framework is versioned using GHC's version and platform.\n\n* The target configures the tree for the deployment location and builds the tree.\n\n* This target installs the framework not into its final destination, but into a build directory using the DESTDIR feature of GHC build system (unless the deployment flag in the build rules is set).\n\n* The idea is that the framework at the build location is being turned into a package and the package installer eventually puts its at its final destination. \n";
                        dependencies = (
                        );
                        name = "GHC-systemwide";
index dbf7886..eef5661 100644 (file)
@@ -28,20 +28,21 @@ endif
 
 include ../../mk/custom-settings.mk
 
-# The ProjectVersionInt is GHC's idea of an API version and hence determines
-# the framework version.
-FRAMEWORK_VERSION = $(ProjectVersionInt)
+# The framework version is a string like
+#     7.0.1-i386
+# for an i386 build of GHC 7.0.1. It's used for the subdirectory of
+# /Library/Frameworks/GHC.framework/Versions/
+FRAMEWORK_VERSION = $(ProjectVersion)-$(TargetArch_CPP)
 
 # Xcode requires CURRENT_PROJECT_VERSION to be an int or float.  We use this
 # only as the build version (aka CFBundleVersion).
 CURRENT_PROJECT_VERSION = $(ProjectVersionInt).$(ProjectPatchLevel)
 
-# The user-visible CFBundleShortVersionString is set to the standard GHC 
-# version number.
-SHORT_VERSION_STRING = $(ProjectVersion)
+# The user-visible CFBundleShortVersionString
+SHORT_VERSION_STRING = $(FRAMEWORK_VERSION)
 
 # Name of the installer package
-PACKAGE_NAME = GHC-$(ProjectVersion)-$(TargetArch_CPP).pkg
+PACKAGE_NAME = GHC-$(FRAMEWORK_VERSION).pkg
 
 # Determine arguments that should be passed to ./configure from within Xcode
 #
@@ -69,7 +70,7 @@ endif
 DSTROOT=/tmp/GHC.dst
 
 # Tools directory for a system volume install
-TOOLS_SYSTEM=$(DSTROOT)/Library/Frameworks/GHC.framework/Tools
+TOOLS_SYSTEM=$(DSTROOT)/Library/Frameworks/GHC.framework/Versions/$(FRAMEWORK_VERSION)/Tools
 
 PACKAGEMAKER=/Developer/usr/bin/packagemaker
 
@@ -87,6 +88,7 @@ framework-pkg:
        -$(RM) -rf $(DSTROOT)
        mkdir -p $(TOOLS_SYSTEM)
        cp installer-scripts/Uninstaller $(TOOLS_SYSTEM)
+       cp installer-scripts/create-links $(TOOLS_SYSTEM)
        xcodebuild -target GHC-systemwide clean build\
                   CURRENT_PROJECT_VERSION=$(CURRENT_PROJECT_VERSION)\
                   SHORT_VERSION_STRING=$(SHORT_VERSION_STRING)\
@@ -102,7 +104,7 @@ framework-pkg:
        -$(RM) -f GHC-system.pmdoc/*-contents.xml
        $(PACKAGEMAKER) -v --doc GHC-system.pmdoc\
                        $(PACKAGEMAKER_TARGET) -o $(TOP)/$(PACKAGE_NAME)\
-                       -i org.haskell.GHC.$(FRAMEWORK_VERSION)
+                       -i org.haskell.ghc.$(FRAMEWORK_VERSION)
 
 # If we don't specify COMMAND_MODE=unix2003 then xcodebuild defaults
 # to setting it to legacy, which means that ar builds archives
diff --git a/distrib/MacOS/installer-scripts/Uninstaller b/distrib/MacOS/installer-scripts/Uninstaller
deleted file mode 100644 (file)
index 784c7c2..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/sh
-
-# Uninstaller script for GHC.framework 
-# (currently only for system volume installations)
-
-INSTALL_DEST=/Library/Frameworks
-INSTALL_BASE=/
-
-if [ ${INSTALL_BASE} = / ]; then
-  INSTALL_BASE=/usr
-fi
-INSTALL_BIN=${INSTALL_BASE}/bin
-INSTALL_MAN1=${INSTALL_BASE}/share/man/man1
-INSTALL_HTML=${INSTALL_BASE}/share/doc
-
-if [ ! -x ${INSTALL_DEST}/GHC.framework ]; then
-  echo "${INSTALL_DEST}/GHC.framework does not exit"
-  exit 1
-fi
-
-if [ ${USER} != root ]; then
-  echo "GHC.framework installer must be run with admin privileges"
-  echo "Prefix command by 'sudo'"
-  exit 1
-fi
-
-VERSIONS=(`ls ${INSTALL_DEST}/GHC.framework/Versions`)
-NO_VERSIONS=${#VERSIONS[@]}
-
-if [ ${VERSIONS[${NO_VERSIONS}-1]} != Current ]; then
-  echo "Fatal error: last version should be Current"
-  echo "Found versions: ${VERSIONS[@]}"
-  exit 1
-fi
-CURRENT_PHYS=`cd /Library/Frameworks/GHC.framework/Versions/Current; pwd -P`
-CURRENT=`basename ${CURRENT_PHYS}`
-
-if [ ${NO_VERSIONS} -ne 2 ]; then
-  echo "Multiple versions of GHC.framework are currently installed."
-  echo "This uninstaller removes GHC.framework entirely and should only"
-  echo "be used if there is exactly one version."
-  echo
-  echo "To remove individual old versions, simply delete the directory"
-  echo "${INSTALL_DEST}/GHC.framework/Versions/VERSION_TO_REMOVE"
-  echo
-  echo "Found versions: ${VERSIONS[@]}(= ${CURRENT})"
-  exit 1
-fi
-
-echo "Removing symbolic links into GHC.framework"
-for thisfile in ${INSTALL_BIN}/*; do
-  if ls -l "${thisfile}" | grep -q GHC.framework/Versions; then
-    rm -f "${thisfile}"
-  fi
-done
-for thisfile in ${INSTALL_MAN1}/*; do
-  if ls -l "${thisfile}" | grep -q GHC.framework/Versions; then
-    rm -f "${thisfile}"
-  fi
-done
-for thisfile in ${INSTALL_HTML}/*; do
-  if ls -l "${thisfile}" | grep -q GHC.framework/Versions; then
-    rm -f "${thisfile}"
-  fi
-done
-
-echo "Removing ${INSTALL_DEST}/GHC.framework"
-rm -rf ${INSTALL_DEST}/GHC.framework
-
-echo "Removing package recipt"
-# The first is for Leopard packages and the second for Tiger packages.
-rm -f /Library/Receipts/boms/org.haskell.ghc.pkg.bom
-rm -rf /Library/Receipts/ghc.pkg
-
-echo "${INSTALL_DEST}/GHC.framework has been purged!"
diff --git a/distrib/MacOS/installer-scripts/Uninstaller.in b/distrib/MacOS/installer-scripts/Uninstaller.in
new file mode 100644 (file)
index 0000000..8774e07
--- /dev/null
@@ -0,0 +1,91 @@
+#!/bin/sh
+
+# Uninstaller script for GHC.framework 
+# (currently only for system volume installations)
+
+INSTALL_DEST=/Library/Frameworks
+INSTALL_BASE=/
+
+# Turn off things that might make /usr/bin/ls give funky output
+unset CLICOLOR
+unset CLICOLOR_FORCE
+unset LSCOLORS
+
+if [ ${INSTALL_BASE} = / ]; then
+  INSTALL_BASE=/usr
+fi
+INSTALL_BIN=${INSTALL_BASE}/bin
+INSTALL_MAN1=${INSTALL_BASE}/share/man/man1
+INSTALL_HTML=${INSTALL_BASE}/share/doc
+
+if [ ! -x ${INSTALL_DEST}/GHC.framework ]; then
+  echo "${INSTALL_DEST}/GHC.framework does not exit"
+  exit 1
+fi
+
+if [ ${USER} != root ]; then
+  echo "GHC.framework installer must be run with admin privileges"
+  echo "Prefix command by 'sudo'"
+  exit 1
+fi
+
+FRAMEWORK_DIRECTORY="$INSTALL_DEST/GHC.framework"
+VERSIONS_DIRECTORY="$FRAMEWORK_DIRECTORY/Versions"
+
+MY_VERSION=@ProjectVersion@-@TargetArch_CPP@
+MY_DIRECTORY="$VERSIONS_DIRECTORY/$MY_VERSION"
+
+CURRENT_DIRECTORY="$VERSIONS_DIRECTORY/Current"
+CURRENT_VERSION=`readlink "$CURRENT_DIRECTORY"`
+
+if [ "$CURRENT_VERSION" = "$MY_VERSION" ]
+then
+    rm -f "$CURRENT_DIRECTORY"
+
+    removeLinksFrom () {
+        for f in `ls -1 "$MY_DIRECTORY/$1"`
+        do
+            qf="$1/$f"
+            # Sanity check that it is a link like we expect
+            l=`readlink "$qf" | grep GHC.framework/Versions`
+            if [ "$l" != "" ]
+            then
+                rm -f "$qf"
+            fi
+        done
+    }
+
+    removeLinksFrom /usr/bin
+    removeLinksFrom /usr/share/man/man1
+    removeLinksFrom /usr/share/doc
+fi
+
+echo "Removing $MY_DIRECTORY"
+rm -rf "$MY_DIRECTORY"
+
+if [ "$CURRENT_VERSION" = "$MY_VERSION" ]
+then
+    # This isn't ideal, but it's a vague approximation to
+    # "the most recent version":
+    NEW_VERSION=`ls -1 "$VERSIONS_DIRECTORY" | tail -1`
+    if [ "$NEW_VERSION" = "" ]
+    then
+        echo "Removing $FRAMEWORK_DIRECTORY"
+        rm -rf "$FRAMEWORK_DIRECTORY"
+    else
+        ln -s "$NEW_VERSION" "$CURRENT_DIRECTORY"
+        NEW_CREATE_LINKS="$VERSIONS_DIRECTORY/$NEW_VERSION/Tools/create-links"
+        if [ -f "$NEW_CREATE_LINKS" ]
+        then
+            sh "$NEW_CREATE_LINKS"
+        fi
+    fi
+fi
+
+echo "Removing package receipt"
+# The first is for Leopard packages and the second for Tiger packages.
+rm -f "/Library/Receipts/boms/org.haskell.ghc.$MY_VERSION.bom"
+rm -rf "/Library/Receipts/ghc.$MY_VERSION.pkg"
+
+echo "Done."
+
index 2e3dc5e..c12d90a 100644 (file)
@@ -20,8 +20,8 @@ if [ "$INSTALL_BASE" = / ]; then
   INSTALL_BASE=/usr
 fi
 
-ProjectVersionInt=@ProjectVersionInt@
-GHC_BASE="$INSTALL_DEST/GHC.framework/Versions/$ProjectVersionInt"
+VERSION=@ProjectVersion@-@TargetArch_CPP@
+GHC_BASE="$INSTALL_DEST/GHC.framework/Versions/$VERSION"
 
 INSTALL_BIN="$INSTALL_BASE/bin"
 mkdir -p "$INSTALL_BIN"
@@ -34,5 +34,5 @@ INSTALL_HTML="$INSTALL_BASE"/share/doc
 mkdir -p "$INSTALL_MAN1"
 if [ -d "$GHC_BASE"/usr/share/man/man1 ]; then
   ln -sf "$GHC_BASE"/usr/share/man/man1/* "$INSTALL_MAN1/"
-  ln -sf "$GHC_BASE"/usr/share/doc/ghc.$ProjectVersionInt "$INSTALL_HTML/"
+  ln -sf "$GHC_BASE"/usr/share/doc/ghc "$INSTALL_HTML/"
 fi