I am trying to incorporate a C library into some Rcpp code.
I can use the C library in a C++ program easily. I 'make' the C library, which creates the .a and .dll files in the /lib folder. I can then use the package by including the header in the program and running something like this from command line:
cc myfile.cpp -o myfile -Ipath.to.header path.to.lib.a -lz
This essentially tells the compiler to take the .cpp program, include headers from -I, and to link to two libraries.
Getting this to work with Rcpp shouldn't be overly difficult if I understand makevars correctly (which I unfortunately don't seem to).
I add the library to a folder in my package, and in src I add a makevars and makevars.win that look like this:
PKG_CFLAGS=
# specify header location
PKG_CPPFLAGS=-Ipath.to.lib/include
# specify libs to link to
PKG_LIBS=path.to.lib/lib/file.a -lz
# make library
path.to.lib/lib/file.a:
cd path.to.lib;$(MAKE)
This correctly 'makes' the .a and .dll files for the library, however none of the Rcpp magic runs (i.e. in the build I never see the g++ system call that compiles the files in src), so "no Dll was created".
I am fairly certain this is a problem in my makevars target that makes the library. When I remove that portion from the makevars, and 'make' the library from the command line myself before building the package, I get the proper g++ calls with my -I and -l statements, but I get errors about undefined references.
I notice that the -l statements are only included in the final g++ call where the final .dll is made, but isn't included in the earlier g++ calls where the files with the library headers are compiled.
So I have two problems:
How do I fix my makevars so that it 'makes' the library, but doesn't stop Rcpp from compiling the files in src?
How do I deal with the undefined references? The library is clearly not header-only, so I am guessing it needs the -l statement in the earlier g++ calls, but that may not even be possible.
The best approach is to avoid complicated src/Makevars file altogether.
One easy-ish approach around this: use configure to build your static library, then once you actually build just refer to it in src/Makevars.
I use that scheme in Rblpapi (where we copy an externally supplied library in) and in nloptr where we download nlopt sources and build it 'when needed' (ie when no libnlopt is on the system).
Related
I have 'correctly' installed gsl on mac 10.13.2.
In my c++ program, I am calling like usual, for example:
#include <gsl/gsl_math.h>
However while running the code, it can not find the gsl.
fatal error: 'gsl/gsl_math.h' file not found
I was wondering how to correctly link gsl PATH and libraries.
I have tried,
setting PATH and LD_LIBRARY_PATH in .bash_profile
setting PKG_CONFIG_PATH to .../Gsl2.3/lib/pkgconfig
$which gsl-config returns
/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/bin/gsl-config
$pkg-config --libs gsl returns
-L/Users/gkdgoutam/Softwares/HEP_Softwares/Install/Gsl2.3/lib -lgsl -lgslcblas -lm
The only solution I can find is to run everytime with gsl linked.
Like:
g++ $(gsl-config --cflags) mycode.cc $(gsl-config --libs) && ./a.out
But I was wondering if the GSL PATH can be set globally so that I can simply run
g++ mycode.cc && ./a.out
This is how c++ code is compiled and built:
COMPILATION
A compilation unit will take each cpp file and work its way through included headers to locate forward declaration of implementations of symbol signatures of used functionality in your code. In your case this involves gsl/gsl.h. If the file cannot be found in the search directories, which you can expand by specifying C_INCLUDE_PATH and or CPLUS_INCLUDE_PATH. If you omit #include <gsl/gsl_math.h>, your code will not compile as there are signatures, which cannot be found for GSL functions, which you use.
LINKING
Once you have compiled all cpp/cc files you need to link the binary, which can be executed. The linking process consists of a search through all symbols in your .o/.obj... files and a matching of the same to what it can find in your object files and the libraries, which you have specified using for example -lgsl. If all goes well, every lookup finds an according binary implementation for your machine's hardware model (i.e. 64bit/32bit ..., Arm, Intel, ... etc). If some are not found you will find linkage errors.
What you are asking is, is there a way that C++ does not work as above? No!
If you leave out #include <gsl/gsl.h> or if said file is not found in your search paths, compilation will not work or. If you omit -lgsl, linking will fail. If you find it annoying to write all the above stuff in the command line, write a Makefile to reduce the building process to ideally a simple command: make.
Don't forget, that if you are linking against the shared library version of GSL, you might need specifying LD_LIBARAY_PATH on Linux and DYLD_LIBRARY_PATH on Macs as well.
TLDR: you cannot ask a c++ compiler / linker to work differently as designed.
I have a bunch of C++ files that reference functions defined in a sub-directory inside src/. Is there a way to specify the cpp files inside the sub-directory via g++?
Here is the structure of the package:
# SeqLib
# |----src
# |-----|---Makevars
# |-----|---rcpp_hello_world.cpp
# |-----|---SeqLib(a submodule)
# |-----|------|---SeqLib
# |-----|------|---FermiAssembler.h
# |-----|------|---src
# |-----|------|---|----FermiAssembler.cpp
************************* EDIT **************
When running -I../src/SeqLib/, I get an error undefined symbol: _ZN6SeqLib14FermiAssemblerD1Ev. Using c++filt, the symbol references the destructor declared in FermiAssembler.h but, defined in FermiAssembler.cpp
You have to pass all the .cpp files to the compiler command. It's strongly discouraged to include .cpp files in other .cpp files.
The command line that is likely to work for you is:
g++ -ISeqLib -o my_executable rcpp_hello_world.cpp SeqLib/src/FermiAssembler.cpp
If you have a lot of files, it is advised to create a makefile script to avoid recompiling all the code every time.
if your FermiAssembler product contains Makefile.am/in files, it can build itself using a configure script which is probably here. The general idea is the:
cd SeqLib
./configure
make
If it's a library product, it builds as a .a or .so file. In that case, the command line becomes:
g++ -ISeqLib -o my_executable rcpp_hello_world.cpp SeqLib/bin/FermiAssembler.a
(I'm just gessing the path & name of the output library file)
To include .a files from there, just add their path. Not sure that SeqLib/bin/*.a would do it because lib dependencies don't follow alphabetical order. A very bruteforce thing that would work would be specifying all .a files twice (so inter-lib dependencies would work):
g++ -ISeqLib -o my_executable rcpp_hello_world.cpp SeqLib/bin/*.a SeqLib/bin/*.a
it would be better, though, to include only the required .a files, respecting the following order: first the ones depending on the following ones. The last library mustn't depend of any of the previous ones.
I have an already built library made of this files:
A bunch of headers.
A .so file (libmylib.so).
I want to compile a c++ program (sample.cpp), where I included the headers, and where I need to use the library. This is what I've done, and it's working:
Put the headers in usr/local/include.
Put the .so file in usr/local/lib.
Compile the program in this way: g++ sample.cpp -lmylib.
My question is: why is it not working if I omit -lmylib from the last line?
Is there a way to install the library such that I don't need to put it every time in the g++ command?
Thank you.
What libs are used by default depends on some setting in the compiler/linker,
but it´s not "every lib in usr/local/lib" or any directory, just some specific names
(or even just a single one). Call g++ -v or g++ -dumpspecs to list it (and more stuff)
So, either rebuild your compiler with your own lib list, or specify it manually everytime.
I built and installed the source code of spidermonkey, I want to link its library and its include folder with my C++ application, so I wrote this command on linux
g++ -I/home/SpiderMonkey/js-1.8.5/js/src/dist/include
-L/home/SpiderMonkey/js1.8.5/js/src/dist/lib -lmozjs185 helloworld.cpp -o
but it gives me undefined reference error, so what is the problem with this command:
the path which the src code was built in is home/SpiderMonkey/js1.8.5/src
and when I installed the src code, its libs and include folder exist now in usr/local/lib and usr/local/include/js respectively, so which path should I use in the command to compile my hellowrorld.cpp.
Also, I found 3 libraries with the same name but with different extension:
libname.so, libname.so.1.0, libname.so.1.0.0 and libname.a
which library should I use and what are the differences?
Put the libraries after your main.cpp on the compilation command. The linker determines which symbols to pull out of those libraries based on the objects it's already seen, left to right.
As for your addendum question:
libname.a is for static linking.
libname.so, libname.so.1.0 and libname.so.1.0.0 are all the same file, just with names that give you an increasing level of version information granularity.
Which to use is beyond the scope of this answer, but you can find plenty of information about that already existing on the web.
I have access to a large C++ project, full of files and with a very complicated makefile courtesy of automake & friends
Here is an idea of the directory structure.
otherproject/
folder1/
some_headers.h
some_files.cpp
...
folderN/
more_headers.h
more_files.cpp
build/
lots_of things here
objs/
lots_of_stuff.o
an_executable_I_dont_need.exe
my_stuff/
my_program.cpp
I want to use a class from the big project, declared in say, "some_header.h"
/* my_program.cpp */
#include "some_header.h"
int main()
{
ThatClass x;
x.frobnicate();
}
I managed to compile my file by painstakingly passing lots of "-I" options to gcc so that it could find all the header files
g++ my_program.cpp -c -o myprog.o -I../other/folder1 ... -I../other/folderN
When it comes to compiling I have to manually include all his ".o"s, which is probably overkill
g++ -o my_executable myprog.o ../other/build/objs/*.o
However, not only do I have to do things like manually removing his "main.o" from the list, but this isn't even enough since I forgot to also link against all the libraries that he happened to use.
otherproject/build/objs/StreamBuffer.h:50: undefined reference to `gzread'
At this point I am starting to feel I am probably doing something very wrong. How should I proceed? What is the usual and what is the best approach this kind of issue?
I need this to work on Linux in case something platform-specific needs to be done.
Generally the project's .o files should come grouped together into a library (on Linux, .a file if it's a static library, or .so if it's a dynamic library), and you link to the library using the -L option to specify the location and the -l option to specify the library name.
For example, if the library file is at /path/to/big_project/libbig_project.a, you would add the options -L /path/to/big_project -l big_project to your gcc command line.
If the project doesn't have a library file that you can link to (e.g. it's not a library but an executable program and you just want some of the code used by the executable program), you might want to try asking the project's author to create such a library file (if he/she is familiar with "automake and friends" it shouldn't be too much trouble for him), or try doing so yourself.
EDIT Another suggestion: you said the project comes with a makefile. Try makeing it with the makefile, and see what its compiler command line looks like. Does it have many includes and individual object files as well?
Treating an application which was not developed as a library as if it was a library isn't likely to work. As an offhand example, omitting the main might wind up cutting out initialization code that the class you want depends upon.
The responsible thing to do here is to read the code, understand it, and turn the functionality you want into a proper library. Build the "exe you don't need" with debug symbols and set breakpoints in the constructors and methods of the class. Step into them so you get a grasp on the functionality and what parts of the program are relevant and irrelevant to your needs.
Hopefully the code is under some kind of version control system that supports branching (such as Git). If not, make your own repository that does. Edit the files until you've organized them into a library and code that uses the library. Make sure it works properly within the context of the original program. Then turn around and use this library in your own program.
If you've done a good job, you might be able to convince the original authors to accept the separation back into their original codebase. If not, at least version control has your back so you can manage integration of future changes.