【Linux】【编译】编译及Makefile的调试手段和技巧

简介: 【Linux】【编译】编译及Makefile的调试手段和技巧

前言


在Linux开发过程中,经常会遇到各种编译问题。比较简单的问题一目了然,但有些比较复杂,较难分析。本文将编译中常见的调试手段、技巧做一总结,供各位参考。


常用手段和技巧


错误代码


经常遇到某个宏不生效的问题,这种情况,可以在宏控制的部分增加错误,看是否会有编译报错。


部分编译


如果一个项目比较庞大,直接make比较耗时间,此时,有两个选择:


  • 只编译出问题的模块或目录;


  • 注掉部分暂时无问题的模块(比如,有的sdk驱动和用户态app在一起编译,在调试app的编译的过程中,就可以把sdk驱动暂时注掉);


gcc相关


  • -E选项


– 当需要确定预处理相关的信息,如头文件包含、宏展开等情况,可使用这个选项;


– 只激活预处理,不生成文件;


– 仅对依赖关系做初步解析,没有-M等全面深入;


gcc -E hello.c               #默认输出到屏幕上;
gcc -E hello.c -o hello.i    #将输出重定向到文件;
gcc -E hello.c > hello.txt   #将输出重定向到文件;
gcc -E -C hello.c -o hello.i #在第二条的基础上,可阻止预处理器删除源文件和头文件中的注释;


  • 编译器依赖生成选项,-M选项、-MM选项、-MMD选项


其作用在于自动找寻源文件中包含的头文件,并生成一个依赖关系。


gcc -M obj.c              #获取目标obj.c的完整依赖关系
gcc -MD obj.c             #在-M的基础上,将输出导出到.d文件;
gcc -MM obj.c             #在-M的基础上,去除标准库的头文件;
gcc -MMD obj.c            #在-MM的基础上,将输出将导到.d文件:
gcc -MM -MF "obj.d" obj.c #-MF可以指定输出文件,前面几个命令默认用obj.d文件;


例1、一个简单例子:


[qxhgd@localhost]$ gcc -M test.c
test.o: test.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/features.h /usr/include/sys/cdefs.h \


例2、一个完整例子:


SRCS=$(wildcard *.c)
OBJS=$(SRCS:.c=.o)
DEPS=$(SRCS:.c=.d)
.PHONY: all clean
all: main
-include $(DEPS)  
%.o:%.c
    gcc -c -g -Wall $< -o $@ -MD -MF $*.d -MP  #“-MF $*.d ”可以去除;
main: $(OBJS)
    gcc $^ -o $@  
clean: 
  rm -f  *.d *.o main


shell命令


  • echo方法


echo  some info  #显示echo这条命令本身和后面要输出的内容
@echo some info  #不会显示echo这条命令,只会显示后面要输出的内容


例1、打印一个变量值:


@echo "########### VAR=" $(VAR)


例2、将宏定义输入到h文件中:


@echo "#define BUILD_DATE            \"`date +%Y-%m-%d`\"" > $(INCDIR)/version.h


Makefile内置函数


$(info ...)    #不打印当前makefile名和行号
$(warning ...) #不中断makefile的执行,打印信息,并打印当前makefile文件名和行号
$(error ...)   #含warning的功能,同时会中断makefile的执行并退出


例1、打印信息


$(warning These ARMv8 Crypto Extensions modules need binutils 2.23 or higher)


例2、打印变量


$(warning The '$(SPHINXBUILD)' command was not found.)


编译重定向


make xxx > build_output.txt #将编译过程重定向到txt文件,错误在屏幕会显示;
make xxx 2> build_output.txt #仅将make输出中的错误(及警告)信息输出到文件中
make xxx 1> build_output.txt #仅需要把make输出中的正常(非错误,非警告)的信息输出到文件
make xxx 1> build_output_normal.txt 2>build_output_error.txt #正常信息和错误信息,都输出到对应文件中
make xxx > build_output_all.txt 2>&1 #所有的信息都输出到同一个文件中


make命令行选项


--just-print(-n)         #输出makefile中的所有数据,包括所有的规则和变量;只显示命令,但不会执行命令;
--dry-run                  #和-n类似,只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行
--recon                    #和-n类似,只是打印命令,不管目标是否更新,把规则和连带规则下的命令打印出来,但不执行
--print-data-base(-p)    #显示GNU版权信息以及make 所运行的命令,然后输出它的内部数据库;
--debug                    #当你需要知道make如何分析你的依存图时,可以使用--debug 选项。共计五个调试级别和一个修饰符可用,basic、verbose、implicit、jobs、all 以及makefile;
--trace                    #类似于Shell 里头的 set -x;
-W <file>                  # 这个参数需要指定一个文件。一般是是源文件(或依赖文件),Make会根据规则推导来运行依赖于这个文件的命令,一般来说,可以和“-n”参数一同使用,来查看这个依赖文件所发生的规则命令。另外一个很有意思的用法是结合“-p”和“-v”来输出makefile被执行时的信息
--what-if=<file>           #类似于-W;
--assume-new=<file>        #类似于-W;
--new-file=<file>          #类似于-W;
--touch(-t)               #把目标文件的时间更新,但不更改目标文件。也就是说,make假装编译目标,但不是真正的编译目标,只是把目标变成已编译过的状态。


例子:


make --trace xxx #展开xxx目标代码的执行过程;
make --debug xxx #展开整个make解析和执行xxx的过程;


remake


官方链接


  • remake is an enahanced version of GNU Make that adds improved error reporting, better tracing, profiling and a debugger.


小结


上述这些方法,基本可以覆盖Makefile常用的调试场景。

相关文章
|
9天前
|
缓存 NoSQL Linux
Linux调试
本文介绍了Linux调试、性能分析和追踪的培训资料,涵盖调试、性能分析和追踪的基础知识及常用工具。
149 6
Linux调试
|
30天前
|
Linux API 开发工具
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
ijkplayer是由B站研发的移动端播放器,基于FFmpeg 3.4,支持Android和iOS。其源码托管于GitHub,截至2024年9月15日,获得了3.24万星标和0.81万分支,尽管已停止更新6年。本文档介绍了如何在Linux环境下编译ijkplayer的so库,以便在较新的开发环境中使用。首先需安装编译工具并调整/tmp分区大小,接着下载并安装Android SDK和NDK,最后下载ijkplayer源码并编译。详细步骤包括环境准备、工具安装及库编译等。更多FFmpeg开发知识可参考相关书籍。
82 0
FFmpeg开发笔记(五十九)Linux编译ijkplayer的Android平台so库
|
1月前
|
Linux 编译器 C语言
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
【Linux快速入门(一)】Linux与ROS学习之编译基础(gcc编译)
|
17天前
|
Linux
Linux - 如何编译源码安装软件
源码编译安装通常包括三个步骤:1) `./configure` 检测平台特征和依赖项,生成 Makefile;2) `make` 编译源码,生成可执行文件;3) `make install` 将可执行文件安装到指定目录并配置环境变量。
31 0
|
1月前
|
Linux C++
Linux c/c++之makefile的基础使用
Linux下C/C++项目中makefile的基本使用,包括基础、进阶和高级用法,以及如何创建和使用makefile来自动化编译过程。
15 0
Linux c/c++之makefile的基础使用
|
1月前
|
Linux 编译器 C语言
Linux c/c++之多文档编译
这篇文章介绍了在Linux操作系统下使用gcc编译器进行C/C++多文件编译的方法和步骤。
39 0
Linux c/c++之多文档编译
|
1月前
|
Linux 开发工具
【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)
【Linux快速入门(二)】Linux与ROS学习之编译基础(make编译)
|
2月前
|
Linux
用clang编译Linux内核
用clang编译Linux内核
|
5天前
|
Linux
在 Linux 系统中,“cd”命令用于切换当前工作目录
在 Linux 系统中,“cd”命令用于切换当前工作目录。本文详细介绍了“cd”命令的基本用法和常见技巧,包括使用“.”、“..”、“~”、绝对路径和相对路径,以及快速切换到上一次工作目录等。此外,还探讨了高级技巧,如使用通配符、结合其他命令、在脚本中使用,以及实际应用案例,帮助读者提高工作效率。
22 3
|
5天前
|
监控 安全 Linux
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景
在 Linux 系统中,网络管理是重要任务。本文介绍了常用的网络命令及其适用场景,包括 ping(测试连通性)、traceroute(跟踪路由路径)、netstat(显示网络连接信息)、nmap(网络扫描)、ifconfig 和 ip(网络接口配置)。掌握这些命令有助于高效诊断和解决网络问题,保障网络稳定运行。
17 2