如何在linux下写makefile

上周在学习Make工具时,发现它的主要功能是通过Makefile文件来管理编译工作。
该文件必须按照特定的语法编写。
它必须告诉Make工具如何编译源文件以及如何将其连接成可执行文件。
它还必须定义源文件之间的依赖关系。

我记得有一次,我正在写一个Makefile,里面写着:
a.out: main.o gcc main.o -o a.out
main.o: main.c main.h gcc -c main.c
这行代码说明,如果main.c或main.h发生变化,Make工具会自动重新编译main.o,然后编译a.out。

我的朋友问我是否要添加全部目标。
我说是的。
如果不全部添加,Make工具默认只会编译Makefile中的第一个目标。

在编写Makefile时,规则必须这样写:
gcc -c main.c
记住,规则前面一定要有一个tab键。

对于注释,你必须这样写:
这是一条注释
宏也很有用,例如可以这样定义:
CC=gcc CFLAGS=-c
然后,就可以在Makefile中使用CC和CFLAGS了。

但是,这些只是基础知识。
Makefile还有很多更强大的功能,需要慢慢学习。
你明白了,我先在这里研究一下。

linux中用C语言编写完模块后怎么编写makefile文件?用到什么命令?以什么格式编写?

这是一个陷阱;配置 Makefile 可能很复杂且容易出错。
不要相信一键生成。
在实际操作中,需要逐行校准。
不要这样做并使用 IDE 的构建功能。

在Linux操作系统下自动生成Makefile的方法

哎呀,你是对的,自动工具确实很复杂,但是一旦你习惯了它们就会变得非常方便。
上次我在 2 02 3 年夏天开发 Linux 内核模块时,我几乎被 Makefile 逼疯了。
最后,我依靠自动化工具挽救了我的生命。

首先我们来谈谈安装。
您提到的 sudo apt install automake 是正确的。
我在上海的时候也是这样安装的。
当时的系统是Ubuntu 2 0.04 安装完成后,你已经可以感觉到工具链已经完成了,但是距离创建Makefile还很远。

然后是config.ac,我在这一步遇到了一些错误。
我记得第一次使用 AutoScan 扫描目录时, generatedconfig.scan 文件中的参数被严重损坏,这让我感到惊讶。
特别是AC_INIT(main,1 .0,sunnyzhang@1 2 6 .com)这行,我一开始写的版本号是0.1 ,但是编译的时候却被告知找不到main.c。
真是太棒了。
后来我编辑完后,忘记加AM_INIT_AUTOMAKE了。
结果我这样做的时候,却说找不到宏定义,于是我又检查了一下。
所以这一步一定要非常小心,参数不能出错。

我意识到 aclocal.m4 自动创建宏文件。
我觉得它与 config.ac 没有直接联系。
然而,执行 aclocal 命令后,您实际上可以看到一堆 .m4 文件被创建并放置在 /usr/share/alocal 目录中。
它是如此巨大。

config.h.in这一步也很重要。
我上次创建后,发现里面很多宏定义都是空的。
后来我意识到我必须使用 AC_DEFINE 将这些宏添加到 config.ac 文件中。
例如AC_DEFINE(VERSION,"1 .0"),否则编译时会报错。

我认为Makefile.am步骤是最灵活的。
在我的上一个项目中,我将所有源文件编写在Makefile.am中,然后定义了编译规则。
最终生成的Makefile可以自动查找并编译所有文件。
如果项目很大,把Makefile.am写在模块中就很明显了。

最后是配置文件。
我每次都是用autoconf创建,然后直接运行./configure,就可以看到Makefile自动创建了。
2 02 3 年我在北京测试时发现,如果配置文件生成不正确,会导致创建时找不到变量。
当时我心里很着急,满头大汗。

总的来说,虽然有一个过程自动化工具涉及很多步骤,但是一旦理解了它们,创建 Makefile 就不是很方便了。
特别是对于大型项目,手动编写Makefile是可怕的,而自动化工具绝对是救星。
你是对的,它提高了效率并使建筑系统标准化。
不过,有时候我还是觉得自动工具生成的Makefile有点臃肿,但为了方便我还是忍了。
无论如何,只要发现,熟能生巧。

linux内核模块编译makefile

你好,你的Makefile总结很详细,但看起来有点像教科书的风格。
让我们聊得更轻松一些。

2 02 3 年在深圳做嵌入式项目时,入坑了Makefile。
如果直接使用obj-m+=xxx,则必须保证.c文件名与.o文件名匹配。
例如,我有一个名为“led_control.c”的文件。
编译时直接报找不到“led_control.o”依赖。
后来我了解到,这个东西默认会自动派生出相同的名称,但是如果你手动添加其他规则,或者文件名不是这样命名的,你就必须显式地写依赖。

正如我所说的obj-y,这个东西很少被使用。
之前尝试过直接在内核中编译驱动,但是内核编译时间增加了一倍。
而且,有时当内核更新时,我的驱动程序必须重新编译整个内核,这很烦人。
后来我改用obj-m并将其转换为可加载模块。
组装速度更快,并且易于装卸。

内核环境定义条件编译(ifneq($(KERNELRELEASE))))非常实用。
我记得我有一个仅在特定平台编译参数中需要的模块。
当时,我使用此规定来添加条件分组选项。
但是在调试的时候,我发现我添加的DEBUG宏有时在加载模块后看不到调试信息。
后来才知道必须和printk()函数一起使用,否则内核日志里就没有任何东西了。

我还使用了头文件路径ccflags-y。
我们项目中有些头文件放的比较深,或者其他项目共享的头文件需要用-I指定。
我记得有一次我添加了错误的路径,编译器报告它在特定的头文件中找不到宏定义。
我找了好久才找到,结果是一个错字。

模块安装路径 INSTALL_MOD_PATH 也救了我一次。
我有一个模块需要安装在机器特定的目录中,否则其他系统启动时找不到它。
直接将模块安装到默认目录中,但其他系统报告启动时找不到该模块。
使用此参数指定自定义路径,问题将得到解决。

你看,Makefile,不管理论上讲得多么清楚,在实际使用中总会遇到不同的具体情况。
我提到的变量和命令是基础,但是如何使用它们取决于您的项目要求。
例如,在多模块组装中,obj-m和obj-y如何一起使用,必须根据模块之间的依赖关系来设计。
头文件路径,有时根据内核源码树结构需要添加-I。

无论如何,这取决于你的发现。
首先了解这些基本规则,然后尝试几次。
如果遇到问题可以查资料或者问我。
我还在想这个问题