ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I've made a start on learning C, and (to my surprise) so far so good.
I was testing my understanding by writing a quadratic-equation solver, which makes use of the sqrt() function.
If I put a number into sqrt(), I can compile with just "gcc quadratic.c", but if I ask it to sqrt() a variable, which is what I actually want, I get the error "undefined reference to 'sqrt'"
I googled it, and found that I needed to add "-lm" to the end of the gcc command, and that did indeed solve the problem.
But I don't understand WHY, and neither Google nor that gcc man page is helping me. What does -lm do, and why is it needed in this instance when I've never needed it before?
By passing -lm to gcc you tell it to link against the shared library libm.so which contains the code for sqrt and other mathematical functions. (basicly if you use math.h you need to link against libm) In the case when you used sqrt with a constant(numeric literal) probably gcc optimizes the call at compile time so actually you don't use any function.
sqrt() is a function which is *defined* in the maths library.
when you use -lm to link your executable against the math library.
In simpler terms,
somebody has written the sqrt() function (so that you do not need
to write it)and compiled it .the compiled code is there in a
file named libm.so.* along with many other functions like
pow(),log(),sin() etc.
Now when you call the function sqrt() from your code ,the
compiler needs to know where to find the code for sqrt().
You tell the compiler to look for it in the file libm.so.*
by using the compiler flag '-lm'.
All the library file names start with 'lib' like libm.so.*,libc.so.*,
etc. look under the folder /usr/lib or /usr/include/lib to see
how the library files are named.
If you had to link with library file libxyz.so.* you had to
compile it with '-lxyz' .
Hope it clears your doubts.
The '*' in the end of the library file name is just a number.
So the actual name for the math library is like
libm.so.1 or libm.so.2 .
Just a small correction - when linking with '-lxxx', GNU ld searches for 'libxxx.so'. Usually the shared libraries are named 'libxxx.so.version' and symlinked to 'libxxx.so'.
Okay.. I now understand what the "-lm" is actually doing. Thanks to all who replied for that.
So am I right in thinking that the "#include <math.h>" at the start of the code declares the function sqrt() but doesn't define it, and then libm.so.* actually defines it, hence both being needed?
Distribution: Solaris 11.4, Oracle Linux, Mint, Debian/WSL
Posts: 9,789
Rep:
Quote:
Originally Posted by oneandoneis2
Okay.. I now understand what the "-lm" is actually doing. Thanks to all who replied for that.
So am I right in thinking that the "#include <math.h>" at the start of the code declares the function sqrt() but doesn't define it, and then libm.so.* actually defines it, hence both being needed?
Indeed, include files usually do not define functions.
Your confusion probably comes from the fact that the library functions you used before (say printf, malloc, ...) are present in the standard C library.
This library (libc/glibc) is included by default in the linker list of libraries to use, so linking is done transparently (no need to use -lc).
When you call any function that isn't in this standard library, like maths, X11, gtk or whatever, you need to explicitely tell the linker what to use.
Your confusion probably comes from the fact that the library functions you used before (say printf, malloc, ...) are present in the standard C library.
Yep, I think that nails it dead-on! I couldn't quite grasp why printf, scanf, and the like all worked with just an #include while sqrt didn't.
Some of the functions in libm.so can be inlined by gcc if you use the "fast-math" option (-ffast-math). This causes gcc to emit floating-point instructions instead of function calls for instructions that are implemented on the FPU (such as sqrt, sin, cos, atan2). It's usually a good idea to use this unless strict IEEE compliance is required.
Learning any language is a mind-blowing experience, but it does get easier.
You're right in observing that the ".h" files declare the function's existence. They provide all that the compiler needs in order to produce a program that expects to know (say...) how to calculate a square-root.
In some funky cases, the ".h" file actually includes declarations that enable the compiler to outright generate the code that (say) does the square-root calculation. Although you write it as a function-call, sometimes the compiler is told how to "inline" that function - to generate the code itself.
In the more general case, however, what the compiler does is to generate a program that will "make a call to an external function named 'sqrt.'" The term "external" means that the output-file generated by the compiler refers to the function but does not, itself, contain it. Therefore, before the program can actually run and produce square-roots, it must be linked to the appropriate function -- which was written by very smart people somewhere far away and put into a library.
There are actually several ways that this linking can occur. One way is static linking, where the 'sqrt' routine is found in its library, inserted into the program file, and made a part of it so that the program no longer refers to 'sqrt' but rather contains it. Each program therefore contains its own (redundant) copy of the 'sqrt' code. The library is only needed by the developer who's building the program.
Another way to do it is dynamic linking, a la the "DLL" files in Microsoft Windows. In this scenario, the link to the appropriate 'sqrt' routine actually occurs as the program is being loaded into memory. A single, shared copy of the library will live in the computer's memory and be used by all. A program that relies upon a shared-library routine can't run on a system that doesn't have that library.
Last edited by sundialsvcs; 09-22-2006 at 09:10 PM.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.