Can GCC warn about undefined functions in libraries? - c

Consider the following test project:
test.h:
#ifndef TEST_H
#define TEST_H
void test1(int);
void test2(int);
#endif /* TEST_H */
text.c:
#include "test.h"
void test1(int x) { (void) x; }
Oops, I forgot to define test2()! I would like some kind of feedback when I do this, preferably refusal to compile although a warning at least would be nice. However GCC 10.2 (on Ubuntu 20.10) compiles it fine with no warnings:
gcc -Wall -Wextra -Wpedantic -std=c11 -o libtest.o -c test.c
I think I understand why: what if test2() is actually meant to come from another library, maybe a system library? Make it the problem of whichever program ends up linking everything into an executable! But I want to know about it before then. In this case, it's not declared in any included header file. It's not called anywhere. Can that be detected?
I've tried:
--no-undefined which resulted in gcc: error: unrecognized command-line option ‘--no-undefined’; did you mean ‘-Wno-undef’?
-Wno-undef - accepted but no warning
-z,defs - accepted but no warning
-Wimplicit-function-declaration - accepted but no warning
-Werror=missing-declarations - I know this is for the opposite situation but I was getting desperate.

This isn't possible, as no linking is performed at the stage of assembling a static library.
I'd suggest having a "test container" for your library. Set up your build system to build the test executable any time you are building the library. It could even just be a single .c file in the same directory as the library sources, but obviously not in the list of objects that are part of the library.
The test executable calls all of the functions that you wish to be entry points for the library.
Probably that is something you should be doing anyway in order to test the library's functionality before doing a release.

Related

Error "undefined reference to symbol 'sqrt##GLIBC_2.17'" [duplicate]

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

Bash script error "undefined reference to sin" [duplicate]

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

How to organize Header files

Using header files in this way gives me the error "undefined reference to somefunc". What is the proper way to make sure somefunc.c is seen so this error doesn't occur? It seems simply including somefile.h in main.c isn't enough to see the definitions in somefile.c
main.c
#include "somefile.h"
int main() {
somefunc();
return 0;
}
somefile.h
#ifndef SOMEFILE_H
#define SOMEFILE_H
void somefunc();
#endif
somefile.c
#include <stdio.h>
#include "somefile.h"
void somefunc() {
printf("hello\n");
}
I don't understand why I am getting errors because this is the same manner in which they are used in tutorials and videos i've been viewing while looking for an answer. The code above is an answer given earlier but it is still has the same error.
Undefined reference to somefunc is a linker error, not a compiler error.
This means that, although when compiling main.c the header somefile.h is found, you are not compiling the file somefile.c together with main.c. So when linking occurs the linker is not able to find the implementation of somefunc in any object file to resolve the call from main().
If you are using GCC or Clang just compile both source files to your command, eg
gcc somefunc.c main.c -o output
If you are using an IDE instead, make sure that somefile.c is compiled together with main.c when building the application.
This doesn't appear to be a problem with the header file.
This appears to be a problem in linking, which depends on how you build the project. If you use an IDE, it means that somefile.c is not included in the project. If you're using make and a makefile, it means that somefile.c is not listed in the makefile, or at least not included for the linker. If you're building at the command line (not using make or some build tool, but using gcc), then you're not including somefile.c in the command.
The undefined reference error means the linker couldn't find the code in somefile.c, because the linker didn't know to include it.

How to compile with --pedantic-errors on OS X?

Here's a simple C file:
#include <stdio.h>
#include <stdlib.h>
int
main() {
printf("hi there!\n");
return 0;
}
Compiling with gcc -ansi -pedantic -pedantic-errors gives this:
In file included from /usr/include/i386/_structs.h:38,
from /usr/include/machine/_structs.h:31,
from /usr/include/sys/_structs.h:57,
from /usr/include/sys/signal.h:154,
from /usr/include/sys/wait.h:116,
from /usr/include/stdlib.h:65,
from test.c:2:
/usr/include/mach/i386/_structs.h:91: error: type of bit-field ‘__invalid’ is a GCC extension
With lots more errors about GCC extensions. I know that I could just remove the -pedantic-errors switch and recompile, but for one reason and another, that isn't in the cards. Is there a way to get past this error; perhaps downloading & installing another C library? I'm working locally on code that needs to compile on a remote machine, so I can't set up the Makefile to point at a special library location, unfortunately.
You could possibly modify /usr/include/mach/i386/_structs.h:91 to use the __extension__ keyword. Although you'd have to wonder why this is not already the case.
Another file level solution is to add a #pragma GCC system_header directive to the top of _structs.h.
To fix it at the build level, add -isystem /usr/include/mach/i386/ to the compiler options. All headers in that folder will then be included as if they were system headers (which should be the case already but apparently is not).

Including source files in C

So I get the point of headers vs source files. What I don't get is how the compiler knows to compile all the source files. Example:
example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
int example(int argument); // prototype
#endif
example.c
#include "example.h"
int example(int argument)
{
return argument + 1; // implementation
}
main.c
#include "example.h"
main()
{
int whatever;
whatever = example(whatever); // usage in program
}
How does the compiler, compiling main.c, know the implementation of example() when nothing includes example.c?
Is this some kind of an IDE thing, where you add files to projects and stuff? Is there any way to do it "manually" as I prefer a plain text editor to quirky IDEs?
Compiling in C or C++ is actually split up into 2 separate phases.
compiling
linking
The compiler doesn't know about the implementation of example(). It just knows that there's something called example() that will be defined at some point. So it just generated code with placeholders for example()
The linker then comes along and resolves these placeholders.
To compile your code using gcc you'd do the following
gcc -c example.c -o example.o
gcc -c main.c -o main.o
gcc example.o main.o -o myProgram
The first 2 invocations of gcc are the compilation steps. The third invocation is the linker step.
Yes, you have to tell the compiler (usually through a makefile if you're not using an IDE) which source files to compile into object files, and the compiler compiles each one individually. Then you give the linker the list of object files to combine into the executable. If the linker is looking for a function or class definition and can't find it, you'll get a link error.
It doesn't ... you have to tell it to.
For example, whe using gcc, first you would compile the files:
gcc file1.c -c -ofile1.o
gcc file2.c -c -ofile2.o
Then the compiler compiles those files, assuming that symbols that you've defined (like your example function) exist somewhere and will be linked in later.
Then you link the object files together:
gcc file1.o file2.o -oexecutable
At this point of time, the linker looks at those assumtions and "clarifies" them ie. checks whether they're present. This is how it basically works...
As for your IDE question, Google "makefiles"
The compiler does not know the implementation of example() when compiling main.c - the compiler only knows the signature (how to call it) which was included from the header file. The compiler produces .o object files which are later linked by a linker to create the executable binary. The build process can be controlled by an IDE, or if you prefer a Makefile. Makefiles have a unique syntax which takes a bit of learning to understand but will make the build process much clearer. There are lots of good references on the web if you search for Makefile.
The compiler doesn't. But your build tool does. IDE or make tool. The manual way is hand-crafted Makefiles.

Resources