MacOS – How to install framework (from pkg file) in a non-standard location

installmacospkgpython

In brief, my question is this:

How can I install a framework from a *.pkg file somewhere other than under /Library/Frameworks (or /System/Library/Frameworks)?


Background

I want to install a version of Python 2.7.3 that lives under $HOME/Library/Frameworks/Python.framework and $HOME/python.

My goal here is to have a version of Python that is as independent as possible from the Python that comes with OS X Lion. In particular, I want to have an installation of Python that is, as much as possible, not liable to be altered "behind-my-back" by system updates or other software updates. That's why I want to keep this installation as clear as possible away from the "standard" places for them.

Among the problems I am trying to avoid by doing this is the buggy Tk framework that comes with the latest versions of OS X.

Therefore, a key sub-goal here is to install new Tcl and Tk frameworks, separate from the system-supplied ones. The ones I want to install come from ActiveState ("Mac OS X (10.5+, x86_64/x86)"), in the form of a *.pkg file.

When I click on this file, I get presented with the usual "wizard"-like sequence of steps ("Introduction", "License", etc.). At no point during this sequence I am offered the opportunity to choose a different installation location for these frameworks before I reach the choice of clicking on the INSTALL button.1

I suspect that if I click on this button, the installed files will go under /Library/Frameworks (or possibly under /System/Library/Frameworks), which is what I'm trying to avoid. (Indeed, when I click on INSTALL, I'm immediately presented with an password-entry dialog, which is a pretty good indication that the installation will put files somewhere under /Library or /System.)

Therefore I'm looking for an alternative way to perform this installation that will allow me to explicitly set the destination folder for the installed files.

1Yes, the installer allows me choose a different volume for the installation, but it does not let me specify, e.g., $HOME/Library/Frameworks as the destination for the installed files.

Best Answer

Generally speaking, you can only relocate a package (that is, install it into a different directory) that has been built with relocation in mind.

If the package supports it, it can be relocated with the command line equivalent of Installer.app, conveniently called installer, with option -target (from man installer):

The target volume is specified with the -target parameter (-tgt is accepted as a synonym).

The argument to -target is:

  1. A volume mount point (/Volumes/HDD), device node (/dev/disk0s5) or volume UUID (376C4046-083E-334F-AF08-62FAFBC4E352), for example:

    installer -pkg InstallMe.pkg -target / 
    
  2. Any of the values returned by -dominfo (LocalSystem or CurrentUserHomeDirectory), for example:

    installer -pkg InstallMe.pkg -target CurrentUserHomeDirectory
    

(As you see, the latter command looks very promising. It would install InstallMe.pkg in the hierarchy of the home directory of the current user.)

In our specific case, unfortunately, ActiveState's Tcl package wasn't designed to be relocated:

  • It doesn't return any information for -dominfo:

    $ installer -verbose -dominfo -pkg ActiveTcl-8.6.pkg
    Domain information:
    NoDomainsAvailable
    
  • Although the pkg file can be successfully installed on another volume:

    $ sudo installer -verbose -pkg ActiveTcl-8.6.pkg -target /Volumes/DISK2GO/
    installer: Package name is ActiveState ActiveTcl 8.6.0.0.296563
    installer: Installing at base path /Volumes/DISK2GO
    (...)   
    #
    installer: Writing files….....
    (...)
    installer: The software was successfully installed......
    installer: The install was successful.
    #
    

    as can be seen here:

    enter image description here

    it doesn't work:

    $ cd /Volumes/DISK2GO/usr/local/bin/
    $ ./tclsh8.6
    dyld: Library not loaded:
    /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl
      Referenced from: /Volumes/DISK2GO/usr/local/bin/./tclsh8.6
      Reason: image not found
    Trace/BPT trap: 5
    $  ./tclselect 
    -bash: ./tclselect: /usr/local/bin/tclsh: bad interpreter: No such file or directory
    

The reason is that scripts and compiled tools use and are linked to /Library/Frameworks:

$ cd /Volumes/DISK2GO/usr/local/bin/
$ otool -L tclsh8.6 
 tclsh8.6:
 /Library/Frameworks/Tcl.framework/Versions/8.6/Tcl (compatibility version 8.6.0, current version 8.6.0)
(...)
$ grep Library tclselect 
#  /Library/Frameworks
# installation. I.e. a Tcl installed in '/Library/Frameworks' and
return /Library/Frameworks/Tcl.framework/Versions

If you wish to use ActiveState's Tcl you must install the package in its default location.

And as far as I can tell, it won't conflict with the installed Tcl framework:

  • OS X own framework is installed in /System/Library/Frameworks/Tk.framework/, some binaries in /usr/bin.

  • ActiveState's Tcl installs in /Library/Frameworks/Tcl.framework, /Library/Frameworks/Tk.framework, /Library/Tcl and /usr/local/bin (for a full listing, double click the pkg file and select File>ShowFiles).