草庐IT

【Ubuntu】gcc与Makefile操作

程序喵正在路上 2023-07-17 原文

🔥 本文由 程序喵正在路上 原创,CSDN首发!
💖 系列专栏:虚拟机
🌠 首发时间:2022年9月10日
🦋 欢迎关注🖱点赞👍收藏🌟留言🐾
🌟 一以贯之的努力 不得懈怠的人生

阅读指南

什么是gcc?

  • Linux 环境下编译 C 语言程序的工具

在命令终端输入:gcc -v 可以查询当前系统安装的 gcc 版本

如果我们有 hello.cC 语言源代码,那么编译的命令是:gcc -o hello hello.c

gcc处理源代码的流程

  1. 预处理阶段:对 .c 文件的包含、预处理等语句的处理,并生成名为 test.i 的中间文件
  2. 编译阶段:以 test.i 为输入,编译生成汇编语言文件 test.s
  3. 汇编阶段:以 test.s 为输入,生成目标文件 test.o
  4. 链接阶段:将使用到库函数链接到可执行程序中的正确位置,形成二进制代码文件

gcc常用的参数选项

  • -c:仅生成拓展名为 .o 的目标文件,不链接生成可执行文件
  • -o 文件名:指定 gcc 可执行文件名,系统默认生成的可执行文件名为 a.out
  • -g:编译时加入调试信息,使得后期方便对程序进行调试,主要是为支持 gdb 的调试

Ubuntu下的C程序

那么在 ubuntu 中我们怎么来创建和编辑 C 语言程序呢?

很简单

  1. 使用 Ctrl + Alt + t 打开终端
  2. 使用 mkdir 文件夹名 来创建文件夹
  3. 使用 touch mytest.cpp 创建 C 文件
  4. 创建完 C 文件后,我们需要进行编写文件。ubuntu 中提供了一个程序编辑软件 gedit,我们借助命令 gedit mytest.cpp 就会弹出编辑对话框,如何就可以在其中进行编辑,当然你也可以选择找到 mytest.cpp 后双击打开
  5. 编辑完记得保存文件
  6. 在命令行中输入 gcc mytest.cpp 编译文件,若没有出错则编译成功
  7. 编译成功后会生成一个可执行文件 a.out,在命令行中输入 ./a.out 运行程序

mytest.cpp

操作如图:

编译后可以发现多了一个 a.out 文件

刚才的编译是没有带参数的,下面我们试试看使用带参数的编译

gdb的简单使用

什么是 gdb ?

  • gdbgnu 开源组织发布的、用来调试 C 程序的调试工具

怎么使用?

  • gdb 程序名

常用的 gdb 功能如下

  • list 命令:显示程序源代码
  • break 行号:给程序对应的行号打断点
  • break 函数名:给函数的入口设置断点
  • info break:查看全部断点信息
  • delete 断点号:删除对应编号的断点
  • run:开始运行程序,直到遇到断点
  • continue(缩写为 c):程序继续执行
  • next(缩写为 n):执行下一语句
  • quit:退出调试

直接采用gcc编译文件的问题

当一个应用程序涉及到的 C 语言源代码文件达到成百上千后,直接采用 gcc 编译会出现以下问题:

  • 手动去敲每个编译命令不现实
  • 当修改某个文件时,要避免对所有的文件进行编译链接,只对依赖该文件的部分进行重新编译链接,节省时间

Makefile

什么是Makefile?

  • 自动化编译 C 语言程序的脚本工具

为什么需要 Makefile 呢?

  • 为了解决 gcc 编译的不足

如何使用 Makefile?

  • 根据应用程序的文件数量,依赖关系等书写 Makefile 编译脚本
  • 包含 Makefile 编译脚本的目录下,敲击 make 命令

创建两个文件:cal.cadd.c

对应的 Makefile

cal: cal.o add.o
	gcc -o cal cal.o add.o
cal.o: cal.c 
	gcc -c cal.c
add.o: add.c 
	gcc -c add.c

冒号左边的文件依赖于右边的文件

cal.cadd.c 文件的同目录下创建一个名为 Makefile 的文本文件:

Makefile 的自动推导功能

make 命令可以自动推导文件以及文件依赖关系后面的命令,make 会自动识别并自己推导命令。只要 make 查到某个 .o 文件,它就会自动把相关的 .c 加到依赖文件中

Makefile 常用的符号

  • $@:表示当前目标文件的名字
  • $^:表示用空格隔开的所有依赖文件
  • $<:表示第一个依赖文件
  • $+:与 $^ 类似,只是没有排除重复的条件
  • $*:目标的主文件名,不包含拓展名

简化的 Makefile 如下:

cal: cal.o add.o
	gcc -o $@ $^
cal.o: cal.c 
	gcc -c $<
add.o: add.c 
	gcc -c $<

多层次目录结构的Makefile

之前的案例:cal.cadd.c 源代码与 Makefile 在同一个目录

现在:cal.cadd.c 位于 src 目录,而 Makefile 位于 src 的父级目录

要求:编译 cal.cadd.c 文件,并将可执行文件放置于父级目录

环境需要自己准备,记得将 Makefile 改成这样:

编译运行过程:

清理掉不需要的文件:

有关【Ubuntu】gcc与Makefile操作的更多相关文章

  1. ruby-on-rails - 无法在centos上安装therubyracer(V8和GCC出错) - 2

    我正在尝试在我的centos服务器上安装therubyracer,但遇到了麻烦。$geminstalltherubyracerBuildingnativeextensions.Thiscouldtakeawhile...ERROR:Errorinstallingtherubyracer:ERROR:Failedtobuildgemnativeextension./usr/local/rvm/rubies/ruby-1.9.3-p125/bin/rubyextconf.rbcheckingformain()in-lpthread...yescheckingforv8.h...no***e

  2. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

    我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

  3. Vscode+Cmake配置并运行opencv环境(Windows和Ubuntu大同小异) - 2

    之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m

  4. 在VMware16虚拟机安装Ubuntu详细教程 - 2

    在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主

  5. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  6. ruby - 如何使用 Selenium Webdriver 根据 div 的内容执行操作? - 2

    我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption

  7. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  8. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  9. ruby - 在 Ruby 中是否有一种惯用的方法来操作 2 个数组? - 2

    a=[3,4,7,8,3]b=[5,3,6,8,3]假设数组长度相同,是否有办法使用each或其他一些惯用方法从两个数组的每个元素中获取结果?不使用计数器?例如获取每个元素的乘积:[15,12,42,64,9](0..a.count-1).eachdo|i|太丑了...ruby1.9.3 最佳答案 使用Array.zip怎么样?:>>a=[3,4,7,8,3]=>[3,4,7,8,3]>>b=[5,3,6,8,3]=>[5,3,6,8,3]>>c=[]=>[]>>a.zip(b)do|i,j|c[[3,5],[4,3],[7,6],

  10. ruby-on-rails - 如何让 Rails View 返回其关联的操作名称? - 2

    我有一个非常简单的Controller来管理我的Rails应用程序中的静态页面:classPagesController我怎样才能让View模板返回它自己的名字,这样我就可以做这样的事情:#pricing.html.erb#-->"Pricing"感谢您的帮助。 最佳答案 4.3RoutingParametersTheparamshashwillalwayscontainthe:controllerand:actionkeys,butyoushouldusethemethodscontroller_nameandaction_nam

随机推荐