我写了一个关于结构的示例程序。我写了3个源文件和1个头文件。这是该计划的完整来源:
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);
}
我还写了一个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
我在cmd编译程序:
make fish
它说:
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
如果我删除main.c中的注释并仅编译它,它可以工作,但是当我如上所述闯入小块时它不起作用。
有什么不对?
答案 0 :(得分:4)
您需要将所有 .c 文件一起编译,以便您可以使用 label.c 和 catalog.c中定义的函数< / em>在 main.c 。
您可以使用gcc:
一步完成此操作gcc main.c label.c catalog.c -o fish
这将编译每个单独的源文件并生成object files,它们将链接在一起以生成可执行文件。您正在查看的错误发生在链接阶段,当gcc尝试查找catalog
和label
函数时。
答案 1 :(得分:3)
gcc main.c -o fish
仅汇编main.c
。 main.c
不了解label.c
。它只知道它必须调用一个名为“label”的函数,这个函数在别处定义。然后,链接器查看所有生成的目标文件,并将它们“链接”到一个可执行文件中:
gcc main.c -c
gcc label.c -c
gcc catalog.c -c
ld main.o label.o catalog.o -o fish
这是
的明确版本gcc main.c label.c catalog.c -o fish
答案 2 :(得分:2)
此链接规则:
fish: fish.o
gcc fish.o -o fish
适用于从单个对象文件fish
(可能是从fish.o
编译)构建程序fish.c
。
您需要一个不同的规则:
OBJECTS = main.o label.o catalog.o
fish: ${OBJECTS}
${CC} -o $@ ${OBJECTS}
如果您愿意,可以根据需要将${CFLAGS}
和${LDFLAGS}
以及${LDLIBS}
(或${LDLIBES}
)添加到链接行,但对于简单程序,我展示的内容就足够了。
您无需告诉make
如何将main.c
转换为main.o
;它已经知道了。它将使用如下规则:
%.o: %.c
${CC} -c ${CFLAGS} $<
从匹配的.o
文件创建.c
文件。 (这是GNU Make notation; POSIX make
和make
的其他经典版本使用替代但松散等效的符号.c.o:
代替%.o: %.c
。)
如果您不介意每次都编译所有来源,您可以使用类似的规则:
SOURCES = main.c label.c catalog.c
fish: ${OBJECTS}
${CC} ${CFLAGS} -o $@ ${SOURCES}
这一次,${CFLAGS}
几乎是强制性的(尽管你的裸机样本程序中没有它就会离开)。
请注意,make
很挑剔; ${CC}
行等命令行必须以 TAB 开头;空白不会。