I'm trying to compile some AES implementation code from http://www.efgh.com/software/rijndael.htm, I got a txt file and splitted it up so I got 3 files:
encrypt.c
decrypt.c
rijndael.h
Having all this 3 files in the same folder, I try to compile any of encrypt.c or decrypt.c files but it throws some errors about undefined functions which actually are in rijndael.h
I'm performing compilation this way:
gcc -o encrypt encrypt.c or gcc -o decrypt decrypt.c
And I get:
/tmp/cch6JvXT.o: In function main:
encrypt.c:(.text+0x127): undefined reference to rijndaelSetupEncrypt
encrypt.c:(.text+0x1c6): undefined reference to rijndaelEncrypt
collect2: error: ld returned 1 exit status
But rijndaelSetupEncrypt and rijndaelEncrypt are in the rijndael.h file
There is a difference between an "undeclared function" error and an "undefined function" error. The first one is given when it can not find the prototype (meaning only the function header) of a function you've used, prototypes being usually put in the .h files and included in your .c files. The second error appears when it finds the prototype but not the definition of the function. The definition of a function (meaning the entire body of a function) can be fount either in a library or in another .c file that you should add to your compile command.
For "undefined function" error you could try
gcc -o enc_dec encrypt.c decrypt.c
if the function it cannot find is in one of the two .c files you've mentioned.
If it's not, you might have forgotten to link a library.
Later edit:
With the rijndael.c file:
gcc -o decrypt rijndael.c decrypt.c
gcc -o encrypt rijndael.c encrypt.c
It doesn't matter if rijndael.h hasn't got a main function. I suppose it has definitions for some of the functions used in decrypt.c and encrypt.c
Actually in your example, you should have 4 files, encrypt.c decrypt.c rijndael.c and rijndael.h
So you have to compile rijndael.c and encrypt.c or same with decrypt together. .h files will be automatically used during compilation of c file which included the .h (header) file.
Related
Say I have a parent directory A with two subdirectories B and C.
Sub-directory C has a helper.c and helper.h as shown:
//helper.c
void print(){
printf("Hello, World!\n");
}
//helper.h
void print();
Now, in sub directory B, I have a main.c which just calls the print function:
//main.c
#include<stdio.h>
#include"../C/helper.h"
void main(){
print();
}
I tried the following commands for compiling main.c:
Command 1: gcc main.c //Gives undefined reference to 'print' error
Command 2: gcc main.c ../C/helper.c //Compiles successfully
Now I removed the #include"../C/helper.h" from main .c and tried the Command 2 again. It still works.
So I have the following questions:
i) What difference does it make whether the helper.h file is included or
helper.c?
ii) Why command 1 fails?
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
What happens when you execute:
Command 1: gcc main.c //Gives undefined reference to 'print' error
When execute gcc main.c
Compiler compiles main.c and creates objective file. This file will contain unresolved link to function print(). Because there is no implementation of function print() in main.c file.
After compilation gcc tries to make full executable file. To do this gcc combines all objective files and tries to resolve all unresolved links. As you remember there is unresolved link for function print(), gcc can't find implementation and raise the error.
When you execute
Command 2: gcc main.c ../C/helper.c //Compiles successfully
gcc compiles both files. Second file ../C/helper.c contains implementation of function print(), so linker can find it and resolve reference to it in function main().
i) What difference does it make whether the helper.h file is included or helper.c?
In your case helper.h contains forward declaration of function print(). This gives information to compiler how to make call of function print().
ii) Why command 1 fails?
See above.
iii) Is there a way to compile my C program without having to specify helper.c everytime?
Use make utility. Compile helper.c in separate objective file helper.o and use it in linkage command.
helper.o: ../C/helper.c ../C/helper.h
gcc -c ../C/helper.c
main.o: main.c main.h
gcc -c main.c
testprog: main.o helper.o
g++ main.o helper.o -o testprog
See make utility manual for details.
Commands should be indented by TAB.
First you need to understand that #include simply adds whatever text is in the #include parameter to the position in the file the statement is in, for example:
//file1.h
void foo();
//main.c
#include "file1.txt"
int main(int argc, char **argv)
{
foo();
return 0;
}
Will cause the pre-compilation to generate this unified file for compilation:
//main.c.tmp
void foo();
int main(int argc, char **argv)
{
foo();
return 0;
}
So to answer your first and second questions:
When you include a header file (or any file) that only contains declarations (i.e function signatures) without definitions (i.e function implementations), as in the example above, the linker will fail in finding the definitions and you will get the 'undefined reference' error.
When you include a c code file (or any file) that contains definitions, these definitions will be merged to your code and the linker will have them, that's why it works.
and as for your third question
It is bad practice to include c files directly in other c files, the common approach is to keep separate c files with headers exposing the functionality they provide, include the header files and link against the compiled c files, for example in your case:
gcc main.c helper.c -o out
Will allow you to include helper.c in main.c and still work because you instructed the compiler to compile both files instead of just main.c so when linking occurs the definitions from the compilation will be found and you will not get the undefined behavior error
This is, in a nutshell. I abstracted a lot of what's going on to pass on the general idea. this is a nice article describing the compilation process in fair detail and this is a nice overview of the entire process.
I'll try to answer:
i) What difference does it make whether the helper.h file is included or helper.c?
When you include a file, you don't want to expose your implementation, hence its better to include h files, that contains only the "signatures" - api of your implementation.
ii) Why command 1 fails?
When you compile you must add all your resources to the executable, otherwise he won't compile.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can use Makefile to compile your program. Maybe this tutorial can help you.
i) What difference does it make whether the helper.h file is included
or helper.c?
Including helper.c means that helper.c gets compiled each time as if it were part of main.c
Including helper.h lets the compiler know what argument types the function print() takes and returns so the compiler can give an error or warning if you call print() incorrectly
ii) Why command 1 fails?
The compiler is not being told where to find the actual code for the print function. As explained, including the .h file only helps the compiler with type checking.
iii) Is there a way to compile my C program without having to specify
helper.c everytime?
You can compile it once into an object file and optionally you can add that obj to a static or dynamically loaded library. You still need to help the compiler find that obj or library. For example,
gcc -c helper.c
gcc main.c helper.o
The correct way to avoid compiling modules that don't need compiling is to use a Makefile. A Makefile compares when a module was last compiled compared to when it was last modified and that way it knows what needs to be compiled and what doesn't.
When I compiled my program and ran it, I got a a symbol lookup error. I was doing this:
$ gcc -o parts parts.c -lnettle
$ ./parts
$ ./parts: symbol lookup error: ./parts: undefined symbol: nettle_pbkdf2
My code included these header files:
#include <nettle/pbkdf2.h>
#include <nettle/hmac.h>
#include <pbkdf2-hmac-sha1.c>
I solved my problem by including the object files for the two included header files during gcc compilation.
$ gcc -o parts parts.c hmac.o pbkdf2.o -lnettle
The thing is, I don't understand what is going on and therefore why this works. Why must I include the .o files and not just the header files to avoid symbol lookup or undefined reference errors?
As Tobias mentioned, a header file tells the compiler what is done, the object file tells the compiler how it is done. You can see here what an object file is, but in reality it's just a precompiled version of a source file.
Truly, you were not actually getting compiler errors, but linker errors. It knew how to compile your source file, but it couldn't put everything together until it got the other object files.
I've just completed a school assignment and I'm having a problem testing my code because I keep getting the following output after running make packetize (it's a makefile the professor gave us)
cc packetize.c -o packetize
/tmp/ccJJyqF6.o: In function `block_to_packet':
packetize.c:(.text+0xb1): undefined reference to `crc_message'
collect2: ld returned 1 exit status
make: *** [packetize] Error 1
block_to_packet is defined in a file called packetize.c, crc_message is defined in crc16.c (both of which contain an #include "data.h" line). data.h also has the function heading for crc_message in it All of these files are in the same directory. I've been trying to compile them for the past hour and a half and have searched Google endlessly with no avail. It has something to do with linking I've read, my instructor has not taught this and so I don't know how to compile these files to test their outputs. Can anyone let me know what's wrong?
Your header files are absolutely OK. What you have there is a linker error: The compilation of packetize.c ran without problems, but then you're trying to link an executable file packetize (since you did not give the -c option which states "compile to object file"). And the executable would need the compiled code from crc16.c as well.
Either you have to give all sources on the compiler line:
cc packetize.c crc16.c -o myApp
Or you have to compile into individual object files, eventually linked together:
cc -c packetize.c -o packetize.o
cc -c crc16.c -o crc16.o
cc packetize.o crc16.o -o myApp
The former is what you'd do in a one-shot command line, the latter is what a Makefile usually does. (Because you do not need to recompile crc16.c if all you did was modify packetize.c. In large projects, recompiles can take significant amounts of time.)
Edit:
Tutorial time. Take note of the existence / absence of -c options in the command lines given.
Consider:
// foo.c
int foo()
{
return 42;
}
A source file defining the function foo().
// foo.h
int foo();
A header file declaring the function foo().
// main.c
#include "foo.h"
int main()
{
return foo();
}
A source file referencing foo().
In the file main.c, the include makes the compiler aware that, eventually, somewhere, there will be a definition of the function foo() declared in foo.h. All the compiler needs to know at this point is that the function will exist, that it takes no arguments, and that it returns int. That is enough to compile the source to object code:
cc -c main.c -o main.o
However, it is not enough to actually compile an executable:
cc main.c -o testproc # fail of compile-source-to-exe
ld main.o -o testproc # fail of link-object-to-exe
The compiler was promised (by the declaration) that a definition of foo() will exist, and that was enough for the compiler.
The linker however (implicitly run by cc in the first example) needs that definition. The executable needs to execute the function foo(), but it is nowhere to be found in main.c. The reference to foo() cannot be resolved. "Unresolved reference error".
You need to either compile both source files in one go...
cc foo.c main.c -o testproc # compile-source-to-exe
...or compile foo.c as well and provide the linker with both object files so it can resolve all references:
cc -c foo.c -o foo.o
ld foo.o main.o -o testproc # link-objects-to-exe
Post Scriptum: Calling ld directly as pictured above most likely will not work just like that. Linking needs a couple of additional parameters, which cc adds implicitly -- the C runtime support, the standard C library, stuff like that. I did not give those parameters in the examples above as they would confuse the matter and are beyond the scope of the question.
You have to compile crc16.c as well and link these two object files to build the binary. Otherwise packetize.c, from where crc_message() is being called, has no knowledge of it.
Try using
cc packetize.c crc16.c -o packetize
Your call crc_message() from packetize.c would just be fine.
As Totland writes crc_message is defined in crc16.c; which means that packetize.c can't see the definition, no matter how many shared headers they have. You do not have a compile error but an error from the linker.
If you compile your c files first to object files and then link everything to an executable it will work.
I have two files, main.o and modules.o, and I'm trying to compile them so that main.o can call functions in modules.o. I was explicitly told not to try #include module.o. I really don't know what I should be doing instead. I tried a few different versions of gcc (such as gcc -x c driver main.o modules.o), but nothing I get works: the compiler continuously returns
error: called object is not a function
The .o files are my source code files (I was instructed to put my source code in files with extension .o.) What do I do to compile this?
If you have your two source files, you can compile them into object files without linking, as so:
gcc main.c -o main.o -c
gcc module.c -o module.o -c
where the -c flag tells the compiler to stop after the compilation phase, without linking. Then, you can link your two object files as so:
gcc -o myprog main.o module.o
This is all perfectly normal behavior, you'll usually get your makefile to compile things separately and link them at the end, so you don't have to recompile every single source file every time you change one of them.
Talking about main.o "calling functions in" module.o is perfectly fine, but an .o file is not a source file, it's a compiled object file. If "put my source code in files with extension .o" actually meant "compile my source code into files with extension .o" then the situation would make a whole lot more sense.
You should define the functions that you want to call from modules.c into main.c into a header file, let us say modules.h, and include that header file in main.c. Once you have the header file, please compile both of the files together: gcc main.c modules.c -o output
Two additional notes. First, modules.o is an object file and it should not be included in a C source file. Second, we cannot have a C file have a .o extension. You should actually get an error when compiling a .o file. Something like:
$ cat t.o
int main() {
int x = 1;
return 0;
}
$
$ gcc t.o
ld: warning: in t.o, file is not of required architecture
Undefined symbols:
"_main", referenced from:
start in crt1.10.6.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
$
program: main.o
gcc -o main main.c anotherSource.c
This works for me.
You should be including .h files which are "headers". So if your main file is using modules then you should include module's header file.
I am using net beans, and am trying to define function in an external C file, and use them in my main C file. It seems like the linker isn't working or something, as I am getting a build error:
undefined reference to `setPixel'
The file containing my functions is myLib.c. The file that I am calling the function in is main.c
Both of these files #include myLib.h which contains the function prototypes for the functions within myLib.c
I shouldn't be getting this error, any ideas?
What does your compile command look like? Obviously myLib.c will need compiling or the link will fail..
gcc main.c myLib.c