Compiling a shared object folder without libc - linux

Is it possible to build a shared object file on Linux without using libc? I tried building the shared object using -nostdlib, and it complains that there is a conflicting type for built-in function 'memset'(I have my own version of the function defined within the shared object I am trying to build).
I am not using any libc functions from within the shared object file. I am building the shared object as follows :-
CC = gcc
CFLAGS = -Wall -Wextra -Werror -nostdlib
OUTPUTDIR = ./build
test: outputdir
$(CC) $(CFLAGS) -c -fPIC test.c -o ${OUTPUTDIR}/test.o
$(CC) $(CFLAGS) ${OUTPUTDIR}/test.o -shared -o ${OUTPUTDIR}/libtest.so
outputdir:
mkdir -p ${OUTPUTDIR}
clean:
rm -rf ${OUTPUTDIR}

If you link with -nostdlib, you should also compile with -ffreestanding and/or -fno-builtin as well.
You also have to be careful that you do not reference a libc.so.6 symbol without linking against glibc. Things may appear to work superficially, but it tends to introduce breakage in certain environments, especially once additional IFUNCs are added to glibc. (Intel did that with the ICC 16 compiler library.)

Related

g++ link an .a file and its dependencies into a static .so

I have a libSomelib.a that can be linked to an executable by the following command:
g++ -L. -lsomeLib -lpcrecpp -lpcre -lpthread main.cpp -o main
But how could I link a shared object from it, that contains all depentencies?
I want to achieve the following with my new someLib.so:
g++ -L. -lsomeLib main.cpp -o main
I have tried the following:
g++ -shared -L. -lsomeLib -lpcrecpp -lpcre -lpthread -o libSomelib_static.so
This gives me an .so file with no symbols.
PS: I'm completely beginer of compilers.
There are a few issues at play here:
Linkers only use object files from an archive that resolve unresolved symbols. This is why the order of archives in the command line is important. Correct order is object files, followed by static libraries, followed by shared libraries. E.g. g++ -o main -pthread main.cpp -L. -lsomeLib -lpcrecpp -lpcre.
When you build the shared library that archive does not resolve any symbols, hence the linker ignores it completely. See 1.
Object files for a shared library must be compiled as position independent code (-fPIC compiler flag). Archives are normally built without this flag.
Use -pthread flag both when compiling and linking multi-threaded applications, not -lpthread.

how to pass -fPIC to GCC on linux

I am trying to compile libedit on linux using GCC 5.3 and am getting a cryptic error message.
/home/mybin/libgcc/x86_64-unknown-linux-gnu/5.3.0/../../../libcurses.a(lib_termcap.o): relocation R_X86_64_32 against `_nc_globals' can not be used when making a shared object; recompile with -fPIC
/home/mybin/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../libcurses.a: could not read symbols: Bad value
To what does the recompile with -fPIC refer, ncurses or libedit? and then how do I pass the -fPIC flag. I have tried adding CFLAGS=-fPIC to the configure of ncurses & libedit but still did not work.
I have found may posts on SO about what -fPIC is, but none on how to set the flag.
thanks Art
Perhaps you ran afoul of the changes outlined in Fedora's Changes/Harden All Packages which use a linker spec that only works if you have compiled using either -fPIC or -fPIE. The linker message is almost useless; only the part about -fPIC has any usefulness.
To address this problem, you can add/modify the compiler flags in several ways. One of the simplest is to set it in the CFLAGS environment variable, e.g.,
export CFLAGS='-O -fPIC'
If you happen to be building ncurses, this means that you would have to also be configuring to build only shared libraries, e.g.,
configure --with-shared --without-normal --without-debug
Of course that all works best if you do not have a previous set of makefiles, etc.
You're looking at the wrong part of the error message. The "relocation R_X86_64_32" means that you're trying to build 32-bit code against a 64-bit library or vice versa. Make sure you have selected the same architecture for both.
-fPIC is used to generate position independent code, it is used to create shared libraries. the make file has a problem, to fix it:
edit the Makefile, line 98 :
.c.o:
${CC} ${CFLAGS} -c $<
after CC add -fpic after CC like this :
.c.o:
${CC} -fpic ${CFLAGS} -c $<
also in line 103:
libedit.so: ${OOBJS}
${CC} --shared -o $# ${OOBJS}
add -fpic after --shared:
libedit.so: ${OOBJS}
${CC} --shared -fpic -o $# ${OOBJS}
if you are wondering what is the difference between -fPIC and -fpic note that they both do the same thing but -fpic is more efficient, check this for more informations What is the difference between `-fpic` and `-fPIC` gcc parameters?.

How to link custom object file with Haskell library?

I've created a Haskell package that makes FFI calls to functions defined in CUDA code. I'd like to compile .cu file to an object (.o) file during package build and force linker to link it in.
So far, I tried to use a technique found this question. I've customized buildHook to:
run nvcc
run default buildHook
create ar library file with nvcc compiled code.
Setup.hs is available here.
This solution has a major disadvantage in restricting this package to static linking. Although cabal produces a shared library, it won't work because it has no way of resolving symbols located in the object file.
Is there a simpler way to link custom code during building?
I do a similar thing. I have a Haskell file which calls CUDA code.
Here's how I compile CUDA libraries and link with Haskell:
$(NVCC) -c -E $(NVCC_OPTS) -o build/file.i file.cu
$(NVCC) -c $(NVCC_OPTS) -o build/file.o file.cu
I then link everything into a C++ Shared Library called LibSO with Haskell options
$(CXX) -shared -Wl,-rpath=\$$$$ORIGIN $(CXX_LINK_LIBS) $(PACKAGE_RPATH) -Lbuild -rdynamic -L/usr/local/lib/ghc-7.6.3 -lHSrts-ghc7.6.3 -o build/LibSO.so build/file.o
where
CXX_LINK_LIBS = -Lbuild -lcudart -lcuda -lpthread -lcupti -lcurand -lnvidia-ml
NVCC_OPTS = --compiler-options -fPIC -maxrregcount=0 --machine 64 --DCUDA
I then take my Haskell files and compile them into o and hi files. (I compile twice because of TemplateHaskell)
ghc -v0 -Wall -rtsopts -threaded -stubdir build -ibuild/ -no-hs-main -o build/iop.o -ohi build/iop.hi -c haskell/iop.lhs
ghc -v0 -Wall -rtsopts -threaded -stubdir build -ibuild/ -no-hs-main -fPIC -dynamic -osuf dyn_o -hisuf dyn_hi -o build/iop.dyn_o -ohi build/iop.dyn_hi -c haskell/iop.lhs
So now we have haskell dynamic objects and a C++ shared library.
In the end, I link a main haskell file with everything:
ghc -optl "-Wl,-rpath=\$$ORIGIN" $(CXX_LINK_LIBS) -Lbuild -rtsopts -threaded -lstdc++ -lLibSO -o build/Main build/iop.dyn_o
Does this sort of help?

undefined reference while using shared library

I want to use one program as a shared library for an other program.
I started as follows:
I have a application which I have compiled using:
/usr/bin/g++ -I/usr/include/libxml2 -Xlinker -zmuldefs -fPIC -c a.cpp
/usr/bin/g++ -I/usr/include/libxml2 -Xlinker -zmuldefs -fPIC -c b.cpp
/usr/bin/g++ -I/usr/include/libxml2 -Xlinker -zmuldefs -fPIC -c c.cpp
Then I have created a shared object library from the objects I get from this file using this command:
g++ -fPIC -Xlinker -zmuldefs -shared -o libabc.so a.o b.o c.o
After this I get the libabc.so file which I copy to the
sudo cp libabc.so /usr/local/lib/libabc.so
Now when I compile my orignal application which will use this newly created library libabc.so using this command:
/usr/local/lib/libabd.so: undefined reference to `xmlXPathNewContext'
I get errors for all the functions I used from the included library libxml2 in the first application and the function which has this undefined reference is actually the library I include in the first program I mean I have tested it.
So kindly anyone guide me where I need corrections.
You may have to pass the path also using -I/path/to/library, or alternatively export it to LD_LIBRARY_PATH.
I don't see the command line that you used to link your application against your library, but I suppose that adding -lxml2 to the flags passed to the linker should solve the problem.

Creating shared objects with mpicc - does not seem to find pthread routines

I am learning to create shared libraries in Linux, subsequently to develop parallelised scientific computing programs. I took the toy example from here for shared library. I modified the Makefile from this question to suit the toy example. My Makefile now is
CC = mpicc
INCDIR = -I ./
CFLAGS = -Wall -rdynamic -g -fPIC $(INCDIR)
LIBADD = -L ./ -lcalc_mean
all: dyn_main.out
dyn_main.out: libcalc_mean.so
$(CC) -o $# main.c $(LIBADD)
libcalc_mean.so: calc_mean.o
$(CC) -shared --export-dynamic -o $# $<
calc_mean.o: calc_mean.c
$(CC) $(CFLAGS) -c $<
clean :
-rm *.o
-rm *.out
-rm *.so
.PHONY:
clean
When I make with CC = gcc in the Makefile, things run fine. I could run the binary even with mpirun.
When I have CC = mpicc in the Makefile, I get the following error.
mpicc -Wall -rdynamic -g -fPIC -I ./ -c calc_mean.c
mpicc -shared --export-dynamic -o libcalc_mean.so calc_mean.o
mpicc -o dyn_main.out main.c -L ./ -lcalc_mean
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_key_create'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_getspecific'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_create'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_atfork'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_setspecific'
/home/elan/localinstalls/lib/libmpi.so: undefined reference to `pthread_join'
collect2: ld returned 1 exit status
make: *** [dyn_main.out] Error 1
I added the path to libpthread.so,.a to LD_LIBRARY_PATH, but no avail. I have a self compiled openmpi-1.5.4. If this were a openmpi dependency, shouldn't it have been resolved when I configured it?
Is this error familiar? I am using Ubuntu 11.04, with gcc 4.5.2. I already built and run some mpi parallel programs successfully. But they are large packages configured with autotools. One of the config.log s display the same error. But even that one runs fine.
References to / examples of creating static/shared libraries with mpi will also be appreciated (though Openmpi discourages fully static libraries.)
Thank you very much,
Elan.
You should be able to just add -lpthread.
Open MPI probably didn't add it because it found that adding -lpthread wasn't necessary (likely due to some other dependency implicitly pulling in the pthread library). But with the linker flags you're using, you might well have changed that implicit dependency, so the pthread library isn't being pulled in automatically anymore.
If adding -lpthread to the command line fixes the issue, then see this FAQ entry for how to update the wrapper compilers (E.g., add your own flags): http://www.open-mpi.org/faq/?category=mpi-apps#override-wrappers-after-v1.0
You can see what options the Open MPI compiler wrapper supplies to the underlying compiler and linker using the -showme option or one of its specific variants:
-showme:compile to just show the compiler flags
-showme:link to just show the linker flags
For example:
$ mpicc -showme
icc -I/opt/MPI/openmpi-1.5.3/linux/intel/include -I/opt/MPI/openmpi-1.5.3/linux/intel/include/openmpi -fexceptions -pthread -I/opt/MPI/openmpi-1.5.3/linux/intel/lib -Wl,-rpath,/opt/MPI/openmpi-1.5.3/linux/intel/lib -I/opt/MPI/openmpi-1.5.3/linux/intel/lib -L/opt/MPI/openmpi-1.5.3/linux/intel/lib -lmpi -ldl -Wl,--export-dynamic -lnsl -lutil

Resources