I already know the differences between a header file and a library. However, when I'm writing my makefile, I have some difficulties on deciding if I should put something as a dependency of the file or just at the linking rule.
For example: I have 2 simple files:
main.c:
#include <stdio.h>
main(){
printf("this is the sine or 90");
sinus(90);
}
and func.c:
#include <math.h>
sinus(int num){
return sin(num);
}
and my makefile is:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c
main.o: main.c
Well, my question is why this makefile works and this one doesn't:
main: main.o func.o
gcc main.o func.o -lm -o main
func.o: func.c math.h
main.o: main.c
You don't need to make func.o depend on math.h as that file is very unlikely to change.
Regarding the error you get if you do is because you don't explicitly specify how make should compile the file so it tries to deduce how to compile it and it only works in simple cases. I'm not sure exactly how make does it but I think it just does gcc -o target.o -c <your deps>.
Because make is looking for a file "math.h" in the current directory and trying to do cc func.c math.h to produce func.o
Problem is that you don't know exactly how Makefile is resolved after using implicit rules - definitely there's one which causes problems you have. (maybe try to compile math.h, or math.h is not found etc.. (you didn't posted errors you have so we can only speculate).
I would advice you to disable implicit rules by calling make with "-r" and do everything explicitly - this way you will learn more as you'll know how makefile works instead of knowing how to write makefiles which works under some circumstances.
More on implicit rules: Make documentation - Implicit rules
More on make Make documentation
Related
This really shouldn't be something I have to ask, but somehow I can find absolutely nothing by searching to answer my question.
In order to ask another question, I made three files: main.c, sub.c and sub.h. main.c has the 'main' function, while sub.c contains only function definitions.
Initially, main.c had '#include "sub.h"' as its only include statement.
Trying 'gcc main.c -O3 -o test' resulted in an error, saying that the function f() (declared in sub.h, defined in sub.c, and referenced in main.c) was unreferenced.
Trying 'gcc main.c sub.c -O3 -o test' resulted in expected behaviour.
I then modified test.c, removing the #include and references to f. 'gcc main.c -O3 -o test2' worked as expected.
I then re-added the references to f, and forgot to re-add the #include. Despite this, 'gcc main.c sub.c -O3 -o test3' worked as expected.
I noticed the mistake, and re-added the include intentionally as '#include sub.c'. 'gcc main.c sub.c -O3 -o test4' resulted in an error, saying f() was defined multiple times. 'gcc main.c -O3 -o test4 returned to working as expected.
The only conclusion I can draw from this is that as far as local files are concerned, if the file is a source code file then include it and don't add it to the command, else add its source to the command and don't bother including it, because apparently it doesn't matter whether you include it or not. I guess?
Basically my question is, is the behaviour above intended, and if so is it documented, and where, so I can read it and make better informed decisions about how to handle my included files in the future.
I then re-added the references to f, and forgot to re-add the #include. Despite this, 'gcc main.c sub.c -O3 -o test3' worked as expected.
For suitably loose definitions of "worked"; I'm going to bet that f() returns an int, and that gcc was defaulting to C89 mode.
Prior to C99, if the compiler encountered a function call before it saw a function definition or declaration, it assumed that the called function returned an int. Thus, as long as f() actually returns an int, your code will compile and run successfully. If f() doesn't return an int the code will still compile, but you will have a runtime problem. All the linker cares about is that the symbol is there; it doesn't care about type mismatches.
C99 did away with implicit int typing, so under a C99 compiler your code would fail to compile if you didn't have a declaration for f() in scope (either by including sub.h or adding the declaration manually).
The only conclusion I can draw from this is that as far as local files are concerned, if the file is a source code file then include it and don't add it to the command, else add its source to the command and don't bother including it, because apparently it doesn't matter whether you include it or not. I guess?
That is the exact wrong conclusion to draw. You do not want to include a .c file within another .c file as a regular practice, as it can lead to all kinds of mayhem. Everything in main.c is visible to sub.c and vice versa, leading to potential namespace collisions - for example, both files could define a "local" helper function named foo(). Normally such "local" functions aren't visible outside of the source file, but by including one source file within the other, both versions of foo() are visible and clash with each other. Another problem is that if a .c file includes another .c file which includes another .c file, etc., you may wind up with a translation unit that's too large for the compiler to handle. You will wind up recompiling both files every time you change one or the other where it isn't necessary. It's just bad practice all the way around.
The right thing to do is compile main.c and sub.c separately and make sure sub.h is included in both (you want to include sub.h in sub.c to make sure your declarations line up with your definitions; if they don't, the compiler will yak while translating sub.c).
Edit
Answering the following question in the comments:
When you say to compile main.c and sub.c separately, I'm assuming you mean to make object files out of them each individually and then link them (3 commands total)? Is there any way to do that with a single command?
The command gcc -o test main.c sub.c does the same thing, it just doesn't save the respective object files to disk. You could also create a simple Makefile, like so:
CC=gcc
CFLAGS=-O3 -std=c99 -pedantic -Wall -Werror
SRCS=main.c sub.c
OBJS=$(SRCS:.c=.o)
test: $(OBJS)
$(CC) -o $# $(CFLAGS) $(OBJS)
clean:
rm -rf test $(OBJS)
Then all you need to do is type make test:
[fbgo448#n9dvap997]~/prototypes/simplemake: make test
gcc -O3 -std=c99 -pedantic -Wall -Werror -c -o main.o main.c
gcc -O3 -std=c99 -pedantic -Wall -Werror -c -o sub.o sub.c
gcc -o test -O3 -std=c99 -pedantic -Wall -Werror main.o sub.o
There are implicit rules for building object files from .c files, so you don't need to include those rules in your Makefile. All you need to do is specify targets and prerequisites.
You may need to drop the -pedantic flag to use some platform-specific utilities, and you may need to specify a different standard (c89, gnu89, etc.) as well. You will definitely want to keep the -Wall -Werror flags, though - they'll enable all warnings and treat all warnings as errors; they'll force you to deal with warnings.
If you compile a program then the main function should be there. If you compile a program without main, then you can only generate object files. In your case, it looks like main.c contains main() and sub.c contains some function definitions. Other important thing is when you define a header file, ensure you have preprocessor directive to prevent including the header file multiple times.
An example is here:
http://www.tutorialspoint.com/cprogramming/c_header_files.htm
I have written c program, Which has 3 file(.c ) , Main program has
two threads and one file has mysql connection function, One file has
thread functions definition. I don't know how to compile all these
codes, Normally I tried like this,
cc -pthread main.c
But if I compile like this I am getting error called mysql functions
are undefined But I have written thread as separate program and
mysql as separate program and complied individually , it complied
successfully and I got output. So please help me to compile my
project File names are,
main.c (2 threads are declared) functions.c (thread function
definition, and mysql func declared) db.c ( mysql function
definition)
please help to compile my code?
You have two basic options when compiling multiple .c files:
Option 1)
cc file1.c file2.c file3.c -o executable_name
Advantage: simple
Disadvantage: if all you change is one file you are recompiling all the files
Option 2)
cc file1.c -c -o file1.o
cc file2.c -c -o file2.o
cc file3.c -c -o file3.o
cc file1.o file2.o file3.o -o executable_name
Advantage: If you change one file you do not have to recompile everything
Disadvantage: Multiple commands (but you should use a Makefile at this point)
The -c flag tells the compiler to compiler but not link. You don't want to link as you have not compiled all of your files. The final invocation of cc links all the .o files into the executable executable_name
It is a little bit difficult to understand exactly what you need, but I can tell you from what you've stated that you'll need to include specific libraries in your compile statement you currently are not. Also, a -l flag needs to prefix your libraries.
Try something like this:
gcc -lpthread main.c functions.c db.c -o main $(mysql_config --libs)
To explain, mysql_config --libs returns all the configuration libraries needed to run mysql ddl inside your C program.
Given your updates on your file declarations I'm guessing you're a Java programmer. C is not Java. If you are declaring functions you are only going to use once in main.c you should put them inside main.c unless you need them to be portable.
I am writing C code (not C++) on a Linux system. I am trying to compile one executable from 2 .c files and 1 header file: main.c, sort.c, and sort.h.
main.c's first line reads: #include "sort.h"
inside sort.h, each function in sort.c is defined like this example:
extern void aFunct(int param);
However, when I try to call a function in sort.c from main.c, I get the following error upon compilation: "undefined reference to 'aFunct'".
If i replace #include "sort.h" with #include "sort.c" my program works without issue. However, as I understand it, this is bad form and I would prefer to avoid this. Thanks for any help.
edit: I am compiling this with a makefile containing the following code:
all: index sort.o
sort.o: sort.c sort.h
gcc -Wall -g -c sort.c
index: main.c sort.o
gcc -Wall -g -o index main.c
clean:
rm index
rm sort.o
edit: I have fixed the problem. The problem did not stem from a misunderstanding of C files and how they link, but rather a misunderstanding of the makefile/gcc commands themself. My program works with the following makefile:
all: index sort.o
sort.o: sort.c
gcc -Wall -g -c sort.c
index: main.c sort.o
gcc -Wall -g -o index main.c sort.o
clean:
rm sort.o
rm index
You should include #include "sort.h" in sort.c as well.
You might be doing this already.
The important point is, you need to make sure that you are building both the .c files [main.c and sort.c]
Now both these obj files [main.o and sort.o] should be the input to linker.
As per my guess, you are not compiling sort.c , so linker is not able to see the implementation of the functions.
When you include one source code file to other (e.g. #include "sort.c") you can have a troubles if you include sort.c file to more than one c-file of the same project. But as I understand you just compile one c-file in which you include sort.c... so it works. But, better read some tutorials, for example How to Create Multi-Module Programs
This question already has answers here:
Why is #include <stdio.h> not required to use printf()?
(3 answers)
Closed 8 years ago.
I have two .c files which I compile over a makefile.
foo.c:
void foo()
{
printf("this is foo");
}
main.c:
#include <stdio.h>
int main()
{
printf("this is main\n");
foo();
}
the makefile looks like that:
all: main.o foo.o
gcc -o prog foo.o main.o
main.o: main.c
gcc -c main.c
foo.o: foo.c
gcc -c foo.c
So the question is:
how can foo.c use printf() without me including stdio.h AND how can main.c use the method foo() without me including foo.c.
My guess/research is that the makefile works as a linker. But I dont have prove for that and want to understand how this works excactly.
Correct me if I misunderstood something.
In the compilation phase, the compiler checks function calls against prototypes. Any function that lacks a prototype is assumed to return int and to accept any number of arguments.
If you turn up the warning level, gcc will warn you if a prototype is missing. You should add -Wall and you could also add -pedantic to get diagnostics on additional things the compiler think are suspicious.
If the compilation step succeeds, the compiler creates an object file which contains the compiled code and 2 reference tables. The first table is the export table. It contains the names of all functions and variables that are exported from the object file.
The second table is the import table. It contains a list of all functions and variables that are referenced, but where the declaration was missing.
In your case we have:
foo.o:
Export:
foo
Import:
printf
main.o
Export:
main
Import:
printf
foo
In the linker phase, the linker will take the list of imports and exports and match them. In addition to the object files and libraries you specify on the command line, the linker will automatically link with libc, which contains all functions defined by the c language.
In the makefile you can force the complier to include <stdio> or any other header:
From the docs:
-include file
Process file as if #include "file" appeared as the first line of the
primary source file. However, the first directory searched for file is
the preprocessor's working directory instead of the directory
containing the main source file. If not found there, it is searched
for in the remainder of the #include "..." search chain as normal. If
multiple -include options are given, the files are included in the
order they appear on the command line.
Just add -include filename.h in the GCC/compiler command line within the makefile.
The makefile is not a linker. It is input to make. The makefile just tells make what commands to execute under what conditions.
Your all target is running gcc in linking/linker mode gcc -o prog foo.o main.o.
The same way your foo.o and main.o targets are running gcc in compilation mode gcc -c foo.c.
For the record you can combine the two .o targets into just
%.o: %.c
gcc -c $^
which is, in fact, already a default rule in make so you need not include that rule at all.
Additionally your all target is not following bet make practices because it generates a file that does not match the name of the target. So you should use
all: prog
prog: main.o foo.o
gcc -o prog foo.o main.o
instead.
Though once again there make has you covered by default and so your entire makefile can be replaced by
all: prog
prog: main.o foo.o
and you should get the same results.
I'm trying to compile a program that have main.c and a lot of .c and .h files .
Is there any way to compile and link without passing all .c file in the gcc command
like
gcc main.c file.c file2.c -o main
Your shell can expand wildcards. So you can:
gcc *.c -o main
Of course, you'll have to make sure that you don't have any extra *.c files in the directory that you don't actually want compiled. A better option is to use a build system such as Make or SCons.
'make' is the tool for building C apps. Below is the hello world version.
$ cat main.c
#include <stdio.h>
int main (char *argv[], int argc) {
printf("Hello World\n");
return 0;
}
$ make main
cc main.c -o main
$ ./main
Hello World
Edited in deference to Shahbaz comment:
The original question was trying to simplify the command-line for gcc. The right direction for the programmer is to learn about make. Since there is a bit of a learning curve with make, I wanted to offer simple stepping stone which does something useful. By getting started in this way, you don't need a make file. Simply type 'make programname' as shown above. Make uses its default rules and associated varabiles. $(CC) -c $(CFLAGS) $(CPPFLAGS) The astute programmer can build on this by setting well-know variables.
From here one can tinker with a makefile. In the spirit of stepping stones, consider this trival makefile
$ cat makefile
SRCS = main.c
OBJ = ${SRCS:.c=.o}
CC=gcc
main: ${OBJ}
$ make
gcc main.o -o main
By setting the well-known make variable CC to control which compiler is used. OBJ is computed from the list of source files. The trival target starts one on the road to rules.
Anyway, my hope is this post and other answers get the original questioner on there way.
Regards,
-jk
If you're asking about the command-line, you can just use wildcards to specify all the .c files as #Man of One Way suggested. But in general, C applications of any-but-trivial-size are built using "makefiles" which are extremely helpful.
You might want to read a tutorial such as http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/makefile.html
gcc -o main -I. `find . -name "*\.c"`
This way you could have the .c and .h files in subfolders if you wish.
However, this is not a good way of doing it. A better way would be to create a Makefile
As already said, make is the best way to go
Learn just what you need at every point
Besides, it is important to also use some flags that will help you out while coding:
-Wall -> sets all warning flags
-g, -ggdb -> generates debug code
-ansi, -std=c99
A really good book on how to use make is,
http://shop.oreilly.com/product/9780937175903.do