makefile文件编写

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

一、单文件编译链接

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

文件内容:

  1.    
  2.     #include <iostream>  
  3. int main(int argc,char *argv[])  
  4. {  
  5.     std::cout << "hello, world" << std::endl;  
  6.     return(0);  
  7. }</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   内容如下:

  1.     #include <iostream>  
  2. class Speak  
  3. {  
  4.     public:  
  5.         void sayHello(const char *);  
  6. };</iostream>  

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

  1. #include "speak.h"  
  2. void Speak::sayHello(const char *str)  
  3. {  
  4.     std::cout << "Hello " << str << "\n";  
  5. }  

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

  1. /* hellospeak.cpp */  
  2. #include "speak.h"  
  3. int main(int argc,char *argv[])  
  4. {  
  5.     Speak speak;  
  6.     speak.sayHello("world");  
  7.     return(0);  
  8. }  

现在有两个.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 ,文件内容:

  1. outfile : speak.o helloworld.o  
  2. g++ speak.o helloworld.o -o outfile  
  3. speak.o : speak.cpp speak.h  
  4. g++ -c speak.cpp -o speak.o  
  5. helloworld.o : helloworld.cpp speak.h   
  6. g++ -c helloworld.cpp -o helloworld.o  

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

编写注意事项:

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

否则会出现如下错误:

 

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

  1. bj=speak.o \   
  2. helloworld.o   
  3. outfile:$(obj)   
  4. g++ $(obj) \   
  5. -o outfile   
  6. helloworld.o speak.o:speak.h  

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

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

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

  1. obj=speak.o helloworld.o  
  2. outfile : $(obj)  
  3. g++ $(obj) -o outfile  
  4. speak.o : speak.cpp speak.h  
  5. g++ -c speak.cpp -o speak.o  
  6. helloworld.o : helloworld.cpp speak.h   
  7. 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也会被自动推导出来,那么以上的命令我们又可以继续简化为:

                                                                                                                                                                                                   

  1.    
  2. obj=speak.o helloworld.o  
  3. outfile : $(obj)  
  4. g++ $(obj) -o outfile  
  5. speak.o :  speak.h  
  6. helloworld.o :  speak.h   

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

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

  1.    
  2. obj=speak.o helloworld.o  
  3. outfile : $(obj)  
  4. g++ $(obj) -o outfile  
  5. helloworld.o speak.o : speak.h  

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

本文地址:http://blog.csdn.net/hjimce/article/details/45567689    作者:hjimce    
多个文件的情况(假定有2个文件文件分别是1.cpp和2.cpp):

        第一种方法

        g++  -c  1.cpp  -o  1.o

        g++  -c  2.cpp  -o  2.o

        g++  1.o  2.o  -o prog  (或者linux下输入g++  1.o  2.o  -o prog.out 

        第二种方法

        单个文件一般用g++  -o  filename  filename.cpp

        多个文件时用   g++  -o  file  file1.cpp   file2.cpp  ...

        注意:gcc可以用来编译链接.c源程序,gcc同样可以编译.cpp文件,但是不能链接.cpp文件生成可执行文件。只有g++可以编译并且链接.cpp,g++在编译.cpp文件的时候自动调用gcc进行源文件的编译。

      当然上面的使用方式具体选择哪个就看个人喜好了。

      更多相关信息可参考如下的文章:

       gcc/g++执行的步骤及参数简介

       linux下编译器gcc/g++编译步骤

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值