I was using gcc/g++ 4.4 to build my project, and now i'm trying to switch to gcc 4.5, but getting odd "undefined reference" errors when linking C program with C++ library. Here is my testcase:
source.c
#ifdef LIBRARY
extern "C" int one() {
return 1;
}
#else
#include <stdio.h>
int one();
int main() {
printf ("%i\n", one());
return 0;
}
#endif
Makefile
all: clean program
program: source.c library.so
$(CC) -L. -lrary -o $# $<
library.so: source.c
$(CXX) -shared -DLIBRARY -fPIC -o $# $<
.PHONY: clean
clean:
rm -f program library.so
Everything works fine while using GCC 4.4:
$ CXX=g++-4.4 CC=gcc-4.4 make
rm -f program library.so
g++-4.4 -shared -DLIBRARY -fPIC -o library.so source.c
gcc-4.4 -L. -lrary -o program source.c
But not working while using GCC 4.5:
$ CXX=g++-4.5 CC=gcc-4.5 make
rm -f program library.so
g++-4.5 -shared -DLIBRARY -fPIC -o library.so source.c
gcc-4.5 -L. -lrary -o program source.c
/tmp/ccC4kNHP.o: In function `main':
source.c:(.text+0xa): undefined reference to `one'
collect2: ld returned 1 exit status
make: *** [program] Error 1
Or GCC 4.6:
$ CXX=g++-4.6 CC=gcc-4.6 make
rm -f program library.so
g++-4.6 -shared -DLIBRARY -fPIC -o library.so source.c
gcc-4.6 -L. -lrary -o program source.c
/tmp/ccxNRNSS.o: In function `main':
source.c:(.text+0xa): undefined reference to `one'
collect2: ld returned 1 exit status
make: *** [program] Error 1
Anyone can shed a light on this issue?
PS: This one was built using 4.6:
$ nm -D library.so
w _Jv_RegisterClasses
0000000000201010 A __bss_start
w __cxa_finalize
w __gmon_start__
0000000000201010 A _edata
0000000000201020 A _end
00000000000005a8 T _fini
0000000000000458 T _init
000000000000055c T one
It is because of linker's --as-needed option being used i.e. the library is not linked until a symbol is actually found in the source which is part of the library. You should move your source files before linking in the compilation command. You could try changing your Makefile rule program from $(CC) -L. -lrary -o $# $< to $(CC) $< -L. -lrary -o $#. Or alternatively, you could pass --no-as-needed to the linker i.e. $(CC) -Wl,--no-as-needed -L. -lrary -o $# $<. The first method is better suited to be used.
Hope this helps!
Related
I'm trying to write my own makefile for a paho.mqtt project on a Raspberry Pi 4.
I've downloaded & tested the paho.mqtt install and its all working as expected.
So I'm now testing some C code but I just cant figure out the makefile (I'm new to this), my file so far,
NAME = mqtt_test
OBJ = $(NAME).o
LIBS = -libpaho-mqtt3c -libpaho-mqtt3cs
CFLAGS = -Wall -I/usr/local/include -L/usr/local/lib
CC = gcc
EXTENSION = .c
all: $(NAME)
%.o: %$(EXTENSION) $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
$(NAME): $(OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
#rm -f *.o *~ core $(NAME)
This returns,
gcc -o mqtt_test mqtt_test.o -Wall -I/usr/local/include -L/usr/local/lib -libpaho-mqtt3c -libpaho-mqtt3cs
/usr/bin/ld: cannot find -libpaho-mqtt3c
/usr/bin/ld: cannot find -libpaho-mqtt3cs
collect2: error: ld returned 1 exit status
make: *** [makefile:14: mqtt_test] Error 1
I've checked & the includes and libraries are in the directories I put after the-I and -L flags.
When I look in /usr/bin there is no ld but there are paho files prefixed with paho_ but no library files.
What am I missing?
You don't use -libpaho-mqtt3c (etc.)
The option is -l so when you write -libpaho-mqtt3c the linker is looking for libraries named ibpaho-mqtt3c which of course do not exist: that would be either libibpaho-mqtt3c.a or libibpaho-mqtt3c.so.
You want to use -lpaho-mqtt3c: remove the lib at the front and the extension .a or .so, and add in the option -l.
I'm trying to link a static library archive file (libx/libx.a) with a C code. The library requires 2 flags (-lx -lpthread). After linking the static library my ultimate goal is to create a shared library. I have the following Make file,
rsa-engine: rsa/rsa.c rsa/bignum.c rsa/aes.c rsa/x509parse.c rsa/pem.c
gcc -fPIC -o rsa/rsa.o -c rsa/rsa.c
gcc -fPIC -o rsa/bignum.o -c rsa/bignum.c
gcc -fPIC -o rsa/aes.o -c rsa/aes.c
gcc -fPIC -o rsa/x509parse.o -c rsa/x509parse.c
gcc -fPIC -o rsa/pem.o -c rsa/pem.c
gcc -fPIC rsa-engine.c libx/libx.a -L.libx/ -lx -lpthread -o rsa-engine.o
gcc -shared -o librsa_engine.so -lcrypto rsa-engine.o rsa/rsa.o rsa/bignum.o rsa/aes.o rsa/x509parse.o rsa/pem.o
clean:
rm -f *.o rsa/*.o *.so rsa-engine
After using the make command it produces the following output,
/usr/bin/ld: cannot find -lx
collect2: error: ld returned 1 exit status
Makefile:2: recipe for target 'rsa-engine' failed
make: *** [rsa-engine] Error 1
I found similar questions here. But that did not help. Seems like I can't make the link work. Any help with what I'm doing wrong?
I would like to achieve the same result generated by the following command,
CC := gcc
CFLAGS := -Wall -g -MD -O2 -I ../
LDFLAGS := -lx -lpthread
tests_files := hello
all: $(tests_files)
hello: hello.o ../libx/libx.a
$(CC) $(CFLAGS) -static $(<) -L../libx/ $(LDFLAGS) -o $(#)
It seems that your libx.a is located in libx, yet -L references .libx directory. Anyway, since you reference libx/libx.a directly, you may skip both -L.libx/ -lx and it should link just fine.
I am having issues getting my Makefile to compile a very simple main function, and I can't seem to find the issue. Here is my Makefile:
main: main.o Recursion.o
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
gcc -Wall -c main.c
Recursion.o: Recursion.c Recursion.h
gcc -Wall -c Recursion.c
clean:
rm main *.o
When I enter the make command in the UNIX terminal, this is the result I get:
-bash-4.2$ make
cc -c -o main.o main.c
cc -c -o Recursion.o Recursion.c
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
make: main.o:: Command not found
make: *** [Makefile:3: main] Error 127
-bash-4.2$
I cannot figure out what's wrong. It is generating the executable main, but I'm not sure what exactly the issue is on the command line. Any suggestions?
Makefiles are indentation-sensitive.
Try this:
main: main.o Recursion.o
gcc -Wall -o main main.o Recursion.o
main.o: main.c Recursion.c
gcc -Wall -c main.c
Recursion.o: Recursion.c Recursion.h
gcc -Wall -c Recursion.c
clean:
rm main *.o
I have got 4 files: pass1.c , pass2.c, main.c and header1.h.
Each of these files, include the file header.h
I wrote the following makefile:
assembler: pass1.o pass2.o main.o
gcc pass1.o pass2.o -o assembler
pass1.o: pass1.c
gcc -c -ansi -Wall -pedantic pass1.c -o pass1.o
pass2.o: pass2.c
gcc -c -ansi -Wall -pedantic pass2.c -o pass2.o
main.o: main.c
gcc -c -ansi -Wall -pedantic main.c -o main.o
When I did make, I got the following error:
/usr/lib/gcc/x86_64-linux-gnu/6/../../../x86_64-linux-gnu/Scrt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
makefile:2: recipe for target 'assembler' failed
make: *** [assembler] Error 1
Note that I didn't write a function called 'start'.
What is the problem here and how can I fix it?
gcc pass1.o pass2.o -o assembler
should be
gcc main.o pass1.o pass2.o -o assembler
Rename main.c to assembler.c and your entire makefile can be condensed to
CFLAGS := -ansi -Wall -pedantic
objects := assembler.o pass1.o pass2.o
assembler: $(objects)
$(objects): header.h
assuming that cc on your system is a symlink to gcc.
I got this error when I do make
gcc -o tests/simple_test tests/simple_test.o -L. libtraceback.a -Wall -Werror -gdwarf-2 -O0 -m32 -fno-stack-protector -fno-omit-frame-pointer -Itraceback/ -mpreferred-stack-boundary=2 -static
/usr/bin/ld: cannot find crt1.o: No such file or directory
/usr/bin/ld: cannot find crti.o: No such file or directory
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc.a when searching for -lgcc
/usr/bin/ld: cannot find -lgcc
/usr/bin/ld: skipping incompatible /usr/lib/gcc/x86_64-linux-gnu/4.8/libgcc_eh.a when searching for -lgcc_eh
/usr/bin/ld: cannot find -lgcc_eh
/usr/bin/ld: cannot find -lc
collect2: error: ld returned 1 exit status
I read one post and tried
sudo ln -s /usr/lib/x86_64-linux-gnu /usr/lib64
But it doesn't help, is there any reason for this?
Im running on a surface pro 2 using vmware running 64bits ubuntu 13.10.
If you do not have any parcticular reason to build a 32bit application on a 64bit machine just do not use the option -m32.
In case you are following this tutorial then fixed make file code is below working on Ubuntu 20
# $# = target file
# $< = first dependency
# $^ = all dependencies
# First rule is the one executed when no parameters are fed to the Makefile
all: run
kernel.bin: kernel-entry.o kernel.o
ld -m elf_i386 -o $# -Ttext 0x1000 $^ --oformat binary --entry main
kernel-entry.o: kernel-entry.asm
nasm $< -f elf -o $#
kernel.o: kernel.c
gcc -m32 -ffreestanding -c $< -o $# -fno-pie
mbr.bin: mbr.asm
nasm $< -f bin -o $#
os-image.bin: mbr.bin kernel.bin
cat $^ > $#
run: os-image.bin
qemu-system-i386 -fda $<
clean:
$(RM) *.bin *.o *.dis
To run make file
make run
to clean all output files
make clean