gcc_to_use
gcc
概要
- GCC:GNU Compiler Collection(GUN 编译器集合),是GNU项目中符合ANSI C标准的编译系统,它可以编译C、C++、JAV、Fortran、Pascal、Object-C、Ada等语言。并且GCC是一个交叉平台编译器,能够在当前CPU平台上为多种不同体系结构的硬件平台开发软件,因此尤其适合在嵌入式领域的开发编译。
- gcc是GCC中的GUN C Compiler(C 编译器)。
- g++是GCC中的GUN C++ Compiler(C++编译器)。
- GCC编译流程:
- 预处理(Pre-Processing)
- 编译(Compiling)
- 汇编(Assembling)
- 链接(Linking)

- GCC特点:
- GCC是一个可移植的编译器,支持多种硬件平台。例如ARM、X86等等。
- GCC不仅是个本地编译器,它还能跨平台交叉编译。所谓的本地编译器,是指编译出来的程序只能够在本地环境进行运行。而GCC编译出来的程序能够在其他平台进行运行。例如嵌入式程序可在x86上编译,然后在arm上运行。
- GCC有多种语言前端,用于解析不同的语言。
- GCC是按模块化设计的,可以加入新语言和新CPU架构的支持。
- GCC是自由软件。任何人都可以使用或更改这个软件。
基本指令及功能(以gcc为例)
- gcc编译文件
| 后缀 | 解析 | 后缀 | 解析 |
|---|---|---|---|
| .c | C原始程序 | .s/.S | 汇编语言 |
| .C/.cc/.cxx | C++原始程序 | .h | 预编译头文件 |
| .m | Objective-C原始程序 | .o | 目标文件 |
| .i | 已预处理C原始程序 | .a/.so | 库文件 |
| .ii | 已预处理C++原始程序 |
- gcc编译选项
| 选项 | 作用 |
|---|---|
| -o file | 产生目标file文件.i/.s/.o/可执行文件等 |
| -E | 只运行C预编译器 |
| -S | 产生汇编文件.s/.S后停止编译 |
| -c | 产生目标文件.o但不链接形成可执行文件 |
| -Wall | 使gcc对源程序代码有问题的地方发出警告 |
| -I dir | 将dir目录加入搜索头文件目录路径 |
| -L dir | 将dir目录加入搜索库文件目录路径 |
| -llib | 链接到名为lib的库 |
| -g | 在目标文件嵌入调试信息,方便gdb/cgdb程序调试 |
| -ansi | 只支持ANSI标准编译,禁止GNU C的某些特色(如asm/typeof关键字) |
| -DMACRO | 以字符串"1"定义MACRO宏 |
| -DMACRO=DEFN | 以字符串"DEFN"定义MACRO宏 |
| -IDIRECTORY | 指定额外的头文件搜索路径DIRECTORY |
| -LDIRECTORY | 指定额外的函数库搜索路径DIRECTORY |
| -m486 | 针对486进行代码优化 |
| -o FILE | 生成指定的输出文件,用在生成可执行文件时 |
| -O0 | 不进行优化处理 |
| -O/-O1/-O2/-O3 | 优化生成代码 |
| -shared | 生成共享目标文件,通常用在建立共享库时 |
| -static | 禁止使用共享连接 |
| -UMACRO | 取消对MACRO宏的定义 |
| -w | 不生成任何警告信息 |
- 编译案例
指令一般格式:gcc [选项] 要编译的文件 [选项] [目标文件]
# 对hello.c文件进行预处理,生成了hello.i 文件
gcc -E hello.c -o hello.i
# 对预处理文件进行编译,生成了汇编文件
gcc -S hello.i -o hello.s
# 对汇编文件进行编译,生成了目标文件
gcc -c hello.s -o hello.o
# 对目标文件进行链接,生成可执行文件
gcc hello.o -o hello
# 直接编译链接成可执行目标文件
gcc hello.c -o hello
# 编译生成可重定位目标文件
gcc -c hello.c or gcc -c hello.c -o hello.o
# gcc输出警告选项
gcc -Wall hello.c -o hello
- 独立编译和一次编译
# 一次编译
gcc hello.c main.c -o main
# 独立编译
gcc -Wall -c main.c -o main.o
gcc -Wall -c hello.c -o hello.o
gcc -Wall main.o hello.o -o main
独立编译运用到复杂项目时,当其中某个模块代码发生改变,只需编译该模块代码,
不必重新编译所有程序文件,这样可以节省编译时间。
- 库
- 可重用函数关联功能函数
- 模块化开发
- 可维护性
- 静态库(.a):程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。静态库比较占用磁盘空间,而且程序不可以共享静态库。运行时也是比较占内存的,因为每个程序都包含了一份静态库。
- 动态库(.so):程序在运行的时候才去链接共享库的代码,多个程序共享使用库的代码,这样就减少了程序的体积。
- 头文件及库文件位置
- /usr/include及其子目录底下的include文件夹
- /usr/local/include及其子目录底下的include文件夹
- /usr/lib
- /usr/local/lib
- /lib
- 库生成及使用
# rcs(replace and create)生成静态库
ar rcs libhello.a hell.o
# 使用静态库
gcc -Wall main.c libhello.a -o main
# 其中lhello为libhello的缩写
gcc -Wall -L main.c -o main -lhello
# 生成共享库(动态库)
gcc -shared -fPIC hello.o -o libhello.so
# 使用动态库
gcc -Wall main.o -o main -L. -lhello
# 库路径的搜索原则:库的搜索路径遵循几个搜索原则:从左到右搜索-I -l指定的目录,如果在这些目录中找不到,
那么gcc会从由环境 变量指定的目录进行查找。头文件的环境变量是C_INCLUDE_PATH,库的环境变量是LIBRARY_PATH.如果还是找不到,那么会从系统指定指定的目录进行搜索。
# 共享库有时候并不在当前目录下,需要配置到gcc可寻找的路径下(3种方式)
# 1. copy .so文件到系统共享库路径/usr/lib下
# 2. 在~/.bash_profile文件中,配置LD_LIBRARY_PATH变量
# 3. 配置/etc/ld.so.conf,配置完成后调用ldconfig更新ld.so.cache
gcc -gdb
gcc -cmake
- cmake基本语法规则
- 变量使用${}取值,IF控制语句中直接使用变量名
- 指令(参数1 参数2 ...)
- 指令大小写无关,参数和变量大小写相关,推荐全部使用大写
- 指定cmake最小版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.5.1)
- 设置项目名称(此处自动引入两个变量 hello_BINARY_DIR 和 hello_SOURCE_DIR)
PROJECT(hello)
- 生成可执行文件
ADD_EXECUTABLE(hello hello_world.cpp)
- 设置编译类型
ADD_LIBRARY(hello hello.cpp) # 默认生成静态库
ADD_LIBRARY(hello STATIC hello.cpp) # 指定为静态库
ADD_LIBRARY(helloshared SHARED hello.cpp) # 指定为共享库
假设 hello.cpp 文件中没有 main 函数,意味着这个库中没有可执行文件。添加上述命令,cmake 后会依次生成下面几个文件:
libhello.a
libhello.a
libhello_shared.so
静态库以 .a 为后缀名,共享库以 .so 为后缀名,所有库都是一些函数打包后的集合,静态库每次被调用都会生成一个副本,而共享库则只有一个副本,更省空间。
库文件是一个压缩包,里面有编译好的二进制函数,仅有 .a 或 .so 库文件,别人并不知道里面的函数是什么样的,或如何调用;这就需要提供一个头文件,有了库文件和头文件,就可以调用这个库。
- 设置变量
- set直接设置变量值
SET(SRC_LIST a.cpp b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})
- set追加设置变量值
SET(SRC_LIST a.cpp)
SET(SRC_LIST ${SRC_LIST} b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})
- LIST追加或删除变量值
SET(SRC_LIST a.cpp)
LIST(APPEND SRC_LIST b.cpp)
LIST(REMOVE_ITEM SRC_LIST b.cpp)
ADD_EXECTUABLE(demo ${SRC_LIST})
- 指定源文件
- 明确指定(空格或分好隔离开)
ADD_LIBRARY(hello hello.cpp a.cpp b.cpp)
- 所有源文件
# AUX_SOURCE_DIRECTORY(dir VAR) 发现一个目录下所有的源代码文件并将列表存储在一个变量中
AUX_SOURCE_DIRECTORY(. SRC_LIST) # 搜索当前目录下的所有.cpp文件
ADD_LIBRARY(hello ${SRC_LIST})
- 查找指定库文件
FIND_LIBRARY(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。默认的搜索路径为 cmake 包含的系统库。
类似的命令还有 find_file()、find_path()、find_program()、find_package()等。 - 设置包含目录
# case 0
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
# case 1
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -I${CMAKE_CURRENT_SOURCE_DIR}")
- 设置链接库搜索目录
# case 0
LINK_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/libs
)
# case 1
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_SOURCE_DIR}/libs")
- 设置target需要链接的库
# 指令TARGET_LINK_LIBRARIES(target_lib link_lib_path)
# 指定链接静态库或动态库
TARGET_LINK_LIBRARIES(hello libhello.a)
TARGET_LINK_LIBRARIES(hello libhello_shared.so)
# 设置全路径
TARGET_LINK_LIBRARIES(hello ${CMAKE_CURRENT_SOURCE_DIR}/libs/libhello.a)
TARGET_LINK_LIBRARIES(hello ${CMAKE_CURRENT_SOURCE_DIR}/libs/libhello_shared.so)
编译流程
- 编写hello.cpp源文件和CMakeLists.txt文件
- 新建build目录,在build目录下cmake ..命令,生成了 CMakeFIles 文件夹和CMakeCache.txt, cmake_install.cmake, Makefie 文件
- 在build路径下执行make命令
CMakeLists.txt文件demo
# cmake 版本
cmake_minimum_required(VERSION 2.6)
####
# CMake中指令不区分大小写
# ${} 表示取出变量中的值
####
# 项目名称, 名称后面为支持的语言,不写时默认支持所有语言
PROJECT(project_name [CXX][C][java])
# 或者
PROJECT(name )
# PROJECT(...)语句运行之后,会默认定义两个变量,后面可以直接使用
# name_BINARY_DIR 编译目录
# name_SOURCE_DIR 工程目录
# set表示设置变量名
SET(LIBRARIES /usr/lib/x86_64-linux-gnu/libm.so)
# 变量中只保存一个源文件
SET(SRC_LIST main.c) # 或者 SET(SRC_LIST “main.c”) # 把main.c保存到变量SRC_LIST中
# 也可以是保存多个源文件
SET(SRC_LIST main.c func.c func.h)
# 当然也可以保存所有的源文件,将所有源文件保存到SRC_LIST变量中
AUX_SOURCE_DIRECTORY(directory SRC_LIST)
# 把当前目录下所有源文件全部保存到SRC_LIST变量中
AUX_SOURCE_DIRECTORY(. SRC_LIST)
# 选择指定目录下的源文件保存到变量中
AUX_SOURCE_DIRECTORY(./dir/main.c SRC_LIST)
# message 表示输出提示信息
MESSAGE([SEND_ERROR | STATUS | FATAL_ERROR] "message")
# STATUS 参数较为常用,输出前缀为-的信息
# 第一个参数是消息类型,后面的参数是一条或多条要显示的消息。错误类型有3种:
# SEND_ERROR:表示产生错误信息
# STATUS:表示一般的状态信息
# FATAL_ERROR:我们知道肯定是严重错误信息,cmake会立即停止执行
# 生成可执行文件
ADD_EXECUTABLE(result ${SRC_LIST})
# 添加可执行文件所需要的库
TARGET_LINK_LIBRARIES(result ${LIBRARIES})
# 更改可执行文件的输出目录
SET(EXECUTABLE_OUTPUT_PATH "${CMAKE_BINARY_DIR}/bin")
# 其中CMAKE_BINARY_DIR 变量中的CMAKE_表示项目名的统称,等价于上面所说的 name_BINARY_DIR
gcc_to_use的更多相关文章
随机推荐
- Dubbo 入门系列之基于 Dubbo API 开发微服务应用
目标 从零上手开发基于 Dubbo 的微服务 难度 低 环境要求 系统:Windows.Linux.MacOS JDK 8 及以上(推荐使用 JDK17) Git IntelliJ IDEA(可选) ...
- 玩转web3第二篇——Web3UI Kit
介绍 开发web2应用的时候,可以很方便找到很多优秀的UI库,比如antd,material ui,element ui等等,但web3应用对应的UI库却不多. 今天给大家介绍一款优秀的WEB3的UI ...
- 互斥锁、线程理论、GIL全局解释器、信号量、event事件、进程池和线程池以及协程
目录 一.互斥锁代码实操 1.互斥锁的概念 2.互斥锁的使用 3.死锁现象 4. 小结 二.线程理论 进程 线程 线程简介 为什么要使用多线程? 多线程概念 多进程的优点: 线程与进程的区别 线程的特 ...
- Selenium中免登录的实现方法一option
Selenium中免登录的实现方法一option 在selenium中有很多种可以实现网站的免登录,option就是其中的一种做法. 学员在VIP自动化课程中多有涉及. 1. 准备工作 打开一个网站( ...
- 解决:ChatGPT too many requests in 1 hour.Try again later 怎么办?OpenAI 提示
ChatGPT 提示: Too many requests in 1 hour. Try again later. 如下图,我多次访问也出现同样的问题.中文意思是太多的请求数量在当前 1 个小时内,请 ...
- 接水问题(NOIP 2010 PJT2)
这个的思路就是让各个水龙头所用的时间尽可能地接近,可以先向优先队列中推入前m个数,由于开的是小根堆最小的数在前面我们把它拿出来,加上下一个人所需的时间.如此反复,直到都接完水,最大值就是答案. #in ...
- SpringBoot 学习 step.3数据库
数据库 JPA默认用的是Hibernate. SpringBoot开发WEB应用时,目前菜用较多的是mybatis+mybatis-plus,还有是springboot-data-jpa,jpa默认使 ...
- Creo9.0 安装破解图文教程 【2022年12月29日亲测有效】
前言 creo9.0正式版是一款非常优秀的3D建模设计软件.该软件界面美观,提供了CAD 技术.模制造绘图.多实体建模.多体设计.实时仿真.框架和焊缝设计等一系列强大的辅助设计功能,通过这些功能,让用 ...
- rt-thread模糊到清晰系列: irq.c
#include <rthw.h> #include <rtthread.h> // 进入离开中断的钩子函数 #ifdef RT_USING_HOOK static void ...
- jquery(四:jquery的事件、Ajax)
Jquery事件 jQuery注册事件 1.利用原生的js来为对象注册事件,后面的会把前面的覆盖 2.用jQuery的$()来为对象注册事件,后面不会把前面的覆盖 简单事件绑定-----click() ...