10

我有一个关于在 Makefile 中编译和链接的问题(也许一般来说)。

我有一个 server.c 文件,它由具有功能的主程序组成main()server.c包括 rio.c。我有一个名为的模块rio,它由rio.c和组成rio.h。它没有任何main()功能。

我有两个问题,如何实际编写 Makefile,以及这样做的最佳实践。

Q1:如何编写 Makefile

我有以下 Makefile:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o

all: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd

server.o: server.c
    $(CC) $(CFLAGS) -c server.c

rio.o: rio.c rio.h
    $(CC) $(CFLAGS) -c rio.c

clean:
    rm -f *~ *.o sysstatd

我有与此相关的问题。它说我对 C 中使用的所有函数都有多个定义。我不确定这是怎么可能的,因为 server.c 是用-c标志编译的,所以实际上没有任何链接。它应该知道一些函数存在但实际上并没有链接它们,直到all规则将两个目标文件编译在一起并生成一个包含所有链接的目标文件。

这里有什么问题?

Q2:最佳实践 由于我有一个模块,然后是另一个包含主程序的文件,我应该将主程序编译server.c为一个单独的模块,然后将两者一起all编译,还是编译 server.c 并添加 rio。 o 模块在那里?请注意,这仍然会产生与我上面相同的链接问题,所以我很确定我的问题出在其他地方。

4

1 回答 1

17

您应该稍微修改一下结构:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o

all: sysstatd

sysstatd: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd

server.o: server.c
    $(CC) $(CFLAGS) -c server.c

rio.o: rio.c rio.h
    $(CC) $(CFLAGS) -c rio.c

clean:
    rm -f *~ *.o sysstatd

不同之处在于假规则all取决于是否sysstatd是最新的,并且sysstatd当它是最新的目标文件时是最新的。

现在它只是相当冗长,明确地编写编译操作。使用以下内容就足够了:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o

all: sysstatd

sysstatd: $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o sysstatd

server.o: server.c
rio.o: rio.c rio.h

clean:
    rm -f *~ *.o sysstatd

你也可以辩论:不server.c使用rio.h?如果是这样,则应列出依赖项。如果不是,为什么rio.h存在? make将假设server.o取决于server.c,因此您不必指定它(但它不会对标题做出假设)。您还可以使用宏来防止程序名称重复:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd

all: $(PROG)

$(PROG): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $@

server.o: rio.h
rio.o: rio.h

clean:
    rm -f *~ *.o $(PROG) core a.out

如果您需要其他库,那么您可以使用:

CC = gcc
CFLAGS = -Wall -Werror -Wmissing-prototypes
OBJS = server.o rio.o
PROG = sysstatd
LOCALLIBDIR = /usr/local/lib
LDFLAGS = -L$(LOCALLIBDIR)
LDLIBS  = -lone -ltwo

all: $(PROG)

$(PROG): $(OBJS)
    $(CC) $(CFLAGS) $(OBJS) -o $@ $(LDFLAGS) $(LDLIBS)

server.o: rio.h
rio.o: rio.h

clean:
    rm -f *~ *.o $(PROG) core a.out
于 2012-12-02T21:14:08.543 回答