sample make file用于创建具有不同目录的多个exe文件

时间:2013-09-10 07:38:27

标签: c makefile

我有一个名为test的目录,其中make文件应该是。我有子目录sub1,sub2,sub3。

  

测试/生成文件

     

测试/ SUB1

     

测试/ SUB2

     

测试/ SUB3

我想通过编译sub1来创建exe1,通过编译sub2来编译exe2,从sub3编译exe3。

我可以在vpath中添加多个目录吗?或任何其他解决方案

2 个答案:

答案 0 :(得分:0)

你可以在test目录中拥有一个非常简单的makefile,只需进入子目录并在其中调用makefile。子目录具有正常构建的makefile,但只是将可执行文件放在父目录中。

答案 1 :(得分:0)

首先:是的,您可以在vpath中添加多个目录。每个条目用冒号':'

分隔
vpath %.c test/sub1:test/sub2:test/sub3

但是,一旦你在两个目录中拥有相同的文件名(具有不同的内容),你就会遇到麻烦。考虑:

test/Makefile
test/sub1/main.c
test/sub1/foo.c
test/sub1/bar.c
...
test/sub2/main.c
test/sub2/blish.c
test/sub3/blash.c
...
test/sub3/main.c
test/sub3/okEnoughForNow.c

你的makefile包含:

vpath %.c sub1:sub2:sub3

exe1.exe : main.c foo.c bar.c
    gcc -o $@ $^

exe2.exe : main.c blish.c blash.c
    gcc -o $@ $^

exe3.exe : main.c okEnoughForNow.c
    gcc -o $@ $^

结果将是:

gcc -o exe1.exe sub1/main.c sub1/foo.c sub1/bar.c
gcc -o exe2.exe sub1/main.c sub2/blish.c sub2/blash.c
gcc -o exe3.exe sub1/main.c sub3/okEnoughForNow.c

正如您所看到的,所有exe都包含sub1/main.c,因为这是首先发现的main.c;它的路径首先出现在vpath上。

Joachim的方法是一个简单而且非常常见的解决方案。如果子文件夹中的程序完全不相关,我也会选择它:你可以在每个目录中包含一个包含以下内容的makefile:

SRC := $(wildcard *.c)

%.exe : $(SRC)
    gcc -o $@ $^

假设,每个子*中的所有.c文件都应该是程序的一部分,并且子目录中没有子文件夹。否则,您将需要一种不同的方法来扫描您的.c文件,或单独指定它们。

在主makefile中,您可以使用这些makefile为每个子文件夹运行一个新的make实例。这为您提供了一个主要的Makefile:

# Get all subfolders name without trailing slash
PROGS := $(patsubst %/,%,$(wildcard */))

# Each subfolder can be made by calling make in
# that folder. A file prog.exe is created.
.PHONY : $(PROGS)
$(PROGS) :
    $(MAKE) -C $@ prog.exe

# Now every .exe depends on its subfolder, calls
# Make there - see rule above and copies the
# prog.exe from there into the root, with the name
# of the subfolder. (Alternatively you could use
# mv instead of cp)
%.exe : %
    cp $</prog.exe $@

假设您的.exe名称与目录名称相同,并且所有子文件夹都包含程序。

但是,只要子文件夹生成的文件之间存在任何依赖关系,从正在运行的make实例(递归make)调用make就会引起真正的麻烦。

另一种解决方案:

一种不同的方法不使用递归make 就是动态创建规则。在这种情况下,您的主Makefile可能如下所示。 (我再次假设所有子文件夹都包含程序,所有子文件夹都是平的,这些子文件夹中的所有.c文件都是程序的一部分)这样做的好处是你只需要维护一个makefile,并且可以不同程序之间的任何依赖关系。但它的缺点是你无法单独管理不同的程序。

这是完整的makefile:

%.exe :
    gcc -o $@ $^

PROGS := $(patsubst %/,%,$(wildcard */))
$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(wildcard $(P)/*.c)))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))

.PHONY : all
    all : $(addsuffix .exe,$(PROGS)

我们从编译规则开始:通过调用包含所有先决条件作为源文件的gcc来生成任何.exe。

%.exe :
    gcc -o $@ $^

然后,下一步是通过扫描所有子文件夹并剥离尾部斜杠来获取所有“程序”

PROGS := $(patsubst %/,%,$(wildcard */))

下一步是为每个程序创建一个包含所有Sources的变量。请注意,eval函数会扩展,并将所有内容传递给Make,因为它已在Makefile中编写。

$(foreach P,$(PROGS),$(eval SRC_$(P) := $(wildcard $(P)/*.c)))

因此,您的sub1sub2sub3上面的行将成为:

SRC_sub1 := $(wildcard sub1/*.c)
SRC_sub2 := $(wildcard sub2/*.c)
SRC_sub3 := $(wildcard sub3/*.c)

eval函数甚至可用于创建规则:

$(foreach P,$(PROGS),$(eval $(P).exe : $(SRC_$(P))))

所以这将扩展为(假设上例中的文件结构)

sub1.exe : sub1/main.c sub1/foo.c sub1/bar.c
sub2.exe : sub2/main.c sub2/blish.c sub2/blash.c
sub3.exe : sub3/main.c sub3/okEnoughForNow.c

现在我们有三条没有食谱的规则。 Make说“如果你有一个没有配方的规则,并且可以找到匹配的隐式规则,则此规则与从没有配方的规则添加的先决条件一起使用”因此,对于这3个规则,隐式规则为% .exe以上适用。

基本上就是这个伎俩。为方便起见,您可以添加

.PHONY : all
all : $(addsuffix .exe,$(PROGS))

所以make all会做出一切。

<强>扩展:

如果您希望能够单独创建.o文件,还可以添加一个隐式规则,如:

%.o : %.c
    gcc -c -o $@ $<

并使您的程序依赖于.o而不是.c文件:

$(foreach P,$(PROGS),$(eval OBJ_$(P) := $(patsubst %.c,%.o,$(wildcard $(P)/*.c))))
$(foreach P,$(PROGS),$(eval $(P).exe : $(OBJ_$(P))))

然后你将.exe依赖于.o,可以通过在扫描所有来源后将.c更改为.o来找到。通过隐式规则链%。o:%。c make将知道该怎么做。