From c4e5943a870630b960f3f7185d6dd9016f53b58d Mon Sep 17 00:00:00 2001 From: Atze Dijkstra Date: Fri, 5 Oct 2012 17:39:54 +0200 Subject: [PATCH] prep for 0.1 hackage release --- LICENSE | 1 + README.md | 35 ++++++++++++++++++++++++++- Setup.hs | 2 ++ macosx-make-standalone.cabal | 9 +++++-- src/Cmds.hs | 46 +++++++++++++++++++++++++++++------- src/MakeStandalone.hs | 40 ++++++++++++++++++------------- src/Opts.hs | 8 +++++++ src/Plan.hs | 34 ++++++++++++++------------ 8 files changed, 133 insertions(+), 42 deletions(-) create mode 100644 LICENSE create mode 100644 Setup.hs diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..6549e89 --- /dev/null +++ b/LICENSE @@ -0,0 +1 @@ +BSD3 diff --git a/README.md b/README.md index 9fb1722..e64f36a 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,37 @@ macosx-make-standalone ====================== -Modify a MacOSX app bundle to include non standard .dylibs, so it can be run without development environment \ No newline at end of file +Modify a MacOSX app bundle to include non standard .dylibs, so it can be run without development environment + + +Installation +============ + +- Requires Haskell (7.4.1 onwards) +- Installs via hackage or from this source repo via cabal + - Hackage: + cabal install macosx-make-standalone + - From repo: + cabal configure + cabal build + cabal install + + +Manual +====== + +Invocation: + macosx-make-standalone + +What is does, restrictions: +- Copies all non /usr/lib .dylib files into /Contents/lib/ +- Changes all references to the old library into refs to the copied libraries, in the /Contents/MacOS/ as well as the copied libraries +- Resolves symbolic links of referenced libraries (thus not for ) +- In case of duplicate libraries ending up with the same copy name, an arbitrary one is picked (no problem if they are equal) +- Can only be run once, i.e. is not idempotent + + +Tested with +=========== + +A single wxHaskell based application, on MacOSX 10.8 diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/macosx-make-standalone.cabal b/macosx-make-standalone.cabal index 191cb78..1fb6335 100644 --- a/macosx-make-standalone.cabal +++ b/macosx-make-standalone.cabal @@ -3,14 +3,19 @@ Version: 0.1 Synopsis: Make a macosx app standalone deployable Description: Make a macosx app standalone by bundling all dylibs into it. License: BSD3 +license-file: LICENSE Author: Atze Dijkstra Maintainer: atze@uu.nl -Homepage: https://github.com/atzedijkstra -Bug-Reports: https://github.com/atzedijkstra/issues +Homepage: https://github.com/atzedijkstra/macosx-make-standalone +Bug-Reports: https://github.com/atzedijkstra/macosx-make-standalone/issues Copyright: 2012 Utrecht University Category: Development Build-type: Simple Cabal-version: >=1.6 +source-repository head + type: git + location: git://github.com/atzedijkstra/macosx-make-standalone.git + Executable macosx-make-standalone HS-Source-Dirs: src diff --git a/src/Cmds.hs b/src/Cmds.hs index 23c7884..25203a1 100644 --- a/src/Cmds.hs +++ b/src/Cmds.hs @@ -7,6 +7,9 @@ module Cmds , cmdOTool , cmdCP , cmdChmod + , cmdMkdir + , cmdInstallNameToolId + , cmdInstallNameToolChange ) where ------------------------------------------------------------------------- @@ -51,15 +54,22 @@ showCmdSpec (RawCommand f as) = concat $ intersperse " " (f:as) cmdRunPlain :: Opts -> CreateProcess -> IO () cmdRunPlain opts p = do when (opts ^. optVerbose) (putStrLn (showCmdSpec $ cmdspec p)) - createProcess p + (_, _, _, phandle) <-createProcess p + waitForProcess phandle return () cmdRunOutputPipe :: Opts -> CreateProcess -> IO Handle cmdRunOutputPipe opts p = do when (opts ^. optVerbose) (putStrLn (showCmdSpec $ cmdspec p)) - (_, Just hout, _, _) <- createProcess (p {std_out = CreatePipe}) + (_, Just hout, _, phandle) <- createProcess (p {std_out = CreatePipe}) + waitForProcess phandle return hout +cmdRun :: String -> String -> [FilePath] -> StRun () +cmdRun c m fs = do + opts <- access opts + liftIO $ cmdRunPlain opts $ proc c (m : fs) + ------------------------------------------------------------------------- -- otool ------------------------------------------------------------------------- @@ -98,15 +108,35 @@ cmdOTool f = do ------------------------------------------------------------------------- cmdCP :: String -> FilePath -> FilePath -> StRun () -cmdCP o fFr fTo = do - opts <- access opts - liftIO $ cmdRunPlain opts $ proc "cp" [o, fFr, fTo] +cmdCP o fFr fTo = cmdRun "cp" o [fFr, fTo] ------------------------------------------------------------------------- -- chmod ------------------------------------------------------------------------- cmdChmod :: String -> FilePath -> StRun () -cmdChmod m f = do - opts <- access opts - liftIO $ cmdRunPlain opts $ proc "chmod" [m, f] +cmdChmod o f = cmdRun "chmod" o [f] + +------------------------------------------------------------------------- +-- mkdir +------------------------------------------------------------------------- + +cmdMkdir :: String -> FilePath -> StRun () +cmdMkdir o f = cmdRun "mkdir" o [f] + +------------------------------------------------------------------------- +-- install_name_tool +------------------------------------------------------------------------- + +cmdInstallNameToolChange :: FilePath -> FilePath -> FilePath -> StRun () +cmdInstallNameToolChange fIn fFr fTo = cmdRun "install_name_tool" "-change" [fFr, fTo, fIn] + +cmdInstallNameToolId :: FilePath -> FilePath -> StRun () +cmdInstallNameToolId fIn fTo = cmdRun "install_name_tool" "-id" [fTo, fIn] + +{- + install_name_tool -id @executable_path/../libs/libwx_osx_cocoau_xrc-2.9.4.0.0.dylib ./Dazzle.app/Contents/libs/libwx_osx_cocoau_xrc-2.9.4.0.0.dylib + +* Fixing dependencies on ./Dazzle.app/Contents/libs/libwx_osx_cocoau_xrc-2.9.4.0.0.dylib + install_name_tool -change /Volumes/Work/.cabal/lib/wxc-0.90.0.4/ghc-7.4.1/libwxc.dylib @executable_path/../libs/libwxc.dylib ./Dazzle.app/Contents/libs/libwx_osx_cocoau_xrc-2.9.4.0.0.dylib +-} diff --git a/src/MakeStandalone.hs b/src/MakeStandalone.hs index 1ea1ab0..e74cdb6 100644 --- a/src/MakeStandalone.hs +++ b/src/MakeStandalone.hs @@ -66,9 +66,10 @@ doIt opts fnmApp = do fnm = fpathOfExec opts fnmApp thework = do ldep <- otoolGraphVisit2LibDepGraph fnm - when (opts ^. optVerbose) (liftIO $ putStrLn (show ldep)) - let plan = ldepGraph2Plan opts fnmApp ldep - when (opts ^. optVerbose) (liftIO $ forM_ (seqToList plan) (putStrLn . show)) + when (opts ^. optDebug) (liftIO $ putStrLn (show ldep)) + let plan = seqToList $ ldepGraph2Plan opts fnmApp ldep + when (opts ^. optDebug) (liftIO $ forM_ plan (putStrLn . show)) + forM_ plan planCmdExec return () -- f <- srFreshTmpName -- liftIO $ putStrLn f @@ -117,23 +118,30 @@ ldepGraph2Plan opts fnmApp ldep = [ PlanCmd_CP o n | (n,((o:_),_)) <- Map.toList filesToCopy ] Seq.>< foldr (Seq.><) Seq.empty - [ Seq.fromList $ - PlanCmd_IntlRename n o ri - : [ PlanCmd_ModfRef n u rr - | u <- maybe [] (^. libUses) $ Map.lookup o $ ldep ^. ldepGraph - , let u2 = ldepResolveSymlink ldep u - rr = Map.findWithDefault u2 u2 filesToCopyRev - ] + [ Seq.fromList $ PlanCmd_IntlRename n ri : mkModfRef filesToCopy n o | (n,((o:_),ri)) <- Map.toList filesToCopy ] + Seq.>< + foldr (Seq.><) Seq.empty + [ Seq.fromList $ mkModfRef filesToCopy o o + | (_,((o:_),_)) <- Map.toList filesRoot + ] where - filesToCopy = Map.fromListWith (\(l1,r1) (l2,_) -> (l1++l2,r1)) - [ (n, ([l'],r)) - | l <- Set.toList $ Set.delete (ldep ^. ldepRoot) $ Map.keysSet $ ldep ^. ldepGraph - , let l' = l -- ldepResolveSymlink ldep l - (n,r) = fpathOfNewLib opts fnmApp l' + filesToCopy = mkFilesToCopyMp (Set.delete (ldep ^. ldepRoot) $ Map.keysSet $ ldep ^. ldepGraph) + filesRoot = Map.fromList [ (o,([o],o)) | o <- [ldep ^. ldepRoot] ] + mkFilesToCopyMp fs = Map.fromListWith (\(l1,r1) (l2,_) -> (l1++l2,r1)) + [ (n, ([l],r)) + | l <- Set.toList fs + , let (n,r) = fpathOfNewLib opts fnmApp l + ] + mkFilesToCopyMpRev fMp = Map.fromList [ (o,r) | (n,(os,r)) <- Map.toList fMp, o <- os ] + mkModfRef fMp n o = + [ PlanCmd_ModfRef n u rr + | u <- maybe [] (^. libUses) $ Map.lookup o $ ldep ^. ldepGraph + , let u2 = ldepResolveSymlink ldep u + rr = Map.findWithDefault u2 u2 fMpRev ] - filesToCopyRev = Map.fromList [ (o,r) | (n,(os,r)) <- Map.toList filesToCopy, o <- os ] + where fMpRev = mkFilesToCopyMpRev fMp ------------------------------------------------------------------------- -- File name manipulation diff --git a/src/Opts.hs b/src/Opts.hs index a0190ed..1788c4a 100644 --- a/src/Opts.hs +++ b/src/Opts.hs @@ -5,6 +5,7 @@ module Opts , optImmediateCommands , optVerbose + , optDebug , optProgName , optExcludePrefixes , optIncludeExtensions @@ -21,6 +22,9 @@ module Opts -- Imports ------------------------------------------------------------------------- +import Prelude hiding ((.)) +import Control.Category + import Data.Lens.Common import Data.Lens.Template import Data.Typeable @@ -43,6 +47,7 @@ data ImmediateCommand data Opts = Opts { _optVerbose :: Bool -- ^ be verbose + , _optDebug :: Bool -- ^ dump debug info , _optImmediateCommands :: [ImmediateCommand] -- ^ e.g. help , _optProgName :: String -- ^ the name of this program , _optExcludePrefixes :: [FilePath] -- ^ prefixes of locations which may not be copied @@ -60,6 +65,7 @@ makeLens ''Opts defaultOpts = Opts { _optVerbose = False + , _optDebug = False , _optImmediateCommands = [] , _optProgName = "??" , _optExcludePrefixes = [ "/usr/lib" @@ -81,5 +87,7 @@ cmdLineOpts "output this help" , Option "v" ["verbose"] (NoArg $ optVerbose ^= True) "be verbose" + , Option "d" ["debug"] (NoArg $ (optVerbose ^= True) . (optDebug ^= True)) + "dump debug info" ] diff --git a/src/Plan.hs b/src/Plan.hs index 56957a8..136586e 100644 --- a/src/Plan.hs +++ b/src/Plan.hs @@ -31,7 +31,7 @@ import Data.Typeable -- import System.Environment -- import System.IO -- import System.Exit --- import System.FilePath +import System.FilePath -- import System.Directory -- import System.Cmd -- import System.Process @@ -46,19 +46,18 @@ import Cmds ------------------------------------------------------------------------- data PlanCmd - = PlanCmd_CP -- ^ Copy file - { _pcFrom :: FilePath - , _pcTo :: FilePath + = PlanCmd_CP -- ^ Copy file + { _pcFrom :: FilePath + , _pcTo :: FilePath } - | PlanCmd_ModfRef -- ^ Modify ref in file - { _pcInFile :: FilePath - , _pcFrom :: FilePath - , _pcTo :: FilePath + | PlanCmd_ModfRef -- ^ Modify ref in file + { _pcInFile :: FilePath + , _pcFrom :: FilePath + , _pcTo :: FilePath } - | PlanCmd_IntlRename -- ^ Modify internal name in file - { _pcInFile :: FilePath - , _pcFrom :: FilePath - , _pcTo :: FilePath + | PlanCmd_IntlRename -- ^ Modify internal name in file + { _pcInFile :: FilePath + , _pcTo :: FilePath } deriving (Show,Typeable) @@ -72,9 +71,14 @@ type Plan = Seq PlanCmd planCmdExec :: PlanCmd -> StRun () planCmdExec pcmd = case pcmd of - PlanCmd_CP fFr fTo -> do cmdCP "-f" fFr fTo - cmdChmod "+w" fTo - _ -> return () + PlanCmd_CP fFr fTo -> do + cmdMkdir "-p" $ takeDirectory fTo + cmdCP "-f" fFr fTo + cmdChmod "+w" fTo + PlanCmd_ModfRef fIn fFr fTo -> do + cmdInstallNameToolChange fIn fFr fTo + PlanCmd_IntlRename fIn fTo -> do + cmdInstallNameToolId fIn fTo ------------------------------------------------------------------------- -- Seq extension