8

我正在尝试编写一个makefile,它使用宏一次从多个文件创建多个可执行文件。我尝试搜索以前回答的问题,但是因为我对 C 编程以及使用 gcc 还很陌生,所以我无法找到我的问题的答案。

这是我到目前为止所拥有的:

CC=gcc
CFLAGS=-I.
OBJ = ex1.c ex3.c
EXECUTABLE = ex1 ex3

$(EXECUTABLE): $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

clean:
    rm -f $(EXECUTABLE)

我想要这条线

$(EXECUTABLE): $(OBJ)

分别从文件 ex1.c ex3.c 创建可执行文件 ex1 和 ex3。

4

4 回答 4

18

对于这种特殊情况,每个可执行文件都有一个带有.c扩展名的源文件,您只需要一行 Makefile:

all: ex1 ex3

then的内置默认规则make已经生效:

$ make
cc -O2 -pipe   ex1.c  -o ex1
cc -O2 -pipe   ex3.c  -o ex3

在幕后,make正在使用POSIXly 强制的内置单后缀规则

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

根据您的喜好更改命令make CC=gcc CFLAGS=-O2 LDFLAGS=-s和类似命令。

今日琐事:事实上,如果你愿意在调用时命名目标make你可以使用一个空的,甚至可以在没有任何 Makefile 的情况下运行:

$ make -f /dev/null CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c  -o ex1
gcc -O2 -s ex3.c  -o ex3
$ rm -f Makefile ex1 ex3
$ make CC=gcc CFLAGS=-O2 LDFLAGS=-s ex1 ex3
gcc -O2 -s ex1.c  -o ex1
gcc -O2 -s ex3.c  -o ex3

创造魔法!

根据经验,不要重新发明轮子(或规则),使用已经存在的规则。它大大简化了您的生活。这使得小而性感的 makefile 给女士们留下了深刻的印象:-)

于 2013-05-25T16:43:24.043 回答
3

一些建议(假设您使用GNU make,而不是其他)

首先,运行一次make -p,您将了解内置规则make所知道的内容。特别寻找COMPILE.cLINK.c

那我建议

 CFLAGS= -g -Wall -I.

(因为你真的想要-g调试,并-Wall得到大多数警告)

你可能不需要

$(EXECUTABLE): $(OBJ)
    gcc -o $@ $^ $(CFLAGS)

但是,我建议在大多数其他规则之前添加

.PHONY: all clean

all: $(EXECUTABLES)

实际上,我会将您的Makefile(对于GNU make!)编码如下

# file Makefile
CC= gcc
RM= rm -vf
CFLAGS= -Wall -g
CPPFLAGS= -I.
SRCFILES= ex1.c ex2.c ## or perhaps $(wildcard *.c)
OBJFILES= $(patsubst %.c, %.o, $(SRCFILES))
PROGFILES= $(patsubst %.c, %, $(SRCFILES))

.PHONY: all clean

all: $(PROGFILES)
clean:
     $(RM) $(OBJFILES) $(PROGFILES) *~
## eof Makefile

请记住,这tab是 -s 中的一个重要字符(规则Makefile的操作部分)。在这个答案中,至少以四个空格开头的行应该真正以一个字符开头。tab

调试完所有内容后,请考虑运行make clean以清理所有内容,然后make -j CFLAGS=-O2 all通过优化并行编译所有内容。

最后,我推荐使用remake并运行remake -x来调试复杂的Makefile-s

当然,我假设您的目录只有单文件程序。

顺便说一句,还有其他构建自动化工具。也许您可以考虑使用omakeninja。对于构建大型程序(数百万行源代码行),还要考虑automakeccachecmakeicecream。在某些情况下,考虑使用GPPGNU bisonSWIG等生成一些 C 代码……或使用您自己的PythonGuile脚本(或 C 元程序)。另见本报告草稿

不要忘记对源文件使用git 之类的版本控制系统。现在也是学习这种工具的时候了。

于 2013-05-25T16:36:41.920 回答
1

以下答案包括多个可执行文件,例如initial、process1、process2、...、process4。

LOCAL_INCLUDE=./

all: clean process_first process_second init

process_first:
    gcc -g -o process1  -I$(LOCAL_INCLUDE) process1.c  -lzmq  -L. -L./.
    gcc -g -o process2  -I$(LOCAL_INCLUDE) process2.c  -lzmq  -L. -L./.

process_second:
    gcc -g -o process3  -I$(LOCAL_INCLUDE) process3.c  -lzmq  -L. -L./.
    gcc -g -o process4  -I$(LOCAL_INCLUDE) process4.c  -lzmq  -L. -L./.

init:
    gcc -g -o initiate -I$(LOCAL_INCLUDE) initiate.c -lzmq -lconfig -lpthread -L. -L./. -ldl -lrt

clean:
    rm -rf init_manager.o init_manager
    rm -rf process1 process2 process3 process4

注意:在重新制作它们之前清理并触摸所有可执行文件是一个很好的做法。

于 2016-08-01T10:35:02.033 回答
0

你很接近,但你需要一个模式规则:

$(EXECUTABLE): % : %.c

然后是一个默认规则,使其同时构建:

all: $(EXECUTABLE)
于 2013-05-25T16:34:00.353 回答