Rtools fails compiling shared objects (R software - CRAN) - c++

CRAN is asking to handles some NOTEs.
In particular, they are asking to avoid specifying the c++ standard in the Makevars file according to the "CRAN incoming feseability" . Hence, I should drop the CXX_STD= CXX11 in the Makevars.
A priori, it should not be a problem for the C++ backward compatibilty.
I made the opportune changes and checked the package on linux and as one might expect, the new version of the package passes the usual checks through R CMD check MyPackage.tar.gz.
Relying on rhub functionalities, the new version of the package passes the checks also on macOs.
For what concerns windows, I get an error during the building of the shared object, in the last step of the compilation process.
In particular, dropping CXX_STD= CXX11, using R 4.3.0 (R under development) and relying on rtools43, the last step of the compilation reads as follows:
gcc -shared -s -static-libgcc -o fdaPDE.dll tmp.def ObjectFile1.o .... ObjectFileN.o -LC:/rtools43/x86_64-w64-mingw32.static.posix/lib/x64 -LC:/rtools43/x86_64-w64-mingw32.static.posix/lib -LC:/PROGRA~1/R/R-devel/bin/x64 -lR
C:\rtools43\x86_64-w64-mingw32.static.posix\bin/ld.exe: ObjectFile1.o:ObjectFile.cpp:(.text+0x33f4): undefined reference to `operator new(unsigned long long)'
C:\rtools43\x86_64-w64-mingw32.static.posix\bin/ld.exe: ObjectFile1.o:ObjectFile1.cpp:(.text+0x340b): undefined reference to `std::_Rb_tree_insert_and_rebalance(bool, std::_Rb_tree_node_base*, std::_Rb_tree_node_base*, std::_Rb_tree_node_base&)'
C:\rtools43\x86_64-w64-mingw32.static.posix\bin/ld.exe: ObjectFile1.o:ObjectFile1.cpp:(.text+0x3432): undefined reference to `std::_Rb_tree_decrement(std::_Rb_tree_node_base*)'
C:\rtools43\x86_64-w64-mingw32.static.posix\bin/ld.exe:
.....
and so on
.....
It seems that gcc does not link properly the standard library. Is Rtools broken?
On the other hand, If I specify c++11 as c++ standard then the compilation process ends without any errors and in particular the last steps of the compilation process reads as follows:
g++ -shared -s -static-libgcc -o fdaPDE.dll tmp.def ObjectFile1.o .... ObjectFileN.o -LC:/rtools43/x86_64-w64-mingw32.static.posix/lib/x64 -LC:/rtools43/x86_64-w64-mingw32.static.posix/lib -LC:/PROGRA~1/R/R-devel/bin/x64 -lR
installing via 'install.libs.R' to ...
Same results using R release and R oldrelease compiling the package with rtools42 and rtools40, respectively.
In my knownledge, there is not a trick to force the call of g++ during the linking phase due to the fact that adding CXX=g++ in the Makevars.win file would have no effect on the compilation.
I would be pleased to read any advice or suggestions on this problem,
Thanks

Related

Compiling using gcc of a Cpp code which is calling a TCL script

I have a cpp code in which I have included tcl.h library. I am trying to compile it using the gcc compiler. but I'm getting the following error :
gcc -o top.o -std=c99 top.c
top.c:12: warning: return type defaults to 'int'
/tmp/ccDOTTZQ.o: In function `main':
top.c:(.text+0xa): undefined reference to `Tcl_CreateInterp'
top.c:(.text+0x1f): undefined reference to `Tcl_EvalFile'
top.c:(.text+0x3d): undefined reference to `Tcl_GetVar2Ex'
top.c:(.text+0x75): undefined reference to `Tcl_ListObjGetElements'
top.c:(.text+0xb1): undefined reference to `Tcl_GetString'
top.c:(.text+0xcc): undefined reference to `Tcl_GetInt'
collect2: ld returned 1 exit status
Its not able to find the Cpp-tcl APIs. Kindly help me with this.
Your code is not linking to the Tcl library, so obviously it can't find the implementations of those functions. (In C and C++, the linking to the implementations of functions is a separate stage from the use of the declarations of those functions, which is what the header files provide.)
Except that you're actually calling gcc wrong. You need to use two steps, first with -c to compile the source code to an object file:
gcc -c -o top.o -std=c99 top.c
Then like this to link the result and make an executable:
gcc -o top.exe -std=c99 top.o -ltcl
With the first, you might need to additionally specify an appropriate -I option to locate the include files (if they're not in the standard locations). With the second, you might need to specify an appropriate -L option to locate the library files (libtcl.so). Depending on the system, you might also need to specify some version numbers (e.g., -ltcl86 or -ltcl8.6 instead of -ltcl). These are all options that depend on your build system configuration, so they're hard to predict exactly here.

Boost regex: Undefined references when linking

Until some weeks ago, using the boost_regex library I used to compile a C++ file test.cpp using the following command.
g++-4.9 -Wall -O3 -march=native -flto -DNDEBUG -o test \
--std=c++14 test.cpp -lboost_regex -pthread
The compilation was working perfectly. But at some point, I needed to upgrade my OS (more precisely, it was Ubuntu 14.04, now it is Ubuntu 16.04).
I kept my local folders with my data, and I also installed the Boost library again in the new system, including boost_regex.
The Boost version in the new system is 1.58, unfortunately I cannot know which Boost version I was using before because it is now deleted.
I try to compile again the same file in the new system, with the same command as above, and the linker says it cannot find two functions called maybe_assign and construct_init. If I replace the -o test option with just -c (i.e. without linking) then the program is compiled without errors.
More precisely, when I try to do linking I get the following errors (they were extremely long, I hade to shorten using ... dots).
In function `boost::re_detail::perl_matcher<...>::match_match()':
undefined reference to `boost::match_results<...>::maybe_assign(boost::match_results<...> const&)'
In function `bool boost::regex_search<...>(...)':
undefined reference to `boost::re_detail::perl_matcher<...>::construct_init(...)'
In function `boost::re_detail::perl_matcher<...>::match_prefix()':
undefined reference to `boost::match_results<...>::maybe_assign(boost::match_results<...> const&)'
collect2: error: ld returned 1 exit status
I really don't know how this is possible, the libraries seem perfectly installed, nothing seems missing, and the compilation was working with a previous OS installation (then I guess older libraries).
At these point my only guess could be that Boost authors removed such functions? (maybe they are obsolete?). But I didn't find any trace of this on internet. If this is the case, how can I know the boost versions in which such functions are available?
Am I doing any mistake? Do you have any suggestions to investigate about this?
TL;DR use gcc5.
Ununtu 16.04 comes with gcc5 by default. Every C++ library in it is compiled with that compiler.
Now there was an incompatible C++ ABI change between gcc4 and gcc5. It made binaries built from C++ sources with gcc4 incompatible by default with binaries built with gcc5. This incompatibility often manifests itself as a bunch of undefined symbols that reference std::string and/or std::list.
The standard library comes built with a dual ABI to support objects built with older compilers. Other libraries like boost, hovever, don't.

g++ undefined reference error when linking to third party shared libraries

I'm trying to link a c++ program that uses several shared libraries from 3rd parties. Mainly, these libraries come from a github project called MBSim and I downloaded the latest daily build with all its binaries, libraries and headers, which I installed on /usr/local/mbsim-env.
The most important libraries called are libmbsim, libopenmbvcppinterface, libfmatvec and libboost_filesystem (the last one comes with the MBSim distro).
I set up a simple code to test it and it compiles like a charm using
g++ main.cpp -m64 -g3 -std=c++11 -Wall
-Wfatal-errors -Werror -Wno-unknown-pragmas -fopenmp
`pkg-config --cflags mbsim` -I. -c -o main.o
The pkg-config part calls, as you can wonder, the include directories and flags:
-DHAVE_ANSICSIGNAL -DHAVE_OPENMBVCPPINTERFACE -DHAVE_BOOST_FILE_LOCK
-I/usr/local/mbsim-env/include
-I/usr/include/x86_64-linux-gnu
-I/usr/include/x86_64-linux-gnu/c++/5
-I/usr/local/include
My problems appear when I try to link the objects with the pre-compiled libraries with:
g++ system.o main.o -o teste -L/usr/local/mbsim-env/lib
-lmbsim -lopenmbvcppinterface -lboost_system
-lfmatvec -lm
-Wl,-rpath,/usr/local/mbsim-env/lib
Edit: On the above command, I've tried to use pkg-config --libs as well. The results remain the same.
First of all, the linker issues a warning that I'm linking against an older boost library:
/usr/bin/ld: warning: libboost_system.so.1.53.0,
needed by /usr/local/mbsim-env/lib/libmbsim.so,
may conflict with libboost_system.so.1.61.0
I'm aware of that, but I intentionally want to link against the old one because that's the one that was used to compile the MBSim libraries.
After that, I got several undefined reference warnings for almost every method that I call from MBSim:
system.cpp:59: undefined reference to
MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
It seems to me that this error means that the target libraries don't have the RigidBody method implemented. Well, I know they do.
My first guess was that maybe the linker was looking at the wrong library path, so I set LD_LIBRARY_PATH=/usr/local/mbsim-env/lib and added the -rpath to the same folder. That didn't help at all.
Some googling showed me that the problem could be compiling in 64bits and linking it against 32bits libs. I believe that's not the case: I've done everything in Ubuntu 16.04 64bits and the MBSim libraries are also 64bits.
Could somebody point me out of this dead end?
Could it be that your 3rd party shared libraries are compiled using an older version of GCC? There was a new ABI introduced in GCC 5. It's probably enabled by default on your platform. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html.
You could try switching to the older ABI, but that might require your other libraries to have been compiled with the old ABI also. You might also be able to switch ABIs for the 3rd party libraries explicitly.
undefined reference to MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<std::char_traits<char>, std::allocator<char> > const&)
This is a reference to MBSim::RigidBody::RigidBody(const string&), compiled with g++ -std=c++11 and g++ version 5 or later.
As any1 probably correctly guessed, the binary for libmbsim.so that you downloaded was built with g++ 4.x, and defines the same function with this signature:
MBSim::RigidBody::RigidBody(std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&)
Note lack of __cxx11 namespace. You can easily confirm or disprove this:
nm -C libmbsim.so | grep 'MBSim::RigidBody::RigidBody'
If this mismatch is indeed the cause, simply rebuild this project from source with your compiler. That's what open source is for.

Libquantum code Understanding Makefile

I tried to run .c file called grover.c in this C application libquantum
www.libquantum.de/files/libquantum-1.1.1.tar.gz
Now I this application already contains a Makefile.in and I can generate the executables called shor and grover using the command
./configure
make
make demos
But when I try to run grover.c using gcc or clan like this
clang grover.c
It gives me error of lots of undefined function reference.
In function oracle':
grover.c:(.text+0x50): undefined reference toquantum_sigma_x'
grover.c:(.text+0x89): undefined reference to quantum_toffoli'
grover.c:(.text+0xc8): undefined reference toquantum_toffoli'
grover.c:(.text+0xf2): undefined reference to quantum_cnot'
grover.c:(.text+0x137): undefined reference toquantum_toffoli'
grover.c:(.text+0x16b): undefined reference to quantum_toffoli'
grover.c:(.text+0x1b0): undefined reference toquantum_sigma_x'
I need to know how can I remove this error and if I can run this c code called grover.c in this application.
Thanks,
It looks like your compiler can not find one or more libraries to link to. My hunch is that the makefile has the appropriate commands to invoke the linker.
If you look at your makefile, you probably will see some commands like -L -l,
when the flag -L add a directory to the default search path for libraries and the flag -l is used to name the library to link.
for example -L/lib/openGL -lglut32 would cause the library libglut32.so.X.Y.Z which is found in the directory /lib/openGL. (not this is for a Linux system, but it should be fairly similar for Mac).
N.B. X.Y.Z are the version number of the library.
Once you work this out, there may be issues with the load finding the libraries, especially if they are in non-standard locations.
------------------------ edit --------------------------
After I posted this, and went to bed I realized that I missed a potential case (and thanks to Paul Griffiths for also noticing my omission.....teach me to do multiple things at once).
Any how, just compiling a simple file, say hello.c, as clang hello.c -o hello works because everything is in one file and clang will automatically link to the C run-time library.
If, in your case the code is spread across multiple files, say grover.c and file1.c you would need to do:
clang -c grover.c -o grover.o
clang -c file1.c -o file1.o
clang grover.o file1.o -o grover
(or alteratively clang grover.c file1.c -o grover)
SO what the first two lines are doing is translating the source-code files (grover.c and file1.c) into object files. THe third line covers the two object files into an executable.
Finally, both these cases can be involved. You could have multiple files as well as missing libraries.

Position of compiler flag -l

I'm currently learning OpenCL. Now, when I want to compile my program, I get an error with this command:
g++ -Wall -l OpenCL main.cpp -o main
The errors are mostly undefined references, because the library is not linked, I think (nevertheless I will post the error code at the end).
But with this command everything works fine:
g++ -Wall main.cpp -o main -l OpenCL
So my question is, what do I have to do, to use the -l Flag in front of the command?
(The Background is: I want to use Netbeans to compile my programm and when i add the flag under -> properties -> build -> C++ Compiler -> additional options, it will put in in the Position, shown in the first command)
Thanks in advance for your help
Here's the error code:
/tmp/ccmKP4oI.o: In function `cl::detail::ReferenceHandler<_cl_context*>::release(_cl_context*)':
main.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP11_cl_contextE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP11_cl_contextE7releaseES3_]+0x14): undefined reference to `clReleaseContext'
/tmp/ccmKP4oI.o: In function `cl::detail::ReferenceHandler<_cl_command_queue*>::release(_cl_command_queue*)':
main.cpp:(.text._ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE7releaseES3_[_ZN2cl6detail16ReferenceHandlerIP17_cl_command_queueE7releaseES3_]+0x14): undefined reference to `clReleaseCommandQueue'
/tmp/ccmKP4oI.o: In function `cl::Platform::getInfo(unsigned int, std::string*) const':
main.cpp:(.text._ZNK2cl8Platform7getInfoEjPSs[_ZNK2cl8Platform7getInfoEjPSs]+0x22): undefined reference to `clGetPlatformInfo'
/tmp/ccmKP4oI.o: In function `cl::Platform::get(std::vector<cl::Platform, std::allocator<cl::Platform> >*)':
main.cpp:(.text._ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE[_ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE]+0x41): undefined reference to `clGetPlatformIDs'
main.cpp:(.text._ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE[_ZN2cl8Platform3getEPSt6vectorIS0_SaIS0_EE]+0xb4): undefined reference to `clGetPlatformIDs'
collect2: error: ld returned 1 exit status
Order of [most] arguments to g++ is very important.
Libraries should go last (at least after source and object files). You can't really change that.
The -l should preferably be glued to the library name:
g++ -Wall main.cpp -o main -lOpenCL
# ^^^ glue the -l to the library name
You probably want to also pass -g (in addition of -Wall) to the compiler to get a debuggable binary. Use the gdb debugger.
As James Kanze commented, you might want to replace -g with -ggdb if using specifically gdb.
With g++ (and generally under Unix), -l specifies a source of
input (either a .a or a .so), and input is processed in
order. When the input is a static library (a .a file), it
will be scanned for objects which resolve undefined references;
if it is a .so, there aren't any object files in it, but it
will still only be taken into consideration if it resolves some
undefined symbol.
When you put the -l before any object files, there are no
undefined symbols yet, so nothing will be incorporated into the
program.