C - How are c source files incuded without an include statement - c

I've taken the plunge and am learning C. It's been a pretty good but manageable learning curve coming from a scripting (php, perl) background with only a little bit of C#.
I've used the web-site "Learn C The Hard Way" and am so far grasping reasonably well (I think) but I can't understand this part of one of the exercises:
http://c.learncodethehardway.org/book/ex19.html
He created four source files - object.h, object.c, ex19.h, ex19.c
But I don't understand how the object.c file is included.
The main function is located in ex19.c, and it has the line
#include "ex19.h"
File ex19.h has the line
#include "object.h"
But object.h makes no reference to including object.c. Interestingly object.c contains the line
#include "object.h"
Is there some sort of implied include where if you include the header file, it will automatically include the c source code of the same name?

This is the job of a separate program called the linker. In C, source files need access to the header files of other C source files so that they can see information about what functions, types, and variables are defined by that second C file that the first file might want to use. Each C file is then compiled independently of the rest. The output of the compiler is an object file.
To build a final program, a second program called the linker comes in and combines all the object files together into the overall executable. This program is tasked with taking the implementations of all the different C files and cross-referencing them against one another so that each time one C file references a function or variable in a different C file, that reference can actually be made to the appropriate object.
This is why you don't need to include .c files. Once a source file has a header, it knows enough about the other file in order to use the functions it provides for the compiler to verify that it's using them correctly. The linker then handles of the job of actually making the cross-references. You can think of the compiler as a program that checks to see that if the functions are defined, then the program would work. The linker then actually checks to make sure that those functions are defined in the first place and sets up the appropriate links in the executable.
Hope this helps!

Object.c is not included.
It's compiled as it's own unit and it includes object.h
See the make file:
CFLAGS=-Wall -g
all: ex19
ex19: object.o
clean:
rm -f ex19
ex19: object.o tells you that object.o must be created before ex19 can be built, and this is picked up by default from make file as an object.c exists.
So this make file says
to build all you need ex19, to get ex19 you need object.o, and the to create object.o the makefile picks up object.o built from the object.c
From the page you reference:
make can't see anything in the file for object.o, but it does see an
object.c file, and it knows how to turn a .c into a .o, so it does
that.

The entire logic lies in the makefile and an intelligent compiler. The final binary created has an object file named as object.o which will ideally contain all the function definitions defined in object.h file. It is the linker which links the functions declared in .h file with the definition which are available in .o file.

Related

Contiki: undefined reference to a function defined in a separate source file

I am writing a program using the Contiki operating system.
I have the remote_firmware.c file and a folder called parser with the files parser.h and parser.c where I wrote the method void test(). I included parser.h in remote_firmware.c with:
#include "parser/parser.h"
The Makefile looks like this:
CONTIKI_PROJECT = remote_firmware
all: $(CONTIKI_PROJECT)
#UIP_CONF_IPV6=1
CONTIKI_WITH_RIME = 1
CONTIKI = $(HOME)/contiki
include $(CONTIKI)/Makefile.include
When I try to build this the Error occurs:
undefined reference to 'test'
I am aware that the Makefile needs to know about parser.h, but I do not know how. I tried several solutions which were proposed here but I guess I did something wrong. Maybe somebody of you know what to do?
Thank you a lot.
Where is your source file located? Try adding the source file name to the PROJECT_SOURCEFILES preprocessor variable (i.e PROJECT_SOURCEFILES+=parser.c) and adding the location of the source file to the CONTIKIDIRS preprocessor variable (i.e CONTIKIDIRS+={Directory}).
If parser.c depends on a lot other C files you might want create an C library archive first and then adding the library to your project by adding the name of the library to the TARGET_LIBFILES variable.
The error undefined reference to test is an error from the linker not the compiler. It has nothing to do with including a header file. It means when you linked the executable you didn't include parser.o

Calling methods from multiple C files without custom header files, Makefile Linking

This has gotten a bit lost in translation so I am going to be more precise:
we have classes recursion.c, fib.c, and countUp.c. from recursion.c we have to recursively call fib.c or countUp.c, decided by the input argument. I can't use header files and am only given that I must place prototypes:
int fib(int n);
and
void countUp(int n);
My Makefile
TAR = tar
COMPILER_FLAGS = -g -Wall -std=c99 -c
LINKER_FLAGS = -g -o
OBJS = recurse.o
C_FILES = recurse.c fib.c countUp.c
ASM_FILES = recurse.asm
TARGET_FILE = recurse
TARGET_TAR = PA5.tar
$(TARGET_TAR): $(TARGET_FILE)
$(TAR) -cvf $(TARGET_TAR) $(C_FILES) $(ASM_FILES) $(TARGET_FILE) Makefi$
recurse.o: recurse.c
$(C_COMPILER) $(COMPILER_FLAGS) $(C_FILES)
$(TARGET_FILE): $(OBJS)
$(LD_LINKER) $(LINKER_FLAGS) $(TARGET_FILE) $(OBJS)
where fib and countUp class methods must be called recursively. The recursive.c file is considered our c driver. Do not create or implement any header files OTHER than those that are standard c headers (stdio.h, string.h, etc.). When I try to run this I get:
make
gcc -g -o recurse recurse.o
recurse.o: In function `main':
(file root location)/recurse.c:43: undefined reference to `fib'
(file root location)/recurse.c:46: undefined reference to `countUp'
collect2: ld returned 1 exit status
make: *** [recurse] Error 1
Any clue what is going on.
Original Question:
I have multiple C files that I am combining into an executable. For example say I have math.c, the arguments are passed into it, and then if the input argument calls add it performs functions from add.c, if the argument calls subtract it will call functions from subtract.c, etc. The files are then compiled into a .o file, and then an executable is created. The issue I have is not being able to utilize header (.h) files. Is there any way to break into the separate classes or am I missing something? I really don't know exactly how to ask the question, jargon is pretty bad as far as C goes, sorry :(
I don't really get the idea of a driver I guess. (Not a device driver, she keeps telling us this is a c executable driver).
If I understood correctly, what I think you need to do is add the following prototypes above any of the functions you define in recursion.c. The prototypes will allow you to call these functions from within any function inside recursion.c (In fact, including a header file is akin to copy-pasting all of the prototypes defined in the file, as #Justin and #EdS already pointed out)
int fib(int n);
void countUp(int n);
int main() {
...
}
Then you need to make sure that your project file includes the files recursion.c, fib.c, and countUp.c - When you build your project, the linker will do its job and lookup the entry points in your compiled object files, and will proceed to assemble a single executable file.
What compiler are you using?
Including a header file is just a preprocessor directive to include the contents of that file at the location of the include. To achieve the same thing without a header file just copy and paste the code that you would have put in the header file into the top of each c file.
Of course this isn't very maintainable as if you want to change that contents you need to change it in many files, hence why header files exist in the first place.
Since this is homework and considering the fact that you have told us that A) You have no header files to use, and B) you have not been instructed to utilize the extern keyword, it seems to me that your only choice is to include the .c files themselves:
#include "add.c"
#include "subtract.c"
/* etc... */
int main()
{
// use functions defined in "add.c", "subtract.c", etc.
}
Note that this is bad form as you are including the implementation instead of the interface and likely pulling in a bunch of stuff you don't want or need. If that doesn't answer your question then there is something, some instruction from your teacher, missing in the question.

purpose of creating DEPENDENCIES_OUTPUT file while compiling c program

gcc -MD file.c creates a dependency output file named file.d. But I dont understand the need of creating this file ( dependency file ), because when error comes while compilation, no dependency file is generated. So can anyone throw some light when he/she has used this dependency file or some usefulness of this file / feature of gcc.
The file.d file can be understand by make. You often first generate the .d files, include them into your Makefile and then compile the c-files only if one of the included headers has changed.
Don't bother about if you don't use make.
GCC documentation says:
Instead of outputting the result of preprocessing, output a rule suitable for make describing the dependencies of the main source file. The preprocessor outputs one make rule containing the object file name for that source file, a colon, and the names of all the included files, including those coming from -include or -imacros command line options.

C Header Files with the same declarations but different implementations

I have two sets of header files and .c files in my project i will only ever be including one of these headers but i want the option to quickly swap the header im including. Both header files have some declarations that are exactly the same but the implementations in the .c files are different. Basically what I need is way to tell the compiler to only compile the .c file that is associated with the header im including elsewhere in my program.
You could always specify the .c or .o file that you're going to link against at compile/link time for instance
gcc -o myexe file1.c/file1.o
or
gcc -o myexe file2.c/file2.o
you could even make this a different make directive if you have a makefile if you have the same header file but 2 different implementations. I would recommend just using 1 header file and changing the underlying implementation, no point in having 2 headers with similar declarations.
If both header files are exactly the same then you don't need to maintain two header files. You can keep only one copy. Whichever code includes the header file can include this single header file only.
You can always specify which .c file you want to compile while compiling. In gcc, you can mention the C file to be compiled in the command line. In Visual Studio, you can include the correct C file.
I guess you should maintain only one header file and include that in your code. Introduce a flag to the makefile to link which implementation to be linked. You have not mentioned what are you using to build.

How to link a non-standard header file into a C compiler

I'm trying to use a non-standard header file (http://ndevilla.free.fr/gnuplot). Its used in lots of codes in various different places on my computer. Currently I have to put the header file and the object file in every folder which its needed with the preprocessor directive:
#include "gnuplot_i.h"
In the file. Is there a way by which I can put the header file in one place so I can reference it like other standard header file. Cheers.
Compile with -I<directory>
E.g.
compile with -I/usr/local/gnuplot/inc.
Also it might be worth your reading up on include paths and the difference between:
#include <include_file.h>
and
#include "include_file.h"
Linking in an object file needs to be done explicitly the same way as a C file, which means (I believe) that you need a full path. However if you archive it into a proper library then you can use -l<library name> and -L<library path> instead. E.g.
gcc -I/usr/local/gnuplot/inc -L/usr/local/gnuplot/lib -lgnuplot -o my_prog my_prog.c
Most compilers have a flag -I that lets you add a directory of your choosing to the search path for include files.

Resources