Difference between revisions of "Mac OS X Common Installation Paths"

From HaskellWiki
Jump to navigation Jump to search
 
 
(5 intermediate revisions by 3 users not shown)
Line 1: Line 1:
  +
The default layout for installed Haskell components follows the conventions of most unix-like systems. On Mac OS X, this layout isn't optimal, and a different layout is used. The layout presented here has several advantages:
The following is my initial e-mail to haskell-cafe about installation paths Mac OS X. I'll clean this up from an e-mail to a proposal soon. [[User:MtnViewMark|MtnViewMark]] 05:44, 23 December 2009 (UTC)
 
----
 
   
  +
* Follows Apple's Guidelines for file system layout
I have been thinking about the location of installed Haskell package files on Mac OS X. The choice of location affects:
 
  +
* Makes it easy for a user to locate all the Haskell components, especially user installed packages
* GHC & other Haskell implementations
 
  +
* Enables easy removal of a user installed package, whether they have installed it <tt>--user</tt> or <tt>--global</tt>.
* Haskell Platform
 
  +
* Facilitate creation of unified, hyper-linked Haddock documentation, optionally with source
* Cabal & cabal-install
 
* Haddock
 
If all those agreed on directory locations and layouts, I think the state of Haskell on Mac OS X would be nicer for users. In particular, my hope is for users to end up with an automatically complete Haddock documentation incorporating everything they install.
 
   
  +
Haskell Platform 2011.2.0.0 (March 2011) and later uses this layout and sets up cabal to use it for built packages. On new installs, if you didn't already have a <tt>~/.cabal/config</tt> file, then it is set up by default. Otherwise, the config file for this layout is placed in <tt>~/.cabal/config.platform</tt> and you can manually move it over, or incorporate it into your existing <tt>config</tt> file.
   
1) Packages the user installs --global
 
   
  +
== Implementations ==
I noticed that the default location for global installation with cabal is on Mac OS X is /usr/local:
 
install-dirs global
 
-- prefix: /usr/local
 
   
  +
Haskell implementations are generally installed for use by all accounts on the
This then intermingles all the Haskell package files along with all sorts of other things that live in /usr/local and environs. While this is arguably convenient for executables that end up in /usr/local/bin (in most people's PATH), it does make things less than tidy, and harder to clean up.
 
  +
system. They consist of large collections of executables, libraries, and other
  +
files. These are packaged using Apple's framework, versioning, and bundling
  +
techniques and installed in:
  +
/Library/Frameworks
   
  +
For example, GHC 7.0.2 is installed in:
Taking a cue from the various preinstalled language systems on Mac OS X, up over in /Library might be a better place:
 
  +
/Library/Frameworks/GHC.framework/Versions/7.0.2-i386
   
  +
Executables intended for use from the command line, are be symlink'd into:
* Python puts installed packages in: <br /><tt>/Library/Python/''version''/site-packages</tt>
 
  +
/usr/bin
* Ruby puts installed packages in: <br /><tt>/Library/Ruby/Gems/''version''</tt><br /><tt>/Library/Ruby/Site/''version''</tt>
 
  +
''[Q: Would <tt>/usr/local/bin</tt> be more appropriate? ]''
* Java appears to use <br /><tt>/Library/Java/Extensions</tt><br />and has a link to the packages that come the framework as:<br /><tt>/Library/Java/Home</tt>
 
* Perl put installed packages in:<br /><tt>/Library/Perl/<version></tt>
 
   
  +
Packages that come with the implementation, are be located within the Framework
I suggest that the default place for global installs on Mac OS X be:
 
  +
bundle.
* <tt>/Library/Haskell/</tt>
 
   
  +
If the implementation has any GUI applications, these are installed in:
Since cabal already by default interposes the compiler version into the lib dir, path, there doesn't appear to be a need to put a <version> dir level near the top.
 
  +
/Applications
   
  +
'''NB:''' These guidelines allow for multiple implementations and multiple
  +
versions to co-exist. (With the exception of multiple versions of GUI applications
  +
which can only be done by distinct naming, and the symlinks in <tt>/usr/bin</tt>
  +
which can achieved in the normal way: Append the version number to the executable
  +
and then symlink the 'bare' name to the most recent.
   
  +
If implementations want to be able to be installed "per user", then the above
2) Structure of package pieces
 
  +
paths should be:
  +
~/Library/Frameworks
  +
~/bin
  +
~/Applications
   
  +
Not all software for Mac OS X offers a "per user" option on installation, and while
I notice that cabal/cabal-install's default layout of where a package's pieces go, and GHC's layout of its base packages don't agree. Further, cabal/cabal-install's are not set up so that one can easily delete an installed package without hunting down its parts.
 
  +
nice, it is by no means universal.
   
  +
== User Installed Packages ==
cabal/cabal-install defaults the parts as follows:
 
executables: --prefix--/bin
 
libraries: --prefix--/lib/--pkgid--/--compiler--
 
data: --prefix--/share/--pkgid--
 
doc: --prefix--/share/doc/--pkgid--/
 
html: --prefix--/share/doc/--pkgid--/html
 
That's at least four directories you need to hunt down if you want to clean out a package, and rummaging through bin to figure out which things to remove. (Not to mention libexec, which isn't used by any packages on my system, so I can't say where it goes...)
 
   
  +
User installed packages are placed under a "prefix" that depends on if the user
GHC/Haskell Platform use a different layout:
 
  +
choose to install for all users (<tt>--global</tt>) for just their own use (<tt>--user</tt>):
executables: --prefix--/bin
 
  +
/Library/Haskell --global
libraries: --prefix--/lib/--compiler--/--pkgid--
 
  +
~/Library/Haskell --user
data: --prefix--/share/--pkgid--
 
doc: --prefix--/share/doc/ghc/libraries/--pkgid--/
 
html: --prefix--/share/doc/ghc/libraries/--pkgid--/
 
   
  +
== Package Component Layout ==
I think it best if everything for a package is in one place - making removal very easy:
 
executables: --prefix--/packages/--pkgid--/bin
 
libraries: --prefix--/packages/--pkgid--/lib/--compiler--
 
data: --prefix--/packages/--pkgid--/share
 
doc: --prefix--/packages/--pkgid--/doc
 
html: --prefix--/packages/--pkgid--/doc
 
I put the "packages" level at the top, so that other things, like a master Haddock index dir could be put easily directly under the prefix.
 
   
  +
Cabal offers a large amount of flexibility in where the various pieces of a package
  +
are installed. The GHC package system is rather agnostic about where these pieces are,
  +
and insulates the implementation from such differences. These combine to enable the
  +
choice of package layout to be largely to serve the user.
   
  +
For both <tt>--global</tt> and <tt>--user</tt> installs, this is the recommended package layout on Mac OS X:
3) Symlinks for binaries
 
   
  +
{prefix}
This does suggest that it would be nice for the symlink-bindir facility (is that in cabal itself, or added by cabal-install?) to have a version for --global installs. Users could then either set something like:
 
  +
{compiler}
symlink-global-bindir: /usr/local/bin
 
  +
lib
in .cabal/config.
 
  +
{pkgid}
  +
bin -- binaries ($bindir)
  +
lib -- libraries & .hi files ($libdir, $libdir/$libsubdir, $dynlibdir)
  +
include -- include files ($includedir)
  +
libexec -- private binaries ($libexecdir)
  +
share -- data files ($datadir, $datadir/$datasubdir)
  +
doc -- documentation ($docdir)
  +
html -- html doc ($htmldir, $haddockdir)
  +
man -- man pages ($mandir)
   
  +
This can be achieved with the following cabal configuration defaults:
Or
 
  +
install-dirs user
symlink-global-bindir: /Library/Haskell/bin
 
  +
prefix: ~/Library/Haskell/$compiler/lib/$pkgid
and then put that in their PATH
 
  +
bindir: $prefix/bin
  +
libdir: $prefix/lib
  +
libsubdir:
  +
libexecdir: $prefix/libexec
  +
datadir: $prefix/share
  +
datasubdir:
  +
docdir: $datadir/doc
  +
htmldir: $docdir/html
  +
haddockdir: $htmldir
  +
  +
install-dirs global
  +
prefix: /Library/Haskell/$compiler/lib/$pkgid
  +
bindir: $prefix/bin
  +
libdir: $prefix/lib
  +
libsubdir:
  +
libexecdir: $prefix/libexec
  +
datadir: $prefix/share
  +
datasubdir:
  +
docdir: $datadir/doc
  +
htmldir: $docdir/html
  +
haddockdir: $htmldir
  +
  +
'''N.B.:'''
  +
* Cabal configuration files don't actually support <tt>~</tt>. You must replace that with <tt>/Users/xxx</tt> where <tt>xxx</tt> is your account name.
  +
* All packages for a given compiler are under a single directory. When an old compiler is removed, all the packages compiled for it can be easily removed too.
  +
* All components for a package are under a single directory. This facilitates easy location and removal of a single package, for either a single compiler, or all installed versions.
  +
* If a package generates different doc for different compilers (it may have different APIs available), then this structure preserves each.
  +
* Executables are also per compilation, which is sometimes important (for Haddock, for example).
   
  +
== Executables ==
   
  +
Packages that build executables to be run from the command line present a
4) Quick access to the Framework
 
  +
difficultly. They are built into a per-package <tt>bin</tt> directory, and then should be symlink'd somewhere on the user's PATH. For global installs, the logical place is one of:
  +
/usr/bin
  +
/usr/local/bin
   
  +
For user installs, since <tt>~/bin</tt> is not on the <tt>PATH</tt> by default on Mac OS X and may not exist, binaries are symlink'd into:
I like Java's convenience link 'Home', and suggest that
 
/Library/Haskell/GHC
+
~/Library/Haskell/bin
be a symlink to where the framework's package files are stored:
 
/Library/Frameworks/GHC.framework/Versions/Current/usr/
 
   
  +
Alas, cabal only supports one location for both kinds of build, and so it is set to be the later.
Other implementations could use the same idea.
 
   
Having this here would also (I suspect) help in getting Haddock to be able to find all the bits needed to generate a comprehensive index.
 
   
  +
----
   
  +
== References ==
Thoughts? I'd be happy to help by supplying patches for various tools to normalize all this on some agreed upon layout. I admit that I'm a bit unclear where the directory choices are being made: Haskell Platform's build process, or GHC's? Cabal's defaults or cabal-install's? And then clearly parts of Haddock. Given the number of tools that need to agree, seems best that we hash it out (here or in the wiki) first, before making patches.
 
  +
# [http://developer.apple.com/mac/library/documentation/MacOSX/Conceptual/BPFileSystem/Articles/LibraryDirectory.html#//apple_ref/doc/uid/20002282-BAJHCHJI Apple guidelines for the /Library and ~/Library files]
 
  +
# [http://www.haskell.org/pipermail/haskell-cafe/2009-December/071150.html MtnViewMark's original e-mail on this topic.]
[[User:MtnViewMark|MtnViewMark]] 05:44, 23 December 2009 (UTC)
 

Latest revision as of 05:34, 6 August 2014

The default layout for installed Haskell components follows the conventions of most unix-like systems. On Mac OS X, this layout isn't optimal, and a different layout is used. The layout presented here has several advantages:

  • Follows Apple's Guidelines for file system layout
  • Makes it easy for a user to locate all the Haskell components, especially user installed packages
  • Enables easy removal of a user installed package, whether they have installed it --user or --global.
  • Facilitate creation of unified, hyper-linked Haddock documentation, optionally with source

Haskell Platform 2011.2.0.0 (March 2011) and later uses this layout and sets up cabal to use it for built packages. On new installs, if you didn't already have a ~/.cabal/config file, then it is set up by default. Otherwise, the config file for this layout is placed in ~/.cabal/config.platform and you can manually move it over, or incorporate it into your existing config file.


Implementations

Haskell implementations are generally installed for use by all accounts on the system. They consist of large collections of executables, libraries, and other files. These are packaged using Apple's framework, versioning, and bundling techniques and installed in:

 /Library/Frameworks

For example, GHC 7.0.2 is installed in:

 /Library/Frameworks/GHC.framework/Versions/7.0.2-i386

Executables intended for use from the command line, are be symlink'd into:

 /usr/bin

[Q: Would /usr/local/bin be more appropriate? ]

Packages that come with the implementation, are be located within the Framework bundle.

If the implementation has any GUI applications, these are installed in:

 /Applications

NB: These guidelines allow for multiple implementations and multiple versions to co-exist. (With the exception of multiple versions of GUI applications which can only be done by distinct naming, and the symlinks in /usr/bin which can achieved in the normal way: Append the version number to the executable and then symlink the 'bare' name to the most recent.

If implementations want to be able to be installed "per user", then the above paths should be:

 ~/Library/Frameworks
 ~/bin
 ~/Applications

Not all software for Mac OS X offers a "per user" option on installation, and while nice, it is by no means universal.

User Installed Packages

User installed packages are placed under a "prefix" that depends on if the user choose to install for all users (--global) for just their own use (--user):

 /Library/Haskell  --global
 ~/Library/Haskell --user

Package Component Layout

Cabal offers a large amount of flexibility in where the various pieces of a package are installed. The GHC package system is rather agnostic about where these pieces are, and insulates the implementation from such differences. These combine to enable the choice of package layout to be largely to serve the user.

For both --global and --user installs, this is the recommended package layout on Mac OS X:

{prefix}
  {compiler}
    lib
      {pkgid}
        bin         -- binaries ($bindir)
        lib         -- libraries & .hi files ($libdir, $libdir/$libsubdir, $dynlibdir)
          include   -- include files ($includedir)
        libexec     -- private binaries ($libexecdir)
        share       -- data files ($datadir, $datadir/$datasubdir)    
        doc         -- documentation ($docdir)
          html      -- html doc ($htmldir, $haddockdir)
          man       -- man pages ($mandir)

This can be achieved with the following cabal configuration defaults:

 install-dirs user
   prefix:     ~/Library/Haskell/$compiler/lib/$pkgid
   bindir:     $prefix/bin
   libdir:     $prefix/lib
   libsubdir:  
   libexecdir: $prefix/libexec
   datadir:    $prefix/share
   datasubdir:
   docdir:     $datadir/doc
   htmldir:    $docdir/html
   haddockdir: $htmldir
 
 install-dirs global
   prefix:     /Library/Haskell/$compiler/lib/$pkgid
   bindir:     $prefix/bin
   libdir:     $prefix/lib
   libsubdir:  
   libexecdir: $prefix/libexec
   datadir:    $prefix/share
   datasubdir:
   docdir:     $datadir/doc
   htmldir:    $docdir/html
   haddockdir: $htmldir
 

N.B.:

  • Cabal configuration files don't actually support ~. You must replace that with /Users/xxx where xxx is your account name.
  • All packages for a given compiler are under a single directory. When an old compiler is removed, all the packages compiled for it can be easily removed too.
  • All components for a package are under a single directory. This facilitates easy location and removal of a single package, for either a single compiler, or all installed versions.
  • If a package generates different doc for different compilers (it may have different APIs available), then this structure preserves each.
  • Executables are also per compilation, which is sometimes important (for Haddock, for example).

Executables

Packages that build executables to be run from the command line present a difficultly. They are built into a per-package bin directory, and then should be symlink'd somewhere on the user's PATH. For global installs, the logical place is one of:

/usr/bin
/usr/local/bin

For user installs, since ~/bin is not on the PATH by default on Mac OS X and may not exist, binaries are symlink'd into:

~/Library/Haskell/bin

Alas, cabal only supports one location for both kinds of build, and so it is set to be the later.



References

  1. Apple guidelines for the /Library and ~/Library files
  2. MtnViewMark's original e-mail on this topic.