rquantlib icon indicating copy to clipboard operation
rquantlib copied to clipboard

installation documentation for macOS is incorrect

Open drchriscole opened this issue 3 years ago • 29 comments

I realise this has already been raised on #141 but the issue still stands that the documentation is incorrect for macOS.

Also as it is RQuantLib does not work on macOS using the default instructions. This is what I get when trying load it in R 4.0.3 macOS Catalina.

> library(RQuantLib)
Sufficient QuantLib version with insufficient configuration.
Try configuring your build with the --enable-intraday argument.

As previously stated the Homebrew install has the '--enable-intraday' argument enabled.

I'll also open a ticket with Homebrew and see where the problem stems from as it appears it all should work.

drchriscole avatar Mar 30 '21 16:03 drchriscole

So ... why are you opening a duplicate issue rather than just commenting on the existing one? What does this add? What could I possibly do -- I cannot influence the brew folks.

eddelbuettel avatar Mar 30 '21 16:03 eddelbuettel

If there is documentation to fix, could you kindly provide a URL or file link? I can surely take a look but a global "docs borked" is not exactly operational. As I said a few over the nearly two decades of this project, I don't have a macOS box so ...

eddelbuettel avatar Mar 30 '21 16:03 eddelbuettel

The point is that this isn't brew problem, as far as I can tell. QuantLib is installed with the correct flags as per the requirements of RQuantLib.

Step 4 on the wiki for macOS should be: brew install quantlib

The current version of quantlib in Homebrew is 1.21 so step 6 is unnecessary (plus it seems those 'inline's are already there.

Finally, in step 8 I get a whole bunch of deprecated warnings and build fails with:

Error: package or namespace load failed for ‘RQuantLib’ in dyn.load(file, DLLpath = DLLpath, ...):
 unable to load shared object '/Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs/RQuantLib.so':
  dlopen(/Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs/RQuantLib.so, 6): Symbol not found: __ZN8QuantLib13MultiStepSwap12nextTimeStepERKNS_10CurveStateERSt6vectorImSaImEERS4_IS4_INS_23MarketModelMultiProduct8CashFlowESaIS9_EESaISB_EE
  Referenced from: /Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs/RQuantLib.so
  Expected in: flat namespace
 in /Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs/RQuantLib.so
Error: loading failed
Execution halted
ERROR: loading failed
* removing ‘/Users/ccole/Library/R/4.0/library/RQuantLib’
Warning in install.packages :
  installation of package ‘RQuantLib’ had non-zero exit status

drchriscole avatar Apr 01 '21 11:04 drchriscole

Ok, now I know to look at the wiki, thanks. That was missing.

The 'flat namespace' rings a bell, I think we have seen this with other packages too and I think it has something to do with your local macOS setup. I am sorry that I don't have a pointer as I am not a macOS user myself. Here is one from RcppArmadillo being apparently related to mixing gcc/g++ and clang. Here is one from Rcpp suggesting that if you install something from source that uses Rcpp you may also need Rcpp from source. In sum this suggests that your mixing with precompiled units from brew may not be as plug-and-play as you hoped?

Could you compile QuantLib, Rcpp, RQuantLib from source to check this?

eddelbuettel avatar Apr 01 '21 11:04 eddelbuettel

Just realised that was using gcc v8 from Homebrew. Trying again with the default clang in macOS also has loads of deprecation warnings e.g.

In file included from zero.cpp:20:
In file included from ../inst/include/rquantlib_internal.h:23:
In file included from /usr/local/include/ql/quantlib.hpp:58:
In file included from /usr/local/include/ql/termstructures/all.hpp:18:
In file included from /usr/local/include/ql/termstructures/yield/all.hpp:16:
/usr/local/include/ql/termstructures/yield/nonlinearfittingmethods.hpp:262:14: warning: 'auto_ptr<QuantLib::FittedBondDiscountCurve::FittingMethod>' is deprecated [-Wdeprecated-declarations]
        std::auto_ptr<FittedBondDiscountCurve::FittingMethod> clone() const;
             ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2135:28: note: 'auto_ptr<QuantLib::FittedBondDiscountCurve::FittingMethod>' has been explicitly marked deprecated here
class _LIBCPP_TEMPLATE_VIS _LIBCPP_DEPRECATED_IN_CXX11 auto_ptr
                           ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config:1030:39: note: expanded from macro '_LIBCPP_DEPRECATED_IN_CXX11'
#  define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED
                                      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__config:1019:48: note: expanded from macro '_LIBCPP_DEPRECATED'
#    define _LIBCPP_DEPRECATED __attribute__ ((deprecated))
                                               ^
66 warnings generated.

I can have a look at compiling from source, but not for a few days. I'll keep you posted.

drchriscole avatar Apr 01 '21 11:04 drchriscole

Oh, that is better! Deprecation warnings are a pest, especially as CRAN has a formal (!!) policy to not allow us to suppress them (!!) in packages which is annoying (but makes sense for debugging). The best fix we have is to add them in our personal ~/.R/Makevars so I have something commented I often add back in / alter:

#XTRAFLAGS=-Wno-misleading-indentation -Wno-unused -Wno-ignored-attributes -Wno-parentheses -Wno-address-of-packed-member
[....]
CFLAGS=               -g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS) -std=gnu99

CXXFLAGS=            	-g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS)
CXX1XFLAGS=		-g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS)
CXX11FLAGS=		-g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS)
CXX14FLAGS=		-g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS)
CXX17FLAGS=		-g -O3 -Wall -pipe $(PEDANTIC) $(XTRAFLAGS)

Adjust XTRAFLAGS as needed.

Really appreciate the help on macOS. The 'Venn diagram intersection' of R && QuantLib && macOS && chops_to_build_from_source is pretty sparse.

eddelbuettel avatar Apr 01 '21 11:04 eddelbuettel

Damn, I forgot the rest of it., sorry. The compilation still failed.

installing to /Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs ** R ** data ** demo ** inst ** byte-compile and prepare package for lazy loading ** help *** installing help indices ** building package indices ** testing if installed package can be loaded from temporary location sh: line 1: 22570 Bus error: 10 R_TESTS= '/Library/Frameworks/R.framework/Resources/bin/R' --no-save --no-restore --no-echo 2>&1 < '/var/folders/75/b_5cscrd0dgbbm8n7xxpp8g8wnd8nl/T//RtmplOCplQ/file334e7f408967'

*** caught bus error *** address 0x10b9a6ee0, cause 'non-existent physical address'

Traceback: 1: dyn.load(file, DLLpath = DLLpath, ...) 2: library.dynam(lib, package, package.lib) 3: loadNamespace(package, lib.loc) 4: doTryCatch(return(expr), name, parentenv, handler) 5: tryCatchOne(expr, names, parentenv, handlers[[1L]]) 6: tryCatchList(expr, classes, parentenv, handlers) 7: tryCatch({ attr(package, "LibPath") <- which.lib.loc ns <- loadNamespace(package, lib.loc) env <- attachNamespace(ns, pos = pos, deps, exclude, include.only)}, error = function(e) { P <- if (!is.null(cc <- conditionCall(e))) paste(" in", deparse(cc)[1L]) else "" msg <- gettextf("package or namespace load failed for %s%s:\n %s", sQuote(package), P, conditionMessage(e)) if (logical.return) message(paste("Error:", msg), domain = NA) else stop(msg, call. = FALSE, domain = NA)}) 8: library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE) 9: withCallingHandlers(expr, packageStartupMessage = function(c) tryInvokeRestart("muffleMessage")) 10: suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE)) 11: doTryCatch(return(expr), name, parentenv, handler) 12: tryCatchOne(expr, names, parentenv, handlers[[1L]]) 13: tryCatchList(expr, classes, parentenv, handlers) 14: tryCatch(expr, error = function(e) { call <- conditionCall(e) if (!is.null(call)) { if (identical(call[[1L]], quote(doTryCatch))) call <- sys.call(-4L) dcall <- deparse(call)[1L] prefix <- paste("Error in", dcall, ": ") LONG <- 75L sm <- strsplit(conditionMessage(e), "\n")[[1L]] w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w") if (is.na(w)) w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L], type = "b") if (w > LONG) prefix <- paste0(prefix, "\n ") } else prefix <- "Error : " msg <- paste0(prefix, conditionMessage(e), "\n") .Internal(seterrmessage(msg[1L])) if (!silent && isTRUE(getOption("show.error.messages"))) { cat(msg, file = outFile) .Internal(printDeferredWarnings()) } invisible(structure(msg, class = "try-error", condition = e))}) 15: try(suppressPackageStartupMessages(library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE))) 16: tools:::.test_load_package("RQuantLib", "/Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new") An irrecoverable exception occurred. R is aborting now ... ERROR: loading failed

  • removing ‘/Users/ccole/Library/R/4.0/library/RQuantLib’ Warning in install.packages : installation of package ‘RQuantLib’ had non-zero exit status

drchriscole avatar Apr 01 '21 11:04 drchriscole

Those things tends to go away with Rcpp built from source, along with the Rcpp-using package from source.

"Our problem here" is that the same fix may be needed for QuantLib itself which is Yuge and takes a jolly moment to build.

eddelbuettel avatar Apr 01 '21 11:04 eddelbuettel

I couldn't let this go ;)

Have compiled all three (QuantLib, Rcpp and RQuantlib) from source. No change. Expanding errors to include last compile step:

clang++ -mmacosx-version-min=10.13 -std=gnu++11 -dynamiclib -Wl,-headerpad_max_install_names -undefined dynamic_lookup -single_module -multiply_defined suppress -L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o RQuantLib.so RcppExports.o affine.o asian.o barrier_binary.o bermudan.o bonds.o calendars.o curves.o dates.o daycounter.o discount.o hullwhite.o implieds.o modules.o sabr.o schedule.o utils.o vanilla.o zero.o -L/usr/local/lib -L/usr/local/lib -lQuantLib -L/usr/local/lib/ -F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -Wl,CoreFoundation
installing to /Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new/RQuantLib/libs
** R
** data
** demo
** inst
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded from temporary location
sh: line 1: 59050 Bus error: 10           R_TESTS= '/Library/Frameworks/R.framework/Resources/bin/R' --no-save --no-restore --no-echo 2>&1 < '/var/folders/75/b_5cscrd0dgbbm8n7xxpp8g8wnd8nl/T//RtmptlAYqg/filec1a655866c98'

 *** caught bus error ***
address 0x1086f2150, cause 'non-existent physical address'

Traceback:
 1: dyn.load(file, DLLpath = DLLpath, ...)
 2: library.dynam(lib, package, package.lib)
 3: loadNamespace(package, lib.loc)
 4: doTryCatch(return(expr), name, parentenv, handler)
 5: tryCatchOne(expr, names, parentenv, handlers[[1L]])
 6: tryCatchList(expr, classes, parentenv, handlers)
 7: tryCatch({    attr(package, "LibPath") <- which.lib.loc    ns <- loadNamespace(package, lib.loc)    env <- attachNamespace(ns, pos = pos, deps, exclude, include.only)}, error = function(e) {    P <- if (!is.null(cc <- conditionCall(e)))         paste(" in", deparse(cc)[1L])    else ""    msg <- gettextf("package or namespace load failed for %s%s:\n %s",         sQuote(package), P, conditionMessage(e))    if (logical.return)         message(paste("Error:", msg), domain = NA)    else stop(msg, call. = FALSE, domain = NA)})
 8: library(pkg_name, lib.loc = lib, character.only = TRUE, logical.return = TRUE)
 9: withCallingHandlers(expr, packageStartupMessage = function(c) tryInvokeRestart("muffleMessage"))
10: suppressPackageStartupMessages(library(pkg_name, lib.loc = lib,     character.only = TRUE, logical.return = TRUE))
11: doTryCatch(return(expr), name, parentenv, handler)
12: tryCatchOne(expr, names, parentenv, handlers[[1L]])
13: tryCatchList(expr, classes, parentenv, handlers)
14: tryCatch(expr, error = function(e) {    call <- conditionCall(e)    if (!is.null(call)) {        if (identical(call[[1L]], quote(doTryCatch)))             call <- sys.call(-4L)        dcall <- deparse(call)[1L]        prefix <- paste("Error in", dcall, ": ")        LONG <- 75L        sm <- strsplit(conditionMessage(e), "\n")[[1L]]        w <- 14L + nchar(dcall, type = "w") + nchar(sm[1L], type = "w")        if (is.na(w))             w <- 14L + nchar(dcall, type = "b") + nchar(sm[1L],                 type = "b")        if (w > LONG)             prefix <- paste0(prefix, "\n  ")    }    else prefix <- "Error : "    msg <- paste0(prefix, conditionMessage(e), "\n")    .Internal(seterrmessage(msg[1L]))    if (!silent && isTRUE(getOption("show.error.messages"))) {        cat(msg, file = outFile)        .Internal(printDeferredWarnings())    }    invisible(structure(msg, class = "try-error", condition = e))})
15: try(suppressPackageStartupMessages(library(pkg_name, lib.loc = lib,     character.only = TRUE, logical.return = TRUE)))
16: tools:::.test_load_package("RQuantLib", "/Users/ccole/Library/R/4.0/library/00LOCK-RQuantLib/00new")
An irrecoverable exception occurred. R is aborting now ...
ERROR: loading failed
* removing ‘/Users/ccole/Library/R/4.0/library/RQuantLib’
Warning in install.packages :
  installation of package ‘RQuantLib’ had non-zero exit status

There are the commands used: QuantLib

./configure --with-boost-include=/usr/local/include/ \
            --with-boost-lib=/usr/local/lib/ --prefix=/usr/local/ \
            CXXFLAGS='-O2 -stdlib=libc++ -mmacosx-version-min=10.13' \
            LDFLAGS='-stdlib=libc++ -mmacosx-version-min=10.13'
make
sudo make install

As per their instructions I ran the example which worked fine.

Rcpp install.packages('Rcpp', type = 'source')

RQuantLib install.packages("RQuantLib", configure.args = "--with-boost-include=/usr/local/include/ --with-boost-lib=/usr/local/lib/", type = "source")

This is on an intel Mac, macOS (10.15.7 Catalina) and R 4.0.3. Let me know if there's anything else I can try.

drchriscole avatar Apr 01 '21 13:04 drchriscole

I couldn't let this go ;)

That is the spirit.

I do not have good pointers (as I don't use macOS) but a) we had [when the macOS maintainer at CRAN had time to build QuantLib] working macOS packages so there is no foundational issue and b) I have of course in near-20 years of mucking with QuantLib and RQuantLib (and having Rcpp "fall out" as a happy side effect) seen segfaults like that---invariably they were of my making. Maybe another piece in the middle is still bad / a path wrong pointing to the wrong build / ...

I would now try to triangulate. With QuantLib sources you have examples. Do those build and run? (I guess). Can R call code via Rcpp? Do the old Rcpp::evalCpp("2+2") (which will too). Then step by step meet the two. Write a five liner with a QuantLib header and "manually" link. Then add RQuantLib. In other words a lot of poking with large sticks. Luckily, including R, you really only have four parts...

eddelbuettel avatar Apr 01 '21 13:04 eddelbuettel

Crap. Forgot about Boost. There you go. Likely culprit :-/

eddelbuettel avatar Apr 01 '21 13:04 eddelbuettel

Recompiled Boost from source with same outcome :(

The QuantLib examples run fine as do Rcpp calls. Can you elaborate further on the "Write a five liner with a QuantLib header and "manually" link." bit please? I'm not much of a C++ coder and even less one via Rcpp.

drchriscole avatar Apr 01 '21 19:04 drchriscole

Dang. That makes it weirder.

Sorry, for the five liner (or, with the verbosity of QuantLib, fifty) I meant to add a header file, instantiate object and just print 'hello, world, still here' to again close the gap a little more the working pieces and the fuller (but not working package).

eddelbuettel avatar Apr 01 '21 19:04 eddelbuettel

Created this hello.cpp code:

#include <Rcpp.h>
#include <ql/quantlib.hpp>
// [[Rcpp::export]]
void hello()
{
  Rprintf("Hello, quantlib world!\n");
}

And then ran it as:

library(Rcpp)
sourceCpp('hello.cpp')
hello()

Got a whole bunch of warnings (just like when compiling RQuantLib), but it printed out 'Hello, quantlib world|" just fine. Any other ideas?

p.s. I also did this in a new user account on the same mac with no difference.

drchriscole avatar Apr 12 '21 16:04 drchriscole

I assume you are aware of a) the options for sourceCpp() and cppFunction() to point to dependencies as one does .e.g. with RcppArmadillo to get header and/or RcppGSL to get header and the required library b) that this is actually not actively advertised (I think) as something that works cross-platform with RQuantLib -- I think I looked into it once or twice or three times in the past for use on Linux, and there is of course R/inline.R but I don't think I ever stated "do this on macOS".

So with that: which section of which document are you looking at that makes you think this was working? The overall in the wiki covers, if I recall correctly, only basic install. More could be done, but someone has to lay down the ground work first. Maybe you can?

eddelbuettel avatar Apr 12 '21 16:04 eddelbuettel

Your assumptions regarding Rcpp are incorrect. I have no experience of it at all so am just going on what I find on stackoverflow ;) So if there's any more detailed pointers or links I can follow, I'd be happy o try.>

which section of which document are you looking at that makes you think this was working?

What do you mean by "this"? The Rcpp call, QuantLib, or something else?

From what I can see is that by including 'ql/quantlib.hpp' in the basic code, the header is being compiled into the final executable (hence all the deprecation warnings), but of course nothing is being used.

drchriscole avatar Apr 12 '21 18:04 drchriscole

E.g. your Subject: line here "installation documentation ... incorrect" but I am not all-knowing all-seeing and do not know what document you may have read.

I assume you understand the technical implication of 'header included' possibly leading to 'object instantiated' requiring linking. C++ can be setup differently via header-only libraries and there even once was a trial for (R)QuantLib which I wrapped here -- while not current with current QuantLib it is (far) better than nuttin' at all.

eddelbuettel avatar Apr 12 '21 19:04 eddelbuettel

I had similar issue - installing brew install quantlib and disabling Makevars to use apple complier then install.packages("RQuantLib", configure.args = "--with-boost-include=/usr/local/include/ --with-boost-lib=/usr/local/lib/", type = "source") worked. I've updated wiki... hope this might help.

matthewgson avatar Sep 18 '21 05:09 matthewgson

Thanks for the edit. I don't have a macOS machine so we rely on community-curation.

eddelbuettel avatar Sep 18 '21 12:09 eddelbuettel

For those who are using Macbook M1 If you install quantlib using brew, it will be installed under /opt/homebrew instead of /usr/local, and boost also installed under /opt/homebrew/

This is what I did: I have installed quantlib using brew: Disable Makevars by deleting Makevars in /Users/yourname/.R folder

Change this line "/usr/local/include to /opt/homebrew/include (or create a symbolic link) install.packages("RQuantLib", configure.args = "--with-boost-include=/opt/homebrew/include/ --with-boost-lib=/opt/homebrew/lib/", type = "source")

it worked for me.

hoantran999 avatar Feb 07 '22 19:02 hoantran999