makfile的编译选项:CFLAGS、CPPFLAGS、LDFLAGS、LIBS

article/2025/10/6 7:26:53

1、LDFLAGS & LIBS

关于makefile的依赖规则以及目标生成的步骤,这篇先不介绍,这里主要关注我在看makefile时遇到的一堆CFLAGS与LDFLAGS定义进行说明。

费了牛劲,才查到GNUmake中文手册中关于CFLAGS与LDFLAGS的说明,他们都是是隐含规则的变量,且是一种命令参数变量;然后又到GCC手册中查找有哪些编译选项。

makefile内嵌隐含规则的命令中,所使用的变量都是预定义的变量。我们将这些变量称为“隐含变量”。

这些变量允许对它进行修改:在Makefile中、通过命令行参数或者设置系统环境变量的方式来对它进行重定义

无论是用那种方式,只要make在运行时它的定义有效,make的隐含规则都会使用这些变量。

1.1 先瞅一眼

LDFLAGS是选项,LIBS是要链接的库。
结果都传给ld,前者告诉到哪里找?后者是找什么?

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/libLIBS = -lmysqlclient -liconv

LDFLAGS告诉链接器从哪里寻找库文件,LIBS告诉链接器要链接哪些库文件。

使用时链接阶段这两个参数都会加上,因此将这两个的值互换,也没有问题。

LDFLAGS指定-L虽然能让链接器找到库进行链接,但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,那么我们需要增加这两个库给"-Wl,R"

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib
PS:-Wl,R在GraphicsMagick环境下,用为-R, 也就是LDFLAGS = -L/var/xxx/lib -R/var/xxx/lib

1.2 详细看看

GCC编译选项CFLAGS参数

在这里插入图片描述

GCC链接选项LDFLAGS参数

在这里插入图片描述

CFLAGS = -g -Wall -I./include -I./include/tinyalsa -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -lc
LDFLAGS = -L./lib
ALL:$(CC) $(CFLAGS) $(LDFLAGS) main.c gfifo.c queue.c usbmonitor.c socket_rcv_360_server.c ./lib/srs_librtmp.a ./lib/libcrypto.a ./lib/libssl.a ./lib/libtinyalsa.a -o media_record -static -ldl -lstdc++ -lm -lpthread
clean:rm media_record *.raw *.mp4 *.wav -rfCFLAGS = -g -Wall -I./include -I./include/tinyalsa -Wl,--whole-archive -lpthread -Wl,--no-whole-archive -lc
-g:生成调试信息
-Wall:输出全部的告警信息
-I./include:添加头文件搜索目录./include
-I./include/tinyalsa:添加头文件搜索目录./include/tinyalsa
-Wl,--whole-archive -lpthread:将libpthread.so及以后的库中的所有符号都链接进可执行目标文件
-Wl,--no-whole-archive:关闭之前的-Wl,--whole-archive -lpthread 选项
LDFLAGS = -L./lib,将makefile当前目录下的、lib文件夹添加到库文件搜索目录$(CC):makefile隐含变量,默认选择gcc编译器
$(CFLAGS):引用之前定义的CFLAGS变量,即编译选项参数
$(LDFLAGS):引用之前定义的LDFLAGS变量,即链接参数$(CC) $(CFLAGS) $(LDFLAGS) main.c gfifo.c queue.c usbmonitor.c socket_rcv_360_server.c ./lib/srs_librtmp.a ./lib/libcrypto.a ./lib/libssl.a ./lib/libtinyalsa.a -o media_record -static -ldl -lstdc++ -lm -lpthread
使用定的编译器、编译选项参数、链接选项参数,编译.c文件,并使用静态方式链接制定的库文件,以及编译器目录下的libdl.a、libstdc++.a、libm.a、libpthread.a库文件生成 media_record 可执行目标文件。

重复

CFLAGS 表示用于 C 编译器的选项,

CXXFLAGS 表示用于 C++ 编译器的选项。

这两个变量实际上涵盖了编译和汇编两个步骤。

CFLAGS: 指定头文件(.h文件)的路径,如:CFLAGS=-I/usr/include -I/path/include。同样地,安装一个包时会在安装路径下建立一个include目录,当安装过程中出现问题时,试着把以前安装的包的include目录加入到该变量中来。

LDFLAGS:gcc 等编译器会用到的一些优化参数,也可以在里面指定库文件的位置。

LDFLAGS=-L/usr/lib -L/path/to/your/lib。每安装一个包都几乎一定的会在安装目录里建立一个lib目录。如果明明安装了某个包,而安装另一个包时,它愣是说找不到,可以抒那个包的lib路径加入的LDFALGS中试一下。

LIBS:告诉链接器要链接哪些库文件,如LIBS = -lpthread -liconv

简单地说,LDFLAGS是告诉链接器从哪里寻找库文件,而LIBS是告诉链接器要链接哪些库文件。不过使用时链接阶段这两个参数都会加上,所以你即使将这两个的值互换,也没有问题。

有时候LDFLAGS指定-L虽然能让链接器找到库进行链接,但是运行时链接器却找不到这个库,如果要让软件运行时库文件的路径也得到扩展,那么我们需要增加这两个库给"-Wl,R":

LDFLAGS = -L/var/xxx/lib -L/opt/mysql/lib -Wl,R/var/xxx/lib -Wl,R/opt/mysql/lib

CFLAGS 标志参数实例说明

CFLAGS = -g -O2  -Wall -Werror -Wno-unused

编译出现警告性错误unused-but-set-variable,变量定义但没有使用,解决方法:
增加 CFLAGS 或CPPFLAGS参数如下:

 CPPFLAGS=" -Werror -Wno-unused-but-set-variable" || exit 1

在这里插入图片描述

“-I dir”

正如上表中所述,“-I dir”选项可以在头文件的搜索路径列表中添加dir目录。

由于Linux中头文件都默认放到了“/usr/include/”目录下,因此,当用户希望添加放置在其他位置的头文件时,就可以通过“-I dir”选项来指定,这样,Gcc就会到相应的位置查找对应的目录。
比如在“/root/workplace/Gcc”下有两个文件:

#includeint main(){printf(“Hello!!\n”);return 0;}#include

这样,就可在Gcc命令行中加入“-I”选项:

[root@localhost Gcc] Gcc hello1.c –I /root/workplace/Gcc/ -o hello1

这样,Gcc就能够执行出正确结果。

在include语句中,“<>”表示在标准路径中搜索头文件,““””表示在本目录中搜索。故在上例中,可把hello1.c的“#include”改为“#include “my.h””,就不需要加上“-I”选项了。

“-L dir”

选项“-L dir”的功能与“-I dir”类似,能够在库文件的搜索路径列表中添加dir目录。例如有程序hello_sq.c需要用到目录“/root/workplace/Gcc/lib”下的一个动态库libsunq.so,则只需键入如下命令即可:

[root@localhost Gcc] Gcc hello_sq.c –L /root/workplace/Gcc/lib –lsunq –o hello_sq

需要注意的是,“-I dir”和“-L dir”都只是指定了路径,而没有指定文件,因此不能在路径中包含文件名。

另外值得详细解释一下的是“-l”选项,它指示Gcc去连接库文件libsunq.so。由于在Linux下的库文件命名时有一个规定:必须以lib三个字母开头。因此在用-l选项指定链接的库文件名时可以省去lib三个字母。也就是说Gcc在对”-lsunq”进行处理时,会自动去链接名为libsunq.so的文件。

(2)告警和出错选项

在这里插入图片描述

下面结合实例对这几个告警和出错选项进行简单的讲解。

如有以下程序段:

#includevoid main(){long long tmp = 1;printf(“This is a bad code!\n”);return 0;}

这是一个很糟糕的程序,读者可以考虑一下有哪些问题?

· “-ansi”

该选项强制Gcc生成标准语法所要求的告警信息,尽管这还并不能保证所有没有警告的程序都是符合ANSI C标准的。运行结果如下所示:

[root@localhost Gcc]# Gcc –ansi warning.c –o warning
warning.c: 在函数“main”中:warning.c:7 警告:在无返回值的函数中,“return”带返回值warning.c:4 警告:“main”的返回类型不是“int”

可以看出,该选项并没有发现”long long”这个无效数据类型的错误。

· “-pedantic”

允许发出ANSI C标准所列的全部警告信息,同样也保证所有没有警告的程序都是符合ANSI C标准的。其运行结果如下所示:

[root@localhost Gcc]# Gcc –pedantic warning.c –o warning
warning.c: 在函数“main”中:warning.c:5 警告:ISO C90不支持“long long”warning.c:7 警告:在无返回值的函数中,“return”带返回值warning.c:4 警告:“main”的返回类型不是“int”

可以看出,使用该选项查看出了”long long”这个无效数据类型的错误。

· “-Wall”

允许发出Gcc能够提供的所有有用的报警信息。该选项的运行结果如下所示:

[root@localhost Gcc]# Gcc –Wall warning.c –o warning
warning.c:4 警告:“main”的返回类型不是“int”warning.c: 在函数”main”中:warning.c:7 警告:在无返回值的函数中,”return”带返回值warning.c:5 警告:未使用的变量“tmp”

使用“-Wall”选项找出了未使用的变量tmp,但它并没有找出无效数据类型的错误。

另外,Gcc还可以利用选项对单独的常见错误分别指定警告,有关具体选项的含义感兴趣的读者可以查看Gcc手册进行学习。

(3)优化选项

Gcc可以对代码进行优化,它通过编译选项“-On”来控制优化代码的生成,其中n是一个代表优化级别的整数。对于不同版本的Gcc来讲,n的取值范围及其对应的优化效果可能并不完全相同,比较典型的范围是从0变化到2或3。

不同的优化级别对应不同的优化处理工作:

  • 如使用优化选项“-O”主要进行线程跳转(Thread Jump)和延迟退栈(Deferred Stack Pops)两种优化。
  • 使用优化选项“-O2”除了完成所有“-O1”级别的优化之外,同时还要进行一些额外的调整工作,如处理器指令调度等。
  • 选项“-O3”则还包括循环展开和其他一些与处理器特性相关的优化工作。

虽然优化选项可以加速代码的运行速度,但对于调试而言将是一个很大的挑战。

因为代码在经过优化之后,原先在源程序中声明和使用的变量很可能不再使用,控制流也可能会突然跳转到意外的地方,循环语句也有可能因为循环展开而变得到处都有,所有这些对调试来讲都将是一场噩梦。所以笔者建议在调试的时候最好不使用任何优化选项,只有当程序在最终发行的时候才考虑对其进行优化。

(4)体系结构相关选项

在这里插入图片描述

参考资料:

https://blog.csdn.net/hxlawf/article/details/94623786
https://blog.csdn.net/xinyuan510214/article/details/50457433


http://chatgpt.dhexx.cn/article/rfPvRkgl.shtml

相关文章

Makefile 编译与链接选项及CFLAGS与LDFLAGS说明

CFLAGS与LDFLAGS的说明&#xff0c;他们都是是隐含规则的变量&#xff0c;且是一种命令参数变量&#xff0e; makefile内嵌隐含规则的命令中&#xff0c;所使用的变量都是预定义的变量。我们将这些变量称为“隐含变量”。这些变量允许对它进行修改&#xff1a;在Makefile中、通…

Go新项目-项目添加版本说明,以及参数传递:ldflags、gcflags,外加stripped说明(5)

在Go项目中&#xff0c;会存在展示该项目的版本信息&#xff0c;以及打包日期&#xff0c;项目版本&#xff0c;Go版本等&#xff1b;继Go新项目-编译项目的细节&#xff08;4&#xff09;以后再记录下编译优化方向&#xff0c;刚好也有项目版本输出的需求。 关键词&#xff1…

linux编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解

参考到下面博客&#xff0c;把编译步骤分解的很细 linuxC编译参数CPPFLAGS、CFLAGS、LDFLAGS参数的理解 - yongfengnice - 博客园 CPPFLAGS : 预处理器需要的选项 如&#xff1a;-I (大写i指定头文件路径) CFLAGS&#xff1a;编译的时候使用的参数 –Wall –g -c LDFLAGS &…

【Java位运算】异或运算的使用

异或运算有个特性&#xff1a;两个相同的数做异或运算&#xff0c;结果为0。 n ^ n 0;常用的方式是查找数组中只出现一次的数字。 例如&#xff1a;在一个数组中&#xff0c;只有一个数字出现了一次&#xff0c;其余数字都出现了两次。 求这个数字。利用异或运算的特性进行计…

java中与运算,或运算,异或运算

Java的位运算符详解实例——与&#xff08;&&#xff09;、非&#xff08;~&#xff09;、或&#xff08;|&#xff09;、异或&#xff08;^&#xff09; 位运算符主要针对二进制&#xff0c;它包括了&#xff1a;“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻…

Java中的与、或、非以及异或( | ~ ^)运算符的运算原理

首先&#xff0c;我们要知道Java存储数据是保存的补码&#xff0c;如果对原码、反码以及补码不太懂&#xff0c;可以参考我的另一篇博客。 1. Java的 与( & ) 运算 所有的逻辑运算都是按位计算的&#xff0c;所以第一步就是先把数据转成二进制&#xff0c;然后相应位进行…

java运算符 与()、非(~)、或(|)、异或(^)

欢迎大家关注我的公众号【老周聊架构】&#xff0c;Java后端主流技术栈的原理、源码分析、架构以及各种互联网高并发、高性能、高可用的解决方案。 位运算符主要针对二进制&#xff0c;它包括了&#xff1a;“与”、“非”、“或”、“异或”。从表面上看似乎有点像逻辑运算符&…

java中的异或非运算

一、java 与或非 操作 与&#xff08;&&#xff09;、非&#xff08;~&#xff09;、或&#xff08;|&#xff09;、异或&#xff08;^&#xff09; 1&#xff0e;与运算符 与运算符用符号“&”表示&#xff0c;其使用规律如下&#xff1a; 两个操作数中位都为1&#x…

java运算符异或(^)的用法

Java中的位运算符中有一个叫做异或的运算符&#xff0c;符号为&#xff08;^&#xff09;,其主要是对两个操作数进行位的异或运算&#xff0c;相同取0&#xff0c;相反取1。即两操作数相同时&#xff0c;互相抵消。 试例&#xff1a;13 与15 两个整数的异或 public static void…

一文搞懂 位运算 异或(Java实现)

提起异或想必很多小伙伴们既熟悉又陌生&#xff0c;熟悉是因为好像在离散数学或者学某个编程语言 时听过这个东西&#xff0c;而陌生呢&#xff0c;则是因为自己平时并没有用过&#xff0c;以至于当在某个场景 &#xff08;我猜是在看 题解或者某篇博客时&#xff09; 看到这…

java中异或运算的应用

java中异或运算(^)的应用 异或运算法则 1. a ^ b b ^ a   2. a ^ b ^ c a ^ (b ^ c) (a ^ b) ^ c;   3. d a ^ b ^ c 可以推出 a d ^ b ^ c.   4. a ^ b ^ a b. 异或运算 1、异或是一个数学运算符。应用于逻辑运算。   2、例如&#xff1a;真异或假的结果是…

java的异或运算

一、题目 输入两个数&#xff0c;交换后输出 二、解题思路 一开始学习的语言是c语言&#xff0c;里面非常有特色的是指针&#xff0c;通过传引用可以直接交换两个数。但java无法达成这种操作&#xff0c;翻阅资料找到了一种有趣的解法&#xff1a;异或! 异或原理&#xff1a; …

java基础-异或运算

小伙伴们&#xff0c;你们好呀&#xff01;我是老寇&#xff01; 异或运算主要用于判断两个值是否一样 异或运算的3个性质&#xff1a; 1.任何数和0进行异或运算&#xff0c;结果是原来的数&#xff0c;即b⊕0b 2.任何数和其自身进行异或运算&#xff0c;结果为0&#xff0c;即…

Java中的异或运算符^

Testpublic void test2() {int a2;int b3;aa^b;ba^b;aa^b;System.out.println("a"a",b"b);}第一种&#xff1a;用真实值计算 ^是异或运算符&#xff0c;异或的规则是转换成二进制比较&#xff0c;相同为0&#xff0c;不同为1. 一个数a与另一个数b异或的结果…

java中的异或运算

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是Rockey&#xff0c;不知名企业的不知名Java开发工程师 &#x1f525;如果感觉博主的文章还不错的话&#xff0c;请&#x1f44d;三连支持&#x1f44d;一下博主哦 &#x1f4dd;联系方式&#xff1a;he18339193956&…

HTTP Status 505 – HTTP Version Not Supported

这个大部分的原因不是httpserver不支持&#xff0c;而是请求url里有空格&#xff0c;检查有空格UTF-8编码再传 比如&#xff1a;远程调用服务端地址有空格 去除空格

HTTP Status 500 解决办法

HTTP Status 500 解决办法 在Java web 论坛系统中也遇见了这个问题&#xff0c;在这里就提供一个解决的办法。 图中显示 int idInteger.parseInt(request.getParameter("id")); 这一段有错误。这里是因为id的值不能为null&#xff0c;不然就会出现这个错误 修改如…

Tomcat HTTP Status 404 tomcat 404问题解决

今天初次使用tomcat的时候&#xff0c;用浏览器访问总是不成功。经过一番周折总算成功了&#xff0c;虽然这个知识点不是很难&#xff0c;但还是写篇博客&#xff0c;希望能帮助那些初学者。(注&#xff1a;笔者用的是&#xff1a;tomcat 7) 前提&#xff1a;你的tomcat可以访…

svn提交报错Unexpected HTTP status 413 'Request Entity Too Large' on

问题原因&#xff1a;nginx的client_max_body_size设置过小&#xff0c;默认 1M&#xff0c;如果请求的正文数据大于client_max_body_size&#xff0c;HTTP协议会报错 413 Request Entity Too Large。 解决方案&#xff1a;把这个值调大就可以了。

HTTP Status 404 - 解决办法

HTTP Status 404 - 解决办法 今天&#xff0c;我在从仓库导入web项目的时候出现了一个问题&#xff1a; 首先&#xff0c;我想的是为什么会出现&#xff0c;这样的问题&#xff0c;然后我对这个问题进行了描述&#xff0c;准备在网上找找解决方法&#xff0c;大多数给出的答案…