Debug Rcpp with ldbb: variables not available - rcpp

I'm making a package with RcppArmadillo under the latest version of Rstudio (1.3.959) and R (4.0.0).
Consider the following minimal example, which create the package anRpackage:
library(Rcpp)
library(RcppArmadillo)
RcppArmadillo.package.skeleton()
Setting the working directory in this package, I load it by:
library(devtools)
devtools::load_all()
Then the basic function rcpparma_hello_world() can be executed:
rcpparma_hello_world()
[,1] [,2] [,3]
[1,] 7 0 0
[2,] 0 7 0
[3,] 0 0 7
I want now to debug the code with lldb via the Terminal command R -d lldb in order to check the variable values during the execution via the command frame variable.
R -d lldb
(lldb) breakpoint set --name rcpparma_hello_world()
(lldb) run
> library(devtools)
> devtools::load_all()
> rcpparma_hello_world()
anRpackage.so was compiled with optimization - stepping may behave oddly; variables may not be available.
Indeed, the problem is that most of variables are not available:
> next
> frame variable
(arma::mat) m1 = <no location, value may have been optimized out>
(arma::mat) m2 = <no location, value may have been optimized out>
I read in the previous link the following recommandations:
you may consider producing so-called ‘debug’ builds, with optimization toned down, when attempting to debug these kinds of issues as well. For building R packages, this effectively amounts to something like CXXFLAGS=-g -O0 in your ~/.R/Makevars file)
I have tried it but it seems to have no effect under the compilation flags used since I have a local file Makevars in my package to specify the way of compiling with RcppArdimillo, whose flags are:
CXX_STD = CXX11
PKG_CXXFLAGS = $(SHLIB_OPENMP_CXXFLAGS)
PKG_LIBS = $(SHLIB_OPENMP_CXXFLAGS) $(LAPACK_LIBS) $(BLAS_LIBS) $(FLIBS)
Then, the command devtools::load_all() produces the line-command compilation given below, in which there is indeed -g -O2 making some code optimization:
clang++ -mmacosx-version-min=10.13 -std=gnu++11 -I"/Library/Frameworks/R.framework/Resources/include" -DNDEBUG -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/Rcpp/include' -I'/Library/Frameworks/R.framework/Versions/4.0/Resources/library/RcppArmadillo/include' -I/usr/local/include -fPIC -Wall -g -O2 -c rcpparma_hello_world.cpp -o rcpparma_hello_world.o
Question: how can I have access to the variables in debugging mode?
Thanks

Related

How to fix "error: could not find native static library `c`, perhaps an -L flag is missing?" or how do I compile rust binaries for openwrt?

I'm wanting to compile binaries for openwrt 19.07.7 on mips with limited space.
OpenWrt 19.07.7, r11306-c4a6851c72
-----------------------------------------------------
root#OpenWrt:~# df /
Filesystem 1K-blocks Used Available Use% Mounted on
overlayfs:/overlay 3392 1276 2116 38% /
root#OpenWrt:~# ls -s
662 crosshello 3 helloworld
root#OpenWrt:~# ldd --version
musl libc (mips-sf)
Version 1.1.24
Above you can see the size of crosshello (cross compiled using rust) and helloworld (cross compiled using gcc). There is limited space on the target as you can see.
I followed https://github.com/japaric/rust-cross and it works. However I had to reduce the size of the binary to get it to fit. Following https://github.com/johnthagen/min-sized-rust I got the binary (the "Cross compiling with cargo" hello world with clap from the first link) to fit. I haven't compiled my own program yet. I got stuck a the "Optimize libstd with build-std" section.
I'm getting the above error:
$ cargo +nightly build -Z build-std=std,panic_abort --target=mips-unknown-linux-musl --release
Compiling libc v0.2.106
...
error: could not find native static library `c`, perhaps an -L flag is missing?
error: could not compile `libc` due to previous error
warning: build failed, waiting for other jobs to finish...
error: build failed
How do I fix that? I don't want to static link against the system libc, I want it dynamically linked like other binaries on that platform. But not sure how to do that. If I use the standard libstd the binaries are dynamically linked just fine.
Alternatively I could try nostd but my code would need significant modification and I'm not sure that would fix this problem anyway. Alternatively I could just go ahead compile my actual project with libstd and it might fit. However my project is doing data logging, so the binary is competing for space with data I want to store, so I want to minimize space as much as possible.
I've also seen reference to cargo-bloat so I'll probably check that out to find what all the space is being used for in the binary.
I'm open to different strategies to achieve what I want if anyone has ideas?
On my dev system:
$ cat .cargo/config
[target.mips-unknown-linux-musl]
ar = "/home/alex/projects/openwrt-sdk-19.07.7-ath79-generic_gcc-7.5.0_musl.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-7.5.0_musl/bin/mips-openwrt-linux-ar"
linker = "/home/alex/projects/openwrt-sdk-19.07.7-ath79-generic_gcc-7.5.0_musl.Linux-x86_64/staging_dir/toolchain-mips_24kc_gcc-7.5.0_musl/bin/mips-openwrt-linux-gcc"
$ cat Cargo.toml
#cargo-features = ["strip"]
[package]
name = "crosshello"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
clap = "3.0.0-beta.5"
[profile.release]
#strip = true
opt-level = "z"
lto = true
codegen-units = 1
panic = "abort"
(The binaries are stripped, currently I'm stripping them manually.)

undefined reference to symbol 'pthread_setname_np##GLIBC_2.12' Haskell Stack error on OpenSuse42.3

I have installed haskell stack and I'm trying to setup ghc for the same. stack version is
stack --version
Version 1.5.1, Git revision 600c1f01435a10d127938709556c1682ecfd694e (4861 commits) x86_64 hpack-0.17.1
I have updated the ~/.stack/global-project/stack.yaml as below
# This is the implicit global project's config file, which is only used when
# 'stack' is run outside of a real project. Settings here do _not_ act as
# defaults for all projects. To change stack's default settings, edit
# '/home/rajkumar/.stack/config.yaml' instead.
#
# For more information about stack's configuration, see
# http://docs.haskellstack.org/en/stable/yaml_configuration/
#
flags: {}
extra-package-dbs: []
packages: []
extra-deps: []
resolver: ghc-8.2.1
Then I run stack setup command and got the below error -
stack setup
The GHC located at /home/rajkumar/.stack/programs/x86_64-linux/ghc-8.2.1/bin/ghc failed to compile a sanity check. Please see:
http://docs.haskellstack.org/en/stable/install_and_upgrade/
for more information. Exception was:
Running /home/rajkumar/.stack/programs/x86_64-linux/ghc-8.2.1/bin/ghc /tmp/stack-sanity-check3048/Main.hs -no-user-package-db in directory /tmp/stack-sanity-check3048/ exited with ExitFailure 1
[1 of 1] Compiling Main ( /tmp/stack-sanity-check3048/Main.hs, /tmp/stack-sanity-check3048/Main.o )
Linking /tmp/stack-sanity-check3048/Main ...
/usr/bin/ld.bfd: /home/rajkumar/.stack/programs/x86_64-linux/ghc-8.2.1/lib64/ghc-8.2.1/rts/libHSrts.a(OSThreads.o): undefined reference to symbol 'pthread_setname_np##GLIBC_2.12'
/lib64/libpthread.so.0: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
`gcc' failed in phase `Linker'. (Exit code: 1)
So maybe the problem is that you need GLIBC_2.12 installed on your machine and not 2.26
No, that is not the issue. GLIBC-2.26 most certainly provides the pthread_setname_np##GLIBC_2.12 symbol (see this answer to understand how symbol versioning works).
You can verify that the symbol is indeed available in your GLIBC-2.26 like so:
$ readelf -Ws /lib/x86_64-linux-gnu/libpthread.so.0 | grep pthread_setname_np
89: 00000000000113c0 258 FUNC GLOBAL DEFAULT 13 pthread_setname_np##GLIBC_2.12
704: 00000000000113c0 258 FUNC GLOBAL DEFAULT 13 pthread_setname_np
(Above command was executed on a system with GLIBC-2.19, but you'll get the same output on a system with GLIBC-2.26).
Now to what your real problem is: libHSrts.a(OSThreads.o) references pthread_setname_np (and likely other pthread_* symbols, but you are not linking with -pthread or -lpthread flag.
I don't know where to add this flag to GHC, but once you find that out, your problem will be solved.

Build Duktape for specific platform (ARM 32/ ARM 64)

I'm going to use Duktape for javascript evaluation for ARM 32/64 platforms.
I want to build Duktape only for specific platform & architecture, not for all range.
It seems, that I can build it successfully:
python tools/configure.py \
--source-directory src-input \
--platform linux \
--architecture arm32 \
--config-metadata config/ \
--option-file arm32_config.yaml \
--output-directory /tmp/arm32
arm32_config.yaml:
DUK_USE_32BIT_PTRS: true
DUK_USE_64BIT_OPS: false
DUK_USE_FATAL_HANDLER: false
Build pass usually.That's great!
On Raspberry Pi (use it just for tests):
I have a hello.c:
#include "duktape.h"
int main(int argc, char *argv[]) {
duk_context *ctx = duk_create_heap_default();
duk_eval_string(ctx, "print('Hello world!');");
duk_destroy_heap(ctx);
return 0;
}
and Makefile.hello file:
DUKTAPE_SOURCES = src/arm32/duktape.c
# Compiler options are quite flexible. GCC versions have a significant impact
# on the size of -Os code, e.g. gcc-4.6 is much worse than gcc-4.5.
CC = gcc
CCOPTS = -Os -pedantic -std=c99 -Wall -fstrict-aliasing -fomit-frame-pointer
CCOPTS += -I./src/arm32 # for combined sources
CCLIBS = -lm
CCOPTS += -DUK_USE_32BIT_PTRS
CCOPTS += -DUK_USE_64BIT_OPS
CCOPTS += -DUK_USE_FATAL_HANDLER
# For debugging, use -O0 -g -ggdb, and don't add -fomit-frame-pointer
hello: $(DUKTAPE_SOURCES) hello.c
$(CC) -o $# $(DEFINES) $(CCOPTS) $(DUKTAPE_SOURCES) hello.c $(CCLIBS)
It also works!
But when I'm trying to start program ./hello I've always recived:
Segmentation fault
Could please point out on my mistakes?What have I missed?
Thank you in advance!
ps: gcc version 4.9.2 (Raspbian 4.9.2-10)
The main problem you are most likely having is that you're working from Duktape master (which will become the 2.0.0 release) which no longer provides a built-in "print()" binding. That causes an error to be thrown.
That error is uncaught because you don't have a protected call wrapping the eval call, so that a fatal error occurs. Since you don't provide a fatal error handler (in duk_create_heap() or via DUK_USE_FATAL_HANDLER) that causes the default fatal error behavior which is to cause an intentional segfault (this is so that a debugger can attach).
So the easiest fix is to define a print() binding and maybe add a fatal error handler and/or a protected call for the eval. Here's an example to add a print() binding (before doing the eval):
static duk_ret_t native_print(duk_context *ctx) {
duk_push_string(ctx, " ");
duk_insert(ctx, 0);
duk_join(ctx, duk_get_top(ctx) - 1);
printf("%s\n", duk_safe_to_string(ctx, -1));
return 0;
}
/* ... before doing eval(): */
duk_push_c_function(ctx, native_print, DUK_VARARGS);
duk_put_global_string(ctx, "print");
Other minor comments:
Duktape duk_config.h detects the platform and target you're building for; Duktape never really builds "for all targets" as far as the resulting binary is concerned. So having multiple platforms in duk_config.h doesn't make the result any bigger for example.
You shouldn't need the values in your arm32_config.yaml. ARM32 should be detected automatically.
The Makefile.hello you're using is (adapted) from Duktape 1.x while the code you're compiling is from Duktape master. The CCOPTS options will be ignored by Duktape master (they go into tools/configure.py) and their format is wrong in the example, e.g. -DUK_USE_FATAL_HANDLER defines the preprocessor value UK_USE_FATAL_HANDLER.

Linking GSL library to RcppGSL on Windows machine

I try to link the GSL library to the RcppGSL package. The following is my test function:
# colNorm.cpp
// [[Rcpp::depends(RcppGSL)]]
#include <RcppGSL.h>
#include <gsl/gsl_matrix.h>
#include <gsl/gsl_blas.h>
extern "C" SEXP colNorm(SEXP sM) {
try {
RcppGSL::matrix<double> M = sM; // create gsl data structures from SEXP
int k = M.ncol();
Rcpp::NumericVector n(k); // to store results
for (int j = 0; j < k; j++) {
RcppGSL::vector_view<double> colview = gsl_matrix_column (M, j);
n[j] = gsl_blas_dnrm2(colview);
}
M.free() ;
return n; // return vector
} catch( std::exception &ex ) {
forward_exception_to_r( ex );
} catch(...) {
::Rf_error( "c++ exception (unknown reason)" );
}
return R_NilValue; // -Wall
}
The GSL library is succesfully linked to the RcppGSL if the following command does not throw a compiler error:
sourceCpp("colNorm.cpp")
Since I am using Windows machine, I need to define environment variables such that RcppGSL knows where the GSL library is located.
I tried editing the environment variable, but the following compiler error shows that the package is still unable to find the GSL library:
g++ -m64 -I"C:/PROGRA~1/R/R-31~1.1/include" -DNDEBUG -I"C:/CodeLibrary/lib"/include - I"C:/PROGRA~1/R/R-31~1.1/library/Rcpp/include" -I"C:/PROGRA~1/R/R-31~1.1/library/RcppGSL/include" -I"d:/RCompile/CRANpkg/extralibs64/local/include" -O2 -Wall -mtune=core2 -c colNorm.cpp -o colNorm.o
g++ -m64 -shared -s -static-libgcc -o sourceCpp_38624.dll tmp.def colNorm.o -LC:/CodeLibrary/lib/lib -lgsl -lgslcblas -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lRlapack -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lRblas -lgfortran -Ld:/RCompile/CRANpkg/extralibs64/local/lib/x64 -Ld:/RCompile/CRANpkg/extralibs64/local/lib -LC:/PROGRA~1/R/R-31~1.1/bin/x64 -lR
c:/program files/r/r-3.1.1/rtools/gcc-4.6.3/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lgsl
c:/program files/r/r-3.1.1/rtools/gcc-4.6.3/bin/../lib/gcc/i686-w64-mingw32/4.6.3/../../../../i686-w64-mingw32/bin/ld.exe: cannot find -lgslcblas
collect2: ld returned 1 exit status
I set an environment variable LIB_GSL equal to "C:/CodeLibrary/lib". In the first line, the compiler takes my environment variable and adds /include. In the second line, the compiler adds /lib. Those locations do not exist on my C drive, maybe that's the reason why it cannot find the library.
I would be really happy, if someone with a lot of compiler experience could show how to successfully link a 3rd party library to a package on Windows machine.
Maybe more environment variables need to be defined?
Thanks Dirk for your handholding! I got it finally up and running.
Three things have to be done:
1) Download the local300 folder from your link and allocate folder on your drive. The path cannot contain any whitespaces, i.e. C:/Program Files/local300 will not work but
C:/local300 will work
2) Set the environment variable LIB_GSL equal to this path, e.g. LIB_GSL to C:/local300
3) The compiler looks at LIB_GSL/lib for libgsl.a and libgslcblas.a (-lgsl and -lgslcblas). However, in LIB_GSL/lib are subfolders i386 and x64. I didn't know how to change the place the compiler looks for the files, thus I copied everything from inside x64 and put it into LIB_GSL/lib folder (one folder level above).
This allows RcppGSL to compile code without errors.
Look at this page which is (after a link or two) pointed to from the R Installation and Administration manual, appendix D for Windows.
Expand that, see where it puts headers and the library for GSL and adjust LIB_GSL accordingly.
This is what CRAN itself uses, so we know it works.

Install CUDA for Haskell using Autoconf on Win7

I'm attempting to install the following Haskell package on Windows using Cygwin: HaskellCuda
You can install the package using "cabal install cuda".
Here is the output I get (you may have to "cuda install c2hs" first):
$ cabal install
Configuring cuda-0.4.0.2...
checking for gcc... C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
checking for C compiler default output file name...
configure: error: C compiler cannot create executables
See `config.log' for more details.
Resolving dependencies...
cabal.exe: Error: some packages failed to install:
cuda-0.4.0.2 failed during the configure step. The exception was:
ExitFailure 77
The relevant part from the log file is:
configure:1758: checking for gcc
configure:1785: result: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe
configure:2022: checking for C compiler version
configure:2029: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe --version >&5
configure: line 2030: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2035: $? = 127
configure:2042: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -v >&5
configure: line 2043: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2045: $? = 127
configure:2052: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -V >&5
configure: line 2053: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2055: $? = 127
configure:2078: checking for C compiler default output file name
configure:2105: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe -fno-stack-protector conftest.c >&5
configure: line 2106: C:\Haskell\2011.4.0.0\mingw\bin\gcc.exe: command not found
configure:2108: $? = 127
configure:2146: result:
configure: failed program was: [source elided]
If I go to Cygwin and type
gcc --version
I get something reasonable. The problem appears to be more with the path I guess, but I'm not sure what/how to fix it. I should also note that using "cabal install cuda-0.2.2", an older version of this package, I get past this step (but get a different error later).
To replicate, make sure you install the Haskell Platform in a path without spaces, otherwise you will probably get a different error. That's the only thing I've figured out so far.
Any help with this would be GREATLY appreciated, I've spent about a week so far and haven't gotten anywhere.
EDIT:
$PATH = C:\Haskell\2011.4.0.0\mingw\bin;
C:\Haskell\2011.4.0.0\lib\extralibs\bin;
C:\Haskell\2011.4.0.0\bin;
C:\CUDA\v4.0\bin\;
C:\cygwin\bin\;
...
I managed to get it to install, but it isn't pretty and I don't really understand why it won't work out of the "autoconf" box.
For starters, rather than installing with "cabal install" (using a local copy), I used the sequence
>runhaskell Setup.hs configure
>runhaskell Setup.hs build
>runhaskell Setup.hs install
The main reason for this is because it is simple to change the $CC variable in the configure script using the argument in Setup.hs. I suspected the $CC was the variable giving me the problem. I changed:
[("CC", ccProg)
to
[("CC", "/cygdrive/c/cygwin/bin/gcc.exe")
in Setup.hs, which is the gcc that comes with Cygwin. My initial suspicion was that autoconf didn't like the Windows-style path to gcc, which it was using based on the log file above. I also discovered though that of the multiple copies of gcc on my computer (one in Haskell/mingw, one in a separate installation of mingw, and whichever version $PATH was pointing to, ONLY the cygwin gcc was able to successfully compile the test file that checked for . Using the cygwin gcc, I could run
gcc hello.c
on any file that included (WITHOUT an external include directive), whereas with any other copy of gcc, even something like
gcc -I/cygdrive/c/..../include hello.c
was not able to find . No idea why.
Just changing the $CC to the Cygwin gcc fixed almost all of the errors. The next errors occurred when "checking for library containing cudaRuntimeGetVersion/cuGetDriverVersion".
The file configure was trying to compile was
#define PACKAGE_NAME "Haskell CUDA bindings"
#define PACKAGE_TARNAME "cuda"
#define PACKAGE_VERSION "0.4.0.0"
#define PACKAGE_STRING "Haskell CUDA bindings 0.4.0.0"
#define PACKAGE_BUGREPORT "tmcdonell#cse.unsw.edu.au"
#define STDC_HEADERS 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_SYS_STAT_H 1
#define HAVE_STDLIB_H 1
#define HAVE_STRING_H 1
#define HAVE_MEMORY_H 1
#define HAVE_STRINGS_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_STDINT_H 1
#define HAVE_UNISTD_H 1
#define HAVE_CUDA_H 1
#define HAVE_CUDA_RUNTIME_API_H 1
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char cudaRuntimeGetVersion ();
int main ()
{
return cudaRuntimeGetVersion ();
;
return 0;
}
using the command:
/cygdrive/c/cygwin/bin/gcc.exe -o conftest.exe -fno-stack-protector
-I/cygdrive/c/CUDA/v4.0/include -L/cygdrive/c/CUDA/v4.0/lib conftest.c -lcudart
The error (from the log file) is
/cygdrive/c/Users/crockeea/AppData/Local/Temp/ccKMQJiq.o:conftest.c:(.text+0xc):
undefined reference to `_cudaRuntimeGetVersion'
I'm a little rusty on my C, but it seems like they aren't include the appropriate header file here. That probably isn't right because the same file works on Unix based systems when running configure, but it's my best guess. Also, editing configure to make this file include cuda.h just results in a different error about multiple definitions of cudaRuntimeGetVersion. So my hack was to comment out the lines in the configure file with references to cudaRuntimeGetVersion/cuGetDriverVersion. I put C-comments into the C files that the configure file was going to compile (it is easy enough to find the source code for these in the configure file based on line numbers from the log file). I don't know the consequences of modifying the configure file in this way.
This allowed me to get past the 'build' phase. More comments if I run into any other issues.

Resources