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的更多相关文章

随机推荐

  1. Dubbo 入门系列之基于 Dubbo API 开发微服务应用

    目标 从零上手开发基于 Dubbo 的微服务 难度 低 环境要求 系统:Windows.Linux.MacOS JDK 8 及以上(推荐使用 JDK17) Git IntelliJ IDEA(可选) ...

  2. 玩转web3第二篇——Web3UI Kit

    介绍 开发web2应用的时候,可以很方便找到很多优秀的UI库,比如antd,material ui,element ui等等,但web3应用对应的UI库却不多. 今天给大家介绍一款优秀的WEB3的UI ...

  3. 互斥锁、线程理论、GIL全局解释器、信号量、event事件、进程池和线程池以及协程

    目录 一.互斥锁代码实操 1.互斥锁的概念 2.互斥锁的使用 3.死锁现象 4. 小结 二.线程理论 进程 线程 线程简介 为什么要使用多线程? 多线程概念 多进程的优点: 线程与进程的区别 线程的特 ...

  4. Selenium中免登录的实现方法一option

    Selenium中免登录的实现方法一option 在selenium中有很多种可以实现网站的免登录,option就是其中的一种做法. 学员在VIP自动化课程中多有涉及. 1. 准备工作 打开一个网站( ...

  5. 解决:ChatGPT too many requests in 1 hour.Try again later 怎么办?OpenAI 提示

    ChatGPT 提示: Too many requests in 1 hour. Try again later. 如下图,我多次访问也出现同样的问题.中文意思是太多的请求数量在当前 1 个小时内,请 ...

  6. 接水问题(NOIP 2010 PJT2)

    这个的思路就是让各个水龙头所用的时间尽可能地接近,可以先向优先队列中推入前m个数,由于开的是小根堆最小的数在前面我们把它拿出来,加上下一个人所需的时间.如此反复,直到都接完水,最大值就是答案. #in ...

  7. SpringBoot 学习 step.3数据库

    数据库 JPA默认用的是Hibernate. SpringBoot开发WEB应用时,目前菜用较多的是mybatis+mybatis-plus,还有是springboot-data-jpa,jpa默认使 ...

  8. Creo9.0 安装破解图文教程 【2022年12月29日亲测有效】

    前言 creo9.0正式版是一款非常优秀的3D建模设计软件.该软件界面美观,提供了CAD 技术.模制造绘图.多实体建模.多体设计.实时仿真.框架和焊缝设计等一系列强大的辅助设计功能,通过这些功能,让用 ...

  9. rt-thread模糊到清晰系列: irq.c

    #include <rthw.h> #include <rtthread.h> // 进入离开中断的钩子函数 #ifdef RT_USING_HOOK static void ...

  10. jquery(四:jquery的事件、Ajax)

    Jquery事件 jQuery注册事件 1.利用原生的js来为对象注册事件,后面的会把前面的覆盖 2.用jQuery的$()来为对象注册事件,后面不会把前面的覆盖 简单事件绑定-----click() ...