I have this simple code:
max = (int) sqrt (number);
and in the header I have:
#include <math.h>
But application still says undefined reference to sqrt. Do you see any problem here? It looks like everything should be okay.
You may find that you have to link with the math libraries on whatever system you're using, something like:
gcc -o myprog myprog.c -L/path/to/libs -lm
^^^ - this bit here.
Including headers lets a compiler know about function declarations but it does not necessarily automatically link to the code required to perform that function.
Failing that, you'll need to show us your code, your compile command and the platform you're running on (operating system, compiler, etc).
The following code compiles and links fine:
#include <math.h>
int main (void) {
int max = sqrt (9);
return 0;
}
Just be aware that some compilation systems depend on the order in which libraries are given on the command line. By that, I mean they may process the libraries in sequence and only use them to satisfy unresolved symbols at that point in the sequence.
So, for example, given the commands:
gcc -o plugh plugh.o -lxyzzy
gcc -o plugh -lxyzzy plugh.o
and plugh.o requires something from the xyzzy library, the second may not work as you expect. At the point where you list the library, there are no unresolved symbols to satisfy.
And when the unresolved symbols from plugh.o do appear, it's too late.
I suppose you have imported math.h with #include <math.h>
So the only other reason I can see is a missing linking information. You must link your code with the -lm option.
If you're simply trying to compile one file with gcc, just add -lm to your command line, otherwise, give some informations about your building process.
Just adding the #include <math.h> in c source file and -lm in Makefile at the end will work for me.
gcc -pthread -o p3 p3.c -lm
Here are my observation, firstly you need to include the header math.h as sqrt() function declared in math.h header file. For e.g
#include <math.h>
secondly, if you read manual page of sqrt you will notice this line Link with -lm.
#include <math.h> /* header file you need to include */
double sqrt(double x); /* prototype of sqrt() function */
Link with -lm. /* Library linking instruction */
But application still says undefined reference to sqrt. Do you see any
problem here?
Compiler error is correct as you haven't linked your program with library lm & linker is unable to find reference of sqrt(), you need to link it explicitly. For e.g
gcc -Wall -Wextra -Werror -pedantic test.c -lm
I had the same issue, but I simply solved it by adding -lm after the command that runs my code.
Example.
gcc code.c -lm
Related
This question already has answers here:
Undefined reference to sqrt (or other mathematical functions)
(5 answers)
Closed 4 years ago.
I'm very new to C and I have this code:
#include <stdio.h>
#include <math.h>
int main(void)
{
double x = 0.5;
double result = sqrt(x);
printf("The square root of %lf is %lf\n", x, result);
return 0;
}
But when I compile this with:
gcc test.c -o test
I get an error like this:
/tmp/cc58XvyX.o: In function `main':
test.c:(.text+0x2f): undefined reference to `sqrt'
collect2: ld returned 1 exit status
Why does this happen? Is sqrt() not in the math.h header file? I get the same error with cosh and other trigonometric functions. Why?
The math library must be linked in when building the executable. How to do this varies by environment, but in Linux/Unix, just add -lm to the command:
gcc test.c -o test -lm
The math library is named libm.so, and the -l command option assumes a lib prefix and .a or .so suffix.
You need to link the with the -lm linker option
You need to compile as
gcc test.c -o test -lm
gcc (Not g++) historically would not by default include the mathematical functions while linking. It has also been separated from libc onto a separate library libm. To link with these functions you have to advise the linker to include the library -l linker option followed by the library name m thus -lm.
This is a likely a linker error.
Add the -lm switch to specify that you want to link against the standard C math library (libm) which has the definition for those functions (the header just has the declaration for them - worth looking up the difference.)
Because you didn't tell the linker about location of math library. Compile with gcc test.c -o test -lm
Add header:
#include<math.h>
Note: use abs(), sometimes at the time of evaluation sqrt() can take negative values which leave to domain error.
abs()- provides absolute values;
example, abs(-3) =3
Include -lm at the end of your command during compilation time:
gcc <filename.extension> -lm
What's a good way to find the necessary libraries needed to link against when making a toy executable to play around with another library?
I'll get the appropriate compile command from the compile_commands.json file (generated by CMake), but I still have to manually figure out which libraries I need the executable to link to.
For example: if I have a file called main.cpp:
#include <some_cool_library.hpp>
#include <iostream>
int main() {
some_cool_library::some_cool_type obj{"35"};
return 0;
}
I'll grab the appropriate compile command from the compile_commands.json file that was generated in the project that utilized some_cool_library.hpp (this is so I can pass the correct -I flag(s) to compiler without having to think at all).
Then I'll compile it (making the appropriate compile command modifications):
/usr/bin/clang++ -DBOOST_ALL_NO_LIB -DBOOST_ASIO_HAS_STD_CHRONO -DHAS_ZLIB -DWEBSOCKETPP_STRICT_MASKING -I<some-dir0> -I<some-dir1> -I<some-dir2> -isystem /usr/local/include -Wall -Wno-invalid-partial-specialization -O3 -DNDEBUG -pthread -std=gnu++17 -o prog /home/user/main.cpp && ./prog
Lastly I'll get some output that spits back a bunch of linker errors where I have to manually inspect each one and link the appropriate library. Is there a better way to find these libraries?
The standard way to learn how to use a library is to read that library's documentation.
In some cases, pkg-config can be used to get the necessary compiler and linker flags. This is not guaranteed to work, but there is a reasonable chance of it working if CMake seems to automagically handle the library as a dependency.
I want to use a library that utilizes the QT-class QVector2D to calaculate B-splines (library: https://github.com/ejmahler/SplineLibrary). But I can't figure out how to get the includes / linking right using a simple .cpp file and compiling with g++.
This is my attempt
// test.cpp
// My attempt at including the QVector2D class
#include </home/user/Qt/5.8/gcc_64/include/QtCore/qconfig.h>
#include </home/user/Qt/5.8/gcc_64/include/QtCore/qglobal.h>
#include </home/user/Qt/5.8/gcc_64/include/QtGui/qtguiglobal.h>
#include </home/user/Qt/5.8/gcc_64/include/QtGui/qvector2d.h>
// For spline library
#include <SplineLibrary/spline_library/spline.h>
#include <SplineLibrary/spline_library/vector.h>
#include <SplineLibrary/spline_library/splines/uniform_cr_spline.h>
int main()
{
std::vector<QVector2D> splinePoints{
QVector2D( 0, 1),
...
};
UniformCRSpline<QVector2D> mySpline(splinePoints);
QVector2D interpolatedPosition = mySpline.getPosition(0.5f);
}
Compiling with g++ 5
$ g++ -std=c++17 test.cpp -o test
gives
/home/user/Qt/5.8/gcc_64/include/QtCore/qglobal.h:63:28: fatal error:
QtCore/qconfig.h: No such file or directory compilation terminated.
I have verified that the file qconfig.h exists and that it is in the path as included.
I'm guessing my error is either in how I try to include the QT-headers, that I need to link it somehow.
How do I properly include a single Qt component (in this case QVector2D) and compile the project using g++?
First of all, you should never specify absolute paths in you includes. If someone else wants to use your code, they would need to modify all the files to point to the correct headers on their system. Apart from that you're using internal headers that you're not supposed to include yourself. At the very top of the Qt documentation for QVector2D you can find what header you're supposed to include to use the QVector2D class.
So test.cpp should look like this:
#include <QVector2D>
// For spline library
#include <SplineLibrary/spline_library/spline.h>
#include <SplineLibrary/spline_library/vector.h>
#include <SplineLibrary/spline_library/splines/uniform_cr_spline.h>
int main()
{
std::vector<QVector2D> splinePoints{
QVector2D( 0, 1),
...
};
UniformCRSpline<QVector2D> mySpline(splinePoints);
QVector2D interpolatedPosition = mySpline.getPosition(0.5f);
}
Compiler flags
Now, since you have a custom installation path for Qt5.8, the compiler can't find the header in the default search path, so when compiling this file you need to tell the compiler where to search for the Qt headers. As indicated by the line QT += Gui in the documentation I linked above, QVector2D is part of the QtGui sublibrary, so you need to include the headers in the directory /home/user/Qt/5.8/gcc_64/include/QtGui/. The compiler flag to do so is -isystem /home/user/Qt/5.8/gcc_64/include/QtGui.
However, the QtGui headers themselves depend on QtCore headers, but their path is given relative to the /home/user/Qt5.8/gcc_64/include directory, so in order for the compiler to find the header files the QtGui headers depend on you also need to add the compiler flag -isystem /home/user/Qt/5.8/gcc_64/include. Btw this is also the reason why you got the error QtCore/qconfig.h: No such file or directory compilation terminated., there is no such file QtCore/qconfig.h in the directory where test.cpp is located, nor is there one in the system include path, and you didn't give the compiler the additional path where to look for it.
So the compilation should be successful when executing g++ -std=c++14 -isystem /home/user/Qt/5.8/gcc_64/include -isystem /home/user/Qt/5.8/gcc_64/include/QtGui -fPIC -c test.cpp (assuming that the compiler previously didn't have any problem to find SplineLibrarys includes).
Linker flags
The previous command just compiles test.cpp (note the -c flag), but doesn't produce a binary that you can run. The linker has the same problem as the compiler - it doesn't know where to find the precompiled Qt libraries to link against unless you tell it where to look for them. The flag to do so is -L/home/user/Qt/5.8/gcc_64/lib.
In addition to telling the linker where to look for the precompiled libraries, you also need to tell it which ones you're using. As I've mentioned before, QVector2D is part of the QtGui sublibrary, so you need to add -lQt5Gui. Since QtGui depends on QtCore, -lQt5Core also needs to be added.
Assuming you used the default installer, your installation of Qt only includes dynamic libraries, so you also need to tell the linker to store the information where to find the library files in the created binary. The flag you need to add for this is -Wl,-rpath=/home/user/Qt/5.8/gcc_64/lib.
So putting everything together, the final command you need to run is g++ -std=c++14 -fPIC -isystem /home/user/Qt/5.8/gcc_64/include -isystem /home/user/Qt/5.8/gcc_64/include/QtGui -L /home/user/Qt/5.8/gcc_64/lib -Wl,-rpath=/home/user/Qt/5.8/gcc_64/lib test.cpp -lQt5Core -lQt5Gui.
If you use clang instead of gcc, the same command runs just fine if you replace g++ by clang++.
I know there are many questions related to shared libraries on Linux but maybe because I'm tired of having a hard day trying to create a simple dynamic library on Linux (on Windows it would have taken less than 10 minutes) I can't find what happens in this case.
So, I am trying to create a library to be linked at build-time and used at run-time (not a static library, not a library to be embedded into the executable, in other words). For now it contains a simple function. These are my files:
1.
// gugulibrary.cpp
// This is where my function is doing its job
#include "gugulibrary.h"
namespace GuGu {
void SayHello() {
puts("Hello!");
}
}
2.
// gugulibrary.h
// This is where I declare my shared functions
#include <stdio.h>
namespace Gugu {
void SayHello();
}
3.
// guguapp.cpp
// This is the executable using the library
#include "gugulibrary.h"
int main() {
GuGu::SayHello();
return 0;
}
This is how I try to build my project (and I think this is what is wrong):
gcc -Wall -s -O2 -fPIC -c gugulibrary.cpp -o gugulibrary.o
ld -shared -o bin/libGugu.so gugulibrary.o
gcc -Wall -s -O2 guguapp.cpp -o bin/GuGu -ldl
export LD_LIBRARY_PATH=bin
This is saved as a .sh file which I click and execute in a terminal. The error I get when trying to link the library is this:
/tmp/ccG05CQD.o: In function `main':
guguapp.cpp:(.text.startup+0x7): undefined reference to `SayHello'
collect2: ld returned 1 exit status
And this is where I am lost. I want the library to sit in the same folder as the executable for now and maybe I need some symbols/definitions file or something, which I don't know how to create.
Thanks for your help!
In your C++ file, GuGu::SayHello is declared as a C++ symbol. In your header, you are wrapping it in an extern "C" block. This is actually undefined, as you aren't allowed to use C++ syntax (namespace) in that context. But my guess is that what the compiler is doing is ignoring the namespace and generating a C symbol name of "SayHello". Obviously such a function was never defined by your library. Take out the extern "C" bits, because your API as defined cannot be used from C anyway.
You are inconsistent with your GuGu, there are also Gugu's running around, this needs to be made consistent, then it works (At least on my computer are some Gugu's now)
I am just learning C++. Compiling with g++ version 3.2.3, "g++ hworld.cpp":
double sqrt(double);
int main(){
double x = sqrt(1515.15);
return 0;
}
That compiles fine, but if we were to replace sqrt with "sqrtfoo" the compiler would say sqrtfoo cannot be used as a function. I thought I would have to include cmath, but I guess not? Can someone please explain what my program has access to before any includes? For comparison, gcc does not allow me to do this, saying "undefined reference to 'sqrt'." Thank you.
You don't need to include cmath because your code has a prototype for sqrt in it already, the very first line.
As the existing answers explain, the double sort(double) provides a prototype to let the compiler know that the function exists.
But you also mentioned that this doesn't work under GCC. When you build a C or C++ program, the source code is compiled into object format. The object files are then linked together to form an executable.
To see this in action, try
gcc -c hello.c
This tells GCC to compile (-c) the source file hello.c. Assuming that hello.c exists and has no errors, you'll find hello.o in the current directory. Now try
gcc -o hello hello.o
This tells GCC to link hello.o with the appropriate system libraries, and to generate an output file called "hello". If hello.c uses math functions, you'll also need to link in the math library:
gcc -o hello hello.o -lm
"-l" is used to tell gcc to include extra libraries (beyond the default "libc" C library). "m" refers to "libm", which is the math library containing sqrt. If your program uses only one source file it's common to ask implicitly GCC to compile and link in a single command:
gcc -o hello hello.c -lm
Now to your question. GCC won't compile the above code because you haven't asked it to link in the math library. But g++ is okay with it. There's a very similar question already on Stack Overflow. According to its accepted answer,
the C++ runtime libstdc++ requres libm, so if you compile a C++
program with GCC (g++), you will automatically get libm linked in.
Since "libstdc++" is the C++ language runtime library, it's included by g++ by default. And as it depends on libm, the linker automatically loads libm while producing the final binary program.
Header files hold only declarations (signatures), and you've included one in the first line (prototype: double sqrt(double)).
The compiler compiles it just fine, because you've stated that somewhere this function is defined. The step that occurs after compiling is responsible for actually looking for that function definition. It's called linking, and during that phase linker lookups those definitions. In case of sqrtfoo it cannot find anything, whereas in case of sqrt it finds it in some standard library (I do not know the details here).