From Simon.Urbanek at math.uni-augsburg.de  Sun Nov 30 01:45:16 2003
From: Simon.Urbanek at math.uni-augsburg.de (Simon Urbanek)
Date: Sun Nov 30 01:43:59 2003
Subject: [Rd] R as OS X Framework
Message-ID: <76FE7CAA-22CE-11D8-9485-0003938AF008@math.uni-augsburg.de>

After the recent discussion about future direction of the Mac OS X 
port, I was toying with the idea to make R a proper Mac OS X framework. 
There are several advantages: OS X locates frameworks automatically, 
therefore any program wishing to link against R has only to specify 
"-framework R" at link time. Furthermore versioning is supported, i.e. 
if a program is linked against R 1.7.1 and you install 1.9.0 later, 
then the program will still get the correct 1.7.1 version (if we define 
the 1.9.0 not to be compatible with 1.7.1), but any new program will 
link against the most recent R. The granularity is up the framework 
creator.

It is possible to easily create a R Framework just with the current R 
as follows:

configure your favorite R (I'll use 1.8.1 for illustration) but use the 
following prefix:
--prefix=/Library/Frameworks/R.framework/Versions/1.8.1/Resources
you should also add --enable-R-shlib (if you want to use --enable-aqua, 
read on first!)

after make / make install run the following script as root (you may 
want to edit it if you didin't use 1.8.1 or if you want to install an 
user-private framework):

http://stats.math.uni-augsburg.de/misc/Rframework.sh

This will create a proper framework from what the R installer created - 
and you're all set! You can use such framework for any program - just 
like Apple's system frameworks. It's really great what you can do with 
Xcode then (code completion of R stuff, zero-linking etc ;)). For a 
screenshot of Xcode using R framework, see:
http://stats.math.uni-augsburg.de/misc/Rframework.png

You can even make a symlink from 
/Library/Frameworks/R.framework/Resources/bin/R to /usr/binR and you 
will have the most recent R always at your fingertips.

The nice thing is that you can use ~/Library/Frameworks instead of the 
above /Library/Frameworks if you want. There is no difference from 
system's point of view. You could event supply the R framework inside 
you application's bundle, but I guess that'd be an overkill ;)

Now for some issues that need to be solved:

The current R needs R_HOME to be set before using it even in its 
embedded form. Now this defeats the idea of location independence of 
the framework. The application doesn't have to care whether the 
framework is in /Library/Frameworks, ~/Library/Frameworks or any 
user-defined framework location. Therefore it would be nice to have a 
tiny function in the R shlib, that would tell me where the shlib lives 
(either by using system's API to determine its own location, or at 
least the path used on installation).

BTW: This is not Mac specific - I was fighting this on Windows (and 
unix for that matter) as well - it is possible to run an .exe linked to 
R.dll from anywhere, if R.dll is in the PATH. But then, one has to 
determine R_HOME somehow (yes, there is the registry, but that's not 
really safe if more R versions are installed).

The second issue is a rather minor one which will be solved if RAqua 
uses the framework. If you used --enable-aqua then configure overrides 
the dylib location, which is bad for our framework:
configure.ac @ 1050:
    if test "x${want_aqua}" = xyes; then
       LIBR_LDFLAGS="-dynamiclib -install_name 
/Applications/StartR.app/RAqua.app/Contents/Frameworks/libR.dylib"
     else
       LIBR_LDFLAGS="-dynamiclib -install_name 
\$(Rexeclibdir)/libR.dylib"
     fi
You'll need to remove the aqua part of it, otherwise the libR.dylib is 
not expected inside the framework.

Finally, in order to take advantage of the versioning, we should add 
version information to the dylib. This can be done by adding  
-dylib_compatibility_version and  -dylib_current_version to the 
LIBR_LDFLAGS (e.g. for R-1.8.1 probably 1.8.0 to compatibility and 
1.8.1 to current).

BTW: A side note - if the host application runs a proper event loop 
(like my Rgui runs the standard Cocoa event loop) then the Quartz 
device works flawlessly even without RAqua! Good job, Stefano!

There is still room for improvement - I started this more as a proof of 
concept and was surprised how smoothly it went. Someone interested 
might look into issues like using Tcl/Tk, placing libraries 
conveniently (in ~/Library/Application Support/R/library ?) etc.

---
Simon Urbanek
Department of computer oriented statistics and data analysis
Universit?tsstr. 14
86135 Augsburg
Germany

Tel: +49-821-598-2236
Fax: +49-821-598-2280

Simon.Urbanek@Math.Uni-Augsburg.de
http://simon.urbanek.info


[Rd] R as OS X Framework
Simon Urbanek