gcc编译可执行文件和cmake编译可执行文件

2023-05-16

gcc编译

gcc的下载(下载mingw,里面包含gcc)
下载安装MinGW-w64详细步骤(c/c++的编译器gcc的windows版,win10真实可用)

gcc编译可执行文件

由源码转换为可执行文件要顺序经过四个步骤
1、预处理(pre processing)
2、编译(compiling)
3、汇编(assembling)
4、链接(linking)

预处理gcc命令:

预处理
gcc -E main.c -o main.i
其中 -E -o 是编译选项,-E 指预处理,-o 指生成的目标文件。生成的为 .i 文件(扩展文件)。

编译gcc命令:

编译
gcc -S main.i -o main.s
其中 -S 指编译。生成的为 .s 文件。

汇编gcc命令:

汇编
gcc -c main.s -o main.o
其中 -c 指汇编。生成的为 .o 文件(目标文件)。

链接gcc命令:

链接
gcc main.o -o main
生成的为可执行文件(windows下为.exe)。


gcc main.c -o main
上述命令由源文件生成可执行文件,过程中依然是先构建目标文件,只不过目标文件在编译可执行文件后删除。

 gcc编译可执行文件的流程结果

gcc的编译过程中,不同阶段执行的动作不同。

预处理阶段:

这个步骤的动作会把源文件中引入的头文件展开和一些宏定义的替换。

编译阶段:

这个步骤的动作会先检查源码中是否有语法错误等,然后将高级语言转换为汇编语言。

汇编阶段:

这个步骤的动作会根据编译生成的汇编语言文件,生成二进制代码的目标文件。

链接阶段:

这个步骤是对目标文件中只有声明但没有实现的方法做一个链接库的动作。库包含静态库和动态库,库里包含了方法的实现。

参考
GCC编译的四个阶段
gcc编译的四个过程


静态库和动态库

其中,当一个项目需要引用到别的项目的方法或内容,项目很难将对方的源码引入,这时可以将对方的源码编译成一个库,在编译己方项目时,通过链接库的方法来获取其他项目函数的实现。静态库和动态库的区别为,静态库会编译进可执行文件中。而动态库不随可执行文件,由可执行文件执行到需要动态库的时候才去动态库里找实现。在linux系统中,静态库为.a文件,动态库为.so文件;在windows系统中,静态库为.lib文件,动态库为.dll文件。

gcc编译静态库的方法

ar -rc libtest.a .\test.o

首先由test.c编译出目标文件test.o,根据目标文件生成静态库libtest.a。

gcc编译链接静态库的方法

gcc -o main.exe main.o -L .\test1\ -l test


其中使用 -o 指定目标生成main.exe,是根据main.o生成的。-L 指要链接的文件夹./test/,是所需头文件的路径,-l 指定要链接的库libtest.a,test为库名。


gcc编译动态库的方法

gcc -fPIC -shared test.o -o libtest.so
gcc -fPIC -shared test.c -o libtest.so


在windows系统下动态库的文件格式为dll
gcc -fPIC -shared test.o -o libtest.dll


其中 -shared 说明要编译的是共享库(动态库),动态库可由源文件或目标文件编译而成。

gcc编译使用动态库的方法

如果直接在gcc命令上链接使用动态库会产生报错,找不到动态库。是因为系统默认寻找的动态库路径不包含本项目生成的动态库所在路径,有以下处理:

linux环境下要成功链接动态库有两种方法:
1、将动态库的路径加入到环境变量中

export LD_LIBRARY_PATH=/yourpath:$LD_LIBRARY_PATH


其中 /yourpath 需要修改为动态库所在的绝对路径

2、将动态库复制到 /usr/lib 或 /lib 目录下,这两个是系统默认找动态库的路径

cp libtest.so /usr/lib

windows环境下(目前尝试了一种方法可行):

1、将动态库复制到可执行文件的同一目录下


gcc编译的链接语句和静态库一样

gcc -o main.exe main.o -L . -l test


其中-L . 的 . 指定在当前目录下找

参考帖子:
【gcc】 gcc编译动态库(共享库)、静态库|链接静态库、动态库
GCC编译过程与动态链接库和静态链接库,很详细


cmake编译

cmake和make下载
Windows下CMake的下载与安装详解
windows下安装make

为什么有makefile,cmake,cmakelists

gcc在编译单个文件或少量文件的时候很适用,但随着项目的发展,一个项目往往有大量的文件,此时再一个个敲gcc会稍显麻烦。为了解决文件数过多使用gcc难编译的问题,makefile根据其中的编译规则使用一行shell命令make即可完成大量文件的编译,极大的提高了编译效率。
参考
CMake与CMakeLists是干什么的?

而cmake和cmakelists则是生成makefile的工具和文件。

cmake编译由源文件生成可执行文件的流程分两个阶段:
1、cmake根据cmakelists生成makefile
2、在makefile目录下执行make命令生成可执行文件

编写cmakelists

下面是编写cmakelists的一些简单规则:

main模块

cmake_minimum_required(VERSION 3.24)   # 设置cmake的最小版本

MESSAGE("start")   # MESSAGE可在执行cmakelists的过程中在控制台打印信息

project(c_test01 C)   # 编译的项目名

MESSAGE("middle")
#set(CMAKE_C_STANDARD 11)

add_subdirectory(test1)   # 把子文件夹也要编译

#include_directories(test1)   # 将该文件夹的头文件引入
#link_libraries(test1)   # 链接静态库用,需要在add_executable前使用

add_executable(c_test01 main.c)   # 生成可执行文件

TARGET_LINK_LIBRARIES(${PROJECT_NAME} test1)   # 链接动态库用,在add_executable后使用

MESSAGE("end")

test模块

#add_library(test1 STATIC test.c)   # 生成静态库

add_library(test1 SHARED test.c)   # 生成动态库

其中:
设置cmake版本

cmake_minimum_required(VERSION 3.24)


这里设置编译本项目的cmake最低版本为3.24,一般在cmakelists的开头。可以通过 cmake --version 查看当前的cmake版本,如果当前版本小于上述要求的最低版本,则编译停止。

设置项目名

project(c_test01 C)


声明项目的名字c_test01,后面的 C 是可选项,说明该项目是C语言的

添加子文件夹

add_subdirectory(test1)


编译本项目时将子文件也进行编译,子文件需要包含cmakelists

生成可执行文件

add_executable(c_test01 main.c)


生成可执行文件c_test01,源码为main.c。这里相当于gcc main.c -o mian.exe。

将子文件夹的头文件引入

include_directories(test1)


将该文件夹下的头文件引入到本项目

生成静态库和动态库

add_library(test1 STATIC test.c)
add_library(test1 SHARED test.c)


这两个是在子文件夹下生成静态库和动态库的,test1位库名。STATIC和SHARED指定库为静态库和动态库。库的源码是test.c。

链接静态库

link_libraries(test1)


这个是链接静态库的语句,由于静态库会编译进可执行文件中,所以要在add_executable前使用。

链接动态库

TARGET_LINK_LIBRARIES(${PROJECT_NAME} test1)


这个是链接动态库的语句,由于动态库是在可执行文件执行的过程中才使用,所以在add_executable后使用。

执行cmakelists过程中打印信息

MESSAGE(“start”)
MESSAGE(“middle”)
MESSAGE(“end”)


message是cmakelists的语言规则中可以打印信息到控制台的方法,message可以加一些选项规定打印信息的等级。参考
CMake的内置变量与message打印的用法

cmakelists的语法参考
CMakeLists详解
CMakeLists 入门

使用cmakelists方法

在要编译的cmakelists目录下新建一个build文件夹,这是一种约定俗成的使用习惯。因为执行cmakelists会生成很多文件,为了不影响项目的观感,故将这些文件放在build文件夹下。

mkdir build

然后进入build文件夹执行cmakelists

cd build
cmake ..
# 因为进入到主项目的build的文件夹,而cmakelists在build文件夹的退一层,所以需要 cmake ..
# 如果这步报错可以看看是不是本帖后面遇到的问题

此时build文件夹下会生成makefile和其他文件
执行cmake ..后生成的内容
然后就可以在build的目录下执行makefile来生成可执行文件和库文件了

make
# 如果有报错也可以看看是不是本帖后面遇到的问题

执行make命令后生成的库和可执行文件
接下来就可以执行可执行文件了,由于这里是在windows环境下,链接动态库需要将动态库复制到可执行文件同一目录下

cp .\test1\libtest1.dll ./

将库文件和可执行文件放在同一目录下
执行可执行文件

.\c_test01.exe

执行成功



初次使用遇到问题

其中,在windows使用cmakelists编译过程中

执行

cmake ..

遇到一个小问题

CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage

这里是cmake编译器没指定,解决方法为

cmake -G "MinGW Makefiles" ..

参考
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage

接着遇到问题

CMake Error: CMake was unable to find a build program corresponding to “MinGW Makefiles”. CMAKE_MAKE_PROGRAM is not set. You probably need to select a different build tool. CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage

出现这种问题一般是在安装MinGW 时没有下载相应的 make 的文件,解决办法为

打开MinGW Installation Manager,选择make文件下载


参考
CMake Error: CMake was unable to find a build program corresponding to “MinGW Makefiles“ 解决办法

接着在执行make命令的时候,遇到问题

make : 无法将“make”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 所在位置 行:1 字符: 1

在安装mingw的时候已经安装了make的exe,但名字为mingw32-make.exe,所以要么改一下make文件的名字,或者直接使用mingw32-make。

mingw32-make   

参考
VSCODE中使用CMAKE遇到的问题及其解决方法
windows下安装make

在执行可执行文件的过程中,遇到问题

由于找不到dll,无法继续执行代码,重新安装程序

这个是找不到动态库,我的做法是直接把动态库复制到当前可执行文件所在的目录。

cp .\test1\libtest1.dll ./

windows默认查找动态库的方法有几种,

1.exe文件所在的目录下;
2.进程当前的工作目录;
3.Windows系统目录;
4.Windows目录;
5.环境变量Path下的一系列目录;

参考
VS环境下,关于“找不到 **.dll,无法执行代码,重新安装程序可能会解决此问题。”的四种解决方案

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

gcc编译可执行文件和cmake编译可执行文件 的相关文章

  • Object.defineProperty方法(详解)

    OK xff0c 这一篇主要想说一下Object defineProperty这个方法 这个方法也是Vue数据双向绑定原理的常见面试题 所以也是有必要好好掌握的哦 首先我们知道JS中是支持面向对象编程的 xff0c 也是有着对象和类这样的概
  • 原生JS实现Promise(详解)

    摘要 首先呢 xff0c Promise是异步中比较重要的知识点 xff0c 学习的最好方法就是掌握它的基本原理 所以这一篇主要说一下如何用JS来实现一个自己的promise 构造函数 首先我们来看一下我们是如何使用promise的 xff
  • 解决winscp连接ubuntu虚拟机连续超时

    1 禁用虚拟机网络 在windows系统找到网络适配器 xff0c 禁用VMnet1和VMnet8 2 更改网络连接模式并测试网络是否连通 菜单栏 虚拟机 设置 网络适配器 xff0c 将网络模式改为桥接模式 xff0c 勾选 复制物理网络
  • Http的各种请求方法(详解)

    摘要 我们知道 xff0c 当我们访问各种网页的时候 xff0c 之所以能够看到页面 xff0c 根本原因是发送了http请求然后得到了响应 xff0c 从而页面才会弹出来 再或者我们上传一些照片和视频时 xff0c 之所以可以上传成功也是
  • React中ref的使用方法和使用场景(详解)

    摘要 不管在Vue中还是React xff0c 如果我们想使用一个元素的DOM xff0c 不需要通过JS中操纵DOM的方法 xff0c 它们提供了一个专属的API就是ref 而Vue中的ref可能比较简单 xff0c 这一篇主要讲一下如何
  • 原生JS的拖拽属性draggable(详解)

    摘要 作为h5新增的属性draggable xff0c 它能够给与一切的html元素拖动的效果 而在这个属性之下 xff0c 也有着关于拖动效果的各个方法 而这一篇文章 xff0c 主要就是说一下关于draggable属性的使用以及工作场景
  • 一篇搞定JS的位运算(公式+力扣真题)--- 持续更新

    摘要 位操作 xff08 Bit Manipulation xff09 是程序设计中对位模式或二进制数的一元和二元操作 在许多古老的微处理器上 xff0c 位运算比加减运算略快 xff0c 通常位运算比乘除法运算要快很多 在现代编程语言中
  • 【C++实现HTTP服务器项目记录】HTTP报文处理

    文章目录 一 HTTP报文格式1 请求报文2 响应报文 二 解析HTTP请求报文1 有限状态机2 状态转换图3 代码实现 三 生成HTTP响应报文1 代码实现 四 内存映射五 获取文件属性六 高级I O1 聚集写2 解决大文件传输问题 一
  • 使用PX4 模拟无人机起降 jmavsim或Gazebo环境下

    安装PX4的教程较多 xff0c 可在linux xff0c macos windows上进行安装 推荐Linux 笔者使用的是Ubuntu20 04 原因如下图 xff1a 安装好PX4后 cd到PX4安装目录 xff0c 启动仿真器 x
  • C++标准库--IO类库

    文章目录 前言一 IO类二 文件输入输出1 fstream的操作2 文件模式 三 String流 前言 C 43 43 语言本身没有输入输出 xff0c 而是通过定义在标准库中的类型来处理IO xff0c 这些类型支持从文件 xff0c 控
  • 总线协议一(UART/RS232/RS485/IIC/SPI)

    目录 基础概述 xff1a 一 UART xff08 为串口通信方式 xff09 二 RS232协议 三 RS485协议 四 I2C总线协议 五 SPI总线 六 I2C和SPI的区别 基础概述 xff1a 总线的本质就是一根导线 xff0c
  • HTTP协议分析(完整版)

    HTTP协议 一 http协议简介二 http工作原理1 客户端连接到Web服务器2 发送HTTP请求3 服务器接受请求并返回HTTP响应4 释放连接TCP连接5 客户端浏览器解析HTML内容 三 http请求方法四 http状态码1 状态
  • 【linux网络编程】-UDP客户端

    客户端实现 1 注 xff1a 客户端实现中可以不用bind地址 xff0c 当你发送数据到指定服务端时 xff0c 操作系统会为客户端自动分配端口 span class token keyword int span span class
  • 删除字符串中的各种标点符号的方法

    1 用re findall w 43 string 匹配字母 xff0c 数字和下划线 xff0c 返回列表 2 用 join 列表 将列表中元素再拼接成字符串
  • 在ubuntu18.04中切换python版本(个人记录)

    首先通过ls命令查一下目前ubuntu系统中已安装的python版本 ls l usr bin grep python 然后通过以下命令查看目前有哪些可供选择的python版本 update alternatives list python
  • ORB-SLAM2建立自己的数据集

    ORB SLAM2建立自己的数据集 使用ZED2拍摄视频剪裁视频分割图片运行数据集记录 使用ZED2拍摄视频 这里没有使用程序将ZED2双目相机拍摄成两幅画面 xff0c 而是直接使用软件拍摄视频 若有大佬有相关代码还是很希望能发我下 拍的
  • STM32—DMA功能讲解串口发送

    目录 一 DMA基本介绍 1 DMA的定义 2 DMA数据传输 二 DMA功能框图 编辑 1 DMA请求 2 通道 3 仲裁器 三 DMA数据配置 1 传输方向及地址 2 传输数据大小及单位 3 传输完成 三 DMA初始化结构体详解 1 D
  • 最新 Xilinx vivado IP许可申请

    最新 Xilinx vivado IP许可申请 xilinx的fpga使用vivado开发 xff0c zynq系列fpga的SOC开发成为主流 xff0c 加快fpga开发 xff0c 也进一步提高了fpga开发的灵活性 xilinx提供
  • C++调用Yolov3模型实现目标检测

    C 43 43 调用Yolov3模型实现目标检测 使用开源权重文件 xff0c 此训练模型包含80种物体 文件下载地址 xff1a 预训练权重文件 xff1a https pjreddie com media files yolov3 we
  • 无人驾驶-控制-坐标系转化

    无人驾驶 坐标系转化 一 坐标系概念1 1 WGS 84坐标系1 1 1 简介1 1 2 角度范围1 1 3 基本参数1 1 4 坐标系图示 1 2 ECEF地心坐标系1 2 1 简介1 2 2 坐标系图解 1 3 ENU东北天坐标系1 3

随机推荐

  • 几何实体图形保存成stl格式的ascII和二进制文。用Vc++语言读入文件,给三角网格坐标值乘以2,并保存到另一stl文件。输出完成工作所用的执行时间

    1 题目 xff1a CAD CAM软件生成几何实体图形 xff0c 图形形状不限 xff0c 但图形需包含曲面 xff0c 分别保存成stl格式的ascII和二进制文 用Vc 43 43 语言读入文件 xff0c 给所有三角网格坐标值乘以
  • windows下vscode连接Linux中的MySQL(非常实用)

    于初学Linux系统的小伙伴来说 xff0c 由于对Linux系统及其在windows下的环境配置比较生疏 xff0c 所以当使用windows下vscode连接Linux中的MySQL xff0c 并进行相关研发时 xff0c 颇为头疼
  • UDP通信实现(客户端和服务器端)

    服务器端 xff1a include lt stdio h gt include lt stdlib h gt include lt unistd h gt include lt string h gt include lt arpa in
  • conda环境的激活与关闭

    激活conda环境 conda activate 关闭conda环境 conda deactivate 打开终端自动进入conda环境 conda config set auto activate base true 关闭打开终端自动进入c
  • C语言结构体字节对齐规则

    注 xff1a 图片中蓝色圆圈表示空闲的字节空间 xff0c 黄色表示成员占有的字节空间 编译器一般默认4字节对齐 xff0c 当然也有8字节对齐的 xff0c 但是如果结构体没有使用8字节的数据类型 xff0c 其实也可以认为是4字节对齐
  • c语言输出对齐的方法

    关于c语言输出对其方法 左对齐右对齐附乘法表代码 左对齐 当输出多个数据时 xff0c 由于每个数据的字符长度不同 xff0c 所以需要对齐 xff0c 左对齐时方法如下 xff1a span class token function pr
  • 多线程与网络编程

    一 网络协议 应用层 HTTP FTP TFTP SMTP SNMP DNS 传输层 TCP UDP 网络层 ICMP IGMP IP ARP RARP 数据链路层 由底层网络定义的协议 物理层 由底层网络定义的协议 二 TCP与UDP x
  • const和define区别与比较

    xff08 1 xff09 就起作用的阶段而言 xff1a define是在编译的预处理阶段起作用 xff0c 而const是在编译 运行的时候起作用 xff08 2 xff09 就起作用的方式而言 xff1a define只是简单的字符替
  • FreeRTOS中任务栈内存分配

    前言 在RAM中大多数的空间分配为任务栈和系统栈两部分 任务栈 xff1a 顾名思义就是用来跑任务的 xff0c 当我们xTaskCreate一个任务时 xff0c 但是在这块任务栈里面动态分配空间 系统栈 xff1a 任务栈是不使用这里的
  • 网络编程(0816-林雪阵)

    完成seclect TCP客户端 include lt stdio h gt include lt sys types h gt include lt sys socket h gt include lt arpa inet h gt in
  • yolov5获取边框坐标

    这里使用的是5 0版本 打开detect py xff0c 找到 Write results模块 xff0c 找到 save one box ctr 43 鼠标点击 xff0c 进入general py xff0c 会自动定位到 save
  • ROS介绍以及常用指令

    ROS 1 什么是ros ROS 的雏形诞生 xff1a 斯坦福大学人工智能实验室的STAIR 机器人项目这个项目希望完成一个服务机器人原型 xff0c 在视觉的辅助下 xff0c 可以在复杂环境中运动 xff0c 还可以通过机械臂操控环境
  • 基于ROS的YOLOV3实现目标检测项目过程记录

    2020 08 07 问题记录 1 要命的darknet ros 整体逻辑是用yolo检测出目标 然后通过ros节点将目标类别和位置信息发布出来 因此选择ros darknet 2个问题 1 依赖opencv和boost boost库安装过
  • 【Jetson目标检测SSD-MobileNet应用实例】(五)根据输出的检测结果,使用串口和STM32配合进行电机控制

    Jetson目标检测SSD MobileNet应用实例 xff08 一 xff09 win11中配置SSD MobileNet网络训练境搭建 Jetson目标检测SSD MobileNet应用实例 xff08 二 xff09 制作自己的数据
  • QT5.14串口调试助手:上位机接收数据解析数据帧+多通道波形显示+数据保存为csv文件

    由于业务需要 xff0c 在上个月做了一个关于qt的设计 xff0c 在设计中主要需要解决的问题就是接收单片机采集到的数据并在上位机将数字实时的通过波形显示出来 xff0c 然后上位机要有保存下数据文件的功能 xff0c 便于后续的软件读取
  • 如何使用Cmake编译

    目录 一 Cmake是一种跨平台编译工具 二 CMake说明 三 编写CMakeList txt 四 使用 cmake 一 Cmake是一种跨平台编译工具 比make更高级 xff0c 使用起来要方便得多 CMake主要是编写CMakeLi
  • 51单片机串口通信篇

    串行通信 基本介绍波特率通信校验内部结构 并行通信串行通信串行通信方式同步通信异步通信 串行口的控制寄存器SCON寄存器PCON寄存器中断源及优先级 串口通信配置步骤 相关程序简单例程1简单例程2 基本介绍 单片机通信是指单片机和单片机 或
  • 0基础学会 UDP通信(内附C语言源码)

    include lt sys types h gt include lt sys socket h gt ssize t sendto int socketfd const void buf size t len int flags con
  • C++ --头文件和类的声明

    函数 function 是为了处理数据 数据的实质就是变量 xff08 variables xff09 C是所有的函数都可以去处理任意声明的变量 C 43 43 面向对象的编程思想就是 把函数名和变量名封装起来 xff08 也就是类 xff
  • gcc编译可执行文件和cmake编译可执行文件

    gcc编译 gcc的下载 xff08 下载mingw xff0c 里面包含gcc xff09 下载安装MinGW w64详细步骤 xff08 c c 43 43 的编译器gcc的windows版 xff0c win10真实可用 xff09