您的位置:首页 > 其它

基础知识(三)makefile文件编写初级篇

2016-10-17 21:21 411 查看
Linux下进行c++开发,需要熟悉相关编译器的编译、链接命令。这边主要以实例讲解,如何在linux中,进行c++程序简单的编译链接运行。

一、单文件编译链接

这里先从最简单的单个文件编译链接为例。在桌面下新建一个名字为:helloworld.cpp  

文件内容:

[c++] view
plain copy

   

    #include <iostream>  

int main(int argc,char *argv[])  

{  

    std::cout << "hello, world" << std::endl;  

    return(0);  

}</iostream>  

直接cd文件所在的目录,然后输入命令:g++ helloworld.cpp         将生成可执行文件,名字为a.out的直接生成可执行文件。如果要指定输出的可执行文件名,那么命令为:g++ helloworld.cpp -o file_name      此时将生成文件名为:file_name.out 的可执行文件 ,即 可选项  -o  用于指定文件生成的名字。在大多数系统中GCC安装是会安装一个名为c++的程序,也就是说此时命令:c++ 与g++是相同的,因此也可以使用命令:c++ helloworld.cpp -o file_name
   编译上面的文件。.h文件不需要指定编译,因为程序编译中,会自动根据#include 进行搜索当前目录、系统目录。

总结:如果只有一个.cpp文件的,且里面包含main函数,那么直接用:g++命令,将直接生成可执行文件。

二、多文件链接编译链接

多文件的编译链接需要包含两个步骤:1、编译,用可选命令 -c 进行编译cpp文件,生成.o文件                 2、链接,根据步骤1生成的.o文件生成可执行文件 。看一下以下实例:

建立头文件名:speak.h   内容如下:

[c++] view
plain copy

    #include <iostream>  

class Speak  

{  

    public:  

        void sayHello(const char *);  

};</iostream>  

建立源文件:speak.cpp ,内容如下:

[c++] view
plain copy

#include "speak.h"  

void Speak::sayHello(const char *str)  

{  

    std::cout << "Hello " << str << "\n";  

}  

主函数文件: hellospeak.cpp 调用speak类

                                                                                                                                                                                                   

[c++] view
plain copy

/* hellospeak.cpp */  

#include "speak.h"  

int main(int argc,char *argv[])  

{  

    Speak speak;  

    speak.sayHello("world");  

    return(0);  

}  

现在有两个.cpp文件,其中一个包含有main函数,那么就不能一步直接生成可执行文件,这时要分为两个步骤才能生成可执行文件。采用-c命令,先进行编译,生成.o文件,然后再生成可执行文件,命令如下:

g++ -c  filename1.cpp  main.cpp

g++ filename1.o main.o -o out_filename

或者采用如下两个命令:

g++ -c  filename1.cpp  

g++ filename1.o main.cpp -o out_filename

三、makefile文件编写

以上2个文件编译链接,用简单的命令就可以实现,然而我们遇到的项目,往往是几十个,甚至几百几千个文件的,那么这个时候通过简单的命令编译链接的方法,就会相当复杂,这个时候我们就要用到make了。

makefile文件编写规则:

target1  : prerequisites1

command1

target2 : prerequisites2

command

……

目标:依赖

执行指令 ...

(1)target目标,我们要生成的文件。

(2) prerequisites依赖,就是要生成那个target所需要的文件或是目标。

(3) command命令 ,相关的生成target所需要的编译链接命令。(g++)

make执行的时候,可以根据文件是否更新,进行编译链接。这个就像vs里面,当我们有一个文件被改动的时候,这个文件及其相关的链接文件将被重新编译链接。如果没有更新,则vs不会对这个文件进行重新编译,这样可以减少每次都重复编译,提高效率。makefile这是一个文件的依赖关系,也就是说,target这一个或多个的目标文件依赖于prerequisites中的文件,其生成规则定义在command中。说白一点就是说,prerequisites中如果有一个以上的文件比target文件要新的话,command所定义的命令就会被执行(command一定要以Tab键开始,否者编译器无法识别command),减少重复编译,提高了其软件工程管理效率。

为了简便起见,我们这边继续以上面的例子为试验,进行学习makefile文件的编写。

新建文件名:makefile ,文件内容:

[c++] view
plain copy

outfile : speak.o helloworld.o  

g++ speak.o helloworld.o -o outfile  

speak.o : speak.cpp speak.h  

g++ -c speak.cpp -o speak.o  

helloworld.o : helloworld.cpp speak.h   

g++ -c helloworld.cpp -o helloworld.o  

 然后在终端直接输出命令:make     即可完成编译链接,同时将生成可执行文件名:outfile     

编写注意事项:

1、makefile文件中,命令的换行要用  \   ,这个与matlab用...换行有点类似 \

否则会出现如下错误:

 


正确的写法应该是这样的:

[c++] view
plain copy

bj=speak.o \   

helloworld.o   

outfile:$(obj)   

g++ $(obj) \   

-o outfile   

helloworld.o speak.o:speak.h  

2、makefile的命令g++前面一定要是tab按键,其它的都不行 即便是空格也会报错

 上面简简单单的两个文件编译,就需要些那么多代码,是不是感觉很不爽,接着我们讲一下如何简化:

1、定义变量,以此简化命令,在以上的makefile文件中我们知道,“speak.o helloworld.o”这一段被重复使用了两次,因此以上的makefile我们也可以这样写:

[c++] view
plain copy

obj=speak.o helloworld.o  

outfile : $(obj)  

g++ $(obj) -o outfile  

speak.o : speak.cpp speak.h  

g++ -c speak.cpp -o speak.o  

helloworld.o : helloworld.cpp speak.h   

g++ -c helloworld.cpp -o helloworld.o  

我们定义了变量名obj,使其值为“speak.o helloworld.o”  ,然后在后面,只要有 “speak.o helloworld.o”,我们就用变量$(obj)替换掉。这样就做了第一步,makefile文件的简化,在终端输入make,依然可以生成同样的可执行文件。

2、使用自动推导,简化命令。只要make看到一个[.o]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么 whatever.cpp,就会默认为whatever.o的依赖文件。并且 g++ -c whatever.cpp也会被自动推导出来,那么以上的命令我们又可以继续简化为:

                                                                                                                                                                                                   

[c++] view
plain copy

   

obj=speak.o helloworld.o  

outfile : $(obj)  

g++ $(obj) -o outfile  

speak.o :  speak.h  

helloworld.o :  speak.h   

也就是说如果目标文件是生成.o文件,那么我们可以不必包含 编译命令,及其相应的源文件,只留下其编译所需要的头文件。

3、因为helloworld.o speak.o两个文件都包含同样的一个头文件,当然你也可以这样写:

[c++] view
plain copy

   

obj=speak.o helloworld.o  

outfile : $(obj)  

g++ $(obj) -o outfile  

helloworld.o speak.o : speak.h  



不过这种写法不推荐,很容易混乱掉。

初级部分先讲到这里,后面我会继续讲比较深入的makefile文件编写。本文地址:http://blog.csdn.net/hjimce/article/details/45567689  
 作者:hjimce     联系qq:1393852684   更多资源请关注我的博客:http://blog.csdn.net/hjimce                
 原创文章,版权所有,转载请保留本行信息

 Cmake学习:http://hahack.com/codes/cmake/

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: