How to link static library .o files? - c

I'm experimenting with my first foray into libraries. I am trying to compile the Unity testing framework to a static library using gcc -c -fPIC -std=c99 -Wall -Wextra -pedantic -Werror -Wmissing-declarations -DUNITY_SUPPORT_64 test-framework/unity.c -o bin/libunity.o
This runs just fine.
However when I then try to use that object file:
$ gcc test_hello_world.c -Lbin -lunity -o test
/usr/bin/ld: cannot find -lunity
collect2: error: ld returned 1 exit status
Checking what ld is doing
$ ld -Lbin -luinty --verbose
GNU ld (GNU Binutils for Ubuntu) 2.34
Supported emulations:
elf_x86_64
elf32_x86_64
#
# ... script waffle
#
==================================================
ld: mode elf_x86_64
attempt to open bin/libuinty.so failed
attempt to open bin/libuinty.a failed
attempt to open /usr/local/lib/x86_64-linux-gnu/libuinty.so failed
attempt to open /usr/local/lib/x86_64-linux-gnu/libuinty.a failed
attempt to open /lib/x86_64-linux-gnu/libuinty.so failed
attempt to open /lib/x86_64-linux-gnu/libuinty.a failed
attempt to open /usr/lib/x86_64-linux-gnu/libuinty.so failed
attempt to open /usr/lib/x86_64-linux-gnu/libuinty.a failed
attempt to open /usr/lib/x86_64-linux-gnu64/libuinty.so failed
attempt to open /usr/lib/x86_64-linux-gnu64/libuinty.a failed
attempt to open /usr/local/lib64/libuinty.so failed
attempt to open /usr/local/lib64/libuinty.a failed
attempt to open /lib64/libuinty.so failed
attempt to open /lib64/libuinty.a failed
attempt to open /usr/lib64/libuinty.so failed
attempt to open /usr/lib64/libuinty.a failed
attempt to open /usr/local/lib/libuinty.so failed
attempt to open /usr/local/lib/libuinty.a failed
attempt to open /lib/libuinty.so failed
attempt to open /lib/libuinty.a failed
attempt to open /usr/lib/libuinty.so failed
attempt to open /usr/lib/libuinty.a failed
attempt to open /usr/x86_64-linux-gnu/lib64/libuinty.so failed
attempt to open /usr/x86_64-linux-gnu/lib64/libuinty.a failed
attempt to open /usr/x86_64-linux-gnu/lib/libuinty.so failed
attempt to open /usr/x86_64-linux-gnu/lib/libuinty.a failed
ld: cannot find -luinty
So it looks for bin/libunity.so and bin/libunity.a, but no bin/libunity.o... every internet page I've looked at this evening seems to assume that ld should pick up ".o" files just the same as ".so" or ".a" no questions asked (man pages seem to either similarly expect it or don't mention ".o" at all)... but it's not...
Am I misunderstanding something? Missing some argument?
EDIT: I've now run ar rcs bin/libunity.a bin/unity.o and then the gcc command from above. This seems to work (there are other errors). But I still thought ld should work with .o files, am I, and half the web, wrong?

This should work:
$ gcc test_hello_world.c bin/libunity.o -o test
Possibly shouldn't even really use the word "library" to describe a *.o file.
Never heard of lib*.o files being suitable for lib*.so/lib*.a files.
*.o files are linked directly without any libfoo.o ==> -lfoo magic.
Or if you want to turn .o into a .a, then use $ ar -crs libunity.a libunity.o, (see also: https://www.howtogeek.com/427086/how-to-use-linuxs-ar-command-to-create-static-libraries/).
A static library is an ar archive containing one or more object files.

Related

Undefined references to libm symbols after upgrading Linux distro

I upgraded my Linux distro from Pop OS 19.10 to 20.04, and it naturally included upgrades to glibc & co. Since then, I started getting linker errors for libm symbols like __pow_finite.
Unfortunately, the code that references these symbols is a static library (libWithPowFiniteRef.a in the redacted snippet below) with third-party proprietary code. I don't have access to source.
I checked /lib/x86_64-linux-gnu/libm.so.6 using nm. The symbol is there:
nm -gD /lib/x86_64-linux-gnu/libm.so.6
...
0000000000010e00 W powf64x
00000000000471f0 i __powf_finite
000000000002ed90 i __pow_finite
0000000000010e00 W powl
0000000000019860 T __powl_finite
...
So I can't explain the errors:
g++ -o ./media_tests -Wl,--verbose -Wl,--start-group #"./media_tests.rsp" -ldl -lpthread -lrt ../../third_party/other.so ../../third_party/redacted/lib/Linux/x64/libWithPowFiniteRef.a -Wl,--end-group
...
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libm.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libm.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libm.so succeeded
...
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libm.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/libm.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libm.so succeeded
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libm.so
/usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libm.so
opened script file /usr/lib/gcc/x86_64-linux-gnu/9/../../../x86_64-linux-gnu/libm.so
attempt to open /lib/x86_64-linux-gnu/libm.so.6 succeeded
/lib/x86_64-linux-gnu/libm.so.6
...
/usr/bin/ld:../../third_party/redacted/lib/Linux/x64/redacted.a(redacted.o): in function `RedactedX':
redacted1.c:(.text+0xbb0): undefined reference to `__pow_finite'
/usr/bin/ld: ../../third_party/redacted/lib/Linux/x64/redacted.a(redacted.o): in function `RedactedY':
redacted2.c:(.text+0x7ad9): undefined reference to `__pow_finite'
/usr/bin/ld: redacted.c:(.text+0x8c74): undefined reference to `__pow_finite'
/usr/bin/ld: link errors found, deleting executable `./media_tests'
Maybe we the solution is to request a new static lib from the vendor, but I would like to understand why.

Is there a way to find the root of this error?

Im trying to compile some files with this given gcc command on a server cluster through Mac terminal:
gcc -o driver -std=c11 -Wall -W -ggdb3 driver.c ASMParser.c ParseResult.c Generate.o Grader.o
And get this error:
/usr/bin/ld:Grader.o: file format not recognized; treating as linker script
/usr/bin/ld:Grader.o:1: syntax error
collect2: error: ld returned 1 exit status
but its not very helpful considering Grader.o is a file I didn't even modify, it was provided by the teacher.
Any help on how to fix this? I have compiled it successfully using that gcc command before but after I added a few more implementation details in ASMParser.c it started giving me this error. Im expecting it to create a file called "driver" that I can run like this:
./driver "test file" "results.txt"

Linking a special shared library

I need to link a shared library (LuaSocket) I'm compiling against another special shared library, liblua5.1, that isn't in one of the normal locations. To do this I'm modifying the Makefile.
I cannot figure out what I'm doing wrong, but this particular step that I modified fails:
LIBRARY_PATH=/media/sda2/crank/lib gcc -O -shared -fpic -l liblua5.1 -o socket.so.2.0.2 [...]
(where [...] is a list of .o files that just got built). When I build, I get the error
/usr/lib/gcc/arm-poky-linux-gnueabi/4.8.1/../../../../arm-poky-linux-gnueabi/bin/ld: cannot find -lliblua5.1
collect2: error: ld returned 1 exit status
make: *** [socket.so.2.0.2] Error 1
Inspection of the LIBRARY_PATH confirms that the needed library is there:
# ls /media/sda2/crank/lib/
lgre.so libgre.so libgreio.a liblua.so liblua5.1.so libsbexternal.so
What am I doing wrong?
Change -l liblua5.1 to -llua5.1.
Also, instead of setting LIBRARY_PATH, why not use the -L option? Example: -L/media/sda2/crank/lib.

Error occurs when compiling with GCC

I am attempting to compile a C program with multiple files on window platform. However, when I make it, errors are occurred. I have already tried to modify command in makefile but still could not fix it.
This is my GCC command:
gcc -o "SYSMONTR" $(OBJPATH)/chkdsksp ../chkdsksp.c -g -I"$(DB2PATH)/include" -I"$(MYLIBDIR)" $(MYIQDIR)/iqclilib.a $(OBJPATH)/icrou.a -lc -ldb2 -lnsl -L"$(DB2PATH)/lib"
This is result:
gcc -o "SYSMONTR" ../../iLINKOBJ/chkdsksp ../chkdsksp.c -g -I"C:/Program Files/IBM/SQLLIB/include" -I"../../iLINKCLIB" ../../iLINKIQOBJ/iqclilib.a ../../iLINKOBJ/icrou.a -lc -ldb2 -lnsl -L"C:/Program Files/IBM/SQLLIB/lib"
../../iLINKOBJ/chkdsksp: file not recognized: File format not recognized
collect2: error: ld returned 1 exit status
makefile:49: recipe for target `SYSMONTR' failed
make: *** [SYSMONTR] Error 1
What could cause such error and what should I do with it? Using cygwin on Window (IDE: Eclipse).
Any supports will be appreciated.
If chkdsksp is an object file built by another team to run on AIX, you cannot expect it to function -- or even be recognized by your compiler -- on Cygwin. You must contact that team and get a) the source code or b) a version of the object file compiled for your platform (and tested).

/lib/libmatrix.a: file not recognized: File format not recognized collect2: ld returned 1 exit status

I'm trying to compile a makefile which includes the following line:
gcc -I. -I/home/usr/Documents/MTV/include -ggdb3 -Wall -O2 -o ascii2bin.c \
-L. -L../lib -lmatrix -lseq_io -lpic -lm
And this is what I get:
../lib/libmatrix.a: file not recognized: File format not recognized
collect2: ld returned 1 exit status
Any idea on what might happen to libmatrix.a? How can I read what's inside libmatrix.a? I tried using the 'ar -t' command, but it also says file format not recognized.
The project was compiled on Cygwin before by others, and now I'm using ubuntu gcc to try to redo it, could this be the problem?
A library file built for cygwin will not work on linux.
The library itself must be recompiled from source to match the details (ABI, dynamic system library dependencies, etc) of the system on which it is intended to be used.
Cygwin tries to be source compatible with Linux, so if you have the source rebuilding may be straightforward. But it is not binary-compatible, and libraries are basically binary building blocks with metadata to permit linking them together.

Resources