CC=g++
CFLAGS=-c -Wall
LDFLAGS=
SOURCES=main.cpp hello.cpp factorial.cpp
OBJECTS=$(SOURCES:.cpp=.o)
EXECUTABLE=hello
all: $(SOURCES) $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(LDFLAGS) $(OBJECTS) -o $@
.cpp.o:
$(CC) $(CFLAGS) $< -o $@
$@和$
#1楼
$@和$
例如:
hello.o: hello.c hello.h
gcc -c $< -o $@
在这里, hello.o是输出文件。 这就是$@扩展到的内容。 第一个依赖项是hello.c 。 这就是$
-c标志生成.o文件; 有关详细说明,请参见man gcc 。 -o指定要创建的输出文件。
另外,您可以查看GNU make手册 。 这将使制作文件和调试它们变得更加容易。
如果运行此命令,它将输出makefile数据库:
make -p
#2楼
$@是要生成的文件的名称, $
例如,考虑以下声明:
all: library.cpp main.cpp
在这种情况下:
$@对all求值
$
$^评估为library.cpp main.cpp
#3楼
$@和$
哪里:
$@是目标的文件名。
$
#4楼
从使用GNU Make,第3版管理项目 (受GNU Free Documentation License许可 ):
匹配规则后,由make设置自动变量 。 它们提供对目标和先决条件列表中元素的访问,因此您不必显式指定任何文件名。 它们对于避免代码重复非常有用,但是在定义更通用的模式规则时至关重要。
有七个“核心”自动变量:
$@ :代表目标的文件名。
$% :归档成员规范的文件名元素。
$< :第一个必备条件的文件名。
$? :比目标更新的所有先决条件的名称,用空格分隔。
$^ :所有必备组件的文件名,以空格分隔。 此列表已删除重复的文件名,因为对于大多数用途(例如编译,复制等),不需要重复的文件名。
$+ :类似于$^ ,这是用空格分隔的所有必备组件的名称,除了$+包含重复项。 该变量是为特定情况创建的,例如链接器的参数,其中重复的值具有含义。
$* :目标文件名的主干。 词干通常是没有后缀的文件名。 不建议在模式规则之外使用它。
此外,上述每个变量都有两个变体,以便与其他品牌兼容。 一个变体仅返回值的目录部分。 这是通过在符号$(@D) , $(
#5楼
如果main.cpp , hello.cpp , factorial.cpp任何一个更改,Makefile都会生成hello可执行文件。 实现该规范的最小可能的Makefile可能是:
hello: main.cpp hello.cpp factorial.cpp
g++ -o hello main.cpp hello.cpp factorial.cpp
亲:很容易读
缺点:维护的噩梦,C ++依赖项的重复
缺点:效率问题,即使只更改了一个,我们也重新编译了所有C ++
为了改进上述内容,我们仅编译那些已编辑的C ++文件。 然后,我们仅将结果对象文件链接在一起。
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
main.o: main.cpp
g++ -c main.cpp
hello.o: hello.cpp
g++ -c hello.cpp
factorial.o: factorial.cpp
g++ -c factorial.cpp
专家:修复效率问题
缺点:新的维护噩梦,目标文件规则可能出现错字
为了对此进行改进,我们可以用一个.cpp.o规则替换所有目标文件规则:
OBJECTS=main.o hello.o factorial.o
hello: $(OBJECTS)
g++ -o hello $(OBJECTS)
.cpp.o:
g++ -c $< -o $@
优点:返回简短的makefile,有点容易阅读
在这里, .cpp.o规则定义如何建立anyfile.o从anyfile.cpp 。
$
$@匹配目标,在这种情况下为anyfile.o 。
Makefile中存在的其他更改是:
使将编译器从g ++更改为任何C ++编译器变得更加容易。
使更改编译器选项更加容易。
使更改链接器选项更加容易。
使更改C ++源文件和输出变得更加容易。
添加了默认规则“全部”,该规则可以快速检查以确保在尝试构建应用程序之前所有源文件都存在。