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

Compiling multiple executables with make

本文关键字:可执行文件 编译 make 使用      更新时间:2023-10-16

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

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 做到这一点?谢谢!

扩展我的评论。

考虑规则

$(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)

在此规则之前。

我不知道是什么造就了你,它支持什么,但是如果你使用的是GNU make,你可能会使用静态模式规则和自动变量($@:目标,$^:先决条件,$<:第一个先决条件(。你也可以使用一些make函数(wildcardpatsubst(来自动发现源并推导出目标文件的列表。像这样:

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 $@ $<

$(PROG): %: %.o...规则是静态模式规则。有关完整的描述,请参阅 GNU make 文档。

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