1

我是初学者。我想为 Linux 中的 C 程序创建一个 makefile。

我的程序流程是, 在(但未在其中定义)中声明的cmd.c调用cdirec(), dspecd(), sfile(), hfile()mainl.h

cdirec(), dspecd(), sfile() and hfile()cdirec.c, dspecd.c, sfile.c分别在和中定义hfile.c

cdirec()依次调用mimx(), skloc(), fnc() and fcmp()其中声明的subl.h(但未在其中定义的)

mimx(), skloc(), fnc() and fcmp()分别定义在mimx.c, skloc.c, fnc.c and fcmp.c

我尝试如下创建一个makefile,

all: cmd.o cdir.o dspecd.o sfile.o hfile.o
    cc cmd.o cdir.o dspecd.o sfile.o hfile.o -o sourceinfo
cmd.o: cmd.c mainl.h
    cc -c cmd.c
cdir.o: cdirec.o mimx.o skloc.o fnc.o fcmp.o
    cc cdirec.o mimx.o skloc.o fnc.o fcmp.o -o cdir.o
cdirec.o: cdirec.c mainl.h subl.h
    cc -c cdirec.c
dspecd.o: dspecd.c mainl.h
    cc -c dspecd.c
sfile.o: sfile.c mainl.h
    cc -c sfile.c
hfile.o: hfile.c mainl.h
    cc -c hfile.c
mimx.o: mimx.c subl.h
    cc -c mimx.c
skloc.o: skloc.c subl.h
    cc -c skloc.c
fnc.o: fnc.c subl.h
    cc -c fnc.c
fcmp.o: fcmp.c subl.h
    cc -c fcmp.c

我不明白问题是什么。但是我得到一个未定义的对 main in 的引用cdir.o。cdirec.c 看起来像这样,

#include<stdio.h>
#include "subl.h"

void cdirec()
{
printf("\nAll details of current directory is printed.\n");
mimx();
skloc();
fnc();
fcmp();
}

我没有也不能有 main,因为它只是一个函数声明文件。请指导我。

回答:

all: cmd.o cdirec.o dspecd.o sfile.o hfile.o mimx.o skloc.o fnc.o fcmp.o 
    cc cmd.o cdirec.o dspecd.o sfile.o hfile.o mimx.o skloc.o fnc.o fcmp.o -o sourceinfo
cmd.o: cmd.c mainl.h
    cc -c cmd.c
cdirec.o: cdirec.c mainl.h subl.h
    cc -c cdirec.c
dspecd.o: dspecd.c mainl.h
    cc -c dspecd.c
sfile.o: sfile.c mainl.h
    cc -c sfile.c
hfile.o: hfile.c mainl.h
    cc -c hfile.c
mimx.o: mimx.c subl.h
    cc -c mimx.c
skloc.o: skloc.c subl.h
    cc -c skloc.c
fnc.o: fnc.c subl.h
    cc -c fnc.c
fcmp.o: fcmp.c subl.h
    cc -c fcmp.c
clean:
    rm -rf *.o sourceinfo
4

3 回答 3

3

问题出现在这里:

cdir.o: cdirec.o mimx.o skloc.o fnc.o fcmp.o
    cc cdirec.o mimx.o skloc.o fnc.o fcmp.o -o cdir.o

这是告诉cc将这些给定.o文件链接到一个名为cdir.o. 可执行文件需要一个main函数。但看起来您并没有尝试链接可执行文件;相反,您试图将多个目标文件收集到一个目标文件中。

你不需要这样做;您可以在最终的可执行文件中将所有目标文件链接在一起。如果你只是觉得在一行中处理这么多文件很麻烦,你可以定义一个 Make 变量;一个通用名称是OBJS(“对象”的缩写):

OBJS  = cdirec.o 
OBJS += mimx.o 
OBJS += skloc.o 
OBJS += fnc.o 
OBJS += fcmp.o 
# ... etc

sourceinfo: ${OBJS}
    cc ${OBJS} -o sourceinfo

如果您想将它们收集到一个文件中,您可以构建一个库,然后将其链接到最终的可执行文件中。使用命令构建库ar;它应该有扩展名.a

cdir.a: cdirec.o mimx.o skloc.o fnc.o fcmp.o
    ar rcs cdir.a cdirec.o mimx.o skloc.o fnc.o fcmp.o

然后在构建最终可执行文件时链接它:

cc cmd.o dspecd.o sfile.o hfile.o cdir.a -o sourceinfo

作为对您组织的补充,看起来您可能正在为每个源文件定义一个函数。这很快就会变得非常麻烦。您通常将相关函数组合在同一个源文件中。有可能所有cdirec(), mimx() skloc(),fnc()fcmp()都应该在同一个文件中定义,以便它们生成一个目标文件,但如果没有看到您的实际代码,我不能肯定地说。

Make 中还有其他功能可以使您的 Makefile 更简单。特别是,已经有将.c文件编译成的隐式规则.o,因此您不需要所有这些规则,只需要对标头的依赖项(因为这些不是隐式生成的):

cmd.o: mainl.h
cdirec.o: mainl.h subl.h
dspecd.o: mainl.h
sfile.o: mainl.h
hfile.o: mainl.h
mimx.o: subl.h
skloc.o: subl.h
fnc.o: subl.h
fcmp.o: subl.h

你实际上也可以自动生成这些依赖关系,但这有点复杂,所以我不会在这里讨论它。

于 2012-12-19T07:29:14.020 回答
1

如果您不尝试创建静态/动态库,则需要在某处拥有 main。使用 main 添加一些测试文件,并使用该文件进行编译。
此外,我认为没有必要明确提及所有这些 *.o。Make足够聪明,可以解决这个问题。

于 2012-12-19T07:26:46.323 回答
-1

不要为依赖项的手写而烦恼。使用autotools或轻版本-- gcc -MM ./*

于 2012-12-19T07:11:45.483 回答