[R-SIG-Mac] Compiling a portable binary that includes Fortran code

Simon Urbanek simon.urbanek at r-project.org
Tue Sep 20 15:34:53 CEST 2011


Michael,

On Sep 19, 2011, at 11:06 PM, Michael Braun wrote:

> Simon:
> 
> Thanks for your response.  Either I was not clear in my question, or I am misunderstanding your answer.
> 

I think the latter - I was addressing how to create package binaries that you can distribute.


> The problem is not the version or location of the gfortran runtimes on my machine.  I can compile and run the package myself with a simple R CMD INSTALL -- build.  But what happens if the person I'm giving the package to has neither the developer tools nor a non-R gfortran?  Is there anything I can do to compile a binary for them to make this a simple install on the other end?

Follow the instructions I sent. There are four options you can choose from [b) was really listing two options and the fourth is using Lion Fortran].


> It would seem like static linking would be the way to go.  But I don't know what you mean by "moving ... aside". I would prefer to not start renaming and delete libraries on my system for just one project.
> 
> Is there any other way I could tell R to build with the R gfortran for just this one project? And is there anything else I need to do to be sure that R will find gfortran on the end-user's system?
> 

The problem is really your Fortran as I was explaining. If you insist on using it as-is then you have to tell your users to install it as well - it's that simple. That is the "feature" of your current setup. As I was saying it is not a setup I would choose myself and I would not recommend it if you want to produce binaries for others, but it's your choice.

Cheers,
Simon



> I know these must seem like ridiculously basic questions, so I appreciate your patience with them.
> 
> Michael
> 
> 
> 
> 
> 
> Sent from my iPad
> 
> On Sep 19, 2011, at 10:41 PM, "Simon Urbanek" <simon.urbanek at r-project.org> wrote:
> 
>> Michael,
>> 
>> the problem has nothing to do with your package (you should not be touching any flags at all), but rather the Fortran you use.
>> 
>> If you have both static and dynamic fortran runtime, the dynamic one has always precedence. So there are essentially two possible ways forward:
>> 
>> a) use static Fortran runtime. It simply means moving /usr/local/lib/libgfortran.dylib aside.
>> 
>> b) if you use dynamic Fortran runtime, take the one from R. Since you have R 2.13.x it is shipped in /Library/Frameworks/R.framework/Versions/2.13/Resources/lib/ so you can use it along the lines of
>> cd /usr/local/lib
>> sudo ln -sfn /Library/Frameworks/R.framework/Versions/2.13/Resources/lib/libgfortran.2.dylib .
>> sudo ln -sfn libgfortran.2.dylib libgfortran.dylib
>> Alternatively you can simply use install_name_tool to point your package to R's runtime.
>> 
>> Note also that the more recent Fortran for Lion does not live in /usr/local so if you used that instead, you'd probably not have any issues. 
>> 
>> Cheers,
>> Simon
>> 
>> 
>> 
>> On Sep 19, 2011, at 8:23 PM, Michael Braun wrote:
>> 
>>> I am creating an R package that includes some C++ code that I have written, and some "legacy" Fortran code from another source.  I am able to build and run this package on my own machine (OSX Lion 10.7.1) with no problem.  However, I would like some colleagues to test the package before I post it on CRAN.  Unfortunately, what I have created does not appear to be portable, and I would appreciate some guidance.
>>> 
>>> Ideally, I would not expect my users to have the Apple developer tools, or an R-friendly version of gfortran installed.  So I thought I would compile a binary myself, and link to the gfortran libraries statically.  My Makevars file has exactly two lines.  One is a PKG_CPPFLAGS definition, to point to headers.  The other is PKG_LIBS=/usr/local/lib/libgfortran.a  .  I then build the binary using R CMD INSTALL --binary.  The compiler then does it's thing, and when it gets to the link step, I see:
>>> 
>>> g++-4.2 -arch x86_64 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -o mypkg.so mypkg.o  /usr/local/lib/libgfortran.a -lgfortran -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
>>> 
>>> Note that there is a -lgfortran that I did not include myself.
>>> 
>>> Of course, I want to follow the R manuals as closely as possible.  In Section 1.7.2 of "Writing R Extensions," there is advice to be aware of any dependencies.  So I then ran R CMD otool -L mypkg.so , and got the following:
>>> 
>>> mypkg.so:
>>>   mypkg.so (compatibility version 0.0.0, current version 0.0.0)
>>>   /usr/local/lib/libgfortran.2.dylib (compatibility version 3.0.0, current version 3.0.0)
>>>   /Library/Frameworks/R.framework/Versions/2.13/Resources/lib/libR.dylib (compatibility version 2.13.0, current version 2.13.1)
>>>   /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 635.0.0)
>>>   /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
>>>   /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.0.0)
>>> 
>>> So it looks like there are still some dependencies that, at least according to Section 1.7.2, I don't want.  But I do not know how to get rid of them.  And when my colleague loads the file, of course there is an error, because R cannot find the correct libgfortran dynamic library.
>>> 
>>> I also tried something else.  I know that R comes packaged with libgfortran.2.dylib in the $R_HOME/lib directory.  So what I thought I would do is add -L$(R_HOME)/lib to PKG_LIBS *instead* of doing the static linking thing.  The idea is that all users would have that version of gfortran in the same place.  But when I do that, the linker still seems to want to link to the libgfortran.3.dylib that is in /usr/local/lib, and not the libgfortran.2.dylib that is in $R_HOME/lib.  This happens even if I change the dynamic link of libgfortran.dylib to .2 instead of .3.  When my colleague tries to load mypkg.so, he gets an error that includes:  Library not loaded: /usr/local/lib/libgfortran.3.dylib
>>> 
>>> So really, all I want to do is create a binary someone can just load, without needing to preinstall lots of other stuff.  It doesn't matter to me if it involves static linking to runtime libraries, or telling the loader where to find the dynamic libraries.
>>> 
>>> Thanks in advance for your help with this.  It is much appreciated.
>>> 
>>> 
>>> 
>>> Michael Braun 
>>> MIT Sloan School of Management
>>> braunm at mit.edu
>>> _______________________________________________
>>> R-SIG-Mac mailing list
>>> R-SIG-Mac at r-project.org
>>> https://stat.ethz.ch/mailman/listinfo/r-sig-mac
>> 
> 
> 



More information about the R-SIG-Mac mailing list