c - Makefile、编译和链接

标签 c compilation linker makefile

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

我有一个 server.c 文件,它由具有 main() 函数的主程序组成。 server.c 包含 rio.c。我有一个名为 rio 的模块,它由 rio.crio.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 模块?请注意,这仍然会产生与上面相同的链接问题,因此我很确定我的问题出在其他地方。

最佳答案

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

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是最新的到目前为止 w.r.t 对象文件。

现在它相当冗长,显式地编写编译操作。使用就足够了:

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

关于c - Makefile、编译和链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13664693/

相关文章:

c++ - C/C++ 中的 STL、iostream、new、delete for CUDA

C 函数调用 : Understanding the "implicit int" rule

asp.net - 如何动态编译ashx文件?

iphone - 尝试使用 MPMoviePlayer 时出现链接器错误

c++ - 我如何组织 C++ 代码而不用过多考虑某些内容是否已模板化?

检查字符串中的子字符串,并使字符串的字符大写(当在那里找到子字符串时

c - 使用指针表示法初始化数组

c - 在 GCC 中使用 Make 时权限被拒绝

使用 R 头文件编译 C 代码

c++ - 如果两个静态库使用相同的另一个静态库,如何避免 "LNK2005 Already Defined error"?