GNU Make简明教程

GNU Make简明教程

学写第一个makefile

使用make可以从源文件自动构建可执行程序。
让我们以一个简单的例子来学习make。
编辑下面文件

// hello.c
#include <stdio.h>

int main() {
    printf("Hello, world!\n");
    return 0;
}

创建名为 “makefile” 的文件,注意没有任何的拓展名。
其中包含建立可执行文件的规则,并保存在源文件的同一个目录中。命令如下:

touch makeflie

注意,makefile文件中使用Tab缩进命令(而不是空格)。makefile文件内容如下:

all: hello

hello: hello.o
    gcc -o hello.exe hello.o

hello.o: hello.c
    gcc -c hello.c

clean:
    rm hello.o hello.exe

运行“make”如下:

> make
输出
gcc -c hello.c     
gcc -o hello.exe hello.o

运行没有参数的make,将会从all处开始。
一个makefile是一组规则的集合组成。
一个规则由3部分组成:一个目标,一个先决条件列表和一个命令,如下:

target: pre-req-1 pre-req-2 ...
    command

目标和条件之间用冒号分隔(:)。
在命令前面使用的是Tab缩进命令(而不是空格)。
它开始通过先决条件查找对应文件。

> make
输出
make: Nothing to be done for `all'.

注意

  • 如果命令没有使用Tab缩进命令, 将会得到错误信息 “makefile:4: * missing separator. Stop.”

  • 如果在当前目录下没有makefile,你得到一个错误信息
    “make: * No targets specified and no makefile found. Stop.”

  • makefile可以命名为”makefile”, “Makefile” 或者 “GNUMakefile”, 注意没有无文件扩展名。

Makefile进阶

假目标(或人工目标)

一个目标,如果它并不代表一个文件,则称为假目标。例如,在上面的例子中的clean,只是一个命令的标签。如果目标是一个文件,它将检查其所需的预条件。标准的假目标有:all, clean, install。

变量

使用变量才能处理复杂的问题,GNU Make 的变量将会简化makefile的编写。
一个变量开始于一个$,并被封闭在括号内( (…) or {…})。
单字符变量不需要括号。
例如,

$(CC), $(CC_FLAGS), $@, $^.

自动变量

自动变量通过规则匹配后被设置。这包括:

$@:目标文件名。
$*:目标文件名没有文件扩展名。
$<:第一个先决条件文件名。
$^:所有先决条件的文件名,用空格分隔,丢弃重复。
$+:类似于$,但包括重复。
$?:所有比目标较新的先决条件的名称,用空格隔开。

例如,我们可以把早期的Makefile改写为:

all: hello.exe

# $@ matches the target; $< matches the first dependent
hello.exe: hello.o
    gcc -o $@ $<

hello.o: hello.c
    gcc -c $<

clean:
    rm hello.o hello.exe

虚拟路径

你可以使用VPATH(大写)到指定的目录中搜索相关的依赖项和标文件。例如:

# Search for dependencies and targets from "src" and "include" directories
# The directories are separated by space
VPATH = src include

使用vpath(小写)指定更加精确的文件类型及其搜索路径。

# Search for .c files in "src" directory; .h files in "include" directory
# The pattern matching character '%' matches filename without the extension
vpath %.c src
vpath %.h include

模式规则

模式规则,它使用模式匹配的字符“%”作为文件名,如果没有明确的规则可以应用于创建一个目标。例如,

#适用于创建.o目标文件
#“%”匹配文件名。
# $< 是第一个先决条件
# $(COMPILE.c) 由编译器名称和编译器选项组成
# $(OUTPUT_OPTIONS) 是-o $@
# $@:生成文件名。
%.o: %.c
    $(COMPILE.c) $(OUTPUT_OPTION) $<

#用于从.o object file创建可执行的(无扩展名)
# $^ 匹配所有先决条件(无重复)。
%: %.o
$(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -o $@

一个makefile样例

此示例Makefile是来自Eclipse的”C/C++ Development Guide -Makefile”。

# A sample Makefile
# This Makefile demonstrates and explains 
# Make Macros, Macro Expansions,
# Rules, Targets, Dependencies, Commands, Goals
# Artificial Targets, Pattern Rule, Dependency Rule.

# Comments start with a # and go to the end of the line.

# Here is a simple Make Macro.
LINK_TARGET = test_me.exe

# Here is a Make Macro that uses the backslash to extend to multiple lines.
OBJS =  \
Test1.o \
Test2.o \
 Main.o

# Here is a Make Macro defined by two Macro Expansions.
# A Macro Expansion may be treated as a textual replacement of the Make Macro.
# Macro Expansions are introduced with $ and enclosed in (parentheses).
REBUILDABLES = $(OBJS) $(LINK_TARGET)

# Here is a simple Rule (used for "cleaning" your build environment).
# It has a Target named "clean" (left of the colon ":" on the first line),
# no Dependencies (right of the colon),
# and two Commands (indented by tabs on the lines that follow).
# The space before the colon is not required but added here for clarity.
clean : 
  rm -f $(REBUILDABLES)
  echo Clean done

# There are two standard Targets your Makefile should probably have:
# "all" and "clean", because they are often command-line Goals.
# Also, these are both typically Artificial Targets, because they don't typically
# correspond to real files named "all" or "clean".  

# The rule for "all" is used to incrementally build your system.
# It does this by expressing a dependency on the results of that system,
# which in turn have their own rules and dependencies.
all : $(LINK_TARGET)
  echo All done

# There is no required order to the list of rules as they appear in the Makefile.
# Make will build its own dependency tree and only execute each rule only once
# its dependencies' rules have been executed successfully.

# Here is a Rule that uses some built-in Make Macros in its command:
# $@ expands to the rule's target, in this case "test_me.exe".
# $^ expands to the rule's dependencies, in this case the three files
# main.o, test1.o, and  test2.o.
$(LINK_TARGET) : $(OBJS)
  g++ -g -o $@ $^

# Here is a Pattern Rule, often used for compile-line.
# It says how to create a file with a .o suffix, given a file with a .cpp suffix.
# The rule's command uses some built-in Make Macros:
# $@ for the pattern-matched target
# $< for the pattern-matched dependency
%.o : %.cpp
  g++ -g -o $@ -c $<

# These are Dependency Rules, which are rules without any command.
# Dependency Rules indicate that if any file to the right of the colon changes,
# the target to the left of the colon should be considered out-of-date.
# The commands for making an out-of-date target up-to-date may be found elsewhere
# (in this case, by the Pattern Rule above).
# Dependency Rules are often used to capture header file dependencies.
Main.o : Main.h Test1.h Test2.h
Test1.o : Test1.h Test2.h
Test2.o : Test2.h

# Alternatively to manually capturing dependencies, several automated
# dependency generators exist.  Here is one possibility (commented out)...
# %.dep : %.cpp
#   g++ -M $(FLAGS) $< > $@
# include $(OBJS:.o=.dep)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值