从零开始学习makefile(4)makefile中%、$@、$<、$^的作用

2023-11-02

目录

%

示例

头文件fun.h

main.cpp

fun.cpp

makefile

$@与$<

$^

%

%是通配符。https://www.quora.com/What-does-o-cpp-in-a-Makefile-mean是这样描述%的作用的:

 for every target X.o, if there exists a file named X.cpp, do the following

对于任何一个.o文件,假如存在同名的.cpp文件,做如下操作。

注意,不是根据任何一个cpp文件来找.o文件。makefile的工作流程是从最终的产物(可执行文件或so文件等)开始,寻找“上一级”产生它们的文件,直到最顶端的源代码。:

可执行文件->.o文件->cpp文件/h文件。

正因为这样,makefile才会根据.o文件查找同名.cpp文件,而不是反过来。

示例

看下面的示例:

头文件fun.h

int fun();

main.cpp

#include <stdio.h>
#include "fun.h"

int main(void)
{
	int i = fun();
	printf("i = %d\n", i);
	return 0;
}

fun.cpp

#include "fun.h"
int fun(){
	return 9;
}

makefile

CC=gcc

%.o: %.cpp
	$(CC) -c -o $@ $<
main: main.o fun.o
	$(CC) -o main main.o fun.o

 make之后打印了三行语句:

gcc -c -o main.o main.cpp

gcc -c -o fun.o fun.cpp

gcc -o main main.o fun.o

前两句是由makefile的%.o: %.cpp  gcc -c -o $@ $<  规则展开 。对号入座就能看出,第一次使用%.o时,main字符串代入%。第二次代入使用fun字符串代入%。

$@与$<

将上面的打印结果与%.o: %.cpp  gcc -c -o $@ $<  规则对号入座,不难看出,$@对应%.o;而$<对应%.cpp

https://unix.stackexchange.com/questions/116547/what-do-and-in-a-makefile-mean#:~:text=From%20make%20manpage%3A,rule's%20recipe%20to%20be%20run.解释了$@和$<的意义:

 $@是目标的名字(目标就是冒号":"左边的文件名)。假如冒号左边有不止一个目标,那么$@等于触发当前规则的那个目标。

$<是第一个依赖项(依赖项就是冒号":"右边的文件名)。

再看下面关于$@的例子

  

这个例子说明,当冒号“:”左边有多个目标时,$@一次只会对应一个目标。

另外,all:a.o b.o这句不能省略。省略的话,makefile只会按照生成a.o的规则执行一次

$^

 上面的例子可以进一步抽象,将makefile改写为如下:

CC=gcc

%.o: %.cpp
	$(CC) -c -o $@ $<
main: main.o fun.o
	$(CC) -o $@ $^

注意最后一行。$@取代了main,因为$@就代表main。$^取代了main.o fun.o。因为$^的作用就是代替冒号":"右边的所有依赖项(prerequisites)

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

从零开始学习makefile(4)makefile中%、$@、$<、$^的作用 的相关文章

  • 在 Linux 中使用仅限 CLI 的工具生成磁盘使用情况图/图表

    在这个问题中 https stackoverflow com questions 32230 tracking down where disk space has gone on linux有人询问如何在 Linux 中显示磁盘使用情况 我
  • Amazon EC2 - Apache 服务器重启问题

    当我运行这个命令时 sudo etc init d httpd restart 它给出以下错误 停止 httpd 失败 启动 httpd 98 地址已在使用中 make sock 无法绑定到地址 80 98 地址已在使用 make sock
  • 使用 target_link_libraries 以绝对路径作为库路径进行平台库名称扩展?

    在 CMake 中使用 target link libraries 仅使用库名称 例如 target link library myProject SomeLibrary 将根据平台将 SomeLibrary 扩展为 SomeLibrary
  • 使用 Shell 脚本提供密码

    我已将客户端和服务器设置为无密码登录 就像无密码登录一样 通过将服务器的 RSA 密钥复制到所有客户端的 root ssh id rsa pub 来实现 但这是我手动完成的 我喜欢使用 shell 脚本自动执行此过程 并通过脚本向计算机提供
  • 什么是接口标识符

    我有一台笔记本电脑 使用一个或多个网络适配器连接到我组织的网络 我正在尝试编写一个工具来持续监控每个网络的连接状态和连接质量 然而 我的网络知识有限 术语让我感到困惑 特别是查找所有网络适配器 有人建议我使用命令ifconfig它给了我所谓
  • bash 或 sh 中的“=”和“==”运算符有什么区别

    我意识到 和 运算符都可以在 if 语句中使用 例如 var some string if var some string then doing something fi if var some string then doing some
  • bash 别名中允许使用哪些字符[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我最近添加了 alias cd alias cd alias cd 到我的 bash aliases 文件 玩弄这个 我注意到在别名时 被
  • 从汇编程序获取命令行参数

    通读 专业汇编语言书籍 似乎它提供了用于读取命令行参数的错误代码 我纠正了一点 现在它从段错误变成了读取参数计数 然后是段错误 这是完整的代码 data output1 asciz There are d params n output2
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • 从 Java 读取 /dev/input/js0

    我正在尝试阅读 dev input js0来自Java 但我不断得到 java io IOException Invalid argument at java io FileInputStream read0 Native Method a
  • 尝试 SSH 时设备的 ioctl 不合适

    我正在尝试通过 SSH 连接几台服务器并尝试获取sudo l每个服务器的输出 下面是我正在执行的脚本 bin bash serverlist tmp servers while IFS read r server netgroup user
  • 不同GIT版本的GIT合并结果不同

    在不同的 GIT 版本上运行 merge 命令我们得到不同的结果 命令是 git merge no ff origin master codeline Results 版本2 1 4 gt 合并成功 版本1 7 1 gt 同一提交上的同一合
  • 编译器 libstdc++ 版本与系统版本

    我试图了解 g 如何选择它链接的 libstdc 版本 以及当库的 系统 版本不同时它意味着什么 我正在使用 gcc g 4 1 2 根据ABI 指南 http gcc gnu org onlinedocs libstdc manual a
  • 为什么 GCC 不将 a*a*a*a*a*a 优化为 (a*a*a)*(a*a*a)?

    我正在对科学应用程序进行一些数值优化 我注意到的一件事是 GCC 会优化调用pow a 2 通过将其编译成a a 但是调用pow a 6 没有优化 实际会调用库函数pow 这大大降低了性能 相比之下 英特尔 C 编译器 http en wi
  • 命令行参数中的“-”(破折号)有什么魔力?

    例子 创建 ISO 映像并将其直接刻录到 CD mkisofs V Photos r home vivek photos cdrecord v dev dev dvdrw 更改到上一个目录 cd 侦听端口 12345 并解压发送到该端口的数
  • 如何随时暂停 pthread?

    最近我开始将 ucos ii 移植到 Ubuntu PC 上 我们知道 在pthread的回调函数中的 while 循环中简单地添加一个标志来执行暂停和恢复是不可能模拟ucos ii中的 进程 的 如下解决方案 因为ucos ii中的 进程
  • Linux:通过网络进行屏幕桌面视频捕获和 VNC 帧速率

    抱歉 文字墙很长 TL DR VNC 连接的帧速率是多少 以帧 秒为单位 或者更确切地说 由谁决定 客户端还是服务器 对于桌面屏幕捕获的任何其他建议 但 正确的时间编码 具有不抖动的帧速率 具有稳定的周期 并有可能将其作为未压缩 或无损 图
  • 使用 linux perf 工具测量应用程序的 FLOP

    我想使用 perf Linux 性能计数器子系统的新命令行接口命令 来测量某些应用程序执行的浮点和算术运算的数量 出于测试目的 我使用了我创建的一个简单的虚拟应用程序 请参见下文 因为我找不到任何为测量 FP 和整数运算而定义的 perf
  • 如何修改s_client的代码?

    我正在玩apps s client c in the openssl源代码 我想进行一些更改并运行它 但是在保存文件并执行操作后 我的更改没有得到反映make all or a make 例如 我改变了sc usage函数为此 BIO pr
  • 在 Ubuntu 上用 C 项目编译和链接 GTK 3

    我相信这不是重复的问题 在发布此问题之前我已经看过所有问题 答案 我想我这里的情况有所不同 我使用Ubuntu 12 04并下载GTK 2 和 3 我从 GNOME 网站复制了一个简单的 GTK 源代码 但是当我在终端中使用这个命令时 gc

随机推荐