Why does assert not work here?
^ Apparently, Rcpp has a habit of defining NDEBUG
on its own, even if not defined by myself.
m@m-X555LJ:~/wtfdir$ cat WTF.r
#!/usr/bin/Rscript
library(Rcpp)
sourceCpp("WTF.cpp")
m@m-X555LJ:~/wtfdir$ cat WTF.cpp
#ifdef NDEBUG
#error WTF I did not define this
#endif
m@m-X555LJ:~/wtfdir$ ./WTF.r
WTF.cpp:2:2: error: #error WTF I did not define this
#error WTF I did not define this
^~~~~
make: *** [WTF.o] Error 1
g++ -I"/usr/share/R/include" -DNDEBUG -I"/home/m/R/x86_64-pc-linux-gnu-library/3.5/Rcpp/include" -I"/home/m/wtfdir" -fpic -g -O2 -fdebug-prefix-map=/build/r-base-3U0YWo/r-base-3.5.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -g -c WTF.cpp -o WTF.o
/usr/lib/R/etc/Makeconf:172: recipe for target 'WTF.o' failed
Error in sourceCpp("WTF.cpp") : Error 1 occurred building shared library.
Execution halted
m@m-X555LJ:~/wtfdir$
The answers to the SO question I linked to explain that (a) It is prohibited to call assert
in packages uploaded to CRAN, because (b) C++ code should not halt R code and (c) I should throw exceptions instead, which are caught by Rcpp.
However:
NDEBUG
for testing purposes and then define NDEBUG
just before uploading to CRAN;NDEBUG
would be defined, I already have put quite a few assert
s in my code and also printing diagnostics via std::cerr
is wrapped in #ifndef NDEBUG
s; these fail to work obviously;assert
s are computation heavy;Is there any way to make Rcpp stop defining NDEBUG
? Or am I supposed to simply remove all asserts
and anything else that depends on NDEBUG
and switch to throwing exceptions and stop complaining?
First off, if you grep
for NDEBUG
in R's own Makeconf
(which we can access via a convenience softlink from /etc/R
on Debian and its derivatives due to how I set the .deb package up):
edd@rob:~$ grep NDEBUG /etc/R/Makeconf
R_XTRA_CPPFLAGS = -I"$(R_INCLUDE_DIR)" -DNDEBUG
ALL_CPPFLAGS = -I"$(R_INCLUDE_DIR)" -DNDEBUG $(PKG_CPPFLAGS) $(CLINK_CPPFLAGS) $(CPPFLAGS)
edd@rob:~$
you see that it imposed by R rather than Rcpp
as per your question. So your assumption was wrong. It is under your local control: just edit R's Makeconf
on your machine. You just cannot automate this for hypothetical other users of your code. But per you question, that does not appear to be an immediate concern anyway.
Second, if you want a particular #define
you can just define it:
#include <Rcpp.h>
// [[Rcpp::export]]
void foo() {
#ifdef DEBUG
Rcpp::Rcout << "foo: Debug mode" << std::endl;
#endif
Rcpp::Rcout << "foo: Hello, world" << std::endl;
}
#define DEBUG 1
// [[Rcpp::export]]
void bar() {
#ifdef DEBUG
Rcpp::Rcout << "bar: Debug mode" << std::endl;
#endif
Rcpp::Rcout << "bar: Hello, world" << std::endl;
}
/*** R
foo()
bar()
*/
R> sourceCpp("~/git/stackoverflow/56209693/answer.cpp")
R> foo()
foo: Hello, world
R> bar()
bar: Debug mode
bar: Hello, world
R>
It is quite common to define other logging macros like DEBUG
or FATAL
or ... that behave like assert even if R by default (and for understandable reasons as a primarily-interactive tool) turns assert
off.
Third and last, you can follow the approach in this question and temporarily undefine NDEBUG
to include cassert
and then redefine it. That will give you assert()
and terminate your session as I checked. Not my approach to debug with R but hey if you really must...