您的位置:首页 > 其它

gcc/g++编译makefile文件

2012-08-10 10:19 197 查看
2011-05-24 17:19:05| 分类:

linux | 标签:
|字号大中小 订阅

(本文主要以gcc为演示,如果是C++程序直接将给 gcc改为g++即可)

1. gcc与g++编译流程:

1) 编译流程:





2) 预处理:生成.i的预处理文件。

? 只激活预处理,这个不生成文件,需要把它重定向一个输出文件。

? 演示:





3) 编译:生成.s的编译文件。

? 只激活预处理和编译,把文件编译成汇编代码。

? 演示:





4) 汇编:生成.o的汇编文件。

? 只激活预处理、编译和汇编,把程序做成obj文件。

? 演示:





5) 链接:生成链接文件。

? 激活预处理、编译、汇编和链接。

? 演示:





6) 惯用:





2. gcc与g++常用参数介绍:

1) -E

? -E选项指示编译器仅对输入文件进行预处理。当这个选项被使用时,预处理器的输出被送到标准输出而不是储存在文件里。

? 演示:





2) -S

? -S选项告诉GCC在为C代码产生了汇编语言文件后停止编译。GCC产生的汇编语言文件的缺省扩展名是.s。

? 演示:





3) -c

? -c选项告诉GCC仅把源代码编译为目标代码。缺省时GCC建立的目标代码文件有一个.o的扩展名。

? 演示:





4) -o

? -o选项来为将产生的可执行文件用指定的文件名。

? 演示:





5) -O

? -O选项告诉GCC对源代码进行基本优化,这些优化在大多数情况下都会使程序执行的更快,优化分为4个等级(-O0,-O1,-O2,-O3)。

-O0表示没有优化。

-O1为缺省值,主要进行跳转和延迟退栈两种优化。

-O2除了完成-O1的优化之外,还进行一些额外的指令调整工作。

-O3除了完成-O2的优化之外,还进行包括循环展开和其他一些与处理特性相关的优化工作。

? 演示:





其他优化等级的用法与演示中-O3的用法一样。

6) -x

? 设定文件编译所使用的语言,使后缀名无效。

? 演示:





7) -C

? 在预处理的时候,不删除注释信息。

? 演示:





8) -M

? 生成文件关联信息。包含目标文件所依赖的所有源代码。

? 演示:





2. 编写makefile:

1) 编写一个程序:

? 共5个文件,3个.cpp文件,2个.h文件。





? main.cpp:





? printf1.cpp:





? printf1.h:





? printf2.cpp:





? printf2.h:





? 常规编译:

l 汇编main.cpp:





l 汇编printf1.cpp





l 汇编printf2.cpp





l 将3个obj文件链接到一个文件上:





l 运行:





l 总共生成的文件:





2) 运用makefile文件:

? 优点:

由上例可知,照这样的编译方法,如果是一个项目的话,可能存在上百个文件,岂不是太麻烦了,所以要把编译过程写进一个文件中:makefile。

? 编写规则:

l 以#号开始的为注释

l 具体编译过程:

对象:依赖项

编译方式

l makefile文本向右缩进时使用TAB键,不能用空格代替。

? 编写(以上面得程序为例):

l 创建makefile文件:





l 编写makefile文件:

u 常用写法:





前三行类似一个变量的定义,取值时使用$(定义值)来取值。

u 也可以写成:





等价于上面的写法,缺点是文件一旦过多,修改也不容易。

l 运行makefile文件:





l 生成的文件:





l 运行目标文件:





l 删除生成文件:





。。。。。。。。。。。。。。。。。。。。no understand see next
一个简单的makefile示例及其注释

  相信在unix下编程的没有不知道makefile的,刚开始学习unix平台

下的东西,了解了下makefile的制作,觉得有点东西可以记录下。

  下面是一个极其简单的例子:

现在我要编译一个Hello world,需要如下三个文件:

  1. print.h

      #include<stdio.h>

      void printhello();
  2. print.c

      #include"print.h"

      void printhello(){

        printf("Hello, world\n");

      }
   3. main.c

      #include "print.h"

      int main(void){

        printhello();

        return 0;

      }
  好了,很简单的程序了。如果我们想要编译成功需要哪些步骤呢?

我认为在这里需要理解的就两步:

  # 为每一个 *.c文件生成 *o文件。

  # 连接每一个*o文件,生成可执行文件。

下面的makefile 就是根据这样的原则来写的。
一:makefile 雏形:
#makefile的撰写是基于规则的,当然这个规则也是很简单的,就是:

#target : prerequisites

  command  //任意的shell 命令
实例如下:

makefile:

    helloworld : main.o print.o #helloword 就是我们要生成的目标

                 # main.o print.o是生成此目标的先决条件

      gcc -o helloworld main.o print.o#shell命令,最前面的一定是一个tab键
    mian.o : mian.c print.h

      gcc -c main.c

    print.o : print.c print.h

      gcc -c print.c

    

    clean :          

        rm helloworld main.o print.o

  OK,一个简单的makefile制作完毕,现成我们输入 make,自动调用Gcc编译了,

输入 make clean就会删除 hellowworld mian.o print.o
二:小步改进:
  在上面的例子中我们可以发现 main.o print.o 被定义了多处,

我们是不是可以向C语言中定义一个宏一样定义它呢?当然可以:

makefile:

    objects = main.o print.o #应该叫变量的声明更合适
    helloworld : $(objects) //声明了变量以后使用就要$()了

      gcc -o helloworld$(objects)

    mian.o : mian.c print.h

      gcc -c main.c

    print.o : print.c print.h

      gcc -c print.c

    

    clean :          

        rm helloworld $(objects)

修改完毕,这样使用了变量的话在很多文件的工程中就能体现出方便性了。
三:再进一步:
  再看一下,为没一个*.o文件都写一句gcc -c main.c是不是显得多余了,

能不能把它干掉?而且 main.c 和print.c都需要print.h,为每一个都写上是

不是多余了,能不能再改进?

能,当然能了:

makefile:

    objects = main.o print.o
    helloworld : $(objects)

      gcc -o helloworld$(objects)

    

    $(objects) : print.h # 都依赖print.h

    mian.o : mian.c #干掉了gcc -c main.c 让Gun make自动推导了。

    print.o : print.c     

    clean :          

        rm helloworld $(objects)
好了,一个简单的makefile就这样完毕了,简单吧。

评论这张



转发至微博



转发至微博



0人 |
分享到:

阅读(688)|
评论(0)|
转载
(1) |举报

GCC、GDB软件的安装

linux下调试方法,以及segmentation fault(段错误)产生的原因

历史上的今天

相关文章

Linux-0.12 Kernel/Makefile gcc参数2010-03-08
13:31:57
makefile2010-12-14 22:59:56

郁闷了,Makefile2010-08-24 20:57:12

gcc Makefile 入门2010-10-22 13:03:00

AVR-GCC Makefile文件2010-05-25 12:56:19
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: