gcc l option order? [duplicate] - c

This question already has answers here:
Why does the order in which libraries are linked sometimes cause errors in GCC?
(9 answers)
Closed last year.
gcc -g -O2 -Wall -I/usr/local/include MyAddressBook.pb-c.c addressbooktest.c -lprotobuf-c -o test
worked, but
gcc -g -O2 -Wall -I/usr/local/include -lprotobuf-c -o addressbooktest addressbooktest.c MyAddressBook.pb-c.c
didn't.
man gcc said that
For the most part, the order you use doesn't matter.
Order does matter when you use several options of the same kind; for example, if you specify -L
more than once, the directories are searched in the order specified. Also, the placement of
the -l option is significant.
however I cannot understand how the use of -L and -l option change compile logic.
How can I know where to use -L, -l option?

When you use
gcc -g -O2 -Wall -I/usr/local/include -lprotobuf-c -o addressbooktest addressbooktest.c MyAddressBook.pb-c.c
the linker (which is a separate program which is invoked by the gcc front-end program) runs, it will find the library protobuf-c but since no one (yet) uses any functions from it, it will be ignored.

Related

gcc in Windows cannot compile C program written for Unix/Linux

I am a Unix/Linux newbie who is trying to run a shell script written by a person who left no documentation and has since demised. This script contains line:
./search $opt1 $arg1 < $poly 2>&1 | tee $output
Which is trying to get the file $poly and call program ./search and divert the output to $output.
When I get to this line, I am given message: ./search: cannot execute binary file: Exec format error
search is a C program called from the script and is in the same folder as various other C programs to do with this project. Script and C programs were developed and originally executed on a Unix/Linux box which is no longer available, so I have been asked to try to resurrect this project but under Windows using gcc in NetBeans and cygwin.
The message : ./search: cannot execute binary file: Exec format error is most likely to do with the fact there is no executable file for search. When I try to build the C programs I get the following output:
C:\cygwin64\bin\make.exe -f Makefile
gcc -ansi -g -c cbuild.c
gcc -ansi -g -c complex.c
gcc -ansi -g -c mylib.c
gcc -ansi -g -c poly.c
gcc -ansi -g -c real.c
gcc -ansi -g -c zero.c
gcc -lgmp -lm -lrt -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o
real.o: In function `rabs':
/cygdrive/c/../progs/real.c:9: undefined reference to `__imp___gmpf_abs'
/cygdrive/c/../progs/real.c:9:(.text+0x1e): relocation truncated to fit: R_X86_64_PC32 against undefined symbol `__imp___gmpf_abs'
real.o: In function `radd':
I assume that R_X86_64_PC32 refers to the environment I am using. I am using a 64 bit version of Netbeans with gcc 5.4.0 in a 64 bit version of cygwin on Windows 10.
Can anyone advise what I must to to resolve this so that I can build the C programs?
The problem is this:
gcc -lgmp -lm -lrt -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o
By default, the linker will link libraries and objects in the order specified on the command line, and, when linking a library, will only include symbols needed by things before it on the command line. Since -lgmp is first, there are (as yet) no outstanding symbols (except main), so nothing is included from the library. When later objects need the symbols from it, they won't see them.
Change the order to
gcc -o cbuild cbuild.o complex.o mylib.o poly.o real.o zero.o -lgmp -lm -lrt
and it should work. Alternately, use the -Wl,--as_needed linker option to get the linker to remember earlier libraries and relink them if more symbols from them are referenced by later object files (requires a recent version of the GNU linker -- I have no idea if it works with cygwin).
This kind of misordering is usually a symptom of a broken Makefile. The normal Makefile structure has a bunch of variables that are set to control the default rules that know how to compile source files and link object files. The two variables relevant for linking are LDFLAGS and LDLIBS, and the difference is that LDFLAGS comes before all the object files on the command line and LDLIBS comes after all the object files.
So in order to make things work, you need to ensure that all of the -l options and other libraries are in LDLIBS:
LDLIBS = -lgmp -lrt -lm
and NOT in LDFLAGS

Create static library including ncurses

I want to create a static library implementing a TUI interface using ncurses. I'm new to this topic and applying these answers didn't work
out for me.
rpath
combine multiple libraries
I want to link varViewer.c in a library. I use this code to compile a example file.
Compiling src/example.c and src/viewer/varViewer.c:
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/example.c -o obs/example.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o obs/viewer/varViewer.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
Linking obs/example.o to bin/example:
gcc -o bin/example -Isrc/viewer/
obs/example.o obs/viewer/varViewer.o -lncurses
-fsanitize=undefined -fprofile-arcs -ftest-coverage -Winline -O2
bin/example works as expected. I tried to compile a suitable object file:
Compiling src/viewer/varViewer.c:
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o lib/objects/varViewer.o
-lncurses -fPIC -O2
and put it into library:
ar -cvr lib/libvarViewer.a lib/objects/varViewer.o
when I try to use it in other projects, a include it using
-L ..../src/viewer/lib -lvarViewer
flags but all references to functions I used from ncurses library and
string.h are undefined:
nm /lib/libvarViewer.a
....
U __snprintf_chk
U __stack_chk_fail
U start_color
U stdscr
U strchr
U strlen
U strncmp
U strncpy
U strnlen
U waddnstr
U wborder
U wclear
U wcolor_set
U wgetnstr
U winsdelln
U winsnstr
U wmove
U wrefresh
What is the correct way to call ar? I already tried to produce a "thin" library using -T option.
The command
gcc -Wall -Wextra -Wnonnull -Isrc/viewer/
-c src/viewer/varViewer.c -o lib/objects/varViewer.o
-lncurses -fPIC -O2
will simply compile the varViewer.c file and thus, will ignore the libraries because it won't link to a final executable.
Consequently, the object file varViewer.o will have undefined references (U reported in nm as you have shown) to the symbols not defined within varViewer.c. These not only include the libncurses library but also the regular libc library (which provides symbols such as strlen, strncpy, ...). However, remember that libc will be automatically added into your link stage by the compiler unless you explicitly state otherwise.
You could use the command ar x to extract the object files (.o) from other static libraries and then use ar again to generate a new library. While this is possible I don't think that including all the libraries into yours is a good idea. I think that it is better to link against all the libraries needed because that ensures that the application is linked against the latest version available -- while if you embed one library into yours, then will stick to that version until you upgrade it.

Can't name executable with specified optimization

I have to turn off optimizations while compiling c code I wrote while using the gcc compiler on a linux. I have found that I can compile the code but I can only get the code to compile without the executable name specified (default to a.out).
So this works:
gcc -O0 Problem04b.c
But my problem is that I have to submit this assignment and I can't submit an executable called a.out because my instructor needs to know which problem it is. I realize I can probably just run
cp a.out Problem04b
then
rm a.out
but I want to know if there is a way I can just compile the code directly into the executable Problem04b. I've tried to run the command like this:
gcc -O0 Problem04b Problem04b.c
but I'm having no luck.
Thanks for your help.
It's the -o flag:
gcc -O0 -o Problem04b Problem04b.c
To specify the output file, you need to use the -o <filename> option with gcc.
Note : Please mind the lower case here
In your case, it should be
gcc -O0 -o Problem04b Problem04b.c
For reference: From gcc manual
-o file
Place output in file file. This applies to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code.
Actually, you also want to get warnings (that won't change the produced executable, but it is very helpful to you), so compile with
gcc -O0 -Wall -Wextra Problem04b.c -o Problem04b
The -Wall option asks for nearly all warnings, the -Wextra option asks for even more of them.
To run your thing (the ./ is useful because of possible PATH issues):
./Problem04b
Notice that -O0 is optional (since it is the default), you could remove it.
gcc -Wall -Wextra Problem04b.c -o Problem04b
If you want real optimization, e.g. for benchmarking, use e.g. -O1 or -O2 or -O3
You probably want to compile with debug information, then
gcc -g -Wall -Wextra Problem04b.c -o Problem04b
and of course you need to learn how to use the GDB debugger. So read some tutorial about that, then type
gdb ./Problem04b
You'll get a (gdb) prompt. Try help at that time.
You probably want to read the chapter about invoking GCC of the GCC documentation.

Compile options for alsa project

Question relates to the following build command which is part of a project I have inherited from a lost programmer who I can't ask to explain it. The project was based on the alsa utils 'latency' sample, which he has extended to provide other functionality. The command works on the project but I want to start stripping out all the unused junk in the project and I kind of need to understand whats going here. I can program C and use gcc in the basic sense but I don't understand the below command very well. I wonder if anyone can confirm my assumptions below and explain a couple of bits:
I have this command to build the project:
if gcc -DHAVE_CONFIG_H -I. -I. -I../include -I../include -Wall -pipe -g -g -O2 -MT latency.o -MD -MP -MF ".deps/latency.Tpo" -c -o latency.o latency.c; then mv -f ".deps/latency.Tpo" ".deps/latency.Po"; else rm -f ".deps/latency.Tpo"; fi && /bin/bash ../libtool --tag=CC --mode=link gcc -lvgagl -lvga -Wall -pipe -g -g -O2 -o latency latency.o ../src/libasound.la
I think I understand whats going on here. Wall = warnings, pipe = irrelevant, -g = debugging stuff, -O2 optimization stuff, -MT make an object file instead of executable, and overall the first bit of the command means make a dependency list from latency.c, and also compile latency.o. The dependency file is to be called .deps/latency.Tpo.
If the first command returns success then move .deps/latency.Tpo to .deps/latency.po, if it returns failure delete .deps/latency.Tpo.
Then as long as the delete or move has succeeded, run the last bit (after the &&). Which links latency.o, ../src/libasound.la, lvgagl and lvga together into the executable latency.
Currently the project uses svgalib which I don't need it to do, so I will start by removing that, and I assume I can then remove the -lvgagl -lvga from the libtool command.
However I completely don't understand the '-DHAVE_CONFIG_H -I. -I. -I../include -I../include' portion. I know that -I is a header file search path but why is it repeated twice? And whats the DHAVE_CONFIG_H mean? And why bother making the dependency file if its not used again (I see no other references to it during the libtool step).
Most of that crap is automatically generated by automake and autoconf; you can ignore it.
The duplicated include paths do not hurt, so nobody bothered to avoid them.
The -DHAVE_CONFIG_H is generated by autoconf, but not used by any code in alsa-lib (nor by latency.c).
The only non-standard options in this are the -lvgagl -lvga libraries, which you already know how to handle.
Everything else can be ignored when moving to another build system; the defaults will work fine.

Does gcc -nostdlib prevent explicit appending of standardlibs?

If I call the GCC Linker with the option -nostdlib does this override any manual/explicit appendecis of standardlibs?
GCC is 4.8.1 from MinGW.
Example:
gcc -nostdlib [MyObjectsAndLibraries] -lmsvcrt -o Outfile
Since libmsvcrt is a standard library, will it be added to the link process or will it be ignored? I can't find any reliable data on this., this is why I would also appreciate some kind of source to this.
In this context, "standard libraries" means the libraries that gcc would implicitely link by default. Libraries explicitely mentioned on the command line will always be linked. In fact, gcc documentation at http://gcc.gnu.org/onlinedocs/gcc-4.8.2/gcc/Link-Options.html#Link-Options even points out that unless you really know what you're doing you should add explicitely -lgcc when using -nostdlib, as the compiler may rely on some builtins defined in it:
In other words, when you specify -nostdlib or -nodefaultlibs you should usually specify -lgcc as well. This ensures that you have no unresolved references to internal GCC library subroutines.
Since I found this on Google,
#Virgile's answer is enough, but you may run into linker errors when you link with the style of command you gave. There is two steps to program building: compile and link. You can use GCC to do one or the other or both at the same time.
It is important to note the order of which you specify things. In your build, it may be problematic because your exe never gets linked with msvcrt or gcc. Including two libraries which have potentially the same symbols is also very bad.
Here is canonical build and link statements
gcc -g0 -O2 -Wall -nostdlib -c *.c
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.o -lmsvcrt -lgcc
gcc -g0 -O2 -Wall -nostdlib -o a.exe *.c -lmsvcrt -lgcc
Here is a good reference
https://stackoverflow.com/a/18389266/2262111

Resources