网站首页 > 文章精选 正文
在Linux的系统中,主要是使用gcc/g++、Makefile和CMake这几种方式对C和C++代码进行编译的,本篇文章先简单介绍下gcc工具的使用场景和使用方法,以及静态库及动态库的使用生成和使用方法, Makefile和CMake用法比较复杂,打算在另一篇文章再单独详细介绍。
一、GCC/G++编译器:
1. 作用:
1)GCC主要功能是将高级程序代码翻译成目标机器代码,可以生成在不同系统平台上运行的可执行文件或动态、静态连接库。
2)GCC支持各种不同的目标体系结构,可以被广泛采用到多种架构的处理器平台的应用中。例如,它既支持基于宿主的开发(即在该平台上编译和运行),
也支持交叉编译(即在A平台上编译的程序在平台B使用)
3)GCC还提供了丰富的标准库和常用工具,如make、gdb、valgrind等,使得开发人员可以更方便地编写、调试和优化程序。
2. 编译步骤:
gcc编译程序过程如下:
预处理--->编译和优化 ---> 汇编 ---> 链接 --->可执行程序
1)预处理:将程序中引用的头文件包含进源代码中,并对宏进行替换。
gcc -E test.c -o test.i
预处理主要包括以下内容:
a. 在C/C++源文件中, 以“ #”开头的命令被称为预处理命令; 如,一些包含的头文件:#include<stdio.h> #include “header.h”
b. 宏定义展开. 如:#define定义的一些函数和常量;
c. 根据条件编译命令选择要使用的代码。如:#if, #ifdef , #ifndef等;
2)编译:将高级语言翻译成处理器可识别的汇编语言。
gcc -S test.i(test.c) -o test.s
说明:
a. C/C++代码(比如上述的“.i”文件)“ 翻译” 成汇编代码,所用到的工具为 cc1 ;
b. 检查语法错误;如果语法有误则报错,如果语法没错则编译成汇编语言;
3)汇编:转成二进制目标代码
gcc -c test.s(test.c) -o test.o
说明:
a. 将汇编语言解析成二进制文件(并非纯粹的二进制文件), 在Linux 系统上一般表现为 ELF 目标文件(OBJ 文件),用到的工具为 as;
b. 也可以进行反汇编:将机器代码转换为汇编代码,这在调试程序时常常用到;
反汇编: objdump -d test.o > test.s
4)链接:将所有的目标文件链接成可执行文件。
gcc test.o -o test 或者 gcc test1.o test2.o -o test
说明:
a. 链接就是将上步生成的 OBJ 文件和系统库的 OBJ 文件、 库文件链接起来,最终生成了可以在特定平台运行的可执行文件,用到的工具为 ld 或 collect2。
b. 格式: gcc -o 可执行文件 .c/.i/.s/.o文件都可以;
5)一次性编译多个.c文件
格式: gcc -o 可执行文件 .c文件 .c文件 ...(后面接多个.c文件都行)
说明: 只能有一个main函数;
总结:
1)C中的编译过程也称为将人类可理解代码(C程序)转换为机器可理解代码(二进制代码)的过程;
2)C语言的编译过程包括四个步骤:预处理、编译、汇编和链接;
3)预处理器执行删除注释、宏扩展、文件包含。这些命令在编译过程的第一步执行;
4)编译器可以提高程序的性能,并将中间文件转换为汇编文件;
5)汇编程序有助于将汇编文件转换为包含机器代码的对象文件;
6)链接器用于将库文件与对象文件链接。这是编译中生成可执行文件的最后一步.
7)程序运行:结合不同的处理器系统在内存中进行装载和执行;
3. gcc编译选项:
-c,仅编译生成目标文件.o,不进行链接;
-o outfile,指定生成的可执行文件为outfile,且这个名称不能和源文件同名;如果不指定文件名,默认可执行文件a.out;
-g,产生调试工具所需要的符号信息,如果需要对源代码进行调试,我必须加入这个选项;
-O,对程序进行优化编译、链接的选项,可以提高可执行文件的执行效率,编译和链接的速度就要慢一些;
有4个优化级别:
-O0: 不进行任何优化,在这种情况下,编译器尽量的缩短编译消耗(时间和空间);
-O1(或-Os):优化等级低;
-O2: 优化等级中;
-O3: 优化等级高,编译消耗时间和内存最多;
-I path: 指定编译时需要包括的头文件路径,#include 相关的文件;
-L path: 指定编译时需要链接的动态和静态库文件路径;-llib库所在的文件路径;
-E:只进行预处理,这个不生成目标文件;
-S: 生成汇编程序,不生成目标文件;
-c: 编译生成目标文件;
-o: 编译生成可执行文件,进行链接动作;
-static: 编译生成静态链接库的文件;
-shared:编译生成动态链接库的文件;
-W: 屏蔽所有警告信息;
-Wall:打开所有的警告,具体打开的选项见下面详细说明;
-Wno-:开头关闭特定的警告; 如:gcc -Wall -Wno-unused test.c -o test;
-Werror: 将所有警告当作错误;
-Werror= :指定特定的警告变成错误;
-Wfatal-erros: 编译遇到第一个错误就停止编译
-D: 指定宏定义;-Dname或 -Dname=value 这样的变量名称;
-U name:解除宏定义
-llibrary: 手动指定链接的动态(静态)库文件(注意库的命名格式有要求,如:libtest.so)
-ansi:对于C语言程序来说,其等价于-std=c90;对于C++程序来说,其等价于-std=c++98。
-std= : 指定c/c++版本,编程语言所遵循的标准,例如 c89、c90、c++98、c++11 等。
-Wall 选项详细说明:
相当于同时使用了下列所有的选项(有些选项对于调试程序非常实用的):
.unused-function:遇到仅声明过但尚未定义的静态函数时发出警告;
.unused-label: 遇到声明过但不使用的标号的警告;
.unused-parameter:从未用过的函数参数的警告;
.unused-variable:在本地声明但从未用过的变量的警告;
.unused-value: 仅计算但从未用过的值得警告;
.Format:检查对printf和scanf等函数的调用,确认各个参数类型和格式串中的一致;
.implicit-int:警告没有规定类型的声明;
.implicit-function-:在函数在未经声明就使用时给予警告;
.char-subscripts:警告把char类型作为数组下标。这是常见错误,程序员经常忘记在某些机器上char有符号;
.missing-braces:聚合初始化两边缺少大括号;
.Parentheses:在某些情况下如果忽略了括号,编译器就发出警告;
.return-type:如果函数定义的返回类型与实际不一致时会发出警告;
.sequence-point:出现可疑的代码元素时,发出报警;
.Switch:如果某条switch语句的参数属于枚举类型,但是没有对应的case语句使用枚举元素,编译器就发出警告;
超出枚举范围的case语句同样会导致这个警告。
.strict-aliasing:对变量别名进行最严格的检查。
.unknown-pragmas:使用了不允许的#pragma。
.Uninitialized:在初始化之前就使用自动变量。
----------------------------------------------------------------------
4. 例子说明用法:
##预编译展开的源文件;
gcc -E test.c -o test.i
##生成编译程序;
gcc -S test.i -o test.s
##生成没有链接的目标文件;
gcc -c test.s -o test.o
##链接生成可执行程序
gcc test.s -o test
##默认生成目标文件test.o,没有链接,不能运行;
gcc -c test.c
##同时编译多个.c文件,并链接生成test可执行文件;
gcc test1.c test2.c test3.c -o test
或者如下方法一步步进行:
gcc -c test1.c
gcc -c test2.c
gcc -c test3.c
gcc -o test test1.o test2.o test3.o
##想要使用-Wall来启用个选项,同时又要关闭unused警告
gcc -Wall -Wno-unused test.c -o test
##编译链接可执行文件,且指定包含的头文件路径;同时打开调试信息
gcc -g test.c -o test -I./include/ -D__DEBUG__
##编译链接可执行文件,且指定包含的链接库文件路径
(注意库文件的命名规则,以及-l的用法:libtest.so 调用时使用 -ltest);
gcc test.c -o test -L./lib/ -ldynic_test
##gcc 生成动态库的方法;
gcc test.c -shared -PIC -o libdynic_test.so
##gcc 生成静态库的方法;
gcc -c test1.c test2.c
ar crv libtest.a test1.o test2.o
二、静态库和动态库:
1、库命名规则:
1)静态库:lib + 名字 + .a, 例如: libtest.a
2)动态库:lib + 名字 + .so ,例如:libtest.so
2、制作步骤:
1)静态库:
##把当前目录下的所有.c文件编译成目标文件;
gcc -c *.c -I ../include
##把所有的目标文件打包成静态库
ar rcs libtest.a *.o
###解压当前的静态库文件到当前目录(可用于静态库模块的增删操作):
ar -x libtest.a
2)动态库:
##从源文件直接生成动态库
gcc -fPIC -shared func.c -o libfunc.so
##分步生成,从目标文件生成动态库;
(1) gcc -fPIC -c *.c -I ../include
(2) gcc -shared *.o -o libtest.so
参数说明:
-fPIC:作用于编译阶段,告诉编译器产生与位置无关代码;
-shared: 作用于链接阶段,告诉编译器生成动态库;
3. 调用方法:
1) 指定路径:
gcc test.c -o test -L./lib/ -ltest
运行时需要把库的路径加入到系统变量中:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$PWD/lib
./test
2)把libtest.so库放到/lib/或/usr/lib系统目录下;可直接运行;
3)使用ldconfig命令;
a.自定义一个mytest.conf文件放入到/etc/ld.so.conf.d/下,并修改这个mytest.conf,添加libtest.so的绝对路径;
b.再运行ldconfig 同步更新,即可直接运行;
(感谢关注,更新待续.....)
猜你喜欢
- 2025-01-10 centos 7 升级OpenSSH
- 2025-01-10 Linux动态库和静态库教程
- 2025-01-10 Linux入门系列——软件包管理
- 2025-01-10 AI模型搭建-3
- 2025-01-10 AI模型搭建-2
- 2025-01-10 在深度Linux玩Windows游戏,可以这样安装wine的最新版
- 2025-01-10 ubuntu24.04 vscode调用 c++ opencv报错问题
- 2025-01-10 Nginx使用Lua-nginx模块脚本连接Redis数据库读取静态资源
- 2025-01-10 实用 | 一个高性能通信库的简单使用分享
- 2025-01-10 ffmpeg安装方式及配合python使用
- 04-23关于linux coreutils/sort.c源码的延展思考最小堆为什么不用自旋
- 04-23一文精通如何使用二叉树
- 04-23二叉树(Binary Tree)
- 04-23数据结构入门:树(Tree)详细介绍
- 04-23数据结构错题收录(六)
- 04-23Kubernetes原理深度解析:万字图文全总结!
- 04-23一站式速查知识总结,助您轻松驾驭容器编排技术(水平扩展控制)
- 04-23kubectl常用删除命令
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 稳压管的稳压区是工作在什么区 (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)