Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Nov 13th, 2005, 10:57 PM   #1
kurt
Programmer
 
Join Date: Oct 2005
Posts: 68
Rep Power: 3 kurt is on a distinguished road
Weirdness of -l compile flag

Why is it that i need to add the -lm flag during compilation, when i already included #include <math.h> ?

Quote:
#include <math.h>

main()
{
printf("%f",log(10));
}
The above code won't compile unless i added the -lm flag.

If that is the case, why don't we need to add flags such as -lstring, -lstdio for string.h and stdio.h respectively?
kurt is offline   Reply With Quote
Old Nov 14th, 2005, 5:35 AM   #2
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,207
Rep Power: 5 grumpy is on a distinguished road
You probably would have received an earlier response if you had actually identified your compiler and operating system .... your question is actually specific to those.

In any event, under most flavours of unix (or on ports of unix compilers, such as gcc, to windows) -lm is not a compiler option, it is a linker option.

Your compiler command (eg cc by default on most unixes, gcc if you're using a gnu compiler) does a bit more than you think it does. When you use it in a way that requires a starting point of source code and an end point of an executable, it does (approximately) the following steps;

1) Compile the various source files (with a .c extension for C, or .cpp extension for C++ source) to create an object file (which usually has a .o extension). This is done by invoking the actual compiler (the thing that understands source code). If you're using cc, this step is roughly equivalent to "cc -c <other compiler options> file.c".

2) Collect all of the .o files created in the previous step, and any filenames and command line options, and invoke the linker --- which is a totally different program. The command line options that the linker understand include lists of libraries (the things represented by -l<library_name> and various other things related to creating the final executable file). Essentially it links all the .o files, and the libraries it is told to link in, together to create the executable.

3) Delete the .o files that it created in the first step.

So what's the relevance of the above? Well, -lm is an option supplied to the linker, and tells it to link in the math library. By default, the math library is not linked in because (so it is claimed) the majority of applications do not need it. The catch is that the driver program that pulls together the various steps for compilation and linking does not actually interpret the source code, so does not realise that source code which uses #include <math.h> probably needs the math library. So you need to tell it, by specifying "-lm", to do that. It passes that command line option directly on to the linker.

The reason you don't need to do this for other standard headers is that, by default, the linker is told to link in the standard C library (-l<some_name_I_cannot_remember_offhand>), and that library includes implementations of the functions in string.h and stdio.h.

The above is a very simplistic view of what happens, and is a relatively long-standing tradition in the unix world.

In your case, you would (unless you've done something else wrong) have gotten past the compilation phase, and the linker phase will be failing.
grumpy is offline   Reply With Quote
Old Nov 14th, 2005, 5:00 PM   #3
jim mcnamara
Hobbyist Programmer
 
Join Date: Jun 2005
Location: New Mexico
Posts: 228
Rep Power: 4 jim mcnamara is on a distinguished road
[sarcasm]
-l<somename..> = libc Which is really tough becuase were coding in what language.
[/sarcasm]

Actually the linking thing with the -ell business is confusing and not aat all meaningful.
Plus, it is always
int main( what goes here may vary)
{

    return 0;
}
This is because main, by definition, returns an int. The old style
 main()
will be converted to an int by most but not all compilers.

If you run code like this thru lint or compile with gcc -Wall (either one highly recomended) stuff like this generates all kinds of complaints.

Rule #1 - Never use C code that has compiler complaints. You'll complain later on.

See:

http://www.lysator.liu.se/c/ten-commandments.html

It's meant somewhat in fun but largely to be taken as gospel. Which is why the Elizabethan english....

Rule #2 If ever in doubt see Rule #1.
jim mcnamara is offline   Reply With Quote
Old Nov 14th, 2005, 6:20 PM   #4
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,207
Rep Power: 5 grumpy is on a distinguished road
Quote:
Originally Posted by jim mcnamara
[sarcasm]
-l<somename..> = libc Which is really tough becuase were coding in what language.
[/sarcasm]
Yeah, yeah.

The name actually varies between compilers. I encountered one Irix compiler a few years ago that named the standard C library cstd.

Quote:
Originally Posted by jim mcnamara
Plus, it is always
int main( what goes here may vary)
{

    return 0;
}
This is because main, by definition, returns an int. The old style
 main()
will be converted to an int by most but not all compilers.
The 1989 C standard deemed that a function with no specified return type returns int. That is not true in C++. I don't recall if it is true in the 1999 C standard.

It is often considered bad style (as it is a source of future errors) to rely on that behaviour, which is why ....
Quote:
Originally Posted by jim mcnamara
If you run code like this thru lint or compile with gcc -Wall (either one highly recomended) stuff like this generates all kinds of complaints.
grumpy is offline   Reply With Quote
Old Nov 15th, 2005, 3:59 AM   #5
kurt
Programmer
 
Join Date: Oct 2005
Posts: 68
Rep Power: 3 kurt is on a distinguished road
hehe sorry...i'll be more specific in my future posts.
i'm using gcc on linux.

so basically most compilers would include some -l<??>, and omit some (like for this case, -lm).

Thanks
kurt is offline   Reply With Quote
Old Nov 15th, 2005, 5:34 AM   #6
nnxion
Programming Guru
 
nnxion's Avatar
 
Join Date: Jun 2005
Location: elemental plane
Posts: 1,429
Rep Power: 5 nnxion is on a distinguished road
I may be misunderstanding because of the language barrier, but isn't a linker supposed to link only to those functions used in the source code?
For example
#include <stdio.h>
#include <math.h>

int main()
{
	printf("%d\n", pow(3, 2));
	return 0;
}

Then your linker would only link the printf and pow function, and not all the other functions included in stdio.h and math.h right?
__________________
"Employ your time in improving yourself by other men's writings, so that you shall gain easily what others have labored hard for."
-- Socrates
nnxion is offline   Reply With Quote
Old Nov 15th, 2005, 9:29 AM   #7
jim mcnamara
Hobbyist Programmer
 
Join Date: Jun 2005
Location: New Mexico
Posts: 228
Rep Power: 4 jim mcnamara is on a distinguished road
nnxion -

Link editing does just that. It finds external symbols (function entry points and pointers to memory) that are not locally defined.

by C standard this means

1. linker brings in a file called crt.0 - which is _startup - the thing that invokes main
_startup always does OS dependent stuff- like creating stdin. _startup is not a name defined in the standard, it describes what it does. crt0.o is a standard C object filename in POSIX. What is in crt0.o is also standard - _startup code and _end code.

2. linker brings in _end and then _Exit (from libc because _end invokes it). Al of this is on the "other end" of main(). _Exit is defined in the standard and is called by _end. It unwinds the stack and closes any open file, then does what it takes to get the OS to rundown the process internal data.

3. Look first in libc (standard file name) for any undefined symbols in the object file(s). This is why you should not use names like printf as function names you create.
This is the dash big-ell syntax -L <directory>

4. Lookup undefined symbols using either a directory search of libraries or a search in a list of specified libraries. This is the dash lowercase ell thing. -lm
jim mcnamara is offline   Reply With Quote
Old Nov 15th, 2005, 9:30 AM   #8
jim mcnamara
Hobbyist Programmer
 
Join Date: Jun 2005
Location: New Mexico
Posts: 228
Rep Power: 4 jim mcnamara is on a distinguished road
POSIX and IRIX don't get along too well, as you note, Grumpy.
jim mcnamara is offline   Reply With Quote
Old Nov 16th, 2005, 12:44 AM   #9
grumpy
Programming Guru
 
grumpy's Avatar
 
Join Date: Jun 2005
Location: Adelaide, South Australia
Posts: 1,207
Rep Power: 5 grumpy is on a distinguished road
Quote:
Originally Posted by nnxion
I may be misunderstanding because of the language barrier, but isn't a linker supposed to link only to those functions used in the source code?
Approximately, yes. In practice, it's a little more complex because compiling and linking are separate phases. But, as a very rough rule the linker (as Jim said) is about establishing linkages in an executable between the point where a function is called and the function that is called. In practice, this usually means that a function in a library is only pulled into the executable if it is called. However, it is possible to wind up with a function being included in an executable as dead code (eg if the body is in an object file rather than a library, but it is never called) unless the linker is smart enough to remove dead code. Most linkers are not smart enough to remove dead code.

Quote:
Originally Posted by jim mcnamara
by C standard this means

1. linker brings in a file called crt.0 - which is _startup - the thing that invokes main
_startup always does OS dependent stuff- like creating stdin. _startup is not a name defined in the standard, it describes what it does. crt0.o is a standard C object filename in POSIX. What is in crt0.o is also standard - _startup code and _end code.

2. linker brings in _end and then _Exit (from libc because _end invokes it). Al of this is on the "other end" of main(). _Exit is defined in the standard and is called by _end. It unwinds the stack and closes any open file, then does what it takes to get the OS to rundown the process internal data.

3. Look first in libc (standard file name) for any undefined symbols in the object file(s). This is why you should not use names like printf as function names you create.
This is the dash big-ell syntax -L <directory>

4. Lookup undefined symbols using either a directory search of libraries or a search in a list of specified libraries. This is the dash lowercase ell thing. -lm
None of the above is required by the C standard. I assume it is part of the POSIX specification. But the C standard does not require support of POSIX.
grumpy is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 2:51 AM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC