I’ve written a sample program about structs. I wrote 3 source file and a 1 header file. This is the complete source of the program:
main.c:
#include <stdio.h>
#include <stdlib.h>
#include "fish.h"
/*
struct fish
{
const char *name;
const char *species;
int teeth;
int age;
};
*/
/*
void catalog(struct fish f)
{
printf("%s is a %s with %i teeth. He is %i.",
f.name, f.species, f.teeth, f.age);
}
void label(struct fish f)
{
printf("Name: %s\n", f.name);
printf("Species: %s\n", f.species);
printf("Teeth: %i\n", f.teeth);
printf("Age: %i\n", f.age);
}
*/
int main()
{
struct fish snappy = {"Snappy", "Piranha", 69, 4};
catalog(snappy);
label(snappy);
return 0;
}
label.c:
#include "fish.h"
void label(struct fish f)
{
printf("Name: %s\n", f.name);
printf("Species: %s\n", f.species);
printf("Teeth: %i\n", f.teeth);
printf("Age: %i\n", f.age);
}
catalog.c:
#include "fish.h"
void catalog(struct fish f)
{
printf("%s is a %s with %i teeth. He is %i.",
f.name, f.species, f.teeth, f.age);
}
I also wrote a makefile:
fish.o: main.c label.c catalog.c fish.h
gcc -c main.c label.c catalog.c
fish: fish.o
gcc fish.o -o fish
I compile the program in cmd:
make fish
It says:
gcc -c main.c label.c catalog.c
label.c: In function 'label':
label.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
catalog.c: In function 'catalog':
catalog.c:5:5: warning: incompatible implicit declaration of built-in function 'printf' [enabled by default]
cc fish.o -o fish
cc.exe: error: fish.o: No such file or directory
cc.exe: fatal error: no input files
compilation terminated.
make: *** [fish] Error 1
If I remove the comments in the main.c and compile only it, It works, But when I broke into small pieces as mentioned above it doesn’t work.
What’s the wrong?
This linking rule:
is appropriate for building a program
fishfrom a single object filefish.o(which is presumably compiled fromfish.c).You need a different rule:
You can add
${CFLAGS}and${LDFLAGS}and${LDLIBS}(or${LDLIBES}) to the link line as appropriate if you want to, but for simple programs, what I showed suffices.You don’t have to tell
makehow to convertmain.cintomain.o; it knows that already. It will use a rule such as:to create the
.ofile from the matching.cfile. (This is the GNU Make notation; POSIXmakeand other classic versions ofmakeuse an alternative but loosely equivalent notation.c.o:in place of%.o: %.c.)If you don’t mind compiling all the sources each time, you can use a similar rule:
This time,
${CFLAGS}is practically mandatory (though you’d just about get away without it in your bare-bones sample program).Note that
makeis fussy; the command lines such as the${CC}lines must start with a TAB; blanks will not do.