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