diff --git a/Distribution/MacOSX.hs b/Distribution/MacOSX.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/MacOSX.hs
@@ -0,0 +1,190 @@
+{- | Cabal support for creating Mac OSX application bundles.
+
+GUI applications on Mac OSX should be run as application /bundles/;
+these wrap an executable in a particular directory structure which can
+also carry resources such as icons, program metadata, images, other
+binaries, and copies of shared libraries.
+
+This module provides a Cabal post-build hook for creating such
+application bundles, and controlling their contents.
+
+For more information about OSX application bundles, look for the
+/Bundle Programming Guide/ on the /Apple Developer Connection/
+website, <http://developer.apple.com/>.
+
+-}
+
+module Distribution.MacOSX (
+  appBundleBuildHook,
+  MacApp(..),
+  ChaseDeps(..),
+  Exclusions,
+  defaultExclusions
+) where
+
+import Control.Monad (forM_)
+import Data.String.Utils (replace)
+import Distribution.PackageDescription (PackageDescription(..),
+                                        Executable(..))
+import Distribution.Simple
+import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))
+import Distribution.Simple.Setup (BuildFlags)
+import System.Cmd (system)
+import System.FilePath
+import System.Info (os)
+import System.Directory (copyFile, createDirectoryIfMissing)
+
+import Distribution.MacOSX.Common
+import Distribution.MacOSX.Dependencies
+
+-- | Post-build hook for OS X application bundles.  Does nothing if
+-- called on another O/S.
+appBundleBuildHook ::
+  [MacApp] -- ^ List of applications to build; if empty, an
+           -- application is built for each executable in the package,
+           -- with no icon or plist, and no dependency-chasing.
+  -> Args -- ^ All other parameters as per
+          -- 'Distribution.Simple.postBuild'.
+  -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO ()
+appBundleBuildHook apps _ _ pkg localb =
+  case os of
+    "darwin" -> forM_ apps' $ makeAppBundle localb
+      where apps' = case apps of
+                      [] -> map mkDefault $ executables pkg
+                      xs -> xs
+            mkDefault x = MacApp (exeName x) Nothing Nothing [] [] DoNotChase
+    _ -> putStrLn "Not OS X, so not building an application bundle."
+
+-- | Given a 'MacApp' in context, make an application bundle in the
+-- build area.
+makeAppBundle ::
+  LocalBuildInfo -> MacApp -> IO ()
+makeAppBundle localb app =
+  do appPath <- createAppDir localb app
+     maybeCopyPlist appPath app
+     maybeCopyIcon appPath app
+       `catch` \err -> putStrLn ("Warning: could not set up icon for " ++
+                                 appName app ++ ": " ++ show err)
+     includeResources appPath app
+     includeDependencies appPath app
+     osxIncantations appPath app
+
+-- | Create application bundle directory structure in build directory
+-- and copy executable into it.  Returns path to newly created
+-- directory.
+createAppDir :: LocalBuildInfo -> MacApp -> IO FilePath
+createAppDir localb app =
+  do putStrLn $ "Creating application bundle directory " ++ appPath
+     createDirectoryIfMissing False appPath
+     createDirectoryIfMissing True  $ takeDirectory exeDest
+     createDirectoryIfMissing True  $ appPath </> "Contents/Resources"
+     putStrLn $ "Copying executable " ++ appName app ++ " into place"
+     copyFile exeSrc exeDest
+     return appPath
+  where appPath = buildDir localb </> appName app <.> "app"
+        exeDest = appPath </> pathInApp app (appName app)
+        exeSrc = buildDir localb </> appName app </> appName app
+
+-- | Include any external resources specified.
+includeResources ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO ()
+includeResources appPath app = mapM_ includeResource $ resources app
+    where includeResource :: FilePath -> IO ()
+          includeResource p =
+            do let pDest = appPath </> pathInApp app p
+               putStrLn $ "Copying resource " ++ p ++ " to " ++ pDest
+               createDirectoryIfMissing True $ takeDirectory pDest
+               copyFile p $ pDest
+               return ()
+
+-- | If a plist has been specified, copy it into place.  If not, but
+-- an icon has been specified, construct a default shell plist so the
+-- icon is honoured.
+maybeCopyPlist ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO ()
+maybeCopyPlist appPath app =
+  case appPlist app of
+    Just plPath -> do -- Explicit plist path, so copy it in and assume OK.
+                      putStrLn $ "Copying " ++ plPath ++ " to " ++ plDest
+                      copyFile plPath plDest
+    Nothing -> case appIcon app of
+                 Just icPath ->
+                   do -- Need a plist to support icon; use default.
+                     let pl = replace "$program" (appName app) plistTemplate
+                         pl' = replace "$iconPath" (takeFileName icPath) pl
+                     writeFile plDest pl'
+                     return ()
+                 Nothing -> return () -- No icon, no plist, nothing to do.
+    where plDest = appPath </> "Contents/Info.plist"
+
+-- | If an icon file has been specified, copy it into place.
+maybeCopyIcon ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO ()
+maybeCopyIcon appPath app =
+  case appIcon app of
+    Just icPath ->
+      do putStrLn $ "Copying " ++ icPath ++ " to app's icon"
+         copyFile icPath $
+                  appPath </> "Contents/Resources" </> takeFileName icPath
+    Nothing -> return ()
+
+-- | Perform various magical OS X incantations for turning the app
+-- directory into a bundle proper.
+osxIncantations ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO ()
+osxIncantations appPath app =
+  do putStrLn "Running Rez, etc."
+     system $ rez ++ " Carbon.r -o " ++ appPath </> pathInApp app (appName app)
+     writeFile (appPath </> "PkgInfo") "APPL????"
+     -- Tell Finder about the icon.
+     system $ setFile ++ " -a C " ++ appPath </> "Contents"
+     return ()
+
+-- | Path to @Rez@ tool.
+rez :: FilePath
+rez = "/Developer/Tools/Rez"
+
+-- | Path to @SetFile@ tool.
+setFile :: FilePath
+setFile = "/Developer/Tools/SetFile"
+
+-- | Default plist template, based on that in macosx-app from wx (but
+-- with version stuff removed).
+plistTemplate :: String
+plistTemplate = "\
+    \<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
+    \<!DOCTYPE plist SYSTEM \"file://localhost/System/Library/DTDs/PropertyList.dtd\">\n\
+    \<plist version=\"0.9\">\n\
+    \<dict>\n\
+            \<key>CFBundleInfoDictionaryVersion</key>\n\
+            \<string>6.0</string>\n\
+            \<key>CFBundleIdentifier</key>\n\
+            \<string>org.haskell.$program</string>\n\
+            \<key>CFBundleDevelopmentRegion</key>\n\
+            \<string>English</string>\n\
+            \<key>CFBundleExecutable</key>\n\
+            \<string>$program</string>\n\
+            \<key>CFBundleIconFile</key>\n\
+            \<string>$iconPath</string>\n\
+            \<key>CFBundleName</key>\n\
+            \<string>$program</string>\n\
+            \<key>CFBundlePackageType</key>\n\
+            \<string>APPL</string>\n\
+            \<key>CFBundleSignature</key>\n\
+            \<string>????</string>\n\
+            \<key>CFBundleVersion</key>\n\
+            \<string>1.0</string>\n\
+            \<key>CFBundleShortVersionString</key>\n\
+            \<string>1.0</string>\n\
+            \<key>CFBundleGetInfoString</key>\n\
+            \<string>$program, bundled by cabal-macosx</string>\n\
+            \<key>LSRequiresCarbon</key>\n\
+            \<true/>\n\
+            \<key>CSResourcesFileMapped</key>\n\
+            \<true/>\n\
+    \</dict>\n\
+    \</plist>"
diff --git a/Distribution/MacOSX/Common.hs b/Distribution/MacOSX/Common.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/MacOSX/Common.hs
@@ -0,0 +1,120 @@
+module Distribution.MacOSX.Common where
+
+import Data.List
+import System.FilePath
+
+-- | Mac OSX application information.
+data MacApp = MacApp {
+  -- | Application name.  This should be the name of the executable
+  -- produced by Cabal's build stage.  The app bundle produced will be
+  -- @dist\/build\//appName/.app@, and the executable /appName/ will
+  -- be copied to @Contents\/MacOSX\/@ in the bundle.
+  appName :: String,
+  -- | Path to icon file, to be copied to @Contents\/Resources\/@ in
+  -- the app bundle.  If omitted, no icon will be used.
+  appIcon :: Maybe FilePath,
+  -- | Path to /plist/ file ('property-list' of application metadata),
+  -- to be copied to @Contents\/Info.plist@ in the app bundle.  If
+  -- omitted, and if 'appIcon' is specified, a basic default plist
+  -- will be used.
+  appPlist :: Maybe FilePath,
+  -- | Other resources to bundle in the application, e.g. image files,
+  -- etc.  Each will be copied to @Contents\/Resources\/@, with the
+  -- proviso that if the resource path begins with @resources\/@, it
+  -- will go to a /relative/ subdirectory of @Contents\/Resources\/@.
+  -- For example, @images/splash.png@ will be copied to
+  -- @Contents\/Resources\/splash.png@, whereas
+  -- @resources\/images\/splash.png@ will be copied to
+  -- @Contents\/Resources\/resources\/images\/splash.png@.
+  --
+  -- Bundled resources may be referred to from your program relative
+  -- to your executable's path (which may be computed, e.g., using
+  -- Audrey Tang's FindBin package).
+  resources :: [FilePath],
+  -- | Other binaries to bundle in the application, e.g.  other
+  -- executables from your project, or third-party programs.  Each
+  -- will be copied to a relative sub-directory of
+  -- @Contents\/Resources\/@ in the bundle.  For example,
+  -- @\/usr\/bin\/ftp@ would be copied to
+  -- @Contents\/Resources\/usr\/bin\/ftp@ in the app.
+  --
+  -- Like 'resources', bundled binaries may be referred to from your
+  -- program relative to your executable's path (which may be
+  -- computed, e.g., using Audrey Tang's FindBin package).
+  otherBins :: [FilePath],
+  -- | Controls inclusion of library dependencies for executable and
+  -- 'otherBins'; see below.
+  appDeps :: ChaseDeps
+  } deriving (Eq, Show)
+
+-- | Application bundles may carry their own copies of shared
+-- libraries, which enables distribution of applications which 'just
+-- work, out of the box' in the absence of static linking.  For
+-- example, a wxHaskell app can include the wx library (and /its/
+-- dependencies, recursively), meaning end users do not need to
+-- install wxWidgets in order to use the app.
+--
+-- This data type controls this process: if dependency chasing is
+-- activated, then the app's executable and any 'otherBins' are
+-- examined for their dependencies, recursively (usually with some
+-- exceptions - see below), the dependencies are copied into the app
+-- bundle, and any references to each library are updated to point to
+-- the copy.
+--
+-- (The process is transparent to the programmer, i.e. requires no
+-- modification to code.  In case anyone is interested: @otool@ is
+-- used to discover a binary's library dependencies; each library is
+-- copied to a relative sub-directory of @Contents\/Frameworks\/@ in
+-- the app bundle (e.g. @\/usr\/lib\/libFoo.a@ becomes
+-- @Contents\/Frameworks\/usr\/lib\/libFoo.a@); finally,
+-- @install_name_tool@ is used to update dependency references to
+-- point to the new version.)
+data ChaseDeps
+  = -- | Do not include any dependencies - a sensible default if not
+    -- distributing your app.
+    DoNotChase
+    -- | Include any libraries which the executable and 'otherBins'
+    -- depend on, excluding a default set which we would expect to be
+    -- present on any machine running the same version of OSX on which
+    -- the executable was built.  (n.b.: Creation of application
+    -- bundles which work transparently across different versions of
+    -- OSX is currently beyond the scope of this package.)
+  | ChaseWithDefaults
+    -- | Include any libraries which the executable and 'otherBins'
+    -- depend on, excluding a user-defined set.  If you specify an
+    -- empty exclusion list, then /all/ dependencies will be included,
+    -- recursively, including various OSX Frameworks; /this/
+    -- /probably/ /isn't/ /ever/ /sensible/.  The intended use,
+    -- rather, is to allow extension of the default list, which can be
+    -- accessed via 'defaultExclusions'.
+  | ChaseWith Exclusions
+    deriving (Eq, Show)
+
+-- | A list of exclusions to dependency chasing.  Any library whose
+-- path contains any exclusion string /as a substring/ will be
+-- excluded when chasing dependencies.
+type Exclusions = [String]
+
+-- | Default list of exclusions; excludes OSX standard frameworks,
+-- libgcc, etc. - basically things which we would expect to be present
+-- on any functioning OSX installation.
+defaultExclusions :: Exclusions
+defaultExclusions = 
+  ["/System/Library/Frameworks/",
+   "/libSystem.",
+   "/libgcc_s.",
+   "/libobjc."
+  ]
+
+-- | Compute item's path relative to app bundle root.
+pathInApp :: MacApp -> FilePath -> FilePath
+pathInApp app p
+  | p == appName app = "Contents/MacOS" </> p
+  | p `elem` otherBins app = "Contents/Resources" </> relP
+  | p `elem` resources app = 
+    let p' = if "resources/" `isPrefixOf` p then
+               makeRelative "resources/" p
+             else takeFileName p
+    in "Contents/Resources" </> p'
+  | otherwise = "Contents/Frameworks" </> relP
+  where relP = makeRelative "/" p
diff --git a/Distribution/MacOSX/DG.hs b/Distribution/MacOSX/DG.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/MacOSX/DG.hs
@@ -0,0 +1,75 @@
+-- | Dependency graph handling.
+
+module Distribution.MacOSX.DG (
+  DG(..),
+  FDeps(..),
+  dgEmpty,
+  dgFDeps,
+  dgAddPaths,
+  dgAddFDeps
+) where
+
+import Data.Graph.Inductive.Graph as G
+import Data.Graph.Inductive.Tree (Gr)
+import Data.List
+import Data.Maybe
+
+-- | A dependency graph is an ordinary fgl graph with 'FilePath's on
+-- its nodes, and directed edges.  An edge from A to B indicates that
+-- A depends on B.
+data DG = DG (Gr FilePath ())
+          deriving Show
+
+-- | An FDeps represents some file and its list of library
+-- dependencies.
+data FDeps = FDeps FilePath [FilePath]
+             deriving (Eq, Ord, Show)
+
+-- | Add a file dependency to a dependency graph.
+dgAddFDeps :: DG -> FDeps -> DG
+dgAddFDeps dg (FDeps src tgts) = dgAddDeps src tgts $ dg `dgAddPaths` (src:tgts)
+
+-- | Turn a dependency graph back into a list of FDeps.
+dgFDeps :: DG -> [FDeps]
+dgFDeps (DG g) = map mkFDep (G.labNodes g)
+  where mkFDep :: G.LNode FilePath -> FDeps
+        mkFDep (i, src) = FDeps src $ mapMaybe (G.lab g) (G.suc g i)
+
+-- | Create an empty dependency graph.
+dgEmpty :: DG
+dgEmpty = DG G.empty
+
+-- | Get the node number of a dependency graph node with a specified label.
+dgPathIdx :: DG -> FilePath -> Maybe Int
+dgPathIdx (DG g) p = case find (\x -> p == snd x) (G.labNodes g) of
+                       Just (i, _) -> Just i
+                       Nothing -> Nothing
+
+-- | Check if a certain path is already in a dependency graph.
+dgHasPath :: DG -> FilePath -> Bool
+dgHasPath dg p = case dgPathIdx dg p of
+                   Just _ -> True
+                   Nothing -> False
+
+-- | Add a list of paths as nodes to a dependency graph, dropping
+-- duplicates.
+dgAddPaths :: DG -> [FilePath] -> DG
+dgAddPaths = foldl dgAddPath
+
+-- | Add a single path as a node to a dependency graph, unless already
+-- present.
+dgAddPath :: DG -> FilePath -> DG
+dgAddPath dg@(DG g) p = if dg `dgHasPath` p then dg
+                        else DG $ G.insNode (head $ G.newNodes 1 g, p) g
+
+-- | Given a source path and a list of target paths, add a list of
+-- dependencies (ie edges) to a dependency graph.
+dgAddDeps :: FilePath -> [FilePath] -> DG -> DG
+dgAddDeps src tgts dg = foldl dgAddDep dg $ zip (repeat src) tgts
+
+-- | Add a (src, tgt) dependency (ie edge) to a dependency graph.
+dgAddDep :: DG -> (FilePath, FilePath) -> DG
+dgAddDep dg@(DG g) (src, tgt) = DG $ G.insEdge (getI src, getI tgt, ()) g
+  where getI x = case dgPathIdx dg x of
+                   Just x' -> x'
+                   Nothing -> error "Can't happen" -- if called in context.
diff --git a/Distribution/MacOSX/Dependencies.hs b/Distribution/MacOSX/Dependencies.hs
new file mode 100644
--- /dev/null
+++ b/Distribution/MacOSX/Dependencies.hs
@@ -0,0 +1,221 @@
+{- | Inclusion of bundle-local copies of libraries in application bundles.
+
+OS X application bundles can include local copies of libraries and
+frameworks (ie dependencies of the executable) which aids distribution
+and eases installation.  Xcode and the traditional OS X development
+toolchain support this fairly transparently; this module is an attempt
+to provide similar functionality in the cabal-macosx package.
+
+The basic approach is as follows:
+
+  1. Discover the libraries an object file (executable, other binary, or
+     library) references using @otool -L /path/@
+
+  2. Copy those libraries into the application bundle, at the right
+     place, ie @\@executable_path\/..\/Frameworks\/@ where
+     @\@executable_path@ represents the path to the exeutable in the
+     bundle.
+
+  3. Modify the object file so it refers to the local copy, using
+     @install_name_tool -change /oldLibPath/ /newLibPath/ /path/@ where
+     @/newlibPath/@ points to @\@executable_path\/..\/Frameworks@ as
+     described above (@\@executable_path@ is a special symbol recognised
+     by the loader).
+
+Complications:
+
+  * There's some stuff we don't want to include because we can
+  expect it to be present everywhere, eg the Cocoa framework; see
+  /Exclusions/, below.
+
+  * Libraries can themselves depend on other libraries; thus, we
+  need to copy them in recursively.
+
+  * Because of these transitive dependencies, dependencies can
+  arise on multiple copies of the same library, in different
+  locations (eg @\/usr\/lib\/libfoo@ and @\/opt\/local\/lib\/libfoo@).
+  Thus, we preserve that path info, and (for example) copy
+  @\/usr\/lib\/libFoo@ to
+  @\@executable_path\/..\/Frameworks\/usr\/lib\/@.
+
+The approach followed is to build a dependency graph, seeded with the
+executable and any other binaries being included in the bundle, using
+@otool@; then to walk that graph, copying in the libraries, and
+calling @install_name_tool@ to update the dependencies of entities in
+the bundle.  Going via a dependency graph is a bit unnecessary - we
+could just recursively @otool@/@install_name_tool@, but its helpful if
+we need to debug, etc., and a nice clear abstraction.
+
+/Exclusions/: as described above, a lot of truly common stuff would
+get copied in, so we provide a mechanism to exclude libraries from
+this process: 'buildDependencyGraph' can be passed a list of strings,
+and a library whose path includes any of those strings is excluded.
+If an empty list is passed, then nothing is excluded (which is almost
+certainly not what you want).
+
+-}
+
+module Distribution.MacOSX.Dependencies (
+  includeDependencies,
+  appDependencyGraph
+) where
+
+import Control.Monad
+import Data.List
+import System.Directory
+import System.FilePath
+import System.IO
+import System.Process
+import Text.ParserCombinators.Parsec
+
+import Distribution.MacOSX.Common
+import Distribution.MacOSX.DG
+
+-- | Include any library dependencies required in the app.
+includeDependencies ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO ()
+includeDependencies appPath app =
+  do dg <- appDependencyGraph appPath app
+     let fDeps = dgFDeps dg
+     mapM_ (copyInDependency appPath app) fDeps
+     mapM_ (updateDependencies appPath app) fDeps
+
+-- | Compute application's library dependency graph.
+appDependencyGraph ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp -> IO DG
+appDependencyGraph appPath app =
+  case (appDeps app) of
+    ChaseWithDefaults -> appDependencyGraph appPath app {
+                           appDeps = ChaseWith defaultExclusions
+                         }
+    ChaseWith xs -> do putStrLn "Building dependency graph"
+                       buildDependencyGraph appPath app dgInitial roots [] xs
+    DoNotChase -> return dgInitial
+  where roots = appName app : otherBins app
+        dgInitial = dgEmpty `dgAddPaths` roots
+
+-- | Recursive dependency-graph builder.
+buildDependencyGraph ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> DG -- ^ Dependency graph to be extended.
+  -> [FilePath] -- ^ Queue of paths to object files to be examined for
+                -- dependencies.
+  -> [FilePath] -- ^ List of paths of object files which have already
+                -- been dealt with.
+  -> Exclusions -- ^ List of exclusions for dependency-chasing.
+  -> IO DG
+buildDependencyGraph _ _ dg [] _ _ = return dg
+buildDependencyGraph appPath app dg (x:xs) done excls =
+  do (dg', tgts) <- addFilesDependencies appPath app dg x excls
+     let done' = (x:done)
+         xs'   = addToQueue xs done' tgts
+     buildDependencyGraph appPath app dg' xs' done' excls
+  where addToQueue :: [FilePath] -> [FilePath] -> [FilePath] -> [FilePath]
+        addToQueue q done' = foldl (addOneToQueue (q ++ done')) q
+        addOneToQueue :: [FilePath] -> [FilePath] -> FilePath -> [FilePath]
+        addOneToQueue done' q n = if n `elem` done' then q else q ++ [n]
+
+-- | Add an object file's dependencies to a dependency graph,
+-- returning that new graph and a list of the discovered dependencies.
+addFilesDependencies ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> DG -- ^ Dependency graph to be extended.
+  -> FilePath -- ^ Path to object file to be examined for dependencies.
+  -> Exclusions -- ^ List of exclusions for dependency chasing.
+  -> IO (DG, [FilePath])
+addFilesDependencies appPath app dg p excls =
+  do (FDeps _ tgts) <- getFDeps appPath app p excls
+     let dg' = dgAddFDeps dg (FDeps p tgts)
+     return (dg', tgts)
+
+-- | Compute the library dependencies for some file, removing any
+-- exclusions.
+getFDeps ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> FilePath -- ^ Path to object file to be examined for dependencies.
+  -> Exclusions -- ^ List of exclusions for dependency chasing.
+  -> IO FDeps
+getFDeps appPath app path exclusions =
+  do contents <- readProcess oTool ["-L", absPath] ""
+     case parse parseFileDeps "" contents of
+       Left err -> error $ show err
+       Right fDeps -> return $ exclude exclusions fDeps
+  where absPath = if path == appName app then
+                    appPath </> pathInApp app (appName app)
+                  else path
+        parseFileDeps :: Parser FDeps
+        parseFileDeps = do f <- manyTill (noneOf ":") (char ':')
+                           char '\n'
+                           deps <- parseDep `sepEndBy` char '\n'
+                           eof
+                           return $ FDeps f deps
+        parseDep :: Parser FilePath
+        parseDep = do char '\t'
+                      dep <- manyTill (noneOf " ") (char ' ')
+                      char '('
+                      manyTill (noneOf ")") (char ')')
+                      return dep
+
+-- | Apply an exclusion list to an 'FDeps' value; any dependencies
+-- which contain any of the exclusions as substrings are excluded.
+exclude :: Exclusions -> FDeps -> FDeps
+exclude excls (FDeps p ds) = FDeps p $ filter checkExclude ds
+  where checkExclude :: FilePath -> Bool
+        checkExclude f = not $ any (`isInfixOf` f) excls
+
+-- | Copy some object file's library dependencies into the application
+-- bundle.
+copyInDependency ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> FDeps -- ^ Dependencies to copy in.
+  -> IO ()
+copyInDependency appPath app (FDeps src _) =
+  Control.Monad.unless (src == appName app) $
+         do putStrLn $ "Copying " ++ src ++ " to " ++ tgt
+            createDirectoryIfMissing True $ takeDirectory tgt
+            copyFile src tgt
+    where tgt = appPath </> pathInApp app src
+
+-- | Update some object file's library dependencies to point to
+-- bundled copies of libraries.
+updateDependencies ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> FDeps -- ^ Dependencies to update.
+  -> IO ()
+updateDependencies appPath app (FDeps src tgts) =
+  mapM_ (updateDependency appPath app src) tgts
+
+-- | Update some object file's dependency on some particular library,
+-- to point to the bundled copy of that library.
+updateDependency ::
+  FilePath -- ^ Path to application bundle root.
+  -> MacApp
+  -> FilePath -- ^ Path to object file to update.
+  -> FilePath -- ^ Path to library which was copied in (path before copy).
+  -> IO ()
+updateDependency appPath app src tgt =
+  do putStrLn $ "Updating " ++ newLib ++ "'s dependency on " ++ tgt ++
+                   " to " ++ tgt'
+     let cmd = iTool ++ " -change " ++ show tgt ++ " " ++ show tgt' ++
+                   " " ++ show newLib
+     --putStrLn cmd
+     runCommand cmd
+     return ()
+  where tgt' = "@executable_path/../Frameworks/" </> makeRelative "/" tgt
+        newLib = if src == appName app then src
+                 else appPath </> pathInApp app src
+
+-- | Path to @otool@ tool.
+oTool :: FilePath
+oTool = "/usr/bin/otool"
+
+-- | Path to @install_name_tool@ tool.
+iTool :: FilePath
+iTool = "/usr/bin/install_name_tool"
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,36 @@
+Copyright (c) 2009, Eric Kow, Andy Gimblett
+All rights reserved.
+
+Developed by:
+
+    Eric Kow <eric.kow@gmail.com>
+    Andy Gimblett <haskell@gimbo.org.uk>
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditi ons and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+    * Neither the names of Eric Kow, Andy Gimblett, nor the names of
+      its contributors may be used to endorse or promote products
+      derived from this software without specific prior written
+      permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/cabal-macosx.cabal b/cabal-macosx.cabal
new file mode 100644
--- /dev/null
+++ b/cabal-macosx.cabal
@@ -0,0 +1,40 @@
+Name:                   cabal-macosx
+Version:                0.1.0
+Stability:              Alpha
+Synopsis:               Cabal support for creating Mac OSX application bundles.
+Description:
+
+    GUI applications on Mac OSX must be run as application /bundles/;
+    these wrap an executable in a particular directory structure which
+    can also carry resources such as icons, program metadata, other
+    binaries, and copies of shared libraries.
+
+    This package provides Cabal support for creating such application
+    bundles.
+
+    For more information about OSX application bundles, look for the
+    /Bundle Programming Guide/ on the /Apple Developer Connection/
+    website, <http://developer.apple.com/>.
+
+Category:               Distribution
+License:                BSD3
+License-file:           LICENSE
+Copyright:              Eric Kow & Andy Gimblett
+Author:                 Eric Kow <eric.kow@gmail.com> & Andy Gimblett <haskell@gimbo.org.uk>
+Maintainer:             Andy Gimblett <haskell@gimbo.org.uk>
+Homepage:               http://github.com/gimbo/cabal-macosx
+Build-Type:             Simple
+Cabal-Version:          >=1.6
+
+Source-Repository head
+    Type:         git
+    Location:     http://github.com/gimbo/cabal-macosx
+
+Library
+  Build-Depends:   base >= 4 && < 5, Cabal >= 1.6, directory, fgl,
+                   filepath, MissingH, parsec, process
+  Exposed-modules: Distribution.MacOSX
+  Other-modules:   Distribution.MacOSX.Common,
+                   Distribution.MacOSX.Dependencies,
+                   Distribution.MacOSX.DG
+  ghc-options:     -fwarn-tabs -Wall
