Search code examples
rrcppboost-date-time

How to link to boost date_time


Example

I have an Rcpp function where I would like to call boost::posix_time::time_from_string().

I've taken the example code from the boost documentation and translated it to a c++ function using Rcpp

library(Rcpp)

cppFunction(
  includes = '
    #include <boost/date_time/posix_time/posix_time.hpp>
  ',
  code = '
    void time_test() {
      std::string t = "2002-01-20 23:59:59.000";
      boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
      Rcpp::Rcout << "time from string: " << pt << std::endl;
    }
  ',
  depends = "BH"
)

However, this doesn't compile.

I've seen a few comments saying you need to link to -lboost_date_time, such as this line in Dirk's RcppBDT library

// The next function uses the non-stream-based parsing in Boost Date_Time
// and requires _linking_ with -lboost_date_time which makes the (otherwise
// header-only) build more complicate
// // [ [ Rcpp::export ] ]
// Rcpp::DatetimeVector charToPOSIXctNS(Rcpp::CharacterVector sv) {
//   ... code omitted ...
// }

Question

How do you provide the appropriate links to lboost_date_time, other than including the posix_time.hpp header, so that one can use time_from_string()?


Extra Info

It's possible to use other functions from the boost/date_time library, as demonstrated by this function, so what makes time_from_string() different?

cppFunction(
  includes = '
    #include <boost/date_time/posix_time/posix_time.hpp>
  ',
  code = '
    void time_test() {
      Rcpp::Datetime dt("2002-01-20 23:59:59.000");
      boost::posix_time::hours h( dt.getHours() );
      boost::posix_time::minutes m( dt.getMinutes() );
      boost::posix_time::seconds s( dt.getSeconds() );

      Rcpp::Rcout << h << std::endl;
      Rcpp::Rcout << m << std::endl;
      Rcpp::Rcout << s << std::endl;
    }
  ',
  depends = "BH"
)

time_test() 

# 12:00:00
# 00:59:00
# 00:00:59

Solution

  • As you already found out, you need to link with boost at the system level. The BH package is not sufficient. So first you have to install the required boost library. On Debian (dervied) Linux systems this can be done via

    sudo apt-get install libboost-date-time-dev
    

    Then you need to tell R to add -I/path/to/boost/headers and -L/path/to/boost/libraries -lboost_date_time to the compiler flags. You can do this by setting appropriate environment variables:

    library(Rcpp)
    
    Sys.setenv(PKG_LIBS="-L/usr/lib -lboost_date_time", PKG_CPPFLAGS="-I/usr/include")
    
    cppFunction(
      includes = '
        #include <boost/date_time/posix_time/posix_time.hpp>
      ',
      code = '
        void time_test() {
          std::string t = "2002-01-20 23:59:59.000";
          boost::posix_time::ptime pt(boost::posix_time::time_from_string(t));
          Rcpp::Rcout << "time from string: " << pt << std::endl;
        }
      '
    )
    

    Notes:

    • One could also define a Rcpp plugin for this.
    • In my case -I... and -L... are unnecessary, since the library is installed in a standard location. One does need these flags in other cases, though.