C语言 Makefile,编译和链接

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13664693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:38:31  来源:igfitidea点击:

Makefile, Compiling and Linking

ccompilationlinkermakefile

提问by darksky

I have a question regarding compiling and linking in Makefile (and perhaps in general).

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

I have a server.c file which consists of the main program which has a main()function. server.cincludes rio.c. I have a module called riowhich consists of rio.cand rio.h. It has no main()function.

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

I have two questions, how to actually write the Makefile, and the best practice for doing such a thing.

我有两个问题,如何实际编写 Makefile,以及执行此类操作的最佳实践。

Q1: How to write the Makefile

Q1:如何编写Makefile

I have the following 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

I am having linking issues with this. It says that I have multiple definitions of all the functions used in C. I'm not sure how this is possible since server.c is compiled with the -cflag so nothing is actually linked. It should know that some functions exist but not actually link them until the allrule compiles both object files together and produces a single object file which has everything linked.

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

What is the issue here?

这里有什么问题?

Q2: Best practiceSince I have a module and then another file which contains the main program, should I compile the main program, server.c, as a separate module and then compile both together in all, or compile server.c in all and add the rio.o module there? Note that this still produces the same linking problem I have above so I'm pretty sure I have my issue lies somewhere else.

Q2:最佳实践因为我有一个模块,然后是另一个包含主程序的文件,我应该将主程序编译server.c为一个单独的模块,然后在all. o 模块有吗?请注意,这仍然会产生与上面相同的链接问题,因此我很确定我的问题出在其他地方。

回答by Jonathan Leffler

You should revise the structure a little:

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

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

The difference is that the phoney rule alldepends on sysstatdbeing up to date, and sysstatdis up to date when it is up to date w.r.t the object files.

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

Now it is just rather verbose, writing the compilation actions explicitly. It would be sufficient to use:

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

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

You could also debate: does server.cnot use rio.h? If it does, the dependency should be listed. If not, why does rio.hexist? makewill assume that server.odepends on server.c, so you don't have to specify that (but it won't make assumptions about the headers). You could also use a macro to prevent repetition of the program name:

你也可以辩论:不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

If you needed other libraries, then you might use:

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

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