我希望以下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做到这一点?谢谢!
答案 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)
因为它可能丢失了。