Makefile,编译和链接

dar*_*sky 9 c linker makefile compilation

我有一个关于在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
Run Code Online (Sandbox Code Playgroud)

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

这是什么问题?

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

Jon*_*ler 14

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

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
Run Code Online (Sandbox Code Playgroud)

不同之处在于,虚假规则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
Run Code Online (Sandbox Code Playgroud)

你也可以辩论:不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
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)