我是“Make”的新手。关于以下Makefile:
CXX ?= g++
CFLAGS = -Wall -Wconversion -O3 -fPIC
SHVER = 2
all: svm-train svm-predict svm-scale
lib: svm.o
$(CXX) -shared -dynamiclib svm.o -o libsvm.so.$(SHVER)
svm-predict: svm-predict.c svm.o
$(CXX) $(CFLAGS) svm-predict.c svm.o -o svm-predict -lm
svm-train: svm-train.c svm.o
$(CXX) $(CFLAGS) svm-train.c svm.o -o svm-train -lm
svm-scale: svm-scale.c
$(CXX) $(CFLAGS) svm-scale.c -o svm-scale
svm.o: svm.cpp svm.h
$(CXX) $(CFLAGS) -c svm.cpp
clean:
rm -f *~ svm.o svm-train svm-predict svm-scale libsvm.so.$(SHVER)
如何理解这个Makefile的流程?例如,“all”和“lib”在这里做什么?如何分析
$(CXX) -shared -dynamiclib svm.o -o libsvm.so.$(SHVER)
答案 0 :(得分:3)
如果您输入
$ make all
它将构建all :
右侧的所有内容,例如svm-train,svm-predict和svm-scale
$(CXX) -shared -dynamiclib svm.o -o libsvm.so.$(SHVER)
是构建目标lib的具体规则,它将转换为
g++ -shared -dynamiclib svm.o -o libsvm.so.2
取决于变量CXX和SHVER的值。
答案 1 :(得分:1)
目标all
和lib
的行称为依赖项。
目标all
取决于目标svm-train
,svm-predict
和svm-scale
。
目标lib
取决于 lib.o
。
跟随所有这些依赖关系,然后决定需要执行哪些构建命令。
如果您输入 make all ,那么make会尝试确保目标svm-train
,svm-predict
和svm-scale
都是最新的。然后make会递归检查这些目标的依赖关系,直到耗尽所有依赖关系。
答案 2 :(得分:0)
每个make
规则都以相同的方式运作。如果任何依赖项(:
右侧的值)已过期,则会重建它们,然后运行规则的配方。在这种情况下,all
目标没有配方,因此make
只检查依赖项(svm-train
,svm-predict
和svm-scale
)并构建如果他们已经过时了。
lib
目标类似 - 如果svm.o
已过期,则构建$(CXX) -shared -dynamiclib svm.o -o libsvm.so.$(SHVER)
,然后是食谱
$(CXX)
正在运行。由于这是您要求分析的行,$(SHVER)
和make
是$(CXX)
变量,它们将按照之前的定义填充。在您的情况下,g++
为$(SHVER)
,2
为g++ -shared -dynamiclib svm.o -o libsvm.so.2
。将要运行的命令是:
$(CXX)
至少假设您没有在其他地方定义?=
- 用于进行该分配的make
运算符仅在尚未定义变量时才有效。
在命令行中键入make -d
时,应该在执行时看到标准输出上的每个命令。您可以使用make -n
或{{1}}获取更多调试/日志记录信息。
GNU make manual编写得非常好,是恕我直言网上最好的编程资源之一。
答案 3 :(得分:0)
all
触发器解决了所有依赖关系(访问提到的触发器):svm-train
svm-predict
svm-scale
现在,每个触发器都像脚本一样运行,意思是:编译svm.o
,使用CXX
中使用标志-shared
-dynamiclib
声明的编译器,输出名为libsvm.so.$(SHVER)
的文件(在您的情况下,$(SHVER)
将替换为2
)