简介
「GCC」GNU Compiler Collection,GNU编译器套件
- 由GNU开发的语言编译器
- 原先只支持编译C语言。如今已成为了一个编译集,支持C、C++、Java等语言的编译
「gcc」小写的gcc,代表的是GCC编译集中C语言的编译器
「g++」GCC编译集中C++的编译器。如果不装g++,一些C++的库可能会没有,可能会编译不过
编译过程

编译过程: | 过程 | 说明 | 会出现的错误 | | —- | —- | —- | | 预处理(Preprocessing) | 生成.i文件 | 宏定义错误 | | 编译(Compilation) | 生成.s文件 | 代码错误,比如语法错误等 | | 汇编(Assembly) | 生成.o文件 | | | 链接(Linking) | 生成可执行文件 | 找不到资源、找不到库文件 |
说明:在linux的gcc中,可以对每个步骤分别做处理。而在Windows当中,一般只能控制到预处理、编译和链接部分,汇编一般只有相对硬件开发才会涉及到。
语法
gcc用于编译C语言的代码
- g++用于编译C++的代码
-o(指定输出文件名,生成可执行文件)
此文件名可以没有后缀(test),也可加后缀(test.out)。此输出文件即为可执行文件(类比windows的test.exe)
-c(只编译不链接,生成.o文件)
说明:一个项目若包含很多个文件时,经常会用到这个命令,只编译其中一个cpp,不链接其他的cppgcc -c main.c//只编译main.c,不链接。生成了main.o文件gcc main.o -o main//再链接。生成了执行文件
-E(预编译)
预编译:把所有的头文件、宏全部拼到一个.c文件中gcc -E main.c>main.e//gcc -E main.c之后,在命令行打印出的内容很多,可以使用>把内容输出到文件main.e中vim main.e//打开文件,查看预编译的结果
-S(只编译,不汇编)
gcc -S main.c//只编译,不汇编。生成了一个main.svim main.s//打开看一下结果,main.s即是汇编代码
-g(生成调试信息)
-g即表示生成Debug版本的可执行文件
若没有-g,即默认情况(gcc main.c -o main)是release版本 ```shell gcc -g main.c -o main_d //gcc main.c -o main_d表示编译main.c,结果文件名为main_d(可执行文件) //-g表示这是一个有调试的版本
<a name="ljLEQ"></a># 编译<a name="y9m3H"></a>## 多文件编译- src 文件目录- person- person.h- person.cpp- text.cpp 此文件中使用了person.h```shellg++ main.cppmain.cpp:2:20: fatal error: Person.h: No such file or directorycomilation terminated.//预编译出错。提示找不到Person.h,所以我们要指定头文件路径(-I),如果多个路径,再加-I../Person2g++ main.cpp -o main -I../Person/tmp/cct3XXsz.o: In function 'main':main.cpp:(.text+0x26): undefined reference to `Person::Person()`collect2: error: Id returned 1 exit status//编译出错。找不到Person的实现,即找不到.cpp文件g++ main.cpp ../Person/Person.cpp -o main -I../Person//指定Person.cpp,把它一起编译了
Linux静态编译
静态编译:静态编译会把所有的库都编译到一个文件中,这样把执行文件放到任何环境中都能运行,它并不要求运行环境。
动态编译:动态编译不把依赖库一起编译到可执行文件中。故动态编译会依赖很多库,很依赖于运行环境,如果环境中没有依赖库,就会运行失败。
例如:
g++ main.cpp -o main //编译成动态的可执行文件ldd main //查看main的所有引用linux-vdso.so.1 => (....) //可以看到它引用了很多库g++ main.cpp -o main_static -static //编译成静态的可执行文件ldd main_static //查看引用not a dynamic executable //可以看到静态版本没有引用动态的可执行文件
综上:
- 不建议用静态的方式来编译
- 一方面编译静态库的时间很长(跨平台项目本身编译的时间就很长,1分钟和10分钟的区别),另一方面静态库编译出来的可执行文件很大
- 静态库带来的运行的简单,但编译非常麻烦。
- 当然有一些应用场景,为了运行时的简单,选择静态编译也可以的。
Linux动态编译和调用
动态编译:
调用:g++ Person.cpp -fpic -shared -o libPerson.so//-fpic表示.cpp中的函数与代码位置不相关-->可以通过头文件中的名字找到函数所在的位置//-shared表示这是一个动态库//-o指定生成文件的名称//文件名以lib开头,.so结尾,所以中间的Person才是这个库的名字,即此动态库最终文件名为Person.so
执行:执行的时候会报错误,没有指定这个库的文件路径g++ main.cpp -o main -I../Person -L../Person -lPerson//-L指定动态链接库的路径,如果不指定默认到系统环境变量的lib路径下找//-l指定动态链接库的名称,即上面指定libPerson.so中间的Person

两种解决方案:
- 将.so拷贝到系统的path下面
- 执行脚本的方式,在命令行输入
export LD_LIBRARY_PATH=../Person

