LINUX 下GCC编译C、C++入门

来源:互联网 发布:head first python 2 编辑:程序博客网 时间:2024/05/21 12:46

GNU

是“GNU is Not Unix”的递归缩写,又称革奴计划,是由RichardStallman在1983年9月27日公开发起的。它的目标是创建一套完全自由的操作系统。

GCC

是GNU编译器集合(GNUCompiler Collector)的缩写,GNU编译器集合包括C,C++,Object-c,Fortran,JAVA和Ada的前端以及这些语言对应的库(libstdc++,libgcj,…),早期的gcc是指GNU的C语言编译器(GNU C Compiler),随着C++等语言的加入,gcc的含义才变化成了GNU编译器集合,C作为gcc的原生语言,故编译时不需要额外选项。

 

C、C++在GCC下的编译

1.编译环境的安装

sudo apt-get install build-essential (如果需要编译Fortran ,那么需要安装gfortran或g77)

2.C程序编译

1)简单C程序

#include<stdio.h>void main(){printf("hello world!\n");}
以上文件保存为 hello.c ,要用gcc编译文件,使用:
编译:gcc -g -Wall hello.c -o hello
该命令将文件hello.c中的代码编译为机器码并存储在可执行文件hello中,机器码的文件名是通过-o指定的,如果被省略,输出文件默认为a.out,且如果当前目录中与可执行文件重名的文件会被覆盖。
-Wall:开启编译器几乎所有常用的警告
-g:表示在生成的目标文件中带调试信息,调试信息可以在程序异常终止产生core后,帮助分析错误产生的源头,包括产生错误的文件名和行号等非常多有用的信息。
运行:./hello
这可将执行文件载入内存,并使CPU开始执行其包含的指令,路径./指当前目录。
补充:GCC中的消息总是具有下面的格式: 文件名:行号:消息,编译器对错误和警告区别对待,前者将阻止编译,后者表明可能存在问题但是并不阻止程序编译。

2)编译多个文件

将hello world程序分成3个文件:hello.c ,hello_fn.c,hello.h

主程序hello.c如下:

#include"hello.h"int main(){hello("hello");return 0;}
在hello.c中没有包含stdio.h,因为没有直接调用printf,而hello.h包含了hello()函数的声明,如下:

void hello(const char* name);
而函数的真正的定义在hello_fn.c中,如下:

#include"hello.h"#include<stdio.h>void hello(const char* name){printf("hello world \n");}

若要gcc编译以上源文件,使用下面命令:

gcc -Wall hello.c hello_fn.c -o newhello

注意到hello.h并没有在命令行中,因为愿文件中的#include“hello.h”指示符使得编译器自动将其包含到合适位置

运行:./newhello

源程序各部分被编译为单一的可执行文件,它与先前的例子产生的结果相同。

3)简单的makefile文件

要了解更多的信息,参看GNU Make手册

Make从makefile(默认是当前目录下的名为makefile的文件)中读取项目的描述,makefile指定了一系列目标(如可执行文件)和依赖(如对象文件和源文件)的编译规则。其格式:

目标:依赖

命令

对每一个目标,make检查其对应的依赖文件修改时间来确定目标是否需要利用对应的命令重新建立,注意到,makefile中命令行必须以单个的TAB字符进行缩进,且命令那行必须缩进

GNU Make包含许多默认的规则(参考隐含规则)来简化makefile的构建,比如说,它们指定‘.o’文件可以通过编译'.c'文件得到,可执行文件可以将'.o'链接到一起获得。隐含规则通过被叫做make变量的东西所指定,比如CC(C语言编译器)和CFLAGS(C程序编译选项);在makefile文件中它们通过独占一行的变量=值的形式被设置。对C++其等价的变量是CXX和CXXFLAGS,而变量CPPFLAGS则是编译预处理选项。

上面的makefile文件如下:

CC=gccCFLAGS=-Wallhello:hello.o hello_fn.oclean:         rm -f hello hello.o hello_fn.o

解读:使用C语言编译器gcc和编译选项-Wall ,从对象文件hello.o和hello_fn.o生成目标可执行文件hello(文件hello.o和hello_fn.o是通过隐含规则分别由hello.c和hello_fn.c生成)。目标clean没有依赖文件,它只是简单的移除所有编译生成的文件。rm名字-f抑制文件不存在时产生的错误消息。

注意:如果包含main函数的cpp文件为A.cpp,makefile中最好把可执行文件名也写成A。

要想使用该makefile文件,输入make,不加参数调用make时,makefile文件中的第一个目标被建立,从而生成可执行文件hello
$makegcc -Wall -c -o hello.o hello.ogcc -Wall -c -o hello_fn.o hello_fn.cgcc -Wall -c -o hello.o hello.c$./hellohello world!
一个源文件被修改重新生成可执行文件,简单的再次输入make即可。通过检查目标文件和依赖文件的时间戳,程序make可识别哪些文件已经修改并依据对应的规则更新其对应的目标文件:


一个专业的makefile文件通常包含用于安装(make install)和测试(make check)等额外目标。

4)链接外部库

库是预编的目标文件(.o)的集合,他们被链接进程序,静态库以后缀为'.a'的特殊的存档文件(archive file)存储。
标准系统库可在目录/usr/lib与/lib中找到,比如,在类Unix系统中C语言的数学库一般存储为文件/usr/lib/libm.a该库中国函数的原型声明在头文件/usr/include/math.h中,C标准本身存储为/usr/lib/libc.a,它包含ANSI/ISO C标准指定的函数,比如printf,对于每一个C程序来说,libc.a都默认被链接。
如下,一个调用数学库libm.a中sin函数的例子,创建文件calc.c:
#include<math.h>#include<stdio.h>int main(){double x=2.0;double y=sin(x);printf("the value of sin(2.0) is %f\n",y);return 0;}
执行:gcc -Wall calc.c -o calc报错:


函数sin没有在libc.a中,除非被指定,编译器也不会链接libm.a

为使编译器能将sin链接入主程序,必须提供libm.a,
1.gcc -Wall calc.c /usr/lib/libm.a -o calc  (中间加入其绝对路径,这个路径根据操作系统会有区别)
然后再./cala就OK

但是以上方法很麻烦,编译器为链接函数库提供了快捷选项'-l',
2. gcc -Wall calc.c -lm -o calc
一般来说,选项-lNAME使链接器尝试链接系统库目录中的函数文件libNAME.a,通常要很多-l选项指定链接库

2)C++编译


1)方法一:
使用gcc直接编译:$gcc -Wall hello.cpp -o hello,会报错,因为没有可识别的库
需要$gcc -Wall hello.cpp -o hello -lstdc++
lstdc++用来通知连接器链接静态库libstdc++.a,为什么C不需要呢,因为C是gcc的原生语言
2)方法二:
GCC为C++专门的编译器g++:
g++ -Wall hello.cpp -o hello
没有问题,直接生产hello



0 0
原创粉丝点击