使用make编译多个可执行文件

时间:2017-07-26 05:48:47

标签: c++ c++11 makefile

我希望以下makefile能够编译多个可执行文件:

CXX      = clang++
CXXFLAGS = -g -Wall --std=c++11
OBJS     = two_rung.o three_rung.o dumbinterp.o interp.o writeLadderMPO.o
PROG     = two_rung three_rung dumbinterp interp
SOURCES = two_rung.cc three_rung.cc dumbinterp.cc interp.cc writeLadderMPO.cc
HEADS = writeLadderMPO.h
INCLUDES = -I $(HOME)/ITensor
LIBS     = -L $(HOME)/ITensor/lib -litensor -lstdc++ -framework Accelerate

all: $(PROG)

$(PROG): $(OBJS)
    $(CXX) $(INCLUDES) -o $(PROG) $(OBJS) $(LIBS)

%.o: %.cc $(HEADS)
    $(CXX) $(INCLUDES) -c -o $(OBJS) $(SOURCES)

可执行文件由PROG表示。当我尝试制作其中一个可执行文件时,例如interp,我得到了

Computer:folder username$ make interp
clang++ -I /Users/username/ITensor -c -o two_rung.o three_rung.o dumbinterp.o interp.o writeLadderMPO.o two_rung.cc three_rung.cc dumbinterp.cc interp.cc writeLadderMPO.cc

也就是说,当我把它们称为变量时,Make就是抛弃所有文件,这完全合情合理。但我希望它表现得像:

clang++ -I /Users/username/ITensor -c -o interp.o interp.cc

然后

clang++ -I /Users/username/ITensor -o interp interp.o -L $(HOME)/ITensor/lib -litensor -lstdc++ -framework Accelerate

如何让Make做到这一点?谢谢!

2 个答案:

答案 0 :(得分:2)

扩展我的评论。

考虑规则

$(PROG): $(OBJS)
    $(CXX) $(INCLUDES) -o $(PROG) $(OBJS) $(LIBS)

这将由make扩展为

two_rung three_rung dumbinterp interp: two_rung.o three_rung.o dumbinterp.o interp.o writeLadderMPO.o
    clang++ -I $(HOME)/ITensor -o two_rung three_rung dumbinterp interp two_rung.o three_rung.o dumbinterp.o interp.o writeLadderMPO.o -L $(HOME)/ITensor/lib -litensor -lstdc++ -framework Accelerate

我认为不是你的想法。

相反,您需要明确指定每个可执行目标和依赖项:

two_rung: two_rung.o writeLadderMPO.o

three_rung: three_rung.o writeLadderMPO.o

dumbinterp: dumbinterp.o writeLadderMPO.o

interp: interp.o writeLadderMPO.o

正确设置标志变量后,make会正确链接这些变量。

至于将源文件编译成目标文件,你也遇到了问题,其中

%.o: %.cc $(HEADS)
    $(CXX) $(INCLUDES) -c -o $(OBJS) $(SOURCES)

将扩展为

%.o: %.cc writeLadderMPO.h
    clang++ -I $(HOME)/ITensor -c -o two_rung.o three_rung.o dumbinterp.o interp.o writeLadderMPO.o two_rung.cc three_rung.cc dumbinterp.cc interp.cc writeLadderMPO.cc

这不是真的如何工作,您需要分别从每个源文件创建每个目标文件。幸运的是,您仍然可以使用相同的基本规则,但不需要提供创建目标文件的命令:

%.o: %.cc $(HEADS)

几乎就是这样,不需要命令。然而,你还需要这样做。

CXXFLAGS += $(INCLUDES)

在此规则之前。

答案 1 :(得分:1)

我不知道你拥有什么以及它支持什么,但是如果你使用的是GNU make,你可能会使用静态模式规则和自动变量($@:target,{{1} }:先决条件,$^:第一个先决条件)。您还可以使用一些make函数($<wildcard)来自动发现源并推断出目标文件列表。类似的东西:

patsubst

CXX = clang++ CXXFLAGS = -g -Wall --std=c++11 SOURCES = $(wildcard *.cc) OBJS = $(patsubst %.cc,%.o,$(SOURCES)) PROG = two_rung three_rung dumbinterp interp HEADS = writeLadderMPO.h INCLUDES = -I $(HOME)/ITensor LIBS = -L $(HOME)/ITensor/lib -litensor -lstdc++ -framework Accelerate all: $(PROG) $(PROG): %: %.o writeLadderMPO.o $(CXX) -o $@ $^ $(LIBS) %.o: %.cc $(HEADS) $(CXX) $(CXXFLAGS) $(INCLUDES) -c -o $@ $< 规则是静态模式规则。有关完整说明,请参阅GNU make documentation

注意:我从链接配方中删除了$(PROG): %: %.o...,它没用。但是我在编译配方中添加了$(INCLUDES)因为它可能丢失了。