NDS开发入门教程-MakeFile文件解析
- 格式:pdf
- 大小:196.34 KB
- 文档页数:4
make makefile 的参数make是一个常用的构建工具,用于自动化编译和构建软件项目。
makefile是make工具的配置文件,用于描述项目的构建规则和依赖关系。
本文将介绍makefile的参数,包括常用的参数及其用法。
一、常用参数及其用法1. -f 文件名:指定makefile的文件名,默认为"makefile"或"Makefile"。
通过该参数,可以使用其他名称的makefile文件。
2. -C 目录:指定make命令的工作目录。
在执行make命令时,会切换到指定的目录,并在该目录下查找makefile文件进行构建。
3. -n:显示执行make命令时的操作,但不实际执行。
通过该参数,可以预览make命令的执行过程,检查构建规则是否正确。
4. -p:显示make命令的内置变量和规则。
通过该参数,可以查看make命令的内部工作机制,了解makefile文件的编写规则和使用方法。
5. -B:强制重新构建目标文件。
通过该参数,可以忽略文件的时间戳,强制重新执行构建规则,生成新的目标文件。
6. -j 并发数:指定make命令的并发执行数。
通过该参数,可以提高构建速度,同时执行多个任务。
7. -s:静默模式,不显示执行的命令。
通过该参数,可以减少输出信息,使构建过程更加清晰。
二、makefile的构建规则makefile由一系列构建规则组成,每个规则定义了目标文件、依赖文件和构建命令。
make命令根据构建规则,自动判断需要更新的文件,并执行相应的构建命令。
构建规则的基本格式如下:目标文件: 依赖文件构建命令其中,目标文件是要生成的文件,依赖文件是目标文件依赖的文件,构建命令是生成目标文件的命令。
构建规则中的目标文件和依赖文件可以是文件名,也可以是变量。
通过使用变量,可以提高makefile的可维护性和灵活性。
构建命令可以是任意的Shell命令,包括编译、链接、拷贝等操作。
Makefile中的⼏个常见的符号及其含义= 是最基本的赋值:= 是覆盖之前的值= 是如果没有被赋值过就赋予等号后⾯的值+= 是添加等号后⾯的值“=”和“:=”的区别:1、“=”make会将整个makefile展开后,再决定变量的值。
也就是说,变量的值将会是整个makefile中最后被指定的值。
看例⼦: x = fooy = $(x) barx = xyz在上例中,y的值将会是 xyz bar ,⽽不是 foo bar 。
2、“:=”“:=”表⽰变量的值决定于它在makefile中的位置,⽽不是整个makefile展开后的最终值。
x := fooy := $(x) barx := xyz在上例中,y的值将会是 foo bar ,⽽不是 xyz bar 了。
'@' 符号的使⽤通常makefile会将其执⾏的命令⾏在执⾏前输出到屏幕上。
如果将‘@’添加到命令⾏前,这个命令将不被make回显出来。
例如:@echo --compiling module----; // 屏幕输出 --compiling module----echo --compiling module----; // 没有@ 屏幕输出echo --compiling module----' - ' 符号的使⽤通常删除,创建⽂件如果碰到⽂件不存在或者已经创建,那么希望忽略掉这个错误,继续执⾏,就可以在命令前⾯添加 -, -rm dir;-mkdir aaadir;ref:https:///u012989012/article/details/80572043。
Makefile 语法分析第一部分VERSION = 2# 给变量VERSION赋值PATCHLEVEL = 6# 给变量PATCHLEVEL赋值SUBLEVEL = 22# 给变量SUBLEVEL赋值EXTRAVERSION = .6# 给变量EXTRAVERSION赋值NAME = Holy Dancing Manatees, Batman!# 给变量NAME赋值# *DOCUMENTATION*# To see a list of typical targets execute "make help"# More info can be located in ./README# Comments in this file are targeted only to the developer, do not# expect to learn how to build the kernel reading this file.# Do not:# o use make's built-in rules and variables# (this increases performance and avoid hard-to-debug behavour);# o print "Entering directory ...";MAKEFLAGS += -rR --no-print-directory# 操作符“+=”的作用是给变量(“+=”前面的MAKEFLAGS)追加值。
# 如果变量(“+=”前面的MAKEFLAGS)之前没有定义过,那么,“+=”会自动变成“=”;# 如果前面有变量(“+=”前面的MAKEFLAGS)定义,那么“+=”会继承于前次操作的赋值符;# 如果前一次的是“:=”,那么“+=”会以“:=”作为其赋值符# 在执行make时的命令行选项参数被通过变量“MAKEFLAGS”传递给子目录下的make程序。
MakefileMake的基本规则:Target [属性] 分隔符 [依赖文件] [;命令行 ]{Tab 命令行}注:命令行间可以加入任意多个空行,但空行也要以tab开头。
Cat –v -t -e Makefile会使Makefile文件中tab以^]显示,行尾以$显示。
注:命令过长,用\来连接多行成一行。
注释以#开头,如果#要用作字符符号,―#‖。
分隔符:::目标有多个规则。
哪条规则中的依赖文件比目标新,执行哪条规则。
如果多条规则的依赖文件都比目标新,多条规则都执行。
由于后面的规则可能覆盖前面规则的执行结构,所以规则顺序不同,执行结构也不同。
:^把本规则依赖文件和目标文件已有的依赖文件合起来,生成目标新的依赖文件列表。
:-清除目标已有依赖文件,把本规则依赖文件作为目标依赖文件列表。
:!对每个更新过的依赖文件都执行一次命令菜单。
:|内部规则专用。
如:file.o :file.cfile.o :^ filef.c现依赖文件为file.c filef.cfile.o :- filef.c现依赖文件为 filef.c令行属性:- 若本命令的执行错误,忽略掉,继续向下执行。
(不加该标志,make会停止)+ 始终执行本命令,即使make参数使用了-n-q-t。
(前提是本规则中依赖文件新与目标文件,命令行需要执行)@ 本命令行不在标准输出显示。
Target属性:指定多个目标文件属性:属性属性…… :目标目标……规则中指定单个目标属性:目标属性:[依赖文件] ……·IGNORE 类似与命令行属性-·SILENT 类似与命令行属性@·PRECIOUS 保留中间文件·LIBRARY 目标是一个库。
如果make发现目标是lib(member)或lib((entry))形式,会自动给名为lib的目标加上该属性。
·LIBRARYM 目标是库的一个成员。
如果make发现目标是lib(member)形式,会自动给lib目标加上·LIBRARY,被member目标加上·LIBRARYM。
mk文件语法
“MK文件语法”通常指的是Makefile文件的语法。
Makefile是一种用于自动化构建程序的工具,它描述了如何从源代码生成可执行文件或库文件。
Makefile文件使用特定的语法规则来定义构建规则、依赖关系和编译选项等。
Makefile的语法包括以下部分:
1.变量定义:使用VAR = value的形式定义变量,可以使用${VAR}引用变量
的值。
2.规则定义:使用target: dependencies的形式定义规则,其中target是要
生成的目标文件,dependencies是生成目标文件所需的依赖文件。
例如:hello: main.o utility.ogcc -o hello main.o utility.o
3.命令:定义规则之后可以跟一系列命令,用于生成目标文件。
命令会在执
行Makefile时顺序执行。
例如:%.o: %.cgcc -c $< -o $@
4.条件判断和循环:Makefile支持条件判断和循环结构,可以根据条件执行
不同的命令或重复执行一组命令。
例如:
ifeq ($(CC), gcc)CFLAGS += -O2elseCFLAGS += -O0endif
5.函数:Makefile还提供了一些内置函数,可以在变量、规则和命令中使用。
例如:$(warning "This is a warning message")
以上是Makefile语法的一些基本组成部分。
具体的语法规则和用法可能会根据不同的Makefile版本和工具而有所不同。
文章标题:深入探讨Makefile中的Obj用法在软件开发中,Makefile是一个非常重要的工具,它帮助程序员管理项目的编译和信息过程。
而Makefile中的Obj用法则是Makefile中非常重要的一部分,它用来指定项目中的目标文件。
在本篇文章中,我们将深入探讨Makefile中的Obj用法,从简单到复杂,由浅入深,帮助读者更好地理解和运用Obj用法。
1. 什么是Makefile在开始深入探讨Makefile中的Obj用法之前,我们先来了解一下什么是Makefile。
Makefile是一种文件,其中包含了一系列规则和命令,用于指导编译器如何编译和信息项目中的源文件,最终生成可执行文件。
Makefile通过维护文件之间的依赖关系,可以使得在修改源文件后,只重新编译需要重新编译的文件,而不是整个项目。
这样可以提高编译的效率,特别是在大型项目中非常重要。
2. Obj用法的基础概念Obj用法是Makefile中用来指定目标文件的一个重要部分。
在Makefile中,通常通过指定目标文件来定义一个编译单元,Obj用法就是用来指定这些目标文件的。
在Makefile中,Obj用法通常是在规则中使用的,用来指定编译的目标文件是哪些。
我们可以这样定义一个规则:```main.o : main.cgcc -c main.c -o main.o```在这个例子中,main.o就是通过Obj用法指定的目标文件,它告诉Makefile需要生成名为main.o的目标文件,并且它是由main.c编译而来的。
3. Makefile中的Obj用法进阶除了简单地指定目标文件外,Obj用法还可以进一步扩展。
在实际开发中,一个目标文件可能由多个源文件编译而来,这时候就需要用到Obj用法的进阶用法了。
在Makefile中,我们可以使用通配符来指定一组目标文件,例如:```%.o : %.cgcc -c $< -o $@```这个规则中,%表示任意的文件名,$<表示依赖文件,$@表示目标文件。
makefile基本使用方法makefile是一种用来管理和自动化构建程序的工具。
它可以根据源代码文件的依赖关系和编译规则来自动构建目标文件和可执行文件。
makefile的基本使用方法如下:1. 创建makefile文件:在项目的根目录下创建一个名为makefile 的文件。
2. 定义变量:在makefile中,可以使用变量来存储一些常用的参数和路径,以便于后续的使用。
例如,可以定义一个名为CC的变量来指定编译器的名称,如:CC=gcc。
3. 编写规则:在makefile中,可以使用规则来指定如何编译源代码文件和生成目标文件。
一个规则由两部分组成:目标和依赖。
目标是要生成的文件,依赖是生成目标文件所需要的源代码文件。
例如,可以编写以下规则:```target: dependency1 dependency2command1command2```其中,target是目标文件,dependency1和dependency2是依赖的源代码文件,command1和command2是生成目标文件所需要执行的命令。
4. 编写默认规则:在makefile中,可以使用一个默认规则来指定如何生成最终的可执行文件。
默认规则的目标通常是可执行文件,依赖是所有的源代码文件。
例如,可以编写以下默认规则:```all: target1 target2```其中,target1和target2是生成的目标文件。
5. 编写clean规则:在makefile中,可以使用clean规则来清理生成的目标文件和可执行文件。
例如,可以编写以下clean规则: ```clean:rm -f target1 target2```其中,target1和target2是要清理的目标文件。
6. 运行make命令:在命令行中,使用make命令来执行makefile 文件。
make命令会自动根据规则和依赖关系来编译源代码文件和生成目标文件。
例如,可以运行以下命令:``````make命令会根据makefile文件中的规则和依赖关系来编译源代码文件并生成目标文件和可执行文件。
第四章:Makefile的规则本章我们将讨论Makefile的一个重要内容,规则。
熟悉规则对于书写Makefile至关重要。
Makefile中,规则描述了在何种情况下使用什么命令来重建一个特定的文件,此文件被称为规则“目标”(通常规则中的目标只有一个)。
规则中出目标之外的罗列的其它文件称为“目标”的依赖,而规则的命令是用来更新或者创建此规则的目标。
除了makefile的“终极目标”所在的规则以外,其它规则的顺序在makefile文件中没有意义。
“终极目标”就是当没有使用make 命令行指定具体目标时,make默认的更新的哪一个目标。
它是makefile文件中第一个规则的目标。
如果在makefile中第一个规则有多个目标的话,那么多个目标中的第一个将会被作为make的“终极目标”。
有两种情况的例外:1. 目标名以点号“.”开始的并且其后不存在斜线“/”(“./”被认为是当前目录;“../”被认为是上一级目录);2. 模式规则的目标。
当这两种目标所在的规则是Makefile的第一个规则时,它们并不会被作为“终极目标”。
“终极目标”是执行make的唯一目的,其所在的规则作为第一个被执行的规则。
而其它的规则是在完成重建“终极目标”的过程中被连带出来的。
所以这些目标所在规则在Makefile中的顺序无关紧要。
因此,我们书写的makefile的第一个规则应该就是重建整个程序或者多个程序的依赖关系和执行命令的描述。
4.1 一个例子我们来看一个规则的例子:foo.o : foo.c defs.h # module for twiddling the frobscc -c -g foo.c这是一个典型的规则。
看到这个例子,大家应该能够说出这个规则的各个部分之间的关系。
不过我们还是要把这个例子拿出来讨论。
目的是让我们更加明确地理解Makefile的规则。
本例第一行中,文件“foo.o”是规则需要重建的文件,而“foo.c”和“defs.h”是重建“foo.o”所要使用的文件。
Makefile经典教程0 Makefile概述什么是makefile?或许很多Winodws的程序员都不知道这个东西,因为那些Windows的IDE都为你做了这个工作,但我觉得要作一个好的和professional的程序员,makefile还是要懂。
这就好像现在有这么多的HTML的编辑器,但如果你想成为一个专业人士,你还是要了解HTML的标识的含义。
特别在Unix下的软件编译,你就不能不自己写makefile了,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。
因为,makefile关系到了整个工程的编译规则。
一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。
可见,makefile都成为了一种在工程方面的编译方法。
现在讲述如何写makefile的文章比较少,这是我想写这篇文章的原因。
当然,不同产商的make各不相同,也有不同的语法,但其本质都是在“文件依赖性”上做文章,这里,我仅对GNU的make进行讲述,我的环境是RedHat Linux 8.0,make的版本是3.80。
必竟,这个make是应用最为广泛的,也是用得最多的。
而且其还是最遵循于IEEE 1003.2-1992 标准的(POSIX.2)。
在这篇文档中,将以C/C++的源码作为我们基础,所以必然涉及一些关于C/C++的编译的知识,相关于这方面的内容,还请各位查看相关的编译器的文档。
Makefile使⽤总结1. Makefile 简介Makefile 是和 make 命令⼀起配合使⽤的.很多⼤型项⽬的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项⽬中各种库和代码之间的依赖关系不知会多复杂. Makefile的组织流程的能⼒如此之强, 不仅可以⽤来编译项⽬, 还可以⽤来组织我们平时的⼀些⽇常操作. 这个需要⼤家发挥⾃⼰的想象⼒.本篇博客是基于⽽整理的, 有些删减, 追加了⼀些⽰例.⾮常感谢 gunguymadman_cu 提供如此详尽的Makefile介绍, 这正是我⼀直寻找的Makefile中⽂⽂档.1.1 Makefile 主要的 5个部分 (显⽰规则, 隐晦规则, 变量定义, ⽂件指⽰, 注释)Makefile基本格式如下:target ... : prerequisites ...command......其中,target - ⽬标⽂件, 可以是 Object File, 也可以是可执⾏⽂件prerequisites - ⽣成 target 所需要的⽂件或者⽬标command - make需要执⾏的命令 (任意的shell命令), Makefile中的命令必须以 [tab] 开头1. 显⽰规则 :: 说明如何⽣成⼀个或多个⽬标⽂件(包括⽣成的⽂件, ⽂件的依赖⽂件, ⽣成的命令)2. 隐晦规则 :: make的⾃动推导功能所执⾏的规则3. 变量定义 :: Makefile中定义的变量4. ⽂件指⽰ :: Makefile中引⽤其他Makefile; 指定Makefile中有效部分; 定义⼀个多⾏命令5. 注释 :: Makefile只有⾏注释 "#", 如果要使⽤或者输出"#"字符, 需要进⾏转义, "\#"1.2 GNU make 的⼯作⽅式1. 读⼊主Makefile (主Makefile中可以引⽤其他Makefile)2. 读⼊被include的其他Makefile3. 初始化⽂件中的变量4. 推导隐晦规则, 并分析所有规则5. 为所有的⽬标⽂件创建依赖关系链6. 根据依赖关系, 决定哪些⽬标要重新⽣成7. 执⾏⽣成命令2. Makefile 初级语法2.1 Makefile 规则2.1.1 规则语法规则主要有2部分: 依赖关系和⽣成⽬标的⽅法.语法有以下2种:target ... : prerequisites ...command...或者target ... : prerequisites ; commandcommand...*注* command太长, 可以⽤ "\" 作为换⾏符2.1.2 规则中的通配符* :: 表⽰任意⼀个或多个字符:: 表⽰任意⼀个字符[...] :: ex. [abcd] 表⽰a,b,c,d中任意⼀个字符, [^abcd]表⽰除a,b,c,d以外的字符, [0-9]表⽰ 0~9中任意⼀个数字~ :: 表⽰⽤户的home⽬录2.1.3 路径搜索当⼀个Makefile中涉及到⼤量源⽂件时(这些源⽂件和Makefile极有可能不在同⼀个⽬录中),这时, 最好将源⽂件的路径明确在Makefile中, 便于编译时查找. Makefile中有个特殊的变量VPATH就是完成这个功能的.指定了VPATH之后, 如果当前⽬录中没有找到相应⽂件或依赖的⽂件, Makefile 回到VPATH指定的路径中再去查找.. VPATH使⽤⽅法:vpath <directories> :: 当前⽬录中找不到⽂件时, 就从<directories>中搜索vpath <pattern> <directories> :: 符合<pattern>格式的⽂件, 就从<directories>中搜索vpath <pattern> :: 清除符合<pattern>格式的⽂件搜索路径vpath :: 清除所有已经设置好的⽂件路径# ⽰例1 - 当前⽬录中找不到⽂件时, 按顺序从 src⽬录 ../parent-dir⽬录中查找⽂件VPATH src:../parent-dir# ⽰例2 - .h结尾的⽂件都从 ./header ⽬录中查找VPATH %.h ./header# ⽰例3 - 清除⽰例2中设置的规则VPATH %.h# ⽰例4 - 清除所有VPATH的设置VPATH2.2 Makefile 中的变量2.2.1 变量定义 ( = or := )OBJS = programA.o programB.oOBJS-ADD = $(OBJS) programC.o# 或者OBJS := programA.o programB.oOBJS-ADD := $(OBJS) programC.o其中 = 和 := 的区别在于, := 只能使⽤前⾯定义好的变量, = 可以使⽤后⾯定义的变量测试 =# Makefile内容OBJS2 = $(OBJS1) programC.oOBJS1 = programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出虽然 OBJS1 是在 OBJS2 之后定义的, 但在 OBJS2中可以提前使⽤$ makeprogramA.o programB.o programC.o测试 :=# Makefile内容OBJS2 := $(OBJS1) programC.oOBJS1 := programA.o programB.oall:@echo $(OBJS2)# bash中执⾏make, 可以看出 OBJS2 中的 $(OBJS1) 为空$ makeprogramC.o2.2.2 变量替换# Makefile内容SRCS := programA.c programB.c programC.cOBJS := $(SRCS:%.c=%.o)all:@echo "SRCS: " $(SRCS)@echo "OBJS: " $(OBJS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.cOBJS: programA.o programB.o programC.o2.2.3 变量追加值 +=# Makefile内容SRCS := programA.c programB.c programC.cSRCS += programD.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ makeSRCS: programA.c programB.c programC.c programD.c2.2.4 变量覆盖 override作⽤是使 Makefile中定义的变量能够覆盖 make 命令参数中指定的变量语法:override <variable> = <value>override <variable> := <value>override <variable> += <value>下⾯通过⼀个例⼦体会 override 的作⽤:# Makefile内容 (没有⽤override)SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: nothing################################################## Makefile内容 (⽤override)override SRCS := programA.c programB.c programC.call:@echo "SRCS: " $(SRCS)# bash中运⾏make$ make SRCS=nothingSRCS: programA.c programB.c programC.c2.2.5 ⽬标变量作⽤是使变量的作⽤域仅限于这个⽬标(target), ⽽不像之前例⼦中定义的变量, 对整个Makefile都有效.语法:<target ...> :: <variable-assignment><target ...> :: override <variable-assignment> (override作⽤参见变量覆盖的介绍)⽰例:# Makefile 内容SRCS := programA.c programB.c programC.ctarget1: TARGET1-SRCS := programD.ctarget1:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)target2:@echo "SRCS: " $(SRCS)@echo "SRCS: " $(TARGET1-SRCS)# bash中执⾏make$ make target1SRCS: programA.c programB.c programC.cSRCS: programD.c$ make target2 <-- target2中显⽰不了 $(TARGET1-SRCS)SRCS: programA.c programB.c programC.cSRCS:2.3 Makefile 命令前缀Makefile 中书写shell命令时可以加2种前缀 @ 和 -, 或者不⽤前缀.3种格式的shell命令区别如下:不⽤前缀 :: 输出执⾏的命令以及命令执⾏的结果, 出错的话停⽌执⾏前缀 @ :: 只输出命令执⾏的结果, 出错的话停⽌执⾏前缀 - :: 命令执⾏有错的话, 忽略错误, 继续执⾏⽰例:# Makefile 内容 (不⽤前缀)all:echo"没有前缀"cat this_file_not_existecho"错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 @)all:@echo "没有前缀"@cat this_file_not_exist@echo "错误之后的命令" <-- 这条命令不会被执⾏# bash中执⾏make$ make没有前缀 <-- 只有命令执⾏的结果, 不显⽰命令本⾝cat: this_file_not_exist: No such file or directorymake: *** [all] Error 1############################################################ Makefile 内容 (前缀 -)all:-echo"没有前缀"-cat this_file_not_exist-echo"错误之后的命令" <-- 这条命令会被执⾏# bash中执⾏make$ makeecho"没有前缀" <-- 命令本⾝显⽰出来没有前缀 <-- 命令执⾏结果显⽰出来cat this_file_not_existcat: this_file_not_exist: No such file or directorymake: [all] Error 1 (ignored)echo"错误之后的命令" <-- 出错之后的命令也会显⽰错误之后的命令 <-- 出错之后的命令也会执⾏2.4 伪⽬标伪⽬标并不是⼀个"⽬标(target)", 不像真正的⽬标那样会⽣成⼀个⽬标⽂件.典型的伪⽬标是 Makefile 中⽤来清理编译过程中中间⽂件的 clean 伪⽬标, ⼀般格式如下: .PHONY: clean <-- 这句没有也⾏, 但是最好加上clean:-rm -f *.o2.5 引⽤其他的 Makefile语法: include <filename> (filename 可以包含通配符和路径)⽰例:# Makefile 内容all:@echo "主 Makefile begin"@make other-all@echo "主 Makefile end"include ./other/Makefile# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 20K-rw-r--r-- 1 wangyubin wangyubin 125 Sep 2316:13 Makefile-rw-r--r-- 1 wangyubin wangyubin 11K Sep 2316:15 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2316:11 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile'主 Makefile end2.6 查看C⽂件的依赖关系写 Makefile 的时候, 需要确定每个⽬标的依赖关系.GNU提供⼀个机制可以查看C代码⽂件依赖那些⽂件, 这样我们在写 Makefile ⽬标的时候就不⽤打开C源码来看其依赖那些⽂件了.⽐如, 下⾯命令显⽰内核源码中 virt/kvm/kvm_main.c 中的依赖关系$ cd virt/kvm/$ gcc -MM kvm_main.ckvm_main.o: kvm_main.c iodev.h coalesced_mmio.h async_pf.h <-- 这句就可以加到 Makefile 中作为编译 kvm_main.o 的依赖关系2.7 make 退出码Makefile的退出码有以下3种:0 :: 表⽰成功执⾏1 :: 表⽰make命令出现了错误2 :: 使⽤了 "-q" 选项, 并且make使得⼀些⽬标不需要更新2.8 指定 Makefile,指定特定⽬标默认执⾏ make 命令时, GNU make在当前⽬录下依次搜索下⾯3个⽂件 "GNUmakefile", "makefile", "Makefile",找到对应⽂件之后, 就开始执⾏此⽂件中的第⼀个⽬标(target). 如果找不到这3个⽂件就报错.⾮默认情况下, 可以在 make 命令中指定特定的 Makefile 和特定的⽬标.⽰例:# Makefile⽂件名改为 MyMake, 内容target1:@echo "target [1] begin"@echo "target [1] end"target2:@echo "target [2] begin"@echo "target [2] end"# bash 中执⾏make$ lsMakefile$ mv Makefile MyMake$ lsMyMake$ make <-- 找不到默认的 Makefilemake: *** No targets specified and no makefile found. Stop.$ make -f MyMake <-- 指定特定的Makefiletarget [1] begintarget [1] end$ make -f MyMake target2 <-- 指定特定的⽬标(target)target [2] begintarget [2] end2.9 make 参数介绍make 的参数有很多, 可以通过 make -h 去查看, 下⾯只介绍⼏个我认为⽐较有⽤的.参数含义--debug[=<options>]输出make的调试信息, options 可以是 a, b, v-j --jobs同时运⾏的命令的个数, 也就是多线程执⾏ Makefile-r --no-builtin-rules禁⽌使⽤任何隐含规则-R --no-builtin-variabes禁⽌使⽤任何作⽤于变量上的隐含规则-B --always-make假设所有⽬标都有更新, 即强制重编译2.10 Makefile 隐含规则这⾥只列⼀个和编译C相关的.编译C时,<n>.o 的⽬标会⾃动推导为 <n>.c# Makefile 中main : main.ogcc -o main main.o#会⾃动变为:main : main.ogcc -o main main.omain.o: main.c <-- main.o 这个⽬标是隐含⽣成的gcc -c main.c2.11 隐含规则中的命令变量和命令参数变量2.11.1 命令变量, 书写Makefile可以直接写 shell时⽤这些变量.下⾯只列出⼀些C相关的变量名含义RM rm -fAR arCC ccCXX g++⽰例:# Makefile 内容all:@echo $(RM)@echo $(AR)@echo $(CC)@echo $(CXX)# bash 中执⾏make, 显⽰各个变量的值$ makerm -farccg++2.11.2 命令参数变量变量名含义ARFLAGS AR命令的参数CFLAGS C语⾔编译器的参数CXXFLAGS C++语⾔编译器的参数⽰例: 下⾯以 CFLAGS 为例演⽰# test.c 内容#include <stdio.h>int main(int argc, char *argv[]){printf ("Hello Makefile\n");return 0;}# Makefile 内容test: test.o$(CC) -o test test.o# bash 中⽤make来测试$ lltotal 24K-rw-r--r-- 1 wangyubin wangyubin 69 Sep 2317:31 Makefile-rw-r--r-- 1 wangyubin wangyubin 14K Sep 2319:51 <-- 请忽略这个⽂件-rw-r--r-- 1 wangyubin wangyubin 392 Sep 2317:31 test.c$ makecc -c -o test.o test.ccc -o test test.o <-- 这个是⾃动推导的$ rm -f test test.o$ make CFLAGS=-Wall <-- 命令中加的编译器参数⾃动追加⼊下⾯的编译中了cc -Wall -c -o test.o test.ccc -o test test.o2.12 ⾃动变量Makefile 中很多时候通过⾃动变量来简化书写, 各个⾃动变量的含义如下:⾃动变量含义$@⽬标集合$%当⽬标是函数库⽂件时, 表⽰其中的⽬标⽂件名$<第⼀个依赖⽬标. 如果依赖⽬标是多个, 逐个表⽰依赖⽬标$?⽐⽬标新的依赖⽬标的集合$^所有依赖⽬标的集合, 会去除重复的依赖⽬标$+所有依赖⽬标的集合, 不会去除重复的依赖⽬标$*这个是GNU make特有的, 其它的make不⼀定⽀持3. Makefile ⾼级语法3.1 嵌套Makefile在 Makefile 初级语法中已经提到过引⽤其它 Makefile的⽅法. 这⾥有另⼀种写法, 并且可以向引⽤的其它 Makefile 传递参数.⽰例: (不传递参数, 只是调⽤⼦⽂件夹 other 中的Makefile)# Makefile 内容all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "other makefile end"# bash中执⾏make$ lltotal 28K-rw-r--r-- 1 wangyubin wangyubin 104 Sep 2320:43 Makefile-rw-r--r-- 1 wangyubin wangyubin 17K Sep 2320:44 <-- 这个⽂件不⽤管drwxr-xr-x 2 wangyubin wangyubin 4.0K Sep 2320:42 other$ ll other/total 4.0K-rw-r--r-- 1 wangyubin wangyubin 71 Sep 2316:11 Makefile$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginother makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end⽰例: (⽤export传递参数)# Makefile 内容export VALUE1 := export.c <-- ⽤了 export, 此变量能够传递到 ./other/Makefile 中VALUE2 := no-export.c <-- 此变量不能传递到 ./other/Makefile 中all:@echo "主 Makefile begin"@cd ./other && make@echo "主 Makefile end"# ./other/Makefile 内容other-all:@echo "other makefile begin"@echo "VALUE1: " $(VALUE1)@echo "VALUE2: " $(VALUE2)@echo "other makefile end"# bash中执⾏make$ make主 Makefile beginmake[1]: Entering directory `/path/to/test/makefile/other'other makefile beginVALUE1: export.c <-- VALUE1 传递成功VALUE2: <-- VALUE2 传递失败other makefile endmake[1]: Leaving directory `/path/to/test/makefile/other'主 Makefile end*补充* export 语法格式如下:export variable = valueexport variable := valueexport variable += value3.2 定义命令包命令包有点像是个函数, 将连续的相同的命令合成⼀条, 减少 Makefile 中的代码量, 便于以后维护.语法:define <command-name>command...endef⽰例:# Makefile 内容define run-hello-makefile@echo -n "Hello"@echo " Makefile!"@echo "这⾥可以执⾏多条 Shell 命令!"endefall:$(run-hello-makefile)# bash 中运⾏make$ makeHello Makefile!这⾥可以执⾏多条 Shell 命令!3.3 条件判断条件判断的关键字主要有 ifeq ifneq ifdef ifndef语法:<conditional-directive><text-if-true>endif# 或者<conditional-directive><text-if-true>else<text-if-false>endif⽰例: ifeq的例⼦, ifneq和ifeq的使⽤⽅法类似, 就是取反# Makefile 内容all:ifeq ("aa", "bb")@echo "equal"else@echo "not equal"endif# bash 中执⾏make$ makenot equal⽰例: ifdef的例⼦, ifndef和ifdef的使⽤⽅法类似, 就是取反# Makefile 内容SRCS := program.call:ifdef SRCS@echo $(SRCS)else@echo "no SRCS"# bash 中执⾏make$ makeprogram.c3.4 Makefile 中的函数Makefile 中⾃带了⼀些函数, 利⽤这些函数可以简化 Makefile 的编写.函数调⽤语法如下:$(<function> <arguments>)# 或者${<function> <arguments>}<function> 是函数名<arguments> 是函数参数3.4.1 字符串函数字符串替换函数: $(subst <from>,<to>,<text>)功能: 把字符串<text> 中的 <from> 替换为 <to>返回: 替换过的字符串# Makefile 内容all:@echo $(subst t,e,maktfilt) <-- 将t替换为e# bash 中执⾏make$ makemakefile模式字符串替换函数: $(patsubst <pattern>,<replacement>,<text>)功能: 查找<text>中的单词(单词以"空格", "tab", "换⾏"来分割) 是否符合 <pattern>, 符合的话, ⽤ <replacement> 替代.返回: 替换过的字符串# Makefile 内容all:@echo $(patsubst %.c,%.o,programA.c programB.c)# bash 中执⾏make$ makeprogramA.o programB.o去空格函数: $(strip <string>)功能: 去掉 <string> 字符串中开头和结尾的空字符返回: 被去掉空格的字符串值# Makefile 内容VAL := " aa bb cc "all:@echo "去除空格前: " $(VAL)@echo "去除空格后: " $(strip $(VAL))# bash 中执⾏make去除空格前: aa bb cc去除空格后: aa bb cc查找字符串函数: $(findstring <find>,<in>)功能: 在字符串 <in> 中查找 <find> 字符串返回: 如果找到, 返回 <find> 字符串, 否则返回空字符串# Makefile 内容VAL := " aa bb cc "all:@echo $(findstring aa,$(VAL))@echo $(findstring ab,$(VAL))# bash 中执⾏make$ makeaa过滤函数: $(filter <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *保留* 符合模式 <pattern> 的单词, 可以有多个模式返回: 符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.o program.a反过滤函数: $(filter-out <pattern...>,<text>)功能: 以 <pattern> 模式过滤字符串 <text>, *去除* 符合模式 <pattern> 的单词, 可以有多个模式返回: 不符合模式 <pattern> 的字符串# Makefile 内容all:@echo $(filter-out %.o %.a,program.c program.o program.a)# bash 中执⾏make$ makeprogram.c排序函数: $(sort <list>)功能: 给字符串 <list> 中的单词排序 (升序)返回: 排序后的字符串# Makefile 内容all:@echo $(sort bac abc acb cab)# bash 中执⾏make$ makeabc acb bac cab取单词函数: $(word <n>,<text>)功能: 取字符串 <text> 中的第<n>个单词 (n从1开始)返回: <text> 中的第<n>个单词, 如果<n> ⽐ <text> 中单词个数要⼤, 则返回空字符串# Makefile 内容all:@echo $(word 1,aa bb cc dd)@echo $(word 5,aa bb cc dd)@echo $(word 4,aa bb cc dd)# bash 中执⾏make$ makeaadd取单词串函数: $(wordlist <s>,<e>,<text>)功能: 从字符串<text>中取从<s>开始到<e>的单词串. <s>和<e>是⼀个数字.返回: 从<s>到<e>的字符串# Makefile 内容all:@echo $(wordlist 1,3,aa bb cc dd)@echo $(word 5,6,aa bb cc dd)@echo $(word 2,5,aa bb cc dd)# bash 中执⾏make$ makeaa bb ccbb单词个数统计函数: $(words <text>)功能: 统计字符串 <text> 中单词的个数返回: 单词个数# Makefile 内容all:@echo $(words aa bb cc dd)@echo $(words aabbccdd)@echo $(words )# bash 中执⾏make$ make41⾸单词函数: $(firstword <text>)功能: 取字符串 <text> 中的第⼀个单词返回: 字符串 <text> 中的第⼀个单词# Makefile 内容all:@echo $(firstword aa bb cc dd)@echo $(firstword aabbccdd)@echo $(firstword )# bash 中执⾏make$ makeaaaabbccdd3.4.2 ⽂件名函数取⽬录函数: $(dir <names...>)功能: 从⽂件名序列 <names> 中取出⽬录部分返回: ⽂件名序列 <names> 中的⽬录部分# Makefile 内容all:@echo $(dir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ make/home/ ./ ../ ./取⽂件函数: $(notdir <names...>)功能: 从⽂件名序列 <names> 中取出⾮⽬录部分返回: ⽂件名序列 <names> 中的⾮⽬录部分# Makefile 内容all:@echo $(notdir /home/a.c ./bb.c ../c.c d.c)# bash 中执⾏make$ makea.c bb.cc.cd.c取后缀函数: $(suffix <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的后缀返回: ⽂件名序列 <names> 中各个⽂件名的后缀, 没有后缀则返回空字符串# Makefile 内容all:@echo $(suffix /home/a.c ./b.o ../c.a d)# bash 中执⾏make$ make.c .o .a取前缀函数: $(basename <names...>)功能: 从⽂件名序列 <names> 中取出各个⽂件名的前缀返回: ⽂件名序列 <names> 中各个⽂件名的前缀, 没有前缀则返回空字符串# Makefile 内容all:@echo $(basename /home/a.c ./b.o ../c.a /home/.d .e)# bash 中执⾏make$ make/home/a ./b ../c /home/加后缀函数: $(addsuffix <suffix>,<names...>)功能: 把后缀 <suffix> 加到 <names> 中的每个单词后⾯返回: 加过后缀的⽂件名序列# Makefile 内容all:@echo $(addsuffix .c,/home/a b ./c.o ../d.c)# bash 中执⾏make$ make/home/a.c b.c ./c.o.c ../d.c.c加前缀函数: $(addprefix <prefix>,<names...>)功能: 把前缀 <prefix> 加到 <names> 中的每个单词前⾯返回: 加过前缀的⽂件名序列# Makefile 内容all:@echo $(addprefix test_,/home/a.c b.c ./d.c)# bash 中执⾏make$ maketest_/home/a.c test_b.c test_./d.c连接函数: $(join <list1>,<list2>)功能: <list2> 中对应的单词加到 <list1> 后⾯返回: 连接后的字符串# Makefile 内容all:@echo $(join a b c d,1234)@echo $(join a b c d,12345)@echo $(join a b c d e,1234)# bash 中执⾏make$ makea1 b2 c3 d4a1 b2 c3 d4 5a1 b2 c3 d4 e3.4.3 foreach语法:$(foreach <var>,<list>,<text>)⽰例:# Makefile 内容targets := a b c dobjects := $(foreach i,$(targets),$(i).o)all:@echo $(targets)@echo $(objects)# bash 中执⾏make$ makea b c da.ob.oc.od.o3.4.4 if这⾥的if是个函数, 和前⾯的条件判断不⼀样, 前⾯的条件判断属于Makefile的关键字语法:$(if <condition>,<then-part>)$(if <condition>,<then-part>,<else-part>)⽰例:# Makefile 内容val := aobjects := $(if $(val),$(val).o,nothing)no-objects := $(if $(no-val),$(val).o,nothing)all:@echo $(objects)@echo $(no-objects)# bash 中执⾏make$ makea.onothing3.4.5 call - 创建新的参数化函数语法:$(call <expression>,<parm1>,<parm2>,<parm3>...)⽰例:# Makefile 内容log = "====debug====" $(1) "====end===="all:@echo $(call log,"正在 Make")# bash 中执⾏make$ make====debug==== 正在 Make ====end====3.4.6 origin - 判断变量的来源语法:$(origin <variable>)返回值有如下类型:类型含义undefined<variable> 没有定义过default<variable> 是个默认的定义, ⽐如 CC 变量environment<variable> 是个环境变量, 并且 make时没有使⽤ -e 参数file<variable> 定义在Makefile中command line<variable> 定义在命令⾏中override<variable> 被 override 重新定义过automatic<variable> 是⾃动化变量⽰例:# Makefile 内容val-in-file := test-fileoverride val-override := test-overrideall:@echo $(origin not-define) # not-define 没有定义@echo $(origin CC) # CC 是Makefile默认定义的变量@echo $(origin PATH) # PATH 是 bash 环境变量@echo $(origin val-in-file) # 此Makefile中定义的变量@echo $(origin val-in-cmd) # 这个变量会加在make的参数中@echo $(origin val-override) # 此Makefile中定义的override变量@echo $(origin @) # ⾃动变量, 具体前⾯的介绍# bash 中执⾏make$ make val-in-cmd=val-cmdundefineddefaultenvironmentfilecommand lineoverrideautomatic3.4.7 shell语法:$(shell <shell command>)它的作⽤就是执⾏⼀个shell命令, 并将shell命令的结果作为函数的返回.作⽤和 `<shell command>` ⼀样, ` 是反引号3.4.8 make 控制函数产⽣⼀个致命错误: $(error <text ...>)功能: 输出错误信息, 停⽌Makefile的运⾏# Makefile 内容all:$(error there is an error!)@echo "这⾥不会执⾏!"# bash 中执⾏make$ makeMakefile:2: *** there is an error!. Stop.输出警告: $(warning <text ...>)功能: 输出警告信息, Makefile继续运⾏# Makefile 内容all:$(warning there is an warning!)@echo "这⾥会执⾏!"# bash 中执⾏make$ makeMakefile:2: there is an warning!这⾥会执⾏!3.5 Makefile中⼀些GNU约定俗成的伪⽬标如果有过在Linux上, 从源码安装软件的经历的话, 就会对 make clean, make install ⽐较熟悉.像 clean, install 这些伪⽬标, ⼴为⼈知, 不⽤解释就⼤家知道是什么意思了.下⾯列举⼀些常⽤的伪⽬标, 如果在⾃⼰项⽬的Makefile合理使⽤这些伪⽬标的话, 可以让我们⾃⼰的Makefile看起来更专业, 呵呵 :)伪⽬标含义all所有⽬标的⽬标,其功能⼀般是编译所有的⽬标clean删除所有被make创建的⽂件install安装已编译好的程序,其实就是把⽬标可执⾏⽂件拷贝到指定的⽬录中去print列出改变过的源⽂件tar把源程序打包备份. 也就是⼀个tar⽂件dist创建⼀个压缩⽂件, ⼀般是把tar⽂件压成Z⽂件. 或是gz⽂件TAGS更新所有的⽬标, 以备完整地重编译使⽤check 或 test⼀般⽤来测试makefile的流程。
Helloworld在我写教程之前,我先感谢一下libnds的开发人员以及维护人员。
他们给我们提供了十分方便的开发库libnds,让我们能够更加快捷简单的开发NDS程序。
下面我们进入正题。
由于devKitPro采用的是makefile机制来生成的最终输出。
所以我们的工程中必须要有makefile文件,否则将会无法编译并生成最终目标。
由于这个是入门教程这里我就不再赘述太多,等以后我们需要用到makefile文件的时候我们再去详细查看makefile的详细内容。
说明:本教程假设你已经安装好了devKitPro,只有完成了这个前提我们才能够进行一下的步骤。
1.在devKitPeo的安装目录下找到”G:\GameTools\devkitPro\examples\nds\hello_world”。
将helloworld工程完全复制出来放在你的工作区间里。
注意,工作区间的路劲不能有中文,并且路径中不能带有空格,一般的编程软件都有这个要求的。
2.接下来打开工程,如果你使用的是devKitPro编辑器的话就直接打开工程更目录下的.pnproj为后缀的文件(前提是你已经安装了devkitPro)。
如果你要是Visual Studio编写程序,请参考我的“VS下配置NDS开发环境“这篇文章。
3.打开main.c文件,开始我们的编码工作。
#include <nds.h> //包含libnds的库的头文件#include <stdio.h> //libnds的标准输入输出int main(void){consoleDemoInit(); //这个就是libnds给我们的第一个好处,一句话就将所有的初始化步骤完成。
printf(“Helloworld!\n”); //C语言的函数在libnds中重新实现,功能相同。
while( 1 ) //这里必须构造这样一个循环,写过单片机程序的同学都知道,如果没有这个循环是看不到代码运行的效果的{swiWaitForVBlank();}}4.确定代码正确无误以后,编译代码。
makefile四则运算标题:深入理解Makefile中的四则运算在软件开发过程中,Makefile是一个非常重要的工具,它主要用于自动化编译和链接程序。
而在Makefile中,我们可以使用一些特殊的语法进行数学运算,包括四则运算(加、减、乘、除)。
本文将详细解析Makefile 中的四则运算,帮助你更好地理解和使用这一功能。
一、Makefile中的变量与赋值在开始四则运算之前,我们首先需要了解Makefile中的变量和赋值。
在Makefile中,我们可以使用"="或者":="来为变量赋值。
其中"="表示延迟赋值,会在需要时才进行计算;而":="表示立即赋值,会在定义时就进行计算。
例如:VAR1 = 10VAR2 := 20在这段代码中,VAR1被赋值为10,VAR2被赋值为20。
二、Makefile中的四则运算在Makefile中,我们可以使用"(shell expr ...)"命令来进行四则运算。
这个命令会执行shell命令expr,并将结果返回。
以下是一些基本的四则运算示例:1. 加法:makefileSUM := (shell expr (VAR1) + (VAR2))在这个例子中,SUM会被赋值为VAR1和VAR2的和,即30。
2. 减法:makefileDIFF := (shell expr (VAR1) - (VAR2))在这个例子中,DIFF会被赋值为VAR1和VAR2的差,即-10。
3. 乘法:makefilePRODUCT := (shell expr (VAR1) \* (VAR2))注意,由于"*"在Makefile中有特殊含义,所以我们需要使用"\*"来表示乘法。
在这个例子中,PRODUCT会被赋值为VAR1和VAR2的乘积,即200。
⾯试题----makefile⽂件的作⽤
make⼯具和makefile⽂件
make⼯具和makefile⽂件简介
make命令和makefile⽂件的结合提供了⼀个在项⽬管理领域⼗分强⼤的⼯具。
它不仅常被⽤于控制源代码的编译和链接,⽽且还⽤于⼿册页的编写以及将应⽤程序安装到⽬标⽬录。
makefile⽂件由⼀组依赖关系和规则构成。
每个依赖关系⼜⼀个⽬标(即将要创建的⽂件)和⼀组该⽬标所依赖的源⽂件组成。
⽽规则描述了如何通过这些依赖⽂件创建⽬标。
⼀般来说,⽬标是⼀个单独的可执⾏⽂件。
make命令会读取makefile⽂件的内容,它先确定⽬标⽂件和要创建的⽂件,然后⽐较该⽬标所依赖的源⽂件的⽇期和时间以决定该采取那条规则来构建⽬标。
通常在创建最终的⽬标⽂件之前,它需要先创建⼀些中间⽬标。
make命令会根据makefile⽂件来确定⽬标⽂件的创建顺序以及正确的规则调⽤顺序。
⾯试题:makefile⽂件的作⽤是什么?
makefile⽂件和make⼯具⼀起使⽤,⽤于控制⼯程项⽬的编译和链接,也可以⽤来编写⼿册页和程序的安装。
make⼯具⽤于解释执⾏makefile⽂件中的内容。
makefile⽂件中通常包含源⽂件和⽬标⽂件的依赖关系以及从源⽂件⽣成⽬标⽂件的规则。
make⼯具可以根据makefile判断哪些⽂件需要被重新编译,⽬标⽂件的构建顺序等。
海思makefile结构解析全文共四篇示例,供读者参考第一篇示例:海思芯片是一家领先的半导体公司,在国际市场上拥有广泛的市场份额。
海思芯片的产品广泛应用在手机、网络通信、物联网、智能家居等领域,其芯片性能卓越,在同行业内享有很高的声誉。
在海思芯片的开发中,makefile是一个非常重要的工具,它负责管理整个项目的编译、链接和部署过程,帮助开发人员更高效地完成工作。
makefile是一个用于自动化编译的脚本文件,通过编写makefile 文件,可以告诉计算机如何编译源代码,生成可执行文件。
海思makefile结构解析主要包括以下几个部分:1. 定义变量:在makefile中定义变量是非常重要的,可以方便地管理项目的路径、编译参数等信息。
海思makefile中通常会定义一些常用的变量,比如CC表示编译器的路径,CXX表示C++编译器的路径,CFLAGS表示编译参数等。
通过定义这些变量,可以在整个makefile中直接引用,减少了代码的冗余,提高了代码的可维护性。
2. 设置编译规则:在makefile中,通常会定义一些编译规则,告诉make工具如何编译源文件和生成可执行文件。
海思makefile中的编译规则通常使用模式匹配的方式,比如"%.c:%.o"表示将所有的.c文件编译为.o文件,而"%.o:%.c"则表示将所有的.o文件根据对应的.c文件进行重新编译。
通过这些编译规则,make工具可以根据需要自动化地完成整个项目的编译过程。
3. 定义目标:在makefile中通常会定义一些目标,这些目标可以是编译生成可执行文件的命令,也可以是清理生成的临时文件的命令。
海思makefile中的目标通常包括all、clean、install等,通过定义这些目标,可以方便地管理整个项目的编译和部署过程。
4. 调用外部工具:在海思makefile中,通常会调用一些外部工具来完成一些特定的任务,比如编译器、链接器、打包工具等。
Makefile文件解析在我写教程之前,我先感谢一下libnds的开发人员以及维护人员。
他们给我们提供了十分方便的开发库libnds,让我们能够更加快捷简单的开发NDS程序。
下面我们进入正题。
注:以下绿色为文件的原注释,紫色是我后来添加的注释方便大家理解。
#---------------------------------------------------------------------------------.SUFFIXES:#---------------------------------------------------------------------------------ifeq ($(strip $(DEVKITARM)),)$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")endifinclude $(DEVKITARM)/ds_rules#---------------------------------------------------------------------------------# TARGET 输出名称# BUILD 生成文件夹名称,对象文件以及中间文件将会被放在这个文件夹中。
# SOURCES 包含源文件的目录列表# INCLUDES 包含外部头文件的目录列表# DATA 包含二进制数据的目录列表# GRAPHICS 用grit处理文件的目录列表# AUDIO 包含用mmutil来处理的文件的文件目录# SOUNDBANK_NAME maxmod生成的soundbank的名称#MUSIC 外部音频文件目录## 所有的文件必须在与项目相关的能够找到makefile文件的文件目录下。
#---------------------------------------------------------------------------------TARGET := $(notdir $(CURDIR))BUILD := buildSOURCES := sourceINCLUDES := includeMUSIC := maxmod_data#---------------------------------------------------------------------------------# 以上部分相当于编程语言中的宏定义部分,通过:=给宏定义的变量名成进行赋值# 在以下的代码中有使用到这些宏定义。
# 但是这些宏定义的名称以及赋值都是固定的,如果随意设置编译将不会成功。
#---------------------------------------------------------------------------------#---------------------------------------------------------------------------------#对于以上的目录相关,如果不适用则不再其中添加。
#例如本例中未使用DATA则不添加DATA相关项在其中。
#以上代码都可以手动修改单一定要符合以上原则#---------------------------------------------------------------------------------#---------------------------------------------------------------------------------#以下是代码生成选项#---------------------------------------------------------------------------------ARCH := -mthumb -mthumb-interworkCFLAGS := -g -Wall -O2\-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\-ffast-math \$(ARCH)CFLAGS += $(INCLUDE) -DARM9CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptionsASFLAGS := -g $(ARCH)LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)#---------------------------------------------------------------------------------#通常不做修改#---------------------------------------------------------------------------------#---------------------------------------------------------------------------------# 这里添加我们希望连接到工程的外部库。
当我们需要使用外部库的时候,# 我们需要在这里添加外部库的名称。
#---------------------------------------------------------------------------------LIBS := -lmm9 -lnds9#---------------------------------------------------------------------------------# 包含库文件的目录列表, 这个必须是库的顶级文件夹名称#---------------------------------------------------------------------------------LIBDIRS := $(LIBNDS)#---------------------------------------------------------------------------------# 从这个点往后没有你真正需要修改的,除非你需要为不同文件拓展名的文件添加规则#---------------------------------------------------------------------------------ifneq ($(BUILDDIR), $(CURDIR))#---------------------------------------------------------------------------------export OUTPUT := $(CURDIR)/$(TARGET)export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \$(foreach dir,$(DATA),$(CURDIR)/$(dir)) \$(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir))export DEPSDIR := $(CURDIR)/$(BUILD)CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) soundbank.binexport AUDIOFILES := $(foreach dir,$(notdir $(wildcard $(MUSIC)/*.*)),$(CURDIR)/$(MUSIC)/$(dir))#---------------------------------------------------------------------------------# 使用CXX连接C++工程,CC为标准C#---------------------------------------------------------------------------------ifeq ($(strip $(CPPFILES)),)#---------------------------------------------------------------------------------export LD := $(CC)#---------------------------------------------------------------------------------else#---------------------------------------------------------------------------------export LD := $(CXX)#---------------------------------------------------------------------------------endif#---------------------------------------------------------------------------------#---------------------------------------------------------------------------------export OFILES := $(addsuffix .o,$(BINFILES)) \$(BMPFILES:.bmp=.o) \$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \$(foreach dir,$(LIBDIRS),-I$(dir)/include) \-I$(CURDIR)/$(BUILD)export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib).PHONY: $(BUILD) clean#---------------------------------------------------------------------------------$(BUILD):@[ -d $@ ] || mkdir -p $@@make BUILDDIR=`cd $(BUILD) && pwd` --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile#---------------------------------------------------------------------------------clean:@echo clean ...@rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds#---------------------------------------------------------------------------------else#---------------------------------------------------------------------------------# 最终生成目标#---------------------------------------------------------------------------------$(OUTPUT).nds : $(OUTPUT).elf$(OUTPUT).elf : $(OFILES)#---------------------------------------------------------------------------------# 为了使用与不同拓展名的数据,应该为每一个数据目录复制与修改bin2o的规则。