Why krb5 function does not get resolved when we include "krb5.h"? - c

When I include "stdio.h" and try to use "printf" it works fine.
In the same way when I use "krb5.h", its function "krb5_get_init_creds_password" does not get resolved by its own.
Error faced :
bash-4.1$ gcc krb.c
krb.c: In function ‘main’:
krb.c:6: warning: incompatible implicit declaration of built-in function ‘printf’
/tmp/ccTK4DJM.o: In function main':
krb.c:(.text+0x53): undefined reference tokrb5_get_init_creds_password'
collect2: ld returned 1 exit status
I had to compile using -lkrb5 which resolved the issue.
Can someone let me know why do I need to use gcc option "-lkrb5" to get that krb5 function resolved ?
I am using C.

The header file you include only contains the declaration of the function, the actual function definition (the implementation) is in the actual library (usually a file named (using your example) libkrb5.a or libkrb5.so).
The option you pass to the linker is -l (lower-case L) which tells the linker to find and use whatever library you pass as argument to the -l option.
If you have create programs consisting of multiple source files yourself, then this should not have been much of a surprise really. If you have two source files a.c and b.c, where in a.c you call a function defined in b.c you need to declare the function for it to be available in a.c. And then when you link the executable program you need to link with the object file created by b.c to be able to find the definition.
Using a library is really not much different from that.

Related

Compiler does not give line number of error undefined reference

Why does the compiler sometimes not give line number of the error? Where is the use case of that "undefined reference". I've already included everything as header files I myself wrote so it needs to give a specific line number. It is not closed source. Have I changed some setting of the compiler by accident or is it another thing whatever that another thing is?
D:\Projects\DanceOfPixels\GLEW>gcc main.c glad.c -IC:\mingw_dev_lib\include\SDL2 -LC:\mingw_dev_lib\lib -lmingw32 -lopengl32 -lSDL2main -lSDL2 -lSDL2_image -o main.exe -ansi -std=c89 -pedantic -w
C:\Users\user\AppData\Local\Temp\ccMooHZm.o:main.c:(.text+0x126ce): undefined reference to `drawImagePartScaledHW'
collect2.exe: error: ld returned 1 exit status
Edit: I have solved the problem. I have included two different versions of the draw.h, one coming from software renderer, other from OpenGL renderer. Since they use same
#ifndef DRAW_H
#define DRAW_H
...
#endif
structure for both files; the compiler didn't include the second. Once I've changed the DRAW_H to DRAW_HW I managed to compile and run the application.
That error comes from the "linker" (ld), not the compiler proper.
Typically, the compiler compiles each source file into its own, individual object file, containing just the code and data from that source file. Then, the linker combines one or more object files together, and also links in any needed library functions.
Crucially, there's no problem if a single source file (a single object file) calls an undefined function -- that's normal, if the definition of the function is in another source file, or a library. So that's why it's the linker (not the compiler) that finally discovers that there's not a definition for a function anywhere, that it's truly undefined.
But since the linker is working with object files, typically it doesn't know which source file line numbers the functions were originally called on.
(Some C compilers work more closely with their linkers, so that these "undefined external" error messages can, more usefully, contain actual source file line numbers, but that's a relatively recent innovation. For this to work it may be important to compile with debugging enabled, e.g. by using the -g flag, so that the compiler includes source line number information in its object files.)

Struggling compiling a simple c program (gcc)

I have a very old C program and want to compile to Windows. So I try doing this:
gcc -DNO_GLIBC=1 sakide.c -o sakide.exe
and this returns:
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0xa4): undefined reference to `ekiGetLibVersion'
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0x6b6): undefined reference to `ekiGetLibVersion'
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0x8ff): undefined reference to `ekiEncodeUrl'
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0x954): undefined reference to `ekiDecodeUrl'
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0x993): undefined reference to `ekiDecodeUrl'
\AppData\Local\Temp\ccx7khiy.o:sakide.c:(.text+0xa62): undefined reference to `ekiGetKeyInfo'
collect2.exe: error: ld returned 1 exit status
This ekiGetLibVersion is in a .h file:
INT EKIAPI ekiGetLibVersion(char *outBuffer, LPINT outBufferSize);
and I also have a .dll name of it.
Ive never compiled anything with C though
On windows you cannot link against directly with the .dll, you have to link the import library, name .lib. For more information, refer:
On dynamic linking:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682592(v=vs.85).aspx
On implicit linking:
https://msdn.microsoft.com/en-us/library/d14wsce5.aspx
You are getting linker errors.
You need to link the library (or object file) where those functions are defined.
Undefined reference usually means the compiler has not seen a proper declaration for this variable. Did you include the header file (which defines this variable) in your C program ?
#include "header_file.h"

how to make a makefile from object fiiles

I'm trying to figure out how to create a makefile that will create object files and then compile them into an executable but when I try to make an object file that uses a variable that was declared in another file it won't compile to an object file. In other words if I have main.c that has a global variable var and I have another file called other.c which uses var but doesn't declare it like main.c did. Is there a way to compile them both to object files and link them so other.c sees the declaration of var in main.c? I was under the impression there was but I can't figure it out because when I do gcc -c other.c I get an error about var. (I know you can make var extern to fix this issue but I need to able to do this without doing that)
Here's the error messages I get.
foundations.c: In function ‘FoundationC’:
foundations.c:2:2: error: ‘DAYS’ undeclared (first use in this function)
DAYS=DAYS+10;
^
foundations.c:2:2: note: each undeclared identifier is reported only once for each function it appears in
foundations.c:3:2: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
printf("The FoundationC Contractor completed the project - DAY %d\n",DAYS );fflush(stdout);
^
foundations.c:3:85: error: ‘stdout’ undeclared (first use in this function)
printf("The FoundationC Contractor completed the project - DAY %d\n",DAYS );fflush(stdout);
So DAYS is a variable that was declared in main.c not foundations.c
EDIT: Solved I added the needed stl header file and global variable to the other file and then it was able to compile as an object file. Sorry about this question. I made it thinking that object file linking had the ability which would make that unnecessary but I guess not.
...but when I try to make an object file that uses a variable that was declared in another file it won't compile to an object file.
This has nothing to do with a makefile. Commands in the makefile will for example start the compiler on a .c file to produce an object file. Either this compilation succeeds, or it does not in which case the compiler gives you one or more error messages.
The problem you describe of a variable declared in another .c file will NOT halt the compiler; it will just compile the .c file and will at most give warning messages that a variable is not declared. But it will produce an object file.
At link time, the linker must be given all object files so produced (a command in the makefile starts the linker with the list of names on the command line) and then will produce an executable. If now the variable cannot be found in the object files, the link process will fail and no executable is produced. But all object files will have been produced (if there aren't errors in the compilation step).
Maybe his helps to re-formulate your question.

C - Very Strange Implicit Declaration

I had a function in a file "draw.h":
void TileSystem() {
// Some code here.
}
And in the "main.c" file, I call it, because I have #included "draw.h" in the file. The function works nicely well!!
But then, I decide to rename the function to
void CreateTileSystem() {
// Some code here.
}
And I get the following output:
gcc main.c -std=c99 -o main `pkg-config --cflags --libs allegro-5.0 allegro_acodec-5.0 allegro_audio-5.0 allegro_color-5.0 allegro_dialog-5.0 allegro_font-5.0 allegro_image-5.0 allegro_main-5.0 allegro_memfile-5.0 allegro_physfs-5.0 allegro_primitives-5.0 allegro_ttf-5.0`
main.c: In function ‘main’:
main.c:217:12: warning: implicit declaration of function ‘CreateTileSystem’ [-Wimplicit-function-declaration]
/tmp/cclNEg6q.o: In function `main':
main.c:(.text+0xb1e): undefined reference to `CreateTileSystem'
collect2: error: ld returned 1 exit status
make: *** [main] Error 1
And then, I just rename it back to TileSystem and works well. I have no other references in the entire code. It makes no sense at all! I want to rename, in order to use verbs in functions (A more "correct" standard, I think). Well, I would really like to know what happens. I really CAN'T find errors, and the fact that when I rename it, it backs to work, frustrates me even more.
Thank you very much!
You have to also change the name in the header file, draw.h.
That error/warning indicates that there was no forward declaration for the function, which in older C dialects results in an assumption that the function is int fn(int) (if memory serves).
It works when you change it back because the header was never modified, so it's still providing a forward declaration of the old name.
I tried creating a couple of simple files like you've described here, but I don't get any problems. So:
are you sure you used the same name for the new function in both draw.h and main.c (really sure)?
I don't know about allegro: does it happen to have a function called TileSystem in it?
Beyond those, I would recommend starting with a bare bones setup (so just the include, the main function, and the call in main.c, and just the declaration in draw.h), make sure that compiles with gcc main.c -std=c99 -o main, and then build your application up to what it is currently, piece by piece, until the error starts happening again. That should help you identify the source of the problem.
I recreated the header file, without altering anything, and it worked. It really had something to do with me never altering the file (I mean, renaming the file or excluding it). Some very underground compiling issue happened.

Why do I get 'multiple definition' errors when linking against an archive?

I'm using CppUTest to test the C code defined in a fornol.c source file. That file defines the main production main() function.
I also have an AllTests.cpp file that also has a main() function, but that main() is supposed to be used only when running the unit tests.
AllTests.cpp gets compiled to a .o file, whereas fornol.c gets compiled to a libfornol.a archive.
Then CppUTest tries to link everything together, but here is what I get instead:
Linking fornol_tests
cc -o fornol_tests objs/tests/AllTests.o objs/tests/FornolTests.o lib/libfornol.a ../../CppUTest/lib/libCppUTest.a ../../CppUTest/lib/libCppUTestExt.a -lstdc++ -lgcov
lib/libfornol.a(fornol.o): In function `main':
/home/dlindelof/Work/endor/nol/fornol/fornol.c:453: multiple definition of `main'
objs/tests/AllTests.o:/home/dlindelof/Work/endor/nol/fornol/tests/AllTests.cpp:4: first defined here
collect2: ld returned 1 exit status
It looks as if the main() function defined in fornol.c and present in the archive libfornol.a conflicts with the main() defined in AllTests.cpp. But my understanding was that archive/library files are searched only if/when a given symbol hasn't been referenced yet. It should therefore not be a problem to have the same symbol defined more than once, provided all definitions are in archive/library files.
What am I doing wrong here?
You need to remove the main() from AllTests.cpp and put it in its own source file.
When a linker links in a library, it can't split object files in the library; it has to either link or omit each object file in the library as a unit. (I know LLVM is different, but that's another topic.) This is why, if you look at the source for a library like glibc, each function gets its own source file.
So what's happening to you is that the linker needs to pull in an object file (fornol.o) from the library (libfornol.a) to satisfy dependencies, but that object file carries a duplicate symbol with it (main).
It's perfectly okay to put test code in a library (we do this routinely where I work), but keep it in its own source files (we traditionally use main.cc). (This is a better test anyway, because test code should not have access to static-declared symbols.)
A library is supposed not to have a main() function as it is a library.
You should remove that main() from fornol.c and compile it again.
main() is the entry point of an executable file's source code, since a library (especially a static ".a" library) is only pre-compiled source code, you cannot use a main in there.
If you want a main production entry point of your library you could rename the main() in fornol.c to something more explicit and less reserved such as "fornolMain()" for example.
A static library is compiled in your binary executable and thus is not searched only if the symbol is loaded. It is exactly the same as compiling fornol.c and linking fornol.o and your other .o

Resources