我的理解是C有makefile和include语句,所以你没有奇怪的怪物大小文件,你应该在功能上分解你的代码。因此,如果我是对的,我应该能够在.c文件之间进行函数调用,如果我做我的标题并且正确的话。
我正在尝试这样做,但不幸的是我收到了错误。
文件包含以下内容:
文件1)test.c:
#include<stdio.h>
#include"suc.h"
main()
{
printf("Hello World\n\n");
printf("This is the number: %d \n\n", suc(6));
}
文件2)makefile:
CC=gcc
CFLAGS=-c -Wall
test: suc.o
$(CC) -Wall -o test test.c
suc.o: suc.c
$(CC) $(CFLAGS) suc.c
文件3)suc.h
#ifndef SUC_H_GUARD
#define SUC_H_GUARD
// returns the successor of i (i+1)
int suc(int i);
#endif
文件4)suc.c
#include "suc.h"
int suc(int i)
{
return i + 1;
}
当我制作(制作-B)顶部时,我得到:
gcc -c -Wall suc.c
gcc -Wall -o test test.c
test.c:7: warning: return type defaults to 'int'
/tmp/cc/7w7qCJ.o: In function 'main':
test.c: (.text+0x1d): undefined reference to 'suc'
collect2: ld returned 1 exit status
make: *** [test] Error 1
然而: 两者都产生预期的结果: A)这个单个文件程序工作正常!
#include<stdio.h>
main()
{
printf("Hello World\n\n");
printf("This is the number: %d \n\n", suc(6));
}
int suc(int i)
{
return i + 1;
}
B)原始文件中的所有文件,但对test.c进行了以下更改:
#include<stdio.h>
#include"suc.h" //suc() is still defined b/c suc.h is included
main()
{
printf("Hello World\n\n");
printf("This is the number: %d \n\n", 4); //HERE! -> no function call
}
请帮助,谢谢! 我不太明白错误消息试图告诉我的内容。
答案 0 :(得分:4)
您需要将源文件单独编译为其目标文件,然后链接目标文件以获取可执行文件test
。
所以你需要:
CC=gcc
CFLAGS=-c -Wall
test: test.o suc.o
<tab>$(CC) -Wall -o test test.o suc.o
test.o: test.c
<tab>$(CC) $(CFLAGS) test.c
suc.o: suc.c
<tab>$(CC) $(CFLAGS) suc.c
其中<tab>
是标签。
当前makefile中存在的问题是:
test: suc.o
$(CC) -Wall -o test test.c
表示test
取决于suc.o
并获得test
您需要执行的操作:
$(CC) -Wall -o test test.c
但是看看那个编译/链接行,它不包含任何定义了suc
函数的源/目标文件。
您可以将suc.o
添加为:
$(CC) -Wall -o test test.c suc.o
但是它被认为是不好的,因为你说你只更改suc.c
文件然后你的makefile会重新生成suc.o
并且还必须重新生成test
,但是要重新生成test
你正在重新编译test.c
,即使它没有被更改。
答案 1 :(得分:4)
在您的情况下,您将两个文件“suc.c”和“test.c”编译为两个不同的目标文件 - “suc.o”和“test.o”。但是,在链接程序时,只指定一个目标文件,这使链接器无法找到定义或“suc”函数。您必须将make文件更正为:
suc.o: suc.c
$(CC) $(CFLAGS) suc.c
test.o: test.c
$(CC) $(CFLAGS) test.c
test: suc.o test.o
$(CC) -Wall -o test suc.o test.o
祝你好运!
答案 2 :(得分:2)
构建测试时,您没有链接suc.o
。
将test.c
和suc.c
编译到目标文件中,然后将它们链接到最终的test
可执行文件中。
这个makefile应该可以工作(确保用规则中的制表符替换空格):
CC=gcc
CFLAGS=-c -Wall
.PHONY: all
all: test
test: test.o suc.o
$(CC) -Wall test.o suc.o -o test
test.o: test.c
$(CC) $(CFLAGS) test.c
suc.o: suc.c
$(CC) $(CFLAGS) suc.c
答案 3 :(得分:2)
您需要告诉链接器将编译后的代码包含在suc.o
中(在第一个编译步骤中生成),因为C 链接器非常愚蠢;它不知道魔术的功能实现。 (这种方式偶尔会有用!)
使用它进行编译的第二步应该有效:
gcc -Wall -o test test.c suc.o
答案 4 :(得分:2)
除了告诉您与“suc.o”链接的所有答案之外,警告return type defaults to 'int'
告诉您,您忽略了为main()
函数声明返回类型。
正确的定义如下:
int main(int argc, char *argv[])
答案 5 :(得分:1)
此依赖关系行失败:
test: suc.o
$(CC) -Wall -o test test.c
因为你没有链接到suc.o(而且,顺便说一句,测试取决于suc.o和test.o)
你的行应该是:
test: test.o suc.o
$(CC) -Wall -o test test.o suc.o
test.o : test.c
$(CC) -c test.c
答案 6 :(得分:1)
gcc -c file.c
将file.c
编译为目标文件file.o
。
gcc -o test test.c
将编译并将test.c
链接到可执行文件。
但是为了创建可执行文件,您需要链接所需的所有目标文件,在您的情况suc.o
中,所以您必须编写
gcc -c test.c
gcc -c sic.c
gcc -o test test.o sic.o
gcc -o test test.c sic.c
答案 7 :(得分:0)
这里肯定有足够的答案。一个人不能伤害。 Make(通常)非常聪明。让它使用它对标准构建规则的了解,并将Makefile简化为单行:
test: test.o suc.o
不要费心给它简单的构建规则,因为它通常可以猜测它们。 (我正在考虑使用gnu make,但大多数(如果不是全部)版本都会做同样的事情。)
另外,作为旁注,请考虑重命名您的可执行文件。名称“test”是引起混淆的原因,因为无论何时尝试运行它,您都会意外地获得内置shell或/ bin / test。