Jas*_*son 1 c compiler-errors makefile
对于一个项目,我正在与一个合作伙伴一起编写决策树实现.由于我们都是C的相对新手并且必须快速工作,我们基本上将所有功能转储到单个文件中,最终超过1600行.这是一个快速而又肮脏的项目,但是现在下一个任务让我们负责扩展和重新实现代码.在目前的情况下,这是不会发生的.
现在,我正在根据职能责任分解原始来源.事实是,许多功能交织在一起,我的make文件出现重大错误.更具体地说,其他源文件报告在单独文件中声明的函数的隐式声明.
我真的没有多个文件makefile的经验.当前的语法是在去年的系统编程类中从简单的shell实现中借用的,尽管这个当前项目的复杂性要高出一个数量级.
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
Run Code Online (Sandbox Code Playgroud)
我还尝试了以前的版本,其中每个目标文件都是单独编译的
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
Run Code Online (Sandbox Code Playgroud)
并重复.o为每个源创建一个文件,然后将其编译为可执行文件.
但是,这没有用,我得到了大约500行编译器投诉和警告,主要是关于隐式函数声明.
所以,基本上我有两个相关的问题:
先说一下你的makefile.
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o proj2 main.o split.o tree.o id3.o output.o
Run Code Online (Sandbox Code Playgroud)
这应该工作(如果代码是正确的),但如果你正在使用GNUMake(你应该),你可以整理它:
proj2: main.o split.o tree.o id3.o output.o
$(CC) $(CFLAGS) -o $@ $^
Run Code Online (Sandbox Code Playgroud)
现在,您只需要维护一个对象列表的副本.
另一个版本是错的:
main.o: main.c split.c tree.c id3.c output.c
$(CC) $(CFLAGS) -o main.c split.c tree.c id3.c output.c
Run Code Online (Sandbox Code Playgroud)
首先,您正在尝试将所有源文件编译为一个目标文件,这样会破坏目标文件的目的.其次,main.o当一个目标文件确实属于由其制作的目标文件时,您将命名一个目标文件main.cc.第三,该命令告诉编译器将所有其他源文件(split.c,tree.c...)编译成一个名为"main.c"的目标文件 - 这不是非法的,但是你必须自己绊倒.
此外,你应该尝试使用C++,而不是C,但这是另一天.
现在打破泥球大球.我假设您知道如何将大函数分解为较小的函数,因此问题是将函数分离到不同的源文件中(然后正确地编译和链接它们).假设main()调用函数foo():
/* main.c */
void foo()
{
// do foo things
}
int main()
{
// do main things
foo();
return(0);
}
Run Code Online (Sandbox Code Playgroud)
如你所知,foo必须先行,否则编译器在main尝试调用未声明的函数时会犹豫不决.但我们可foo事先声明:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
void foo()
{
// do foo things
}
Run Code Online (Sandbox Code Playgroud)
当编译器到达调用时foo(),它已经知道存在这样的函数,并且信任我们稍后定义它.现在的诀窍是:如果我们指示编译器进行编译,而不是链接(即生成类似的对象文件main.o,而不是类似的可执行文件proj2),它将更信任我们:
/* main.c */
void foo();
int main()
{
// do main things
foo();
return(0);
}
Run Code Online (Sandbox Code Playgroud)
这将main.o很好地编译.void foo()当我们将事物链接到一个可执行文件时,编译器信任我们在某些其他目标文件中提供定义.定义将在另一个文件中,如下所示:
/* foo.c */
void foo()
{
// do foo things
}
Run Code Online (Sandbox Code Playgroud)
我们可以手工制作:
gcc -g -Wall -lm -c foo.c -o foo.o
gcc -g -Wall -lm -c main.c -o main.o
gcc -g -Wall -lm foo.o main.o -o proj2
Run Code Online (Sandbox Code Playgroud)
但这很快就会变得乏味,所以我们将编写一个makefile:
cc= gcc
CFLAGS= -g -Wall -lm
proj2: main.o foo.o
$(CC) $(CFLAGS) -o $@ $^
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.如果这一点很清楚,那么我们可以转到头文件......
| 归档时间: |
|
| 查看次数: |
494 次 |
| 最近记录: |