function in one shared library calling a function in another shared library - c

I have a shared library say libfile2.so (which contains print2() function definition). Now I create a libfile1.so (which contains print1() function definition which in turn calls print2() function in libfile2.so). Now I create a main.c file which contains main() function which calls print1() by dynamically linking libfile1.so.
But I am getting the following error:
./libfile1.so: undefined reference to `print2'**
The following are the commands that I am using:
gcc -c -fpic file1.c
gcc -shared -o libfile1.so file1.o
gcc -c -fpic file2.c
gcc -shared -o libfile2.so file2.o
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
gcc -I. -L. -o main main.c -lfile1

If you have called only print1 in your main.c. Then set the path of the libfile2.so in the LD_LIBRARY_PATH. Because it will try to find the dependencies of libfile1.so while linking with main.c.
gcc -o file1.o -c file.c
gcc -o file2.o -c file.c
gcc -o libfile2.so file2.o -shared
gcc -o libfile1.so file1.o -L. -lfile2 -shared
gcc -o main.o -c main.c
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
gcc -o main.exe main.o -L. -lfile1
If you have called both print1 and print2 in main.c then link both libfile1.so and libfile2.so like below.
gcc -o main.o -c main.c
gcc -o main.exe main.o -L$YOUR_LIB_PATH -lfile1 -lfile2
Because all the symbol used in main.c needs to be resolved while generating executable.

Related

Why while using makefile I receive undefined reference error?

I created the following makefile:
assembler: main.o first_pass.o second_pass.o helpers.o data_array.o symbol_table.o
gcc -Wall -ansi -pedantic main.o first_pass.o second_pass.o helpers.o data_array.o symbol_table.o -o assembler
main.o: main.c header.h
gcc -Wall -ansi -pedantic main.c -o main.o
first_pass.o: first_pass.c header.h
gcc -Wall -ansi -pedantic first_pass.c -o first_pass.o
second_pass.o: second_pass.c header.h
gcc -Wall -ansi -pedantic second_pass.c -o second_pass.o
helpers.o: helpers.c header.h data.h
gcc -Wall -ansi -pedantic helpers.c -o helpers.o
data_array.o: data_array.c header.h data.h
gcc -Wall -ansi -pedantic data_array.c -o data_array.o
symbol_table.o: symbol_table.c header.h data.h
gcc -Wall -ansi -pedantic symbol_table.c -o symbol_table.o
In my 'main.c' file I have #include "header.h". Where in 'header.h' I have the declarations of all the functions.
But I receive the following error:
gcc -Wall -ansi -pedantic main.c -o main.o
/tmp/cc3dP7hx.o: In function `main':
main.c:(.text+0x257): undefined reference to `first_pass`
main.c:(.text+0x2e4): undefined reference to `second_pass'
main.c:(.text+0x37f): undefined reference to build_obj_file
main.c:(.text+0x3a9): undefined reference to build_ent_file
main.c:(.text+0x427): undefined reference to free_all_data
main.c:(.text+0x436): undefined reference to free_all_symbols
main.c:(.text+0x44d): undefined reference to free_all_words
collect2: error: ld returned 1 exit status
makefile:4: recipe for target 'main.o' failed
make: *** [main.o] Error 1
The problem is that your command doesn't create object files, but attempt to build executable programs:
gcc -Wall -ansi -pedantic main.c -o main.o
You need the -c option to create object files:
gcc -Wall -pedantic main.c -c -o main.o
A better idea would be to rely on the make implicit rules so you don't have to explicitly list all commands:
CC = gcc
LD = gcc
CFLAGS = -Wall -pedantic
LDFLAGS =
assembler: main.o first_pass.o second_pass.o helpers.o data_array.o symbol_table.o
You might want to add rules for the header-file dependencies, or figure out some way to auto-generate them (it's possible). Other than that the above Makefile should be enough to build all object files and then link them together into the assembler executable program.
Note that I have removed the -ansi flag, as it's mostly obsolete these days.

Creating several projects from one code in one makefile

I have one program and it uses static or shared library. Now I want to do something like
make static
or
make shared
to compile the project in two cases.
My Makefile looks like
shared: main.o libresult.so
gcc -o shared main.o -L. -lresult -Wl,-rpath,.
main.o: main.c
gcc -c main.c
libresult.so: func.o
gcc -shared -o libresult.so func.o
func.o: func.c
gcc -c -fPIC func.c
static: main.o libresult.a
gcc -o static main.o -L. -lresult
main.o: main.c
gcc -c main.c
libresult.a: func.o
ar cr libresult.a func.o
func.o: func.c
gcc -c func.c
clean:
rm -f *.o *.a *.so static shared
Off course, terminal gives some warnings. It works well, but I dont think that
is much beautiful :). How to make it better?
1) You have two copies of the main.o rule:
main.o: main.c
gcc -c main.c
Delete one of them.
2) You have two versions of the func.o rule:
func.o: func.c
gcc -c -fPIC func.c
func.o: func.c
gcc -c func.c
This is a more serious problem. The object you put in the shared library (libresult.so) must be compiled with -fPIC; the object you put in the static library (libresult.a) may be compiled with -fPIC, but there is no reason to do so and it may prevent the compiler form performing some optimisation. Make doesn't know your intentions, so it is better to make two versions of the object with different names:
func_so.o: func.c
gcc -c -fPIC func.c -o func_so.o
func_a.o: func.c
gcc -c func.c -o func_a.o
(Don't forget to modify the rules that rely on these objects.)
3) Use automatic variables to reduce redundancy and make your makefile cleaner. For example:
main.o: main.c
gcc -c $< -o $#
Further improvements are possible, once you are comfortable with these.

Error when trying link jsoncpp and include it in a CUDA project: undefined reference to `Json::Value::Value(Json::ValueType)'

When I try and #include "json/json.h" in a .cu file, then run make, I get the following error:
nvcc -o sound main.o process.o -L /usr/lib -lopencv_core -lopencv_imgproc -lopencv_highgui -O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64
/usr/local/cuda/bin/crt/link.stub:90:13: warning: ‘void __cudaRegisterLinkedBinary(const __fatBinC_Wrapper_t*, void (*)(void**), void*)’ defined but not used [-Wunused-function]
process.o: In function `count_tracks()':
tmpxft_00006061_00000000-3_process.cudafe1.cpp:(.text+0x75): undefined reference to `Json::Value::Value(Json::ValueType)'
tmpxft_00006061_00000000-3_process.cudafe1.cpp:(.text+0x7d): undefined reference to `Json::Value::~Value()'
collect2: ld returned 1 exit status
make: *** [student] Error 1
in reference to when I try and create a Json::Value. I've tried moving around where I link JsonCpp library, and I wasn't having this problem #including jsoncpp and creating a Json::Value in the main.cpp of the project. It just doesn't seem to be working correctly when in a .cu file.
Here is the pertinent stuff from my Makefile, which I got from Udacity's CUDA course and modified to fit my needs:
NVCC=nvcc
CXX = g++
LDFLAGS = -L ~/parallelcomputing/soundcloud/jsoncpp/build/debug/lib -ljsoncpp
INC = -I ~/parallelcomputing/soundcloud/jsoncpp/include
OPENCV_LIBPATH=/usr/lib
OPENCV_INCLUDEPATH=/usr/include
OPENCV_LIBS=-lopencv_core -lopencv_imgproc -lopencv_highgui
CUDA_INCLUDEPATH=/usr/local/cuda/include
NVCC_OPTS=-O3 -arch=sm_20 -Xcompiler -Wall -Xcompiler -Wextra -m64
GCC_OPTS=-O3 -Wall -Wextra -m64
student: main.o process.o Makefile
$(NVCC) -o sound main.o process.o -L $(OPENCV_LIBPATH) $(OPENCV_LIBS) $(NVCC_OPTS)
main.o: main.cpp
g++ -c main.cpp $(GCC_OPTS) $(LDFLAGS) $(INC) -I $(CUDA_INCLUDEPATH) -I $(OPENCV_INCLUDEPATH)
process.o: process.cu
nvcc -c process.cu $(NVCC_OPTS) $(LDFLAGS) $(INC)
clean:
rm -f *.o *.png hw
You've got LDFLAGS defined in your makefile, but you're not using it in the link phase that I can see.
As a result, -ljsoncpp doesn't show up in the link command you posted, that is showing the error.
Add LDFLAGS to your link phase:
student: main.o process.o Makefile
$(NVCC) -o sound main.o process.o $(LDFLAGS) -L $(OPENCV_LIBPATH) $(OPENCV_LIBS) $(NVCC_OPTS)
(And while we're cleaning up your makefile, LDFLAGS contains link specification, and is not relevant in, and can be safely deleted from, the subsequent compile targets.)
EDIT:
Since that is not working, but you say the link is successful with a .cpp file, try linking the executable with g++ instead of nvcc:
LDFLAGS2=-L/usr/local/cuda/lib64 -lcudart
student: main.o process.o Makefile
$(CXX) -o sound main.o process.o $(LDFLAGS) $(LDFLAGS2) -L $(OPENCV_LIBPATH) $(OPENCV_LIBS)

Building a shared library using gcc on Linux and MinGW on Windows

I'm having trouble with generating a build setup that allows shared libraries to be built in both Linux and Windows using gcc and MinGW, respectively. In Linux, a shared library doesn't have to resolve all dependencies at compile time; whereas, this appears to the case in Windows. Here is the problem setup:
$ cat foo.h
#ifndef FOO_H
#define FOO_H
void printme();
#endif
$ cat foo.c
#include "foo.h"
#include <stdio.h>
void printme() {
printf("Hello World!\n");
}
$ cat bar.h
#ifndef BAR_H
#define BAR_H
void printme2();
#endif
$ cat bar.c
#include "bar.h"
#include "foo.h"
void printme2() {
printme();
printme();
}
$ cat main.c
#include "bar.h"
int main(){
printme2();
}
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.so
gcc -shared bar.o -o libbar.so
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
Now, in Linux, this compiles and runs just fine:
$ make
gcc -fPIC -c foo.c
gcc -fPIC -c bar.c
gcc -fPIC -c main.c
gcc -shared foo.o -o libfoo.so
gcc -shared bar.o -o libbar.so
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ ./main
Hello World!
Hello World!
In Windows, we need to change so to dll, which is minor and fine:
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
However, when we try to build, we get the following error:
$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o -o libbar.dll
bar.o:bar.c:(.text+0x7): undefined reference to `printme'
bar.o:bar.c:(.text+0xc): undefined reference to `printme'
collect2.exe: error: ld returned 1 exit status
make: *** [all] Error 1
Now, we can fix the error by simply including the objects from foo.o into libbar.dll:
$ cat Makefile
.c.o:
gcc -fPIC -c $<
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o foo.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ make
gcc -fPIC -c foo.c
foo.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c bar.c
bar.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -fPIC -c main.c
main.c:1:0: warning: -fPIC ignored for target (all code is position independent) [enabled by default]
gcc -shared foo.o -o libfoo.dll
gcc -shared bar.o foo.o -o libbar.dll
gcc main.o -Wl,-rpath=. -L . -lbar -lfoo -o main
$ ./main
Hello World!
Hello World!
However, I don't like this approach since libbar.dll now contains symbols for both foo and bar. In Linux, it only contains symbols for bar. This separation is important for situations where a library depends on some standard numerical library like BLAS. I'd like to be able to deploy the shared library and have it depend on the optimized version of the numerical library on the user's machine and not my own.
In any case, what's the proper procedure to create a shared library where not all of the symbols are present at compile time?
In case it matters, I compiled these examples with gcc 4.6.3 on Linux and mingw-get-inst-20120426.exe with gcc 4.7.2 on Windows.
On Windows, you need to create an import library for the DLL. An import library looks like a static library, in that it defines all of the needed symbols, but it doesn't have the actual function implementations, it just has stubs. The import library will resolve the "undefined reference" errors while avoiding static linking.
To create an import library with MinGW, follow the instructions here. The key is that when building the DLL, you must pass the option -Wl,--out-implib,libexample_dll.a to the linker to generate the import library libexample_dll.a.
Then, when you compile your main executable, you use the -lexample_dll option (along with -L.) to link against the import library. So with your code, I think this should work:
all: foo.o bar.o main.o
gcc -shared foo.o -o libfoo.dll -Wl,--out-implib,libfoo.a
gcc -shared bar.o foo.o -o libbar.dll -Wl,--out-implib,libbar.a
gcc main.o -Wl,-rpath=. -L. -lbar -lfoo -o main
Also, note that on Windows, the calling convention for exported functions in DLL is almost always __stdcall, not the default __cdecl, so if you want your DLLs to be usable by other software, I'd recommend making them __cdecl. But that's not strictly requires, as long as both the code in the DLL and the header files agree on what the calling convention is.

C makefile errors

I have a custom header file example.h which has prototypes for a few functions. There is a .C file example.c that I implemented which "includes" (#include "example.h") and has the implementations of the functions that has prototype in example.h. Now, I have another function test.c that calls the functions that are prototyped in example.h and defined in example.c.
My make file is as follows
test: test.o
gcc -o test -g test.o
test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
clean:
rm -f *.o test
I get following message for the functions that are defined in example.c
Undefined first referenced
symbol in file
function1 test.o
function2 test.o
function3 test.o
function4 test.o
ld: fatal: Symbol referencing errors. No output written to test
collect2: ld returned 1 exit status
* Error code 1
make: Fatal error: Command failed for target `test'
Any help is most appreciated.
%.o: %.c
gcc -c -g -o $# $^
test: test.o example.o
gcc -o -g $# $^
%.o: %.c This means any *.o file should be builded from its equivalen from c files.
example test.o should be builded from test.c and example.o should be builded from example.c
First of all, you must include the example.o file when generating the executable file : gcc -o test example.o test.o. Then, the dependencies you wrote for target test.o are incorrect. You should split it like this :
test: test.o example.o
gcc -o test test.o example.o
test.o: test.c
gcc -c -Wall test.c
example.o: example.c
gcc -c -Wall example.c
Then, consider the use of variables to store the names of your object files, the flags you want to pass to the linker/compiler etc... This would make your life much easier.
test.o: test.c example.c example.h
gcc -g -c -Wall test.c
gcc -g -c -Wall example.c
as per your code test.o target is calling test.c example.c example.h target which i am not able to see.

Resources