Makefile中的符号说明





1   GNU make
在大型的开发项目中,通常有几十到上百个的源文件,如果每次均手工键入 gcc命令进行编译的话,则会
非常不方便。因此,人们通常利用 make工具来自动完成编译工作。这些工作包括:如果仅修改了某几个
源文件,则只重新编译这几个源文件;如果某个头文件被修改了,则重新编译所有包含该头文件的源文件。
利用这种自动编译可大大简化开发工作,避免不必要的重新编译。
实际上,make工具通过一个称为 makefile 的文件来完成并自动维护编译工作。makefile需要按照某种
语法进行编写,其中说明了如何编译各个源文件并连接生成可执行文件,并定义了源文件之间的依赖关系。
当修改了其中某个源文件时,如果其他源文件依赖于该文件,则也要重新编译所有依赖该文件的源文件。
makefile
文件是许多编译器,包括 Windows NT下的编译器维护编译信息的常用方法,只是在集成开发环
境中,用户通过友好的界面修改 makefile文件而已。
默认情况下,GNU make工具在当前工作目录中按如下顺序搜索 makefile
* GNUmakefile
* makefile
* Makefile
UNIX系统中,习惯使用 Makefile 作为 makfile 文件。如果要使用其他文件作为 makefile,则可利用类
似下面的 make命令选项指定 makefile 文件:
$ make -f Makefile.debug

2   makefile基本结构
makefile中一般包含如下内容:
*
需要由 make工具创建的项目,通常是目标文件和可执行文件。通常使用目标(target一词来表示
要创建的项目。
*
要创建的项目依赖于哪些文件。
*
创建每个项目时需要运行的命令。
例如,假设你现在有一个 C++源文件 test.C,该源文件包含有自定义的头文件 test.h,则目标文件 test.o
明确依赖于两个源文件:test.C test.h。另外,你可能只希望利用 g++命令来生成 test.o 目标文件。

这时,就可以利用如下的 makefile来定义 test.o 的创建规则:
# This makefile just is a example.
# The following lines indicate how test.o depends
# test.C and test.h, and how to create test.o
test.o: test.C test.h
     g++ -c -g test.C
从上面的例子注意到,第一个字符为 #的行为注释行。第一个非注释行指定 test.o 为目标,并且依赖于
test.C
test.h 文件。随后的行指定了如何从目标所依赖的文件建立目标。

test.C test.h 文件在编译之后又被修改,则 make 工具可自动重新编译 test.o,如果在前后两次
编译之间,test.C test.h 均没有被修改,而且 test.o 还存在的话,就没有必要重新编译。这种依赖
关系在多源文件的程序编译中尤其重要。通过这种依赖关系的定义,make工具可避免许多不必要的编译工
作。当然,利用 Shell脚本也可以达到自动编译的效果,但是,Shell 脚本将全部编译任何源文件,包括
哪些不必要重新编译的源文件,而 make工具则可根据目标上一次编译的时间和目标所依赖的源文件的更新
时间而自动判断应当编译哪个源文件。
一个 makefile文件中可定义多个目标,利用 make target 命令可指定要编译的目标,如果不指定目标,
则使用第一个目标。通常,makefile中定义有 clean 目标,可用来清除编译过程中的中间文件,例如:
clean:
     rm -f *.o
运行 make clean时,将执行 rm -f *.o 命令,最终删除所有编译过程中产生的所有中间文件。

3   makefile变量
GNU
make工具除提供有建立目标的基本功能之外,还有许多便于表达依赖性关系以及建立目标的命令的特
色。其中之一就是变量或宏的定义能力。如果你要以相同的编译选项同时编译十几个 C源文件,而为每个目
标的编译指定冗长的编译选项的话,将是非常乏味的。但利用简单的变量定义,可避免这种乏味的工作:
# Define macros for name of compiler
CC = gcc
# Define a macr o for the CC flags
CCFLAGS = -D_DEBUG -g -m486
# A rule for building a object file
test.o: test.c test.h
     $(CC) -c $(CCFLAGS) test.c
在上面的例子中,CC CCFLAGS 就是 make 的变量。GNU make通常称之为变量,而其他 UNIX make
工具称之为宏,实际是同一个东西。在 makefile 中引用变量的值时,只需变量名之前添加 $符号,如

上面的 $(CC) $(CCFLAGS)

4   GNU make的主要预定义变量
GNU make
有许多预定义的变量,这些变量具有特殊的含义,可在规则中使用。表 1-5给出了一些主要的
预定义变量,除这些变量外,GNU make还将所有的环境变量作为自己的预定义变量。
                        
1-5   GNU make的主要预定义变量
预定义变量                      含义
$*              
不包含扩展名的目标文件名称。
$+              
所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
$<              
第一个依赖文件的名称。
$?              
所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
$@              
目标的完整名称。
$^              
所有的依赖文件,以空格分开,不包含重复的依赖文件。
$%              
如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称
                
mytarget.so(image.o),则 $@ mytarget.so,而 $% image.o
AR              
归档维护程序的名称,默认值为 ar
ARFLAGS         
归档维护程序的选项。
AS              
汇编程序的名称,默认值为 as
ASFLAGS         
汇编程序的选项。
CC               C
编译器的名称,默认值为 cc
CCFLAGS          C
编译器的选项。
CPP              C
预编译器的名称,默认值为 $(CC) -E
CPPFLAGS         C
预编译的选项。
CXX              C++
编译器的名称,默认值为 g++
CXXFLAGS         C++
编译器的选项。
FC               FORTRAN
编译器的名称,默认值为 f77
FFLAGS           FORTRAN
编译器的选项。

5  隐含规则
GNU make
包含有一些内置的或隐含的规则,这些规则定义了如何从不同的依赖文件建立特定类型的目标。
GNU make
支持两种类型的隐含规则:
*
后缀规则(Suffix Rule)。后缀规则是定义隐含规则的老风格方法。后缀规则定义了将一个具有某个
后缀的文件(例如,.c文件)转换为具有另外一种后缀的文件(例如,.o 文件)的方法。每个后缀规
则以两个成对出现的后缀名定义,例如,将 .c文件转换为 .o 文件的后缀规则可定义为:
.c.o:
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<
*
模式规则(pattern rules)。这种规则更加通用,因为可以利用模式规则定义更加复杂的依赖性规则。
模式规则看起来非常类似于正则规则,但在目标名称的前面多了一个 %号,同时可用来定义目标和依赖
文件之间的关系,例如下面的模式规则定义了如何将任意一个 X.c文件转换为 X.o 文件:
%.c:%.o
$(CC) $(CCFLAGS) $(CPPFLAGS) -c -o $@ $<

6   makefile范例

。。。

7  运行 make
我们知道,直接在 make命令的后面键入目标名可建立指定的目标,如果直接运行 make,则建立第一个
目标。我们还知道可以用 make -f mymakefile这样的命令指定 make 使用特定的 makefile,而不是
默认的 GNUmakefilemakefile Makefile。但 GNU make 命令还有一些其他选项,表 1-6 给出了
这些选项。
                        
1-6   GNU make命令的常用命令行选项
命令行选项              含义
-C DIR              
在读取 makefile之前改变到指定的目录 DIR
-f FILE             
以指定的 FILE文件作为 makefile
-h                  
显示所有的 make选项。
-i                  
忽略所有的命令执行错误。
-I DIR              
当包含其他 makefile文件时,可利用该选项指定搜索目录。
-n                  
只打印要执行的命令,但不执行这些命令。
-p                  
显示 make变量数据库和隐含规则。
-s                  
在执行命令时不显示命令。
-w                  
在处理 makefile之前和之后,显示工作目录。
-W FILE             
假定文件 FILE已经被修改。

8如何在Makefile中定义宏进行条件编译-- “-D”

在源代码里面如果这样是定义的:
#ifdef MACRONAME
//
可选代码
   
#endif          
   
那在makefile里面

gcc   -DMACRONAME=MACRODEF  
或者  
gcc   -DMACRONAME       
这样就定义了预处理宏,编译的时候可选代码就会被编译进去了。

举例说明:

-Dmacro=string,等价于在头文件中定义:#define   macro   string
-DTRUE=true
,等价于在头文件中定义:#define   TRUE   true  
-Dmacro
,等价于在头文件中定义:#define   macro   1,实际上也达到了定义:#define   macro的目的。

-DLINUX
,等价于:#define   LINUX   1(与#define   LINUX作用类似)。  
--define-macro   macro=string
-Dmacro=string作用相同。


9.其他符号

= 是最基本的赋值
  := 是覆盖之前的值
  ?= 是如果没有被赋值过就赋予等号后面的值
  += 是添加等号后面的值
  1、“=”
  make会将整个makefile展开后,再决定变量的值。也就是说,变量的值将会是整个makefile中最后被指定的值。看例子:
  x = foo
y = $(x) bar
x = xyz
  在上例中,y的值将会是 xyz bar ,而不是 foo bar 。
  2、“:=”
  “:=”表示变量的值决定于它在makefile中的位置,而不是整个makefile展开后的最终值。
  x := foo
y := $(x) bar
x := xyz
  在上例中,y的值将会是 foo bar ,而不是 xyz bar 了。


 

转自:http://hi.baidu.com/xin_jing/blog/item/91506331f32e0019eac4af74.html


智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告