0xEDD1E
0xEDD1E

Reputation: 1162

What's the wrong with this C Code?

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?

Upvotes: 2

Views: 567

Answers (3)

Jonathan Leffler
Jonathan Leffler

Reputation: 754910

This linking rule:

fish: fish.o
    gcc fish.o -o fish

is appropriate for building a program fish from a single object file fish.o (which is presumably compiled from fish.c).

You need a different rule:

OBJECTS = main.o label.o catalog.o

fish: ${OBJECTS}
    ${CC} -o $@ ${OBJECTS}

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 make how to convert main.c into main.o; it knows that already. It will use a rule such as:

%.o: %.c
    ${CC} -c ${CFLAGS} $<

to create the .o file from the matching .c file. (This is the GNU Make notation; POSIX make and other classic versions of make use 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:

SOURCES = main.c label.c catalog.c

fish: ${OBJECTS}
    ${CC} ${CFLAGS} -o $@ ${SOURCES}

This time, ${CFLAGS} is practically mandatory (though you'd just about get away without it in your bare-bones sample program).


Note that make is fussy; the command lines such as the ${CC} lines must start with a TAB; blanks will not do.

Upvotes: 2

Tordek
Tordek

Reputation: 10882

gcc main.c -o fish only compiles main.c. main.c does not know about label.c. It only knows that it has to call some function called "label", which is defined elsewhere. Then, the linker looks at all of the generated object files, and 'links' them into a single executable:

gcc main.c -c
gcc label.c -c
gcc catalog.c -c
ld main.o label.o catalog.o -o fish

This is the explicit version of

gcc main.c label.c catalog.c -o fish

Upvotes: 3

pb2q
pb2q

Reputation: 59637

You'll need to compile all of the .c files together so that you can use your functions defined in label.c and catalog.c in main.c.

You can do this with one step using gcc:

gcc main.c label.c catalog.c -o fish

This will compile each individual source file and produce object files, which will be linked together to produce your executable. The errors that you're seeing occur during the link phase, when gcc is trying to find the catalog and label functions.

Upvotes: 4

Related Questions