packages feed

cabal-macosx 0.1.2.2 → 0.2.4.2

raw patch · 11 files changed

Files

Distribution/MacOSX.hs view
@@ -1,21 +1,25 @@-{- | Cabal support for creating Mac OSX application bundles.+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+  {- | 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.+  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.+  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/>.+  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, appBundleInstallHook,+  appBundleBuildHook,+  appBundleInstallHook,+  appBundleCopyHook,   makeAppBundle,   MacApp(..),   ChaseDeps(..),@@ -23,27 +27,34 @@   defaultExclusions ) where +import Control.Exception+import Prelude hiding ( catch ) import Control.Monad (forM_, when)-import Data.String.Utils (replace)-import Distribution.PackageDescription (PackageDescription(..),-                                        Executable(..))+import Data.List ( isPrefixOf )+import System.Cmd (system)+import System.FilePath+import System.Directory (copyFile, createDirectoryIfMissing, getHomeDirectory)+import qualified Data.Text as T+import qualified Data.Text.IO as T++import Distribution.PackageDescription (PackageDescription(..)) import Distribution.Simple import Distribution.Simple.InstallDirs (bindir, prefix, CopyDest(NoCopyDest)) import Distribution.Simple.LocalBuildInfo (absoluteInstallDirs, LocalBuildInfo(..))-import Distribution.Simple.Setup (BuildFlags, InstallFlags,-                                  fromFlagOrDefault, installVerbosity-                                 )+import Distribution.Simple.Setup (BuildFlags, InstallFlags, CopyFlags, fromFlagOrDefault, installVerbosity, copyVerbosity) import Distribution.Simple.Utils (installDirectoryContents, installExecutableFile)-import Distribution.Verbosity (normal)-import System.Cmd (system)-import System.FilePath+#if MIN_VERSION_Cabal(1,18,0)+import Distribution.System (Platform (..), OS (OSX))+#else import System.Info (os)-import System.Directory (copyFile, createDirectoryIfMissing)-import System.Exit+#endif+import Distribution.Verbosity (normal, Verbosity) +import Distribution.MacOSX.Internal import Distribution.MacOSX.AppBuildInfo import Distribution.MacOSX.Common import Distribution.MacOSX.Dependencies+import Distribution.MacOSX.Templates  -- | Post-build hook for OS X application bundles.  Does nothing if -- called on another O/S.@@ -55,13 +66,15 @@           -- 'Distribution.Simple.postBuild'.   -> BuildFlags -> PackageDescription -> LocalBuildInfo -> IO () appBundleBuildHook apps _ _ pkg localb =+#if MIN_VERSION_Cabal(1,18,0)+  if isMacOS localb+#else   if isMacOS-     then forM_ apps' $ makeAppBundle . toAppBuildInfo localb+#endif+     then do let buildDirLbi = buildDir localb+             let macApps = getMacAppsForBuildableExecutors apps (executables pkg)+             forM_ macApps (makeAppBundle . createAppBuildInfo buildDirLbi)      else putStrLn "Not OS X, so not building an application bundle."-  where apps' = case apps of-                      [] -> map mkDefault $ executables pkg-                      xs -> xs-        mkDefault x = MacApp (exeName x) Nothing Nothing [] [] DoNotChase  -- | Post-install hook for OS X application bundles.  Copies the -- application bundle (assuming you are also using the appBundleBuildHook)@@ -74,42 +87,129 @@   -> Args -- ^ All other parameters as per           -- 'Distribution.Simple.postInstall'.   -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()-appBundleInstallHook apps _ iflags pkg localb = when isMacOS $ do-  let verbosity = fromFlagOrDefault normal (installVerbosity iflags)+appBundleInstallHook apps _ iflags =+	appBundleInstallOrCopyHook apps+	    (fromFlagOrDefault normal (installVerbosity iflags))+{-# DEPRECATED appBundleInstallHook "Use appBundleCopyHook instead" #-}++-- | Post-copy hook for OS X application bundles.  Copies the+-- application bundle (assuming you are also using the appBundleBuildHook)+-- to @$prefix/Applications@+-- Does nothing if called on another O/S.+-- Use this instead of appBundleInstallHook (do not hook+-- both postInst and postCopy).+appBundleCopyHook ::+  [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.postCopy'.+  -> CopyFlags -> PackageDescription -> LocalBuildInfo -> IO ()+appBundleCopyHook apps _ cflags =+	appBundleInstallOrCopyHook apps+	    (fromFlagOrDefault normal (copyVerbosity cflags))++appBundleInstallOrCopyHook ::+  [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.+  -> Verbosity+  -> PackageDescription -> LocalBuildInfo -> IO ()+#if MIN_VERSION_Cabal(1,18,0)+appBundleInstallOrCopyHook apps verbosity pkg localb = when (isMacOS localb) $ do+#else+appBundleInstallOrCopyHook apps verbosity pkg localb = when isMacOS $ do+#endif+  libraryHaskell  <- flip fmap getHomeDirectory $ (</> "Library/Haskell")+  let standardPrefix = (libraryHaskell ++ "/") `isPrefixOf` prefix installDir+  let applicationsDir = if standardPrefix+                           then libraryHaskell    </> "Applications"+                           else prefix installDir </> "Applications"   createDirectoryIfMissing False applicationsDir   forM_ apps $ \app -> do     let appInfo    = toAppBuildInfo localb app-        appPathSrc = appPath appInfo+        appPathSrc = abAppPath appInfo         appPathTgt = applicationsDir </> takeFileName appPathSrc         exe ap = ap </> pathInApp app (appName app)     installDirectoryContents verbosity appPathSrc appPathTgt     installExecutableFile    verbosity (exe appPathSrc) (exe appPathTgt)     -- generate a tiny shell script for users who expect to run their     -- applications from the command line with flags and all-    let script = "`dirname $0`" </> "../Applications"-                                </> takeFileName appPathSrc-                                </> "Contents/MacOS" </> appName app-                 ++ " \"$@\""+    let script = if standardPrefix+                    then bundleScriptLibraryHaskell localb app+                    else bundleScriptElsewhere      localb app         scriptFileSrc = buildDir localb   </> "_" ++ appName app <.> "sh"         scriptFileTgt = bindir installDir </> appName app     writeFile scriptFileSrc script     installExecutableFile verbosity scriptFileSrc scriptFileTgt   where     installDir = absoluteInstallDirs pkg localb NoCopyDest-    applicationsDir = prefix installDir </> "Applications" +bundleScriptLibraryHaskell :: LocalBuildInfo -> MacApp -> String+bundleScriptLibraryHaskell localb app = unlines+  [ "#!/bin/bash"+  , "$HOME/Library/Haskell/Applications"+           </> takeFileName appPathSrc+           </> "Contents/MacOS" </> appName app ++ " \"$@\""+  ]+  where+    appInfo    = toAppBuildInfo localb app+    appPathSrc = abAppPath appInfo+ +bundleScriptElsewhere :: LocalBuildInfo -> MacApp -> String+bundleScriptElsewhere localb app = unlines+  [ "#!/bin/bash"+  , "MAX_DEPTH=256"+  , "COUNTER=0"+  , "ZERO=$0"+  , "STATUS=0"+  , ""+  , "# The counter is just a safeguard in case I'd done something silly"+  , "while [ $STATUS -eq 0 -a $COUNTER -lt $MAX_DEPTH ]; do"+  , "  COUNTER=$(($COUNTER+1))"+  , "  NZERO=`readlink $ZERO`; STATUS=$?"+  , "  if [ $STATUS -eq 0 ]; then"+  , "      # go to my parent dir"+  , "      pushd $(dirname $ZERO)  > /dev/null"+  , "      # now follow the symlink if at all"+  , "      pushd $(dirname $NZERO) > /dev/null"+  , "      ZERO=$PWD/$(basename $NZERO)"+  , "      popd > /dev/null"+  , "      popd > /dev/null"+  , "  fi"+  , "done"+  , "if [ $COUNTER -ge $MAX_DEPTH ]; then"+  , "  echo >&2 Urk! exceeded symlink depth of $MAX_DEPTH trying to dereference $0"+  , "  exit 1"+  , "fi"+  , "`dirname $ZERO`" </> "../Applications"+           </> takeFileName appPathSrc+           </> "Contents/MacOS" </> appName app ++ " \"$@\""+  ]+  where+    appInfo    = toAppBuildInfo localb app+    appPathSrc = abAppPath appInfo++#if MIN_VERSION_Cabal(1,18,0)+isMacOS :: LocalBuildInfo -> Bool+isMacOS localb = case hostPlatform localb of+  Platform _ OSX -> True+  _ -> False+#else isMacOS :: Bool isMacOS = os == "darwin"+#endif + -- | Given a 'MacApp' in context, make an application bundle in the -- build area. (for internal use only) makeAppBundle :: AppBuildInfo -> IO () makeAppBundle appInfo@(AppBuildInfo appPath _ app) =-  do createAppDir appInfo+  do _ <- createAppDir appInfo      maybeCopyPlist appPath app      maybeCopyIcon appPath app-       `catch` \err -> putStrLn ("Warning: could not set up icon for " ++-                                 appName app ++ ": " ++ show err)+       `catch` \(SomeException err) ->+          putStrLn $ "Warning: could not set up icon for " ++ appName app ++ ": " ++ show err      includeResources appPath app      includeDependencies appPath app      osxIncantations appPath app@@ -123,7 +223,7 @@      createDirectoryIfMissing False appPath      createDirectoryIfMissing True  $ takeDirectory exeDest      createDirectoryIfMissing True  $ appPath </> "Contents/Resources"-     putStrLn $ "Copying executable " ++ appName app ++ " into place"+     putStrLn $ "Copying executable " ++ appName app ++ " into place from " ++ exeSrc ++ " to " ++ exeDest      copyFile exeSrc exeDest      return appPath   where exeDest = appPath </> pathInApp app (appName app)@@ -155,9 +255,9 @@     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'+                     let pl  = T.replace "$program"  (T.pack (appName app)) plistTemplate+                         pl' = T.replace "$iconPath" (T.pack (takeFileName icPath)) pl+                     T.writeFile plDest pl'                      return ()                  Nothing -> return () -- No icon, no plist, nothing to do.     where plDest = appPath </> "Contents/Info.plist"@@ -173,62 +273,3 @@          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."-     ExitSuccess <- system $ rez ++ " Carbon.r -o " ++-       appPath </> pathInApp app (appName app)-     writeFile (appPath </> "PkgInfo") "APPL????"-     -- Tell Finder about the icon.-     ExitSuccess <- 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>"
+ Distribution/MacOSX/AppBuildInfo.hs view
@@ -0,0 +1,35 @@+-- | Information used to help create an application bundle+module Distribution.MacOSX.AppBuildInfo where++import Distribution.Simple.LocalBuildInfo (LocalBuildInfo(..))+import System.FilePath++import Distribution.MacOSX.Common++-- | Information needed to build a bundle+--+--   This exists to make it possible to have a standalone+--   macosx-app executable without it necessarily having to+--   know a lot of Cabal internals+data AppBuildInfo = AppBuildInfo+  { -- | Location of the application bundle being built+    abAppPath    :: FilePath+    -- | Location of the original executable that was built+  , abAppOrigExe :: FilePath+    -- |+  , abApp        :: MacApp+  }++-- | @toAppBuildInfo l m@ returns information for an application bundle+--   within the @l@ build directory+toAppBuildInfo :: LocalBuildInfo -> MacApp -> AppBuildInfo+toAppBuildInfo localb app = createAppBuildInfo (buildDir localb) app++-- | @createAppBuildInfo d m@ returns information for an application bundle+--   within the @d@ build directory from LocalBuildInfo+createAppBuildInfo :: FilePath -> MacApp -> AppBuildInfo+createAppBuildInfo buildDirLocalBuildInfo app = AppBuildInfo+  { abAppPath    = buildDirLocalBuildInfo </> appName app <.> "app"+  , abAppOrigExe = buildDirLocalBuildInfo </> appName app </> appName app+  , abApp        = app+  }
Distribution/MacOSX/Common.hs view
@@ -1,3 +1,4 @@+-- | Utility functions module Distribution.MacOSX.Common where  import Data.List
Distribution/MacOSX/DG.hs view
Distribution/MacOSX/Dependencies.hs view
@@ -142,7 +142,9 @@   -> Exclusions -- ^ List of exclusions for dependency chasing.   -> IO FDeps getFDeps appPath app path exclusions =-  do contents <- readProcess oTool ["-L", absPath] ""+  do putStrLn $ "path: " ++ path+     contents <- readProcess oTool ["-L", absPath] ""+     putStrLn $ "contents: " ++ contents      case parse parseFileDeps "" contents of        Left err -> error $ show err        Right fDeps -> return $ exclude exclusions fDeps@@ -152,6 +154,7 @@         parseFileDeps :: Parser FDeps         parseFileDeps = do f <- manyTill (noneOf ":") (char ':')                            _ <- char '\n'+                            deps <- parseDepOrName `sepEndBy` char '\n'                            eof                            return $ FDeps f $ filter (f /=) $ catMaybes deps@@ -159,12 +162,22 @@         parseDepOrName = do c <- oneOf "\t/"                             case c of                               '\t' -> -- A dependency.-                                      do dep <- parseDep-                                         return $ Just dep+                                      do dep <- parseDepOrIgnoreAt+                                         return $ dep                               '/' -> -- Same filename, alternative arch                                      do _ <- manyTill (noneOf ":") (char ':')                                         return Nothing                               _ -> error "Can't happen"+        parseDepOrIgnoreAt :: Parser (Maybe FilePath)+        parseDepOrIgnoreAt = do c <- lookAhead (oneOf "/@")+                                case c of+                                  '/' -> -- A dependency.+                                         do dep <- parseDep+                                            return $ Just $ dep+                                  '@' -> -- ignore entries that start with @+                                         do _ <- manyTill (noneOf ")") (char ')')+                                            return Nothing+                                  _ -> error "Can't happen"         parseDep :: Parser FilePath         parseDep = do dep <- manyTill (noneOf " ") (char ' ')                       _ <- char '('@@ -213,10 +226,17 @@ updateDependency appPath app src tgt =   do putStrLn $ "Updating " ++ newLib ++ "'s dependency on " ++ tgt ++                    " to " ++ tgt'+     -- Ensure we have write permissions while editing the library. Notably,+     -- Homebrew removes write permissions from installed files.+     perm <- getPermissions newLib+     setPermissions newLib perm { writable = True }      let cmd = iTool ++ " -change " ++ show tgt ++ " " ++ show tgt' ++                    " " ++ show newLib-     --putStrLn cmd-     ExitSuccess <- system cmd+     exitCode <- system cmd+     setPermissions newLib perm+     when (exitCode /= ExitSuccess) $+       error $ "Failed to update library dependencies on " ++ show newLib +++        " with command: " ++ cmd      return ()   where tgt' = "@executable_path/../Frameworks/" </> makeRelative "/" tgt         newLib = appPath </> pathInApp app src
+ Distribution/MacOSX/Internal.hs view
@@ -0,0 +1,74 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+{- | 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 internals to 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.Internal (+  getMacAppsForBuildableExecutors,+  osxIncantations+) where++#if MIN_VERSION_Cabal(2,0,0)+import Data.String (fromString)+import Distribution.Text (display)+import Distribution.Types.UnqualComponentName (unUnqualComponentName)+#endif+import Prelude hiding ( catch )+import System.Cmd ( system )+import System.Exit+import System.FilePath+import Control.Monad (filterM)+import System.Directory (doesDirectoryExist)++import Distribution.PackageDescription (BuildInfo(..), Executable(..))+import Distribution.MacOSX.Common++-- | Filter or create new 'MacApp's that are associated by name to buildable 'Executable's.+getMacAppsForBuildableExecutors ::+  [MacApp] -- ^ List of 'MacApp's to filter if any.+  -> [Executable] -- ^ List of 'Executable's from .cabal.+  -> [MacApp] -- ^ Returned list of 'MacApp's that are associated by name to buildable 'Executable's.+getMacAppsForBuildableExecutors macApps executables =+  case macApps of+    [] -> map mkDefault buildables+    xs -> filter buildableApp xs+  where -- Make a default MacApp in absence of explicit from Setup.hs+#if MIN_VERSION_Cabal(2,0,0)+        mkDefault x = MacApp (unUnqualComponentName $ exeName x) Nothing Nothing [] [] DoNotChase+#else+        mkDefault x = MacApp (exeName x) Nothing Nothing [] [] DoNotChase+#endif++        -- Check if a MacApp is in that list of buildable executables.+        buildableApp :: MacApp -> Bool+#if MIN_VERSION_Cabal(2,0,0)+        buildableApp app = any (\e -> exeName e == fromString (appName app)) buildables+#else+        buildableApp app = any (\e -> exeName e == appName app) buildables+#endif++        -- List of buildable executables from .cabal file.+        buildables :: [Executable]+        buildables = filter (buildable . buildInfo) executables++-- | 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 writeFile (appPath </> "PkgInfo") "APPL????"+     return ()
+ Distribution/MacOSX/Templates.hs view
@@ -0,0 +1,46 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Templates for the bundle.++module Distribution.MacOSX.Templates (+  plistTemplate+) where++import Data.Text ( Text )++-- | Default plist template, based on that in macosx-app from wx (but+-- with version stuff removed).+plistTemplate :: Text+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>"
cabal-macosx.cabal view
@@ -1,5 +1,5 @@ Name:                   cabal-macosx-Version:                0.1.2.2+Version:                0.2.4.2 Stability:              Alpha Synopsis:               Cabal support for creating Mac OSX application bundles. Description:@@ -21,27 +21,63 @@ 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+Maintainer:             Daniele Francesconi <dfrancesconi12@gmail.com>+Homepage:               http://github.com/danfran/cabal-macosx Build-Type:             Simple-Cabal-Version:          >=1.6+Cabal-Version:          >=1.8+Tested-With:            GHC == 7.4.2, GHC == 7.6.3, GHC == 7.8.4, GHC == 7.10.1, GHC == 7.10.2, GHC == 7.10.3, GHC == 8.0.1, GHC == 8.0.2  Source-Repository head     Type:         git-    Location:     http://github.com/gimbo/cabal-macosx+    Location:     http://github.com/danfran/cabal-macosx  Library-  Build-Depends:   base >= 4 && < 5, Cabal >= 1.6, directory-               ,   fgl >= 5.4.2.2 && < 5.5-               ,   filepath, MissingH, parsec, process-  Exposed-modules: Distribution.MacOSX-  Other-modules:   Distribution.MacOSX.Common,-                   Distribution.MacOSX.Dependencies,-                   Distribution.MacOSX.DG-  ghc-options:     -fwarn-tabs -Wall+  Build-Depends:    base == 4.*+                    , Cabal >= 1.6, directory+                    , hscolour+                    , fgl+                    , filepath+                    , parsec+                    , process+                    , text+                    , containers+  Exposed-modules:  Distribution.MacOSX+  Other-modules:    Distribution.MacOSX.Internal,+                    Distribution.MacOSX.Common,+                    Distribution.MacOSX.AppBuildInfo,+                    Distribution.MacOSX.Dependencies,+                    Distribution.MacOSX.DG,+                    Distribution.MacOSX.Templates+  ghc-options:      -fwarn-tabs -Wall  Executable macosx-app-  Main-is:         macosx-app.hs-  Build-Depends:   base >= 4 && < 5, Cabal >= 1.6, directory-               ,   fgl >= 5.4.2.2 && < 5.5-               ,   filepath, MissingH, parsec, process+  Main-is:          macosx-app.hs+  Build-Depends:    base == 4.*+                    , Cabal >= 1.6+                    , directory+                    , fgl+                    , filepath+                    , parsec+                    , process+                    , text+                    , containers++test-suite tests+  ghc-options:      -Wall+  hs-source-dirs:   .,tests+  Main-is:          Main.hs+  Type:             exitcode-stdio-1.0+  Other-modules:    Distribution.MacOSX.Internal.Tests,+                    Distribution.MacOSX.Common,+                    Distribution.MacOSX.Internal+  Build-depends:    base == 4.*+                    , HUnit+                    , test-framework+                    , test-framework-hunit+                    , temporary+                    , Cabal >= 1.6+                    , filepath+                    , process+                    , text+                    , containers+                    , directory
macosx-app.hs view
@@ -20,9 +20,9 @@                        , otherBins = []                        , appDeps   = DoNotChase                        } -      appInfo = AppBuildInfo { app        = macapp-                             , appPath    = appName macapp <.> "app"-                             , appOrigExe = exe+      appInfo = AppBuildInfo { abApp        = macapp+                             , abAppPath    = appName macapp <.> "app"+                             , abAppOrigExe = exe                              }   if exeExists      then makeAppBundle appInfo
+ tests/Distribution/MacOSX/Internal/Tests.hs view
@@ -0,0 +1,88 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE CPP #-}+module Distribution.MacOSX.Internal.Tests where++import Prelude hiding (catch)+import Test.HUnit (Assertion, assertEqual)+import Test.Framework (Test, mutuallyExclusive, testGroup)+import Test.Framework.Providers.HUnit (testCase)++#if MIN_VERSION_Cabal(2,0,0)+import Distribution.Types.ExecutableScope+#endif+import Distribution.PackageDescription (BuildInfo(..), Executable(..), emptyBuildInfo, emptyExecutable)++import Distribution.MacOSX.Internal (getMacAppsForBuildableExecutors)+import Distribution.MacOSX.Common++#if MIN_VERSION_Cabal(2,0,0)+getExecutableScopeUnknown :: ExecutableScope+getExecutableScopeUnknown = exeScope $ emptyExecutable+#endif++macosxInternalTests :: Test+macosxInternalTests = testGroup "Distribution.MacOSX.Internal"+    [ mutuallyExclusive $ testGroup "MacOSX Internal"+        [ -- I should consider to use QuickCheck maybe... :)+          testCase "given nothing then should not try to build any mac-app" testBuildMacApp_noInput,+          testCase "given no executables then should not try to build any mac-app" testBuildMacApp_noExecutables,+          testCase "given only two executables then should try to build two mac-apps" testBuildMacApp_twoBuildableExecutables,+          testCase "given only two executables and one not executable then should try to build one mac-app" testBuildMacApp_twoExcetuablesOneBuildableAndOneNot,+          testCase "given two executables and one not executable and two apps then should try to build one mac-app" testBuildMacApp_twoAppsAndTwoExecutablesOneBuildableOneNot+        ]+    ]++testBuildMacApp_noInput :: Assertion+testBuildMacApp_noInput = do+    let actual = getMacAppsForBuildableExecutors [] []+    let expected = []+    assertEqual "nothing should be built" expected actual++testBuildMacApp_noExecutables :: Assertion+testBuildMacApp_noExecutables = do+    let apps = [MacApp "Dummy App" Nothing Nothing [] [] DoNotChase]+    let actual = getMacAppsForBuildableExecutors apps []+    let expected = []+    assertEqual "nothing should be built" expected actual++testBuildMacApp_twoBuildableExecutables :: Assertion+testBuildMacApp_twoBuildableExecutables = do+#if MIN_VERSION_Cabal(2,0,0)+    let execs = [ Executable "Dummy One" "/tmp" getExecutableScopeUnknown emptyBuildInfo+                  , Executable "Dummy Two" "/tmp" getExecutableScopeUnknown emptyBuildInfo ]+#else+    let execs = [ Executable "Dummy One" "/tmp" emptyBuildInfo+                  , Executable "Dummy Two" "/tmp" emptyBuildInfo ]+#endif+    let actual = getMacAppsForBuildableExecutors [] execs+    let expected = [ MacApp "Dummy One" Nothing Nothing [] [] DoNotChase+                     , MacApp "Dummy Two" Nothing Nothing [] [] DoNotChase ]+    assertEqual "two mac-apps should be built" expected actual++testBuildMacApp_twoExcetuablesOneBuildableAndOneNot :: Assertion+testBuildMacApp_twoExcetuablesOneBuildableAndOneNot = do+#if MIN_VERSION_Cabal(2,0,0)+    let execs = [ Executable "Dummy One" "/tmp" getExecutableScopeUnknown (emptyBuildInfo { buildable = False })+                  , Executable "Dummy Two" "/tmp" getExecutableScopeUnknown  emptyBuildInfo ]+#else+    let execs = [ Executable "Dummy One" "/tmp" (emptyBuildInfo { buildable = False })+                  , Executable "Dummy Two" "/tmp" emptyBuildInfo ]+#endif+    let actual = getMacAppsForBuildableExecutors [] execs+    let expected = [ MacApp "Dummy Two" Nothing Nothing [] [] DoNotChase ]+    assertEqual "two mac-apps should be built" expected actual++testBuildMacApp_twoAppsAndTwoExecutablesOneBuildableOneNot :: Assertion+testBuildMacApp_twoAppsAndTwoExecutablesOneBuildableOneNot = do+#if MIN_VERSION_Cabal(2,0,0)+    let execs = [ Executable "Dummy One" "/tmp" getExecutableScopeUnknown (emptyBuildInfo { buildable = False })+                  , Executable "Dummy Two" "/tmp" getExecutableScopeUnknown  emptyBuildInfo ]+#else+    let execs = [ Executable "Dummy One" "/tmp" (emptyBuildInfo { buildable = False })+                  , Executable "Dummy Two" "/tmp" emptyBuildInfo ]+#endif+    let apps = [ MacApp "Dummy One" Nothing Nothing [] [] DoNotChase+                 , MacApp "Dummy Two" Nothing Nothing [] [] DoNotChase ]+    let actual = getMacAppsForBuildableExecutors apps execs+    let expected = [ MacApp "Dummy Two" Nothing Nothing [] [] DoNotChase ]+    assertEqual "one mac-app should be built" expected actual
+ tests/Main.hs view
@@ -0,0 +1,9 @@+module Main (main) where++import Test.Framework (defaultMain)+import Distribution.MacOSX.Internal.Tests (macosxInternalTests)++main :: IO ()+main = defaultMain+  [ macosxInternalTests+  ]