【问题标题】:How to use makefile to compile all sources (some only to object files)?如何使用 makefile 编译所有源文件(一些只编译目标文件)?
【发布时间】:2013-05-29 13:09:36
【问题描述】:

在尝试编译时,我的一个文件出现“未定义的 main 引用”错误。我知道这是因为这个文件没有 main 方法。这只是一些辅助方法的实现文件,所以我只希望它编译为目标文件而不是可执行文件。如果我明确地告诉 makefile 对每个文件做什么,我知道该怎么做,但是我正在尝试编写一个 makefile 来一次编译我的所有源。我尝试使用-c 标志,但随后它将我的所有文件编译为仅目标文件而不是可执行文件。我到底是怎么做到的? 这里是:

CC = gcc
CFLAGS = -g -Wall
SRCS = ./src/server.c ./src/client_slave.c ./src/sockaddrAL.c
EXECS = ./bin/server ./bin/client_slave
OBJS = $(SRCS:.c=.o)

all: clean $(SRCS) server client

server: $(OBJS)
        $(CC) $(CFLAGS) ./src/server.o -o ./bin/server

client: $(OBJS)
        $(CC) $(CFLAGS) ./src/client_slave.o -o ./bin/client_slave

.c.o:
        $(CC) $(CFLAGS) -c $< -o $@

clean:
        @rm -f $(EXECS) $(OBJS)

【问题讨论】:

  • 您发布的示例 Makefile 看起来应该可以正常工作。不是吗?
  • 为了将来参考,不要在获得帮助后使用您从答案中获得的内容来编辑您的 makefile。那些进入这个线程的人会对为什么你有一个“-c”选项感到困惑,但有人建议它

标签: c makefile


【解决方案1】:

您应该将-c 标志添加到构建.o 文件的规则(您的.c.o 后缀规则)并且不将其添加到构建可执行文件的规则(@987654324 @ 规则)。

CC = gcc
CFLAGS = -g -Wall
EXECS = ./bin/server ./bin/client_slave

all: $(EXECS)

./bin/%: ./src/%.o ./src/sockaddrAL.o
        $(CC) $(CFLAGS) -o $@ $^

.c.o:
        $(CC) $(CFLAGS) -c $< -o $@

clean:
        @rm -f $(EXECS) $(OBJS)

您的问题中根本没有显示 sockAddrAL,所以我认为它属于两个可执行文件。另请注意,上述语法假定 GNU make。如果您只想使用 POSIX 标准 make 中提供的功能,您几乎必须全部写出来。

【讨论】:

  • 好的,这解决了这个问题,但现在我遇到了另一个问题,因为我在 client_slave.c 中有一个 main 方法有没有办法使用这样的 makefile 一次编译两个可执行文件?
  • 抱歉,您没有提供足够的信息让我显示生成文件。大概您的一些文件应该用于构建server 程序,而其他文件应该用于构建client 程序。您需要为链接步骤创建两个不同的规则:一个将server 程序与进入server 程序的.o 文件链接,另一个将client 程序与.o 链接进入client 程序的文件。 make 不可能知道这就是你想要的:-)
  • 我更新了 OP 中的 makefile。这就是我想要做的(并且这个 makefile 有效),但正在寻找一种更优雅/更精简的方式。
  • 您的 makefile 不正确。您永远不应该使用像server 这样的目标来创建一个规则,该规则实际上会创建一个具有不同名称的文件,例如./bin/server。我将编辑我的答案。
  • 是的,您需要定义一个新规则server : ./bin/server(不需要配方)。可能您还想添加.PHONY: server,至少对于 GNU make,它将确保名为 server 的本地文件或目录不会破坏您的 makefile(并且它在非 GNU 版本的 make 中是无害的)。
【解决方案2】:

让隐式规则成为你的朋友。您的整个 Makfefile 应该是:

CC = clang
CFLAGS = -O0 -g -Wall
SRCS = server.c client_slave.c sockaddrAL.c
OBJS = $(SRCS:.c=.o)
EXECS = server

server: $(OBJS)

clean:
    @rm -f $(EXECS) $(OBJS)

从 src 目录调用它。

【讨论】:

  • 对不起,我仍然对创建 makefile 有点不满意。我看到这将完成对象规则(.c 文件到 .o 文件),但是如果您不使用 $(CC) 或 $(CFLAGS),它如何知道如何编译为二进制文件?
  • make 有一个很大的内置规则字典,如果您的 makefile 中没有任何规则匹配,它可以应用。要查看它,请运行make -pf/dev/null。这些规则之一描述了如何从具有相同前缀的.o 构建可执行文件(因此,如果您的主文件是server_main.c,这将不起作用)以及您指定的任何其他先决条件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-16
  • 1970-01-01
相关资源
最近更新 更多