您的位置:首页 > 运维架构 > Linux

Unix/Linux C++应用开发-make工具的使用

2011-10-13 09:53 721 查看
 
    经常使用Windows平台IDE做开发的人员,可能对于makefile多少有些陌生。因为Windows下的IDE通常都将这一步封装了,只提供编译按钮,不需要开发人员人为地参与这个过程。Unix/Linux下软件开发工程项目需要开发者自己编写makefile文件。从某种程度上来讲,熟练编写makefile文件也说明了开发者具备完成大型工程的一个方面地能力。

    makefile关系到整个工程的编译规则。通常一个大型的软件工程项目拥有的源文件往往不计其数。按照工程化的思想,这些不计其数的源文件按照功能、模块分别需要放在规划好的不同的目录中。而makefile则定义了一系列的规则来指定源文件的编译顺序,以及哪些文件需要重新编译更新,甚至一些比较复杂的编译操作。通常编写好makefile文件后,就可以执行make命令进行自动化编译,从而提高开发效率。迄今为止,make工具是应用最为广泛,也是使用最多的工具。下面主要介绍makefile编写的基本规则和命令使用。更多的makefile的使用会在后续各个章节加以讲述。

1.makefile基本规范

    一个典型的makefile文件包含目标文件、编译连接过程以及删除编译产生的目标文件和依赖文件。其基本的构成形式如下所示。

[目标文件…]:先决条件…

         command

     …

     …

clean:

         rm …

    其中,目标文件可以为生成的最终可执行程序、中间工程文件以及具体执行动作等。先决条件就是生成目标文件所需要依赖的文件。这些文件生成的规则在下面的command中实现。通常,只要先决条件中有一个文件比目标文件新的话,command命令就会被执行。这就是makefile的基本规则。为了能让初学者有一个清晰的认识,这里一个完整的实际例子如下所示。

testMain : a.o b.o testMain.o                        //目标文件为程序名testMain,它依赖a.o b.o testMain.o三个中间文件

         g++ a.o b.o testMain.o -o testMain    //具体执行程序编译的命令

testMain.o :                                                      //目标文件为testMain.o中间文件命令执行

         g++ -c testMain.cpp                              //具体程序编译成中间文件testMain.o的命令执行

a.o : a.h a.cpp                                                 //目标文件为a.o中间文件命令执行,依赖于a.h a.cpp文件

         g++ -c a.cpp                                           //具体程序编译成中间文件a.o的命令执行

b.o : b.h b.cpp                                                 //目标文件为b.o中间文件命令执行,依赖于b.h b.cpp文件

         g++ -c b.cpp                                           //具体程序编译成中间文件b.o的命令执行

 

clean :                                                               //清理程序目录动作

         rm -f testMain core *.o                         //具体程序中清除文件的操作命令

    如上例子中,整个程序文件包含2个头文件,3个C++源文件。上述例子可以保存为makefile、Makefile或者任意可以命名的文件。用户可以通过make命令加-f选项来指定执行哪个makefile文件。

    根据上述实例配置的makefile在当前目录执行后的过程如下所示。

[developer @localhost ~]$ make

g++ -c a.cpp

g++ -c b.cpp

g++ -c testMain.cpp

g++ a.o b.o testMain.o -o testMain

[developer @localhost ~]$ make clean

rm -f testMain core *.o

[developer @localhost ~]$ make -f makefile

g++ -c a.cpp

g++ -c b.cpp

g++ -c testMain.cpp

g++ a.o b.o testMain.o -o testMain

    上述演示通过make命令执行实例make文件,默认情况下执行的文件名称为makefile,编译代码中间工程文件,最终完成可执行程序编译。也可以执行make的clean命令清除生成的工程文件和可执行程序文件,通过make的-f选项执行指定的名为“makefile”编译依赖关系定义文件,最终生成可执行程序。

    上述实例最终产生的一个目标文件为可执行程序testMain。它的生成依赖于a.o、b.o、testMain.o三个中间工程文件。随后下一行为其生成可执行程序的具体命令。

    这里需要注意执行具体命令的行,其开头一定要以Tab键开作为空格,这是makefile的规定。下面依次是目标文件、依赖文件和具体的执行命令。最后有一个clean,这里的clean并不是像前面的作为目标文件出现的,它是一个动作。当前shell下执行make clean命令时,执行其下面的具体清除目标文件的命令。

2.makefile中使用变量

    通常工程实践中,makefile文件会大量的使用变量定义。这也可能造成初学者学习makefile文件困难之处。大型的工程项目中,源文件、目标中间文件、库等应用非常的多。为了便于维护makefile文件,会使用变量来替换makefile中可能会发生变化的地方。例如,生成目标文件所依赖的中间工程文件就可以采用变量来灵活替换。下面通过一个具体的实例给初学者对makefile应用有一个初步的认识。该makefile编辑如下所示。

OBJECTS=a.o b.o testMain.o                      //定义变量为OBJECTS,表示a.o b.o testMain.o三个中间工程文件

CC=g++                                                           //定义变量为CC,表示使用g++编译器

 

testMain: $(OBJECTS)                                  //目标文件为可执行程序testMain,依赖于变量OBJECTS的生成

         $(CC) $(OBJECTS) -o testMain         //生成可执行程序的命令,可以使用具体变量替换查看

testMain.o:                                                       //目标文件为中间文件testMain.o

         $(CC) -c testMain.cpp                          //生成中间文件testMain.o的具体命令

a.o:a.h a.cpp                                                   //目标文件为中间文件a.o

         $(CC) -c a.cpp                                       //生成中间文件a.o的具体命令

b.o:b.h b.cpp                                                   //目标文件为中间文件b.o

         $(CC) -c b.cpp                                       //生成中间文件b.o的具体命令

clean:                                                                //清理程序目录动作

         rm -f testMain core $(OBJECTS)       //具体程序中清除文件的操作命令

    从之前的例子中可以看出,中间生成的工程文件在makefile中被使用了两次。也就是说,一旦有新的object文件加入时,就只需要修改两处的先决条件。当前的makefile文件比较简单,所以这里添加显得不是很复杂。但是,一旦makefile文件比较复杂后,就容易造成修改地方的遗漏。那么,这种变量定义使用的方式使得删减或增加object文件只需要一处修改即可,这样makefile文件维护更加方便了。变量定义类似于C语言中宏的定义使用,变量基本定义形式很简单,取一个变量名之后,makefile文件中这样定义。

        OBJECTS=example1.o example2.o …

    变量内容可以换行,其后加“\”符号即可。另外,编译器g++也可以采用变量来定义。在单个平台下开发通常只使用单一的C++编译器,但是Unix/Linux系统下C++编译器有多种。不同平台之间的程序移植带来的C++编译器置换,为makefile维护带来麻烦。大型的软件项目中可以将编译器的变量放在单一的文件中,根据检测系统的不同平台替换不同的C++编译器,为软件在不同平台的移植带来极大的方便。

3.一种更为简便的方式

    makefile文件还有一种更为简便的定义方式,那就是让make程序自动推导目标文件及依赖文件之后的命令。上例修改之后如下所示。

OBJECTS=a.o b.o testMain.o                      //定义变量为OBJECTS,表示a.o b.o testMain.o三个中间工程文件

CC=g++                                                            //定义变量为CC,表示使用g++编译器

 

testMain: $(OBJECTS)                                  //目标文件为可执行程序testMain,依赖于变量OBJECTS的生成

         $(CC) $(OBJECTS) -o testMain         //生成可执行程序的命令,可以使用具体变量替换查看

a.o:a.h                                                             //目标文件为中间工程文件a.o,其生成依赖于头文件a.h

b.o:b.h                                                             //目标文件为中间工程文件b.o,其生成依赖于头文件b.h

 

clean:                                                                //清理程序目录动作

         rm -f testMain core $(OBJECTS)       //具体程序中清除文件的操作命令

   

    如上所示,目标文件为中间工程文件下具体执行命令就不需要了。只要列出中间工程文件文件以及其依赖的头文件,make可以自动的推导出需要执行的编译的命令。可见make工具的功能是相当的强大。

    make工具基本使用情况大致如上所述。这里只简单介绍基本makefile文件的组成及其使用情况,更多的实际项目使用会在后面的项目实践中详细讲述。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: