I create a .so file with the code below, but when I compile a file that invokes functions in the .so file with GCC, I get an "undefined reference to 'outlib1'" error.
What's wrong with my code or my command? Thanks.
OS Ubuntu 11.10
gcc 4.6.1
//file name outscreen.c
#include <stdio.h>
void outlib1(void)
{
printf("out screen func1\n");
}
//file name main.c
int main(int argc, char* argv[])
{
outlib1();
}
gcc outscreen.c -fPIC -shared -o outscreen.so
gcc main.c -L. -loutscreen -o call
./call
Try:
$ gcc outscreen.c -fPIC -shared -o liboutscreen.so
$ gcc main.c -L. -loutscreen -o call
(note the change to the first line - the second line is unchanged)
What is the output of this?
nm outscreen.so | grep outlib1
Perhaps it is exporting with an underscore.
Related
I have a statically linked library, containing a global variable barvar. I can compile the library with no problems with either gcc-10 or clang (this is on macOS Catalina). Interestingly, the behavior differs between the two when I try to link it into a program that uses the library. Here's the code:
In globvars.h, int barvar is declared:
#ifndef H_GLOBVARS_H
#define H_GLOBVARS_H
extern int barvar;
#endif
In globvars.c, int barvar is defined:
#include "globvars.h"
int barvar;
In foo.c, the function foo sets and prints barvar:
#include <stdio.h>
#include "globvars.h"
void foo()
{
barvar = 10;
printf("barvar is: %d\n", barvar);
return;
}
Here's test.c, the program that uses the library:
void foo();
int main(int argc, char **argv)
{
foo();
return 0;
}
When I compile and link with gcc-10, no problems:
gcc-10 -c foo.c -o foo.o
gcc-10 -c globvars.c -o globvars.o
gcc-10 -c test.c -o test.o
gcc-ar-10 rcs liblinktest.a foo.o globvars.o
gcc -o testlinkrun test2.o -L. -llinktest
When I compile and link with clang, I get an undefined symbol error at the last step:
cc -c foo.c -o foo.o
cc -c globvars.c -o globvars.o
cc -c test.c -o test.o
ar rcs liblinktest.a foo.o globvars.o
cc -o testlinkrun test2.o -L. -llinktest
with error:
Undefined symbols for architecture x86_64:
"_barvar", referenced from:
_foo in liblinktest.a(foo.o)
Any ideas? Interestingly, it appears the only step that has to be done with gcc-10 is compiling globvars.c. I can use clang and the clang linker for all other steps, and everything is fine. Is it possible that clang is optimizing away all the variables in globvars.c? How can I prevent this?
As #EricPostpischil observed in this comment, the issue is that clang defaults to treating barvar as a common symbol. Either changing int barvar; to int barvar = 0;, or compiling with -fno-common, fix the issue.
Beginning with gcc-10, gcc's default behavior is -fno-common instead of -fcommon.
I am experimenting with externs and various methods of linking to better understand the linking process.
I have three files:
foo.c:
#include "foo.h"
int a = 4;
test.c:
#include <stdio.h>
#include "foo.h"
int main(int, char**);
int mymain();
int mymain() {
main(0, 0);
printf("test\r\n");
return 0;
}
int main(int argc, char** argv) {
printf("extern a has %d\r\n", a);
return 0;
}
foo.h:
extern int a; // defined in foo.c
If I build each file together and link at compile time using gcc like this:
gcc *.c -o final.bin
I can execute final.bin as:
./final.bin
and get expected output
extern a has 4
However, if I compile (but don't link) test.c and foo.c separately, then try and link the object files together at runtime to produce a binary, I get a segmentation fault 11 (which from what I can gather is some generic memory corruption bug like a normal segfault(?)
Here is my makefile I'm using to compile and link separately. Note I am specifying my own entry point and linking against libc to get printf()...
all: test.o foo.o
#echo "Making all..."
ld test.o foo.o -o together.bin -lc -e _mymain
test.o: test.c
#echo "Making test..."
gcc -c test.c -o test.o
foo.o: foo.c
#echo "Making foo..."
gcc -c foo.c -o foo.o
Output when running 'together.bin':
./together.bin
extern a has 4
test
Segmentation fault: 11
Perhaps my function signature for 'mymain' is wrong? My guess is that something is wrong with my 'myentry' usage.
Also, if anyone has any recommendations on good books for how linkers and loaders work, I am certainly in the market for one. I've heard mixed things about 'Linkers and Loaders', so I'm waiting on more opinions before I invest the time in that book in particular.
Thanks for any help on this... My understanding of linkers is sub-par to say the least.
Unless if you have a good reason to do so, just use gcc to link:
$ gcc test.o foo.o "-Wl,-e,_mymain" -o ./final.bin; ./final.bin
extern a has 4
test
gcc calls ld---though, with a few more arguments than you are providing in your example. If you want to know exactly how gcc invokes ld, use the -v option. Example:
$ gcc -v test.o foo.o "-Wl,-e,_mymain" -o ./final.bin
Apple LLVM version 8.0.0 (clang-800.0.38)
Target: x86_64-apple-darwin15.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
"/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -dynamic -arch x86_64 -macosx_version_min 10.12.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk -o ./final.bin test.o foo.o -e _mymain -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/lib/darwin/libclang_rt.osx.a
There are 4 files:
helper.h //contains the signatures of functions in helper.c
helper.c //implements the signatures in helper.h
file.h //has all the includes needed to run file.h
file.c //this file includes file.h and helper.h
In file.c, I need to use the function that is defined in helper.c in my main function. However, file.c is saying that there is an undefined reference to 'func_found_in_helper.c'
Is this structure correct?
Yes, provided file.c contains
#include "helper.h"
and when building your program you link together helper.o and file.o.
You also need to ensure you compile each of the files with -c so that the compiler only compiles (and not links); do the link later with all the object files.
Here's a working example (I don't actually need a main.h but if you have one of those, #include it from main.c):
main.c
#include <stdio.h>
#include <stdlib.h>
#include "helper.h"
int
main (int argc, char **argv)
{
test ();
exit (0);
}
helper.c
#include <stdio.h>
void
test ()
{
printf ("Hello world\n");
}
helper.h
void test ();
To compile
gcc -Wall -Werror -c -o main.o main.c
gcc -Wall -Werror -c -o helper.o helper.c
To link
gcc -Wall -Werror -o test main.o helper.o
In a Makefile
test: main.o helper.o
gcc -Wall -Werror -o test main.o helper.o
%.o: %.c
gcc -c -Wall -Werror -o $# $<
clean:
rm -f *.o test
To run
$ ./test
Hello world
It's a bit difficult to tell what else might be wrong without the program; my guess is you simply forgot the -c flag to gcc, or forgot to link in helper.o.
undefined reference to 'func_found_in_helper.c'
That's a little odd, as it suggests you have tried to call the function using the '.c' extension, rather than just the function name. Maybe the '.' is just a typo in the question ?
Also a linker will flag an undefined symbol, so it may also be that you have not told the linker where to find helper.o ( the helper.c file compiled to the an object file ). The compiler will start the linker automatically. Did you compile helper.c first ?
I try to write simple mongo c client. Source file (a.c):
#include <stdio.h>
#define MONGO_HAVE_STDINT
#include <mongo.h>
void mongo_init_c(mongo *con)
{
mongo_init(con);
}
int main() {
return 0;
}
And i try to compile it with:
gcc -I/usr/local/include -L/usr/local/lib -lmongoc a.c
But get an error:
a.c:(.text+0xd): undefined reference to `mongo_init'
Files /usr/local/include/mongo.h and /usr/local/lib/libmongoc.so exists
How can I correctly compile a.c?
p.s. mongo-2.0.4, gcc-4.6, mongo-c-driver - pulled from github
update
$ nm /usr/local/lib/libmongoc.so | grep init
000034e0 T _init
0000dd10 T bson_init
0000c740 T bson_init_data
0000c7b0 T bson_init_finished_data
0000dc10 T bson_init_size
0000d060 T bson_iterator_init
0000a5e0 T gridfile_init
00009af0 T gridfile_writer_init
000095e0 T gridfs_init
00010a18 R initialBufferSize
00005f40 T mongo_cursor_init
00008da0 T mongo_env_sock_init
00005d90 T mongo_init
000057b0 T mongo_init_sockets
00004800 T mongo_md5_init
00005e40 T mongo_replica_set_init
00005f00 T mongo_replset_init
00005b80 T mongo_write_concern_init
$ gcc -I/usr/local/include -L/usr/local/lib -Wall -Werror -lmongoc a.c
/tmp/cccuNEp1.o: In function `mongo_init_c':
a.c:(.text+0xd): undefined reference to `mongo_init'
Try linking the library after the source file, like gcc a.c -lmongoc. This is because you're using a traditional single-pass linker, which expects to satisfy dependencies with subsequent, not previous, objects specified on the command line.
In libname.h:
int add_libname(int, int);
In libname.c:
#include "libname.h"
int add_libname(int a, int b)
{
return a+b;
}
I can build the shared library this way:
gcc -shared -fPIC libname.c -o libname.so
But I can't use it in another programe test.c:
#include <stdio.h>
#include "libname.h"
int main(int argc, char* argv[])
{
printf("%d\n", add_libname(1,5));
}
Reporting undefined reference to add_libname when I try to build it..
What's wrong here?
Because add_libname takes (int, int) you're giving it (1+5 = 6) or just (int)
I think you meant
add_libname(1, 5);
Also to compile it correctly you must use gcc like so
gcc -o myapp test.c -L. -lname
the lib part of libname is ignored as it is implicit
To create a shared library use these
gcc -fPIC -c libname.c
it gives warning: position independent code and libname.o file is generated.
and now type these command,
gcc -shared libname.so libname.o
libname.so ( the shared library is created with .so extension). To use the shared library
gcc -I/give the path of libname.h sourcefile.c /give the path of your .so file
example if your c file is file.c and the header file libname.h is in c:\folder1\project and your libname.so (shared library) is in c:\folder\project2
then
gcc -I/cygdrive/c/folder1/project file.c /cygdrive/c/folder/project/libname.so
this is the gcc command to be used while using the shared library.
Thank you.