strange g++ linking behavior depending on arguments order - reference

I was trying to compile a simple opengl program on msys using g++. To my surprise the linker was complaining on undefined references:
$ g++ -mwindows -lopengl32 glut_md2.cpp
C:\Users\...\cceQtYAy.o:glut_md2.cpp:(.text+0x67a): undefined reference to `glGenTextures#8'
C:\Users\...\cceQtYAy.o:glut_md2.cpp:(.text+0x696): undefined reference to `glBindTexture#8'
....
After googling for a while I found that the problem was in g++ arguments order:
$ g++ glut_md2.cpp -mwindows -lopengl32
--- all ok! ---
The interesting thing is that the correct argument orders in g++ is in the first example. That is:
$ g++ --help
Usage: g++.exe [options] file...
....
Am I missing something? Why moving options after the file argument makes a compilation success? I never had this issue when compiling natively on linux...

I bumped into this problem once or twice, you should put -L and -l at the end of command line. g++ doesn't link, it invokes ld and pass arguments, ld man:
The linker will search an archive only once, at the location where it
is specified on the command line. If the archive defines a symbol
which was undefined in some object which appeared before the archive
on the command line, the linker will include the appropriate file(s)
from the archive. However, an undefined symbol in an object appearing
later on the command line will not cause the linker to search the
archive again.
ld -o /lib/crt0.o hello.o -lc

Related

Linux programming: Compile code with dependencies

I am new to linux programming and learning it from The Linux Programming Interface by Michael Kerrisk.
I have to compile my first program that has dependencies.
Directory structure:
--linux-programs
|--seek_io.c
|--lib
|--tlpi_hdr.h
|--error_functions.h
|--error_functions.c
|--get_num.h
|--ename.c.inc
I want to compile seek_io.c program with dependencies in the lib directory, so that I can see how the program works.
I tried a few things, absolutely clueless on how they work following this stackoverflow answer. I get all sorts of errors as I am an absolute beginner to Linux programming, not to programming, linux OS and C.
Trials:
gcc -I ./lib/ -c ./lib/error_functions.c and then gcc -o seek_io.c ./error_function.o gives error:
/usr/lib/gcc/x86_64-linux-gnu/crt1.o: In function _start:
(.text+0x20): undefined reference to main
collect2: error: ld returned 1 exit status
After this run, on ls I find that my seek_io.c is not listed.
Basically the author of the book says for tlpi_hdr.h file:
This header file includes various other header files used by many of the example programs, defines a Boolean data type, and defines macros for calculating the minimum and maximum of two numeric values. Using this header file allows us to make the example programs a bit shorter.
Link to codes for files mentioned above:
tlpi_hdr.h
error_functions.h
error_functions.c
get_num.h
get_num.c
seek_io.c
The problem is with your second gcc command, where you're using the -o file to specify the output file where to store the resulting executable file, but passing it the name of the C source file seek_io.c instead...
gcc -o seek_io.c ./error_function.o
This means link file error_function.o and store the executable in seek_io.c. This fails because there is no main function, which is needed for a standalone executable, so your C source file is not overwritten by the failing link command.
You can fix this easily by passing the -o option a proper output file name, which in the case (of this link command) should be the name of the executable that you want to create, such as seek_io:
gcc -o seek_io seek_io.c ./error_function.o
(But this will fail without a -I ./lib/, since seek_io.c includes tlpi_hdr.h which is in that directory. If you add it to that command, it should work.)
You can also decide to split the compile and link steps in two separate steps (the command above will both compile seek_io.c into an object file and then link the two object files into an executable) with:
$ gcc -I ./lib/ -c ./lib/error_functions.c
$ gcc -I ./lib/ -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
One final nitpick is that for the -I flag to specify the directories where to search for the include files, the more common usage has no space between the flag itself and the directory name, so you'll most commonly see -I./lib or even -Ilib.
$ gcc -Ilib -c ./lib/error_functions.c
$ gcc -Ilib -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o

Linux From Scratch (7.9) Chapter 6.10 linking fails

Here is the step I'm on. Everything has gone fine up to this point, but after replacing the old linker with the new one and making the changes to the specs file, I get the following error when trying to compile dummy.c
/tools/libexec/gcc/i686-pc-linux-gnu/5.3.0/collect2 -plugin /tools/libexec/gcc/i686-pc-linux-gnu/5.3.0/liblto_plugin.so -plugin-opt=/tools/libexec/gcc/i686-pc-linux-gnu/5.3.0/lto-wrapper -plugin-opt=-fresolution=/tmp/cciBczi2.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o /tools/lib/gcc/i686-pc-linux-gnu/5.3.0/crtbegin.o -L/tools/lib/gcc/i686-pc-linux-gnu/5.3.0 -L/tools/lib/gcc/i686-pc-linux-gnu/5.3.0/../../../../i686-pc-linux-gnu/lib /tmp/ccxbWIWi.o "" -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /tools/lib/gcc/i686-pc-linux-gnu/5.3.0/crtend.o /usr/lib/crtn.o
/tools/lib/gcc/i686-pc-linux-gnu/5.3.0/../../../../i686-pc-linux-gnu/bin/ld: cannot find : No such file or directory
collect2: error: ld returned 1 exit status
After a lot of google searching, I've seen other posts about similar problems at the same stage, but all of those errors refer to specific files that are missing (usually crt*.o files), but this error is different and perplexing in that it doesn't actually list a file it can't find. I've made sure ld and the various links to it exist and do things when you invoke them. I've even cut and pasted the directory into a cd command and it does work (I was originally thrown off by the /../../../../ in the path but it seems to work so okay). What file is missing or not being found by collect2?
The problem was an extra space in the command issued to compile the file.
The correct command is:
cc dummy.c -v -Wl,--verbose &>dummy.log
What I entered was:
cc dummy.c -v -Wl, --verbose &>dummy.log
That very small difference meant four hours of hair pulling. Thank you to everyone who offered help!

Library linkage in makefile using gfortran

I have a fortran code (pardiso_1.f) and it needs some libraries (BLAS, lapack and Pardiso libraries) to be compiled. When I try to compile it, I link libraries before compilation and I write this line in linux terminal:
gfortran pardiso_1.f -L/home/behnam/Pardiso -lpardiso412-GNU450-X86-64 -L/usr/lib -lblas -llapack -fopenmp
and it works perfectly.
However I have to run the code using makefile. I am so new in writing makefiles and I do not know how to do the linkage. I have written this makefile. could anyone help me to find out what is wrong with that?
FC = gfortran
OPT = -O2
PROGRAMS = pardiso_1
all: $(PROGRAMS)
FFLAGS = -fopenmp
#### BLAS, LAPACK and PTHREAD libraries
LBLAS = /usr/lib/
###location of pardiso file
LIBMKL = /home/behnam/PS2/
#### Series of libraries
LIBRARIES= -llapack -lblas -lpthread -lm -lpardiso412-GNU430-X86-64
PATHFC = /usr/bin/
nlace: ${PATHFC}${FC} ${OPT} ${FFLAGS} -I${PROGRAMS} -o nlace.exe \
-L${LIBMKL} -lpardiso412-GNU430-X86-64\
-L${LBLAS} ${LIBRARIES}
clean:
rm -f *.o *.exe fort.* *~ *.mod
veryclean: clean
rm -f *~ $(PROGRAMS)
The errors are:
behnam#meen-392430:~/testing$ make
make: Warning: File `Makefile' has modification time 23 s in the future
gfortran -fopenmp pardiso_1.f -o pardiso_1
/tmp/ccYNexaH.o: In function `MAIN__':
pardiso_1.f:(.text+0xb3): undefined reference to `pardisoinit_'
pardiso_1.f:(.text+0x2ae): undefined reference to `pardiso_chkmatrix_'
pardiso_1.f:(.text+0x36e): undefined reference to `pardiso_chkvec_'
pardiso_1.f:(.text+0x44c): undefined reference to `pardiso_printstats_'
pardiso_1.f:(.text+0x5ae): undefined reference to `pardiso_'
pardiso_1.f:(.text+0x860): undefined reference to `pardiso_'
pardiso_1.f:(.text+0xb78): undefined reference to `pardiso_'
pardiso_1.f:(.text+0xe00): undefined reference to `pardiso_'
collect2: ld returned 1 exit status
make: *** [pardiso_1] Error 1
Your makefile does not contain the -L/home/behnam/Pardiso part of your command line.
Your rule for PROGRAMS does not contain a recipe that includes the library calls. I presume you want something like your nlace rule, but right now, make is not calling any of your -L switches as part of its operation.

undefined reference while linking with a shared object

I'm a dumb newbie.
I've got a file named file.c with the functions my_putstr(char *) and my_strlen(char *)
my_putstr() writes the parameter with write() (unistd.h)
I wanted to create a library from file.c so I did :
gcc -fPIC -c file.c
gcc -shared -o libfile.so file.o
Then I created a main.c file and called my_putstr() from it.
I tried to compile and link my .so
gcc -L. -lfile main.c -o test
But I got an undefined reference to my_putstr()
I tried to create a .h with my_putstr() and my_strlen() in it, and include it to the main but I got the same error.
Sorry for stupid questions.
Havaniceday.
Your question suffers lack of information, but I can suggest you at first try
gcc main.c ./libfile.so -Wl,-rpath . -o test
If this will fail, you have something wrong with your sources.
If everything is ok at this point, then try
gcc main.c -L . -lfile -Wl,-rpath . -o test
If this will output undefined reference, then probably you already have something like libfile.a without my_putstr(may be from previous experiments) in your lib path.
If everything is ok with it, then your linker is sensible to order in which libraries is supplied to command string, and you must remember, then library always comes after object, that uses this library.

Compiling C++ program with POSIX AIO lib on Linux

I'm having difficulty with the linker when it comes to compiling a sample program that uses the POSIX aio library (e.g. aio_read(), aio_write(), etc) on Linux.
I'm running Ubuntu with a 2.6 kernel, and have used the apt-get utility to install libaio. But even though I'm linking with the aio library, the compiler still gives me linker errors.
root#ubuntu:/home# g++ -L /usr/lib/libaio.a aio.cc -oaio
/tmp/cc5OE58r.o: In function `main':
aio.cc:(.text+0x156): undefined reference to `aio_read'
aio.cc:(.text+0x17b): undefined reference to `aio_error'
aio.cc:(.text+0x191): undefined reference to `aio_return'
collect2: ld returned 1 exit status
Where are all these aio_x functions actually defined, if not in the library libaio.a?
I also had issues linking against libaio in spite of the aio package being correctly installed and the -lrt flag being present.
It turned out that placing -l flags later (for example, last) in the gcc command invocation sometimes fixes this issue. I stumbled upon this solution here on Stack Overflow.
I stopped doing this:
gcc -Wall -Werror -g -o myExe -lrt myExe.c
And started doing this:
gcc -Wall -Werror -g -o myExe myExe.c -lrt
EDIT: according the the man page, libaio.so is not the correct library to link to:
man aio_read
SYNOPSIS
#include <aio.h>
int aio_read(struct aiocb *aiocbp);
Link with -lrt.
so you should link with this:
g++ -lrt aio.cc -o aio
The way libraries work with gcc is like this:
-L adds directory dir to the list of directories to be searched for -l.
-l adds a library itself, if the file is named libsomename.so, you just use "-lsomename"
Does -L specify the search path and -l specifies the actual library?
You want -laio in order to link to libaio. The argument of -o is what you want the compiled executable to be called.
Try:
sudo apt-get install libaio-dev
Then make sure you specify -laio on the link line.
Okay, Evan Teran is correct - it worked when I linked with -lrt. It seems the aio_x functions are defined in a general POSIX extension library.
Thanks, Evan.

Resources