Personal tools

Mac OS X Common Installation Paths

From HaskellWiki

(Difference between revisions)
Jump to: navigation, search
 
(Implementations)
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
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)
+
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:
----
 
   
I have been thinking about the location of installed Haskell package files on Mac OS X. The choice of location affects:
+
* Follows Apple's Guidelines for file system layout
* GHC & other Haskell implementations
+
* Makes it easy for a user to locate all the Haskell components, especially user installed packages
* Haskell Platform
+
* Enables easy removal of a user installed package, whether they have installed it <tt>--user</tt> or <tt>--global</tt>.
* Cabal & cabal-install
+
* Facilitate creation of unified, hyper-linked Haddock documentation, optionally with source
* 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
 
   
I noticed that the default location for global installation with cabal is on Mac OS X is /usr/local:
+
== Implementations ==
install-dirs global
 
-- prefix: /usr/local
 
   
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.
+
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
   
Taking a cue from the various preinstalled language systems on Mac OS X, up over in /Library might be a better place:
+
For example, GHC 7.0.2 is installed in:
  +
/Library/Frameworks/GHC.framework/Versions/7.0.2-i386
   
* Python puts installed packages in: <br /><tt>/Library/Python/''version''/site-packages</tt>
+
Executables intended for use from the command line, are be symlink'd into:
* Ruby puts installed packages in: <br /><tt>/Library/Ruby/Gems/''version''</tt><br /><tt>/Library/Ruby/Site/''version''</tt>
+
/usr/bin
* 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>
+
''[Q: Would <tt>/usr/local/bin</tt> be more appropriate? ]''
* Perl put installed packages in:<br /><tt>/Library/Perl/<version></tt>
 
   
I suggest that the default place for global installs on Mac OS X be:
+
Packages that come with the implementation, are be located within the Framework
* <tt>/Library/Haskell/</tt>
+
bundle.
   
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.
+
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 <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.
   
2) Structure of package pieces
+
If implementations want to be able to be installed "per user", then the above
  +
paths should be:
  +
~/Library/Frameworks
  +
~/bin
  +
~/Applications
   
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.
+
Not all software for Mac OS X offers a "per user" option on installation, and while
  +
nice, it is by no means universal.
   
cabal/cabal-install defaults the parts as follows:
+
== User Installed Packages ==
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...)
 
   
GHC/Haskell Platform use a different layout:
+
User installed packages are placed under a "prefix" that depends on if the user
executables: --prefix--/bin
+
choose to install for all users (<tt>--global</tt>) for just their own use (<tt>--user</tt>):
libraries: --prefix--/lib/--compiler--/--pkgid--
+
/Library/Haskell --global
data: --prefix--/share/--pkgid--
+
~/Library/Haskell --user
doc: --prefix--/share/doc/ghc/libraries/--pkgid--/
 
html: --prefix--/share/doc/ghc/libraries/--pkgid--/
 
   
I think it best if everything for a package is in one place - making removal very easy:
+
== Package Component Layout ==
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.
   
3) Symlinks for binaries
+
For both <tt>--global</tt> and <tt>--user</tt> installs, this is the recommended package layout on Mac OS X:
   
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:
+
{prefix}
symlink-global-bindir: /usr/local/bin
+
{compiler}
in .cabal/config.
+
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)
   
Or
+
This can be achieved with the following cabal configuration defaults:
symlink-global-bindir: /Library/Haskell/bin
+
install-dirs user
and then put that in their PATH
+
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 <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 ==
   
4) Quick access to the Framework
+
Packages that build executables to be run from the command line present a
  +
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
   
I like Java's convenience link 'Home', and suggest that
+
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:
/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/
 
   
Other implementations could use the same idea.
+
Alas, cabal only supports one location for both kinds of build, and so it is set to tbe the later.
   
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.
 
   
+
----
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.
+
== References ==
+
# [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]
[[User:MtnViewMark|MtnViewMark]] 05:44, 23 December 2009 (UTC)
+
# [http://www.haskell.org/pipermail/haskell-cafe/2009-December/071150.html MtnViewMark's original e-mail on this topic.]

Revision as of 11:20, 25 April 2012

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.


Contents

1 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.

2 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

3 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).

4 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 tbe the later.



5 References

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