How to create a .so and .a file in UNIX. Do we have any standard utility for it?
*.a - archive library
to create it compile your sources:
gcc -c -o foo.o foo.c
gcc -c -o boo.o boo.c
ar -rsc yourlib.a foo.o boo.o
so - position independent code shared library
gcc -fPIC -shared -soname,libfoo.so.1 -o libfoo.so.1.0 foo.c boo.c
#create shared library
gcc -Os -fPIC -c test.c
gcc -shared test.so test.o
#create static library
gcc -Os -c test.c
ar rcs test.a test.o
The .a is also called a static library, and the .so is also called a dynamically loaded library.
I like the Program Library HOWTO.
This HOWTO for programmers discusses
how to create and use program
libraries on Linux. This includes
static libraries, shared libraries,
and dynamically loaded libraries.
The Yo Linux tutorial is also useful.
This tutorial discusses the philosophy
behind libraries and the creation and
use of C/C++ library "shared
components" and "plug-ins". The
various technologies and methodologies
used and insight to their appropriate
application, is also discussed. In
this tutorial, all libraries are
created using the GNU Linux compiler.
Take a look at this Makefile I wrote when I was new to C. It clearly shows how to generate and correctly link .a and .so files from a simple demo source.
Related
I've inherited some F77 code from the 1980s that I'd like to eventually use in an R package that is on CRAN. Basically I'll be substituting a slow function written in straight R with a .Call to a F77 subroutine that runs 100x faster. I've done similar heavy lifting with C in the past. However, when I compile the fortran subroutine via R CMD SHLIB I get a warning about one of the arrays being "larger than limit set by '-fmax-stack-var-size='". I can fix this by compiling explicitly with gfortran and setting -fmax-stack-var-size appropriately. However, how can I set the flag when running R CMD SHLIB? In a Makevars file? Eventually, I'll include this in a new release and submit to CRAN and I want to head off any issues. Many thanks.
Yes, in ~/.R/Makevars for your compilations, in src/Makevars for all builds of the package. CRAN has views on which options are portable so you may not be able to ship with the option in src/Makevars.
Here is what I have:
edd#rob:~$ grep ^F .R/Makevars
FLAGS=-Wall -O3 -g -pipe $(PEDANTIC) $(XTRAFLAGS)
FFLAGS=-O3 -g0 -Wall -pipe
FCFLAGS=-O3 -g0 -Wall -pipe
FC=$(CCACHE) gfortran
F77=$(CCACHE) gfortran
F95=$(CCACHE) gfortran
edd#rob:~$
where some of the other values are previoysly set as you can surmise. Note that there are several Fortran compiler variables, details as usual in Writing R Extensions.
I was looking at the verbose=TRUE when I tried to sourceCpp a Rcpp file. The last output is:
DIR: C:/Users/xyz/AppData/Local/Temp/RtmpmielLn/sourcecpp_226416891d0e
C:/PROGRA~1/R/R-31~1.0/bin/x64/R CMD SHLIB -o "sourceCpp_22129.dll" --preclean "myfile.cpp"
g++ -m64 -I"C:/PROGRA~1/R/R-31~1.0/include" -DNDEBUG -I"C:/Users/xyz/Documents/R/win-library/3.1/Rcpp/include" -I"d:/RCompile/CRANpkg/extralibs64/local/include" -O2 -Wall -mtune=core2 -c myfile.cpp -o myfile.o
g++ -m64 -shared -s -static-libgcc -o sourceCpp_22129.dll tmp.def myfile.o -Ld:/RCompile/CRANpkg/extralibs64/local/lib/x64 -Ld:/RCompile/CRANpkg/extralibs64/local/lib -LC:/PROGRA~1/R/R-31~1.0/bin/x64 -lR
I have a few questions regarding this:
the 1nd g++ command refers to -I"d:/RCompile/CRANpkg/extralibs64/local/include" and the 2nd command refers to -Ld:/RCompile/CRANpkg/extralibs64/local/lib/x64 and -Ld:/RCompile/CRANpkg/extralibs64/local/lib . But I don't have a D: drive, or a RCompile folder anywhere. What do these things refer to?
I tried to manually run the 1st g++ which ran file and created myfun.o file, but when I tried to manually run the 2nd g++ it gave me an error saying that it couldn't find the tmp.def file. I couldn't find the tmp.def file anywhere on my drives. Where would this tmp.def file located?
I looked under the hood of sourceCpp function. if I directly run the definition of cmd in the sourceCpp function: C:/PROGRA~1/R/R-31~1.0/bin/x64/R CMD SHLIB -o "sourceCpp_22129.dll" --preclean "myfile.cpp" on Windows' command window , I noticed that it does not include -I"C:/Users/xyz/Documents/R/win-library/3.1/Rcpp/include" and the R CMD SHLIB gives me an error.
How does the system(cmd, ..) within the sourceCpp function include this? The value of the cmd variable in the sourceCpp didn't include -I"C:/Users/xyz/Documents/R/win-library/3.1/Rcpp/include"
the 1nd g++ command refers to -I"d:/RCompile/CRANpkg/extralibs64/local/include" and the 2nd command refers to -Ld:/RCompile/CRANpkg/extralibs64/local/lib/x64 and -Ld:/RCompile/CRANpkg/extralibs64/local/lib . But I don't have a D: drive, or a RCompile folder anywhere. What do these things refer to?
AFAIK these are left in as part of the CRAN R Windows distribution; when R binaries are built on Windows they use something in these library paths on the build servers (but stay baked into R anyhow). You can safely ignore it, but it is a bit odd. Unused / non-existent directories passed through gcc / g++ are just ignored.
I tried to manually run the 1st g++ which ran file and created myfun.o file, but when I tried to manually run the 2nd g++ it gave me an error saying that it couldn't find the tmp.def file. I couldn't find the tmp.def file anywhere on my drives. Where would this tmp.def file located?
tmp.def, as it sounds, is a temporary definition file created by R CMD SHLIB on Windows. If you just re-run what you see it does not get generated, so I suppose R does something behind the curtains to generate it. If you are curious about where it's generated, see share/make/winshlib.mk in the R sources.
I looked under the hood of sourceCpp function. if I directly run the definition of cmd in the sourceCpp function: C:/PROGRA~1/R/R-31~1.0/bin/x64/R CMD SHLIB -o "sourceCpp_22129.dll" --preclean "myfile.cpp" on Windows' command window , I noticed that it does not include -I"C:/Users/xyz/Documents/R/win-library/3.1/Rcpp/include" and the R CMD SHLIB gives me an error.
This is because sourceCpp is setting the appropriate environment flags behind the scenes for you as well -- in this case, the CXXFLAGS environment variable. This gets automatically done on package installs as well when the LinkingTo: entry is specified in the DESCRIPTION file.
I had a very similar g++ compilation command as posted in the question, and the compilation of a very simple C function didn't work for me.
The reason it didn't work is the following option shown in the g++ command:
-I"d:/RCompile/CRANpkg/extralibs64/local/include"
which adds an include directory on a drive that does not exist on my computer. Apparently non-existent directories listed in the -I option are ignored by g++ (as stated by Kevin Ushey) but this seems not to be the case for non-existent drives.
The error message I received was that the sdtlib.h header file was not found:
C:/PROGRA~1/R/R-32~1.0/include/R.h:28:20: fatal error:
d:/RCompile/r-compiling/local/local320/include/stdlib.h: Input/output
error #include
In order to remove the offending -I option from the g++ command I had to edit the Makeconf file located in $(R_HOME}/etc$(R_ARCH) (in my case C:\Program Files\R\R-3.2.0\etc\x64) and comment out the line:
LOCAL_SOFT = d:/RCompile/r-compiling/local/local320
I'm building a package containing an old f77 code that should absolutely be build with the o0 optimization option.
In the /src/Makevars of my package I added this line:
FFLAGS=-O0 -pipe -g $(LTO)
but when I compile my package, I see R is still using
the default compiling options from the /usr/lib/R/etc/Makeconf file:
gfortran -fpic -O3 -pipe -g -c Babar.f -o Babar.o
How can I override the default compilation options for the FORTRAN files of my package in R?
(I intend to distribute that package through CRAN so the compilation option should be set from the Makevars file)
There are two to three things here:
As you note, R itself uses the options encoded from its run of configure, ie built-time. See the file $RHOME/etc/Makeconf
You can override things via src/Makevars on a per-package basis. That is what you probably want here. See R's Makeconf for the list of variables, and set eg FFLAGS.
You can override things for all your builds via a per-user ~/.R/Makevars. Eg I set optimization and warning level for my builds in that file.
See the "Writing R Extensions" manual for details.
Edit: And there is 1.a) You can edit a local file $RHOME/etc/Makeconf.site too. On Debian/Ubuntu, I softlink the directory $RHOME/etc/ into /etc/R which makes that easier too.
Ok, the best solution I found for this is to do it as is done in the quadprog package (ver 1.5-5). Here is what the relevant parts of the src/Makevars file look like:
mypackage_FFLAGS = $(FPICFLAGS) $(SHLIB_FFLAGS)
all: $(SHLIB)
Babar.o: Babar.f
$(F77) $(mypackage_FFLAGS) -O1 -pipe -g -c -o Babar.o Babar.f
So, for example when you send the package to the win-builder here is what the compiler output looks like (confirming that this solution does indeed work):
gfortran -O1 -pipe -g -c -o Babar.o Babar.f
I asked this question on the Qt forums, but they seem to be pretty quiet these days.
I'm running the relatively new Qt Creator 2.6.2 (with Qt 5.0.1). When I try to build the debugger helper, I get the following error:
Building helper(s) with toolchain 'GCC (x86 64bit)'... Building helper
'GDB helper' in
/Developer/Applications/Qt/5.0.1/clang_64//qtc-debugging-helper/
Running /Developer/Applications/Qt/5.0.1/clang_64/bin/qmake -spec
macx-clang dumper.pro -nocache CONFIG+=x86_64 ...
Running /usr/bin/make all -k ... Error running '/usr/bin/make all -k'
in /Developer/Applications/Qt/5.0.1/clang_64//qtc-debugging-helper/:
The process returned exit code 2: clang++ -c -pipe
-mmacosx-version-min=10.6 -O2 -Wall -W -fPIC -DUSE_QT_CORE=1 -DUSE_QT_GUI=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I../mkspecs/macx-clang -I. -I../include -I../include/QtWidgets -I../lib/QtWidgets.framework/Versions/5/Headers -I../include/QtGui -I../lib/QtGui.framework/Versions/5/Headers -I../include/QtCore -I../lib/QtCore.framework/Versions/5/Headers -I. -I/System/Library/Frameworks/OpenGL.framework/Versions/A/Headers -I/System/Library/Frameworks/AGL.framework/Headers -o dumper.o dumper.cpp make: clang++: No such file or directory make: *
[dumper.o] Error 1 make: Target `all' not remade because of errors.
Build failed.
So, I see that it's looking for a file called "clang++" which I evidently don't have. Can someone explain to me what the workaround for this is? I'm accustomed to just using the pre-built install packages for Qt.
Thanks.
You need to install command line tools package for Xcode which includes 'clang++' compiler.
You can find them here under Looking for additional developer tools? link.
Let's say I have a library lib1.so created like that:
gcc 1.cpp -o lib1.so -shared
And I have another library lib2.so created in this way:
gcc 2.cpp -o lib2.so -shared -L. -l1
But linking against lib2.so
gcc main.cpp -o main -L. -l2
gives a warning:
warning: lib1.so, needed by lib2.so, not found (try using -rpath or -rpath-link)
But AFAIK the use of rpath is discouraged because then the library can not be moved to another location.
How do I link "main" against "lib2.so" without specifying "lib1.so" and rpath?
The RPATH header in the binary takes precedence so even if the library has no RPATH header, it will still be found IF you have copied it to the directory mentioned in -rpath