Including Rcpp in a Qt project results in error affecting different included library

427 Views Asked by At

I'm making a static library with Qt Creator, this library will be used in a larger GUI based application. I've used Rcpp before but with R as my starting point - so moving R data to C++ functions to do stuff and get the result and I'm used to doing it with R studio. This time I'm starting in a Qt project and I have need for a table to store some data in and Rcpp::Dataframe would fit the job nicely, as would some of the vector classes. In my .cpp source file I have the include statement #include <Rcpp.h> and I took a look on the web and found an example of the Rcpp / RInside libraries being used in Qt - although it's more about RInside than Rcpp: RInside and Qt

It seems some thing need to be added to the .pro file to get qmake to do the right thing. I've included what I think are required for Rcpp in my .pro file attached below. The problem I'm having is that before inclusion of the Rcpp stuff in the .pro file and the include statement in the .cpp file, the inclusion of the bpp libraries which you can also see in the .pro file below does not result in any errors or warnings in compilation. After the inclusion of the statements to include R and Rcpp in the .pro file, I get many warnings and one error to do with a component of bpp, specifically: /local/yrq12edu/local/bpp/dev/include/Bpp/Numeric/NumConstants.h:96: error: expected unqualified-id before numeric constant. There are also a lot of Wunused-parameter messages, again most of these seem to be comming from files from within bpp. This is the first time I've had to deal with something like this, and although I've read a lot of the Qt docs I'm still a very fresh Qt newb. Why would I get no errors before to do with bpp, but get them now I've tried including Rcpp into my Qt project? And what should I do to take steps to solve this?

#-------------------------------------------------
#
# Project created by QtCreator 2014-09-05T23:27:21
#
#-------------------------------------------------

QT       -= core gui

TARGET = libHybRIDS
TEMPLATE = lib
CONFIG += staticlib

SOURCES += hybridsengine.cpp
HEADERS += hybridsengine.h

INCLUDEPATH += /local/yrq12edu/local/bpp/dev/include
LIBS += -L/local/yrq12edu/local/bpp/dev/lib -lbpp-core
LIBS += -L/local/yrq12edu/local/bpp/dev/lib -lbpp-seq

# Set R home directory
R_HOME =                $$system(R RHOME)
# Set Rcpp include and lib flags.
RCPPINCL =              $$system($$R_HOME/bin/Rscript -e \'Rcpp:::CxxFlags\(\)\')
RCPPLIBS =              $$system($$R_HOME/bin/Rscript -e \'Rcpp:::LdFlags\(\)\')
# Set R cpp and ld flags. Also for BLAS and LAPACK it uses.
RCPPFLAGS =             $$system($$R_HOME/bin/R CMD config --cppflags)
RLDFLAGS =              $$system($$R_HOME/bin/R CMD config --ldflags)
RBLAS =                 $$system($$R_HOME/bin/R CMD config BLAS_LIBS)
RLAPACK =               $$system($$R_HOME/bin/R CMD config LAPACK_LIBS)

RCPPWARNING =           -Wno-unused-parameter

QMAKE_CXXFLAGS +=       $$RCPPWARNING $$RCPPFLAGS $$RCPPINCL
QMAKE_LFLAGS +=         $$RLDFLAGS $$RBLAS $$RLAPACK $$RCPPLIBS


unix {
    target.path = /usr/lib
    INSTALLS += target
}

EDIT: Following suggestions I've used the example pro file in RInside/examples/qt as the start point - keeping the order of the statements:

#-------------------------------------------------
#
# Project created by QtCreator 2014-09-05T23:27:21
#
#-------------------------------------------------

QT       -= core gui

TARGET = libHybRIDS
TEMPLATE = lib
CONFIG += staticlib

SOURCES += hybridsengine.cpp
HEADERS += hybridsengine.h

## comment this out if you need a different version of R,
## and set set R_HOME accordingly as an environment variable
R_HOME =        $$system(R RHOME)
#message("R_HOME is" $$R_HOME)

## include headers and libraries for R
RCPPFLAGS =         $$system($$R_HOME/bin/R CMD config --cppflags)
RLDFLAGS =      $$system($$R_HOME/bin/R CMD config --ldflags)
RBLAS =         $$system($$R_HOME/bin/R CMD config BLAS_LIBS)
RLAPACK =       $$system($$R_HOME/bin/R CMD config LAPACK_LIBS)

## if you need to set an rpath to R itself, also uncomment
RRPATH =        -Wl,-rpath,$$R_HOME/lib

## include headers and libraries for Rcpp interface classes
## note that RCPPLIBS will be empty with Rcpp (>= 0.11.0) and can be omitted
RCPPINCL =      $$system($$R_HOME/bin/Rscript -e \"Rcpp:::CxxFlags\(\)\")
RCPPLIBS =      $$system($$R_HOME/bin/Rscript -e \"Rcpp:::LdFlags\(\)\")

## for some reason when building with Qt we get this each time
##   /usr/local/lib/R/site-library/Rcpp/include/Rcpp/module/Module_generated_ctor_signature.h:25: warning: unused parameter ‘classname
## so we turn unused parameter warnings off
## no longer needed with Rcpp 0.9.3 or later
#RCPPWARNING =      -Wno-unused-parameter

## include headers and libraries for RInside embedding classes
RINSIDEINCL =       $$system($$R_HOME/bin/Rscript -e \"RInside:::CxxFlags\(\)\")
RINSIDELIBS =       $$system($$R_HOME/bin/Rscript -e \"RInside:::LdFlags\(\)\")

## compiler etc settings used in default make rules
QMAKE_CXXFLAGS +=   $$RCPPWARNING $$RCPPFLAGS $$RCPPINCL $$RINSIDEINCL
QMAKE_LIBS +=           $$RLDFLAGS $$RBLAS $$RLAPACK $$RINSIDELIBS $$RCPPLIBS

## addition clean targets
QMAKE_CLEAN +=      qtdensity Makefile

unix {
    target.path = /usr/lib
    INSTALLS += target
}

Putting in my statements to include the bpp libraries from before before or after the statements relating to RInside and Rcpp cause the same error as previously.

The contents of the .h file from bpp are:

#ifndef _NUMCONSTANTS_H_
#define _NUMCONSTANTS_H_

#include <cmath>
#include <limits>

namespace bpp {

  /**
   * @brief this static class contains several useful constant values.
   *
   * This classe uses function in order to avoid the infamous "static initialization order fiasco".
   * C++0x solves this...
   */
  class NumConstants
  {

  public:
    /**
     * @name Golden ratio.
     *
     * The golden ratio, @f$\phi@f$ is equal to @f$\frac{1+\sqrt{5}}{2} = 1.6180339887498948482\ldots@f$.
     * We also define @f$R=\phi-1@f$ and @f$C = 1 - R@f$.
     * @{
     */
    static double GOLDEN_RATIO_PHI() { return (1. + sqrt(5.)) / 2.; }
    static double GOLDEN_RATIO_R() { return GOLDEN_RATIO_PHI() - 1.; }
    static double GOLDEN_RATIO_C() { return 1. - GOLDEN_RATIO_R(); }

    /** @} */

    static double MEGA() { return 1e6; }
    static double KILO() { return 1e3; }
    static double DECI() { return 1e-1; }
    static double CENTI() { return 1e-2; }
    static double MILLI() { return 1e-3; }
    static double MICRO() { return 1e-6; }
    static double NANO() { return 1e-9; }
    static double PICO() { return 1e-12; }

    static double SMALL() { return 1e-6; }
    static double TINY() { return 1e-12; }
    static double VERY_TINY() { return 1e-20; }
    static double VERY_BIG() { return static_cast<double>(1.7E+23); }

    /**
     * @name Define those constants in case they would not be available in stl/limits.
     *
     * @{
     */
    static double INF() { return std::numeric_limits<double>::has_infinity ? -log(0) : std::numeric_limits<double>::max(); }
    static double PINF() { return std::numeric_limits<double>::has_infinity ? -log(0) : std::numeric_limits<double>::max(); }
    static double MINF() { return std::numeric_limits<double>::has_infinity ? log(0) : std::numeric_limits<double>::min(); }
    static double NaN() { return NAN; }
    /** @} */

    static double PI() { return 3.141593; }
  };

}//end of namespace bpp.

#endif  //_NUMCONSTANTS_H_
1

There are 1 best solutions below

0
On

Here's a guess: In R_ext/Constants.h, we have:

trunk/src/include/R_ext/Constants.h
28:#define M_PI 3.141592653589793238462643383279502884197169399375
32:#define PI             M_PI

That macro definition is colliding with the function definition for PI. So you would expect e.g.

#include <R.h> // pulls in 'R_ext/Constants.h'
#include "Bpp stuff" // definition for function named PI collides with macro

would give potential errors. The R macro definition for PI would leak into Bpp, and hence after the preprocessor is done, this line:

static double PI() { return 3.141593; }

will look like

static double 3.141592653589793238462643383279502884197169399375() { return 3.141593; }

and the compiler can only say 'wat'. This is why include order can be important -- including Bpp first would avoid the macro pollution.

It appears this particular bit of pollution could be avoided by defining #define STRICT_R_HEADERS (since that's what the entry is wrapped in).