cabal-macosx-0.1.0: Distribution/MacOSX/Common.hs
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