Ⅰ linux的makefile中":="与"="有什么区别
:= 就是简单的赋值, 比如
foo := $(bar)
将bar的值赋给foo
?= 是条件赋值, 比如
foo ?= $(bar)
只有当foo变量还没有被定义的时候,才会将bar的值赋给foo。 注意,如果foo已经被定义过,但是是空值了话,?=不会给他赋值。比方说你的makefile是
foo = hello
foo ?= new
则最终foo的值是hello
如果你的makefile是
foo =
foo ?= new
foo的值是空
Ⅱ makefile有哪些环境变量
MakeFile中的变量定义
一般在我们书写Makefile时,各部分变量引用的格式我们建议如下:
1. make变量(Makefile中定义的或者是make的环境变量)的引用使用“$(VAR)”格式。
2. 出现在规则命令行中shell变量(一般为执行命令过程中的临时变量,它不属于Makefile变量,而是一个shell变量)引用使用shell的“$tmp”格式。
3. 对出现在命令行中的make变量我们同样使用“$(CMDVAR)” 格式来引用。
MakeFile中给变量赋值有以下两种方式
1.递归展开式,使用=直接定义,例子如下:
foo = $(bar)
bar = $(ugh)
ugh = Huh?
all:;echo $(foo)
执行“make”将会打印出“Huh?”。整个变量的替换过程时这样的:首先“$(foo)”被替换为“$(bar)”,接下来 “$(bar)”被替换为“$(ugh)”,最后“$(ugh)”被替换为“Hug?”。整个替换的过程是在执行“echo $(foo)”是进行的。
这种方式的缺点是
缺点1:使用此风格的变量定义,可能会由于出现变量递归定义而导致make陷入到无限的变量展开过程中,最终使make执行失败.
缺点2:这种风格的变量定义中如果使用了函数,那么包含在变量值中的函数总会在变量被引用的地方执行(变量被展开时)。
2.直接展开式
这种风格的变量使用“:=”来定义变量。在使用“:=”定义变量时,变量值中对另外变量的引用或者函数的引用在定义时被展开(对变量进行替换)。
x := foo
y := $(x) bar
x := later
就等价于:
y := foo bar
x := later
需要CFLAGS := $(include_dirs) -O
include_dirs := -Ifoo -Ibar
由于在变量“include_dirs”的定义出现在“CFLAGS”定义之后。因此在“CFLAGS”的定义中,“include_dirs”的值为空。“CFLAGS”的值为“-O”而不是“-Ifoo -Ibar -O”。注意的是:此风格变量在定义时就完成了对所引用的变量的展开,因此它不能实现对其后定义变量的引用。
变量的替换引用,格式为“$(VAR:A=B)”(或者“${VAR:A=B}”),
意思是,替换变量“VAR”中所有“A”字符结尾的字为“B”结尾的字。
“结尾”的含义是空格之前(变量值多个字之间使用空格分开)。
而对于变量其它部分的“A”字符不进行替换。
自动化变量
$@
代表规则中的目标文件名。如果目标是一个文档(Linux中,一般称.a文件为文档),那么它代表这个文档的文件名。在多目标的模式规则中,它代表的是哪个触发规则被执行的目标文件名。
$%
规则的目标文件是一个静态库文件时,代表静态库的一个成员名。例如,规则的目标是“foo.a(bar.o)”,那么,“$%”的值就为“bar.o”,“$@”的值为“foo.a”。如果目标不是函数库文件,其值为空。
$<
规则的第一个依赖文件名。如果是隐含规则,则它代表通过目标指定的第一个依赖文件。
$?
所有比目标文件更新的依赖文件列表,空格分割。如果目标是静态库文件名,代表的是库成
员(.o文件)的更新情况。
$^
规则的所有依赖文件列表,使用空格分隔。如果目标是静态库文件名,它所代表的只能是所有库成员(.o文件)名。一个文件可重复的出现在目标的依赖中,变量“$^”只记录它的一次引用情况。就是说变量“$^”会去掉重复的依赖文件。
$+
类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时,库的交叉引用场合。
$(@D)
代表目标文件的目录部分(去掉目录部分的最后一个斜杠)。如果“$@”是“dir/foo.o”,那么“$(@D)”的值为“dir”。如果“$@”不存在斜杠,其值就是“.”(当前目录)。注意它和函数“dir”的区别!
$(@F)
目标文件的完整文件名中除目录以外的部分(实际文件名)。如果“$@”为“dir/foo.o”,那么“$(@F)”只就是“foo.o”。“$(@F)”等价于函数“$(notdir $@)”。
$(%D)
$(%F)
当以如“archive(member)”形式静态库为目标时,分别表示库文件成员“member”名中的目录部分和文件名部分。它仅对这种形式的规则目标有效。
$(<D)
$(<F)
分别表示规则中第一个依赖文件的目录部分和文件名部分。
$(^D)
$(^F)
分别表示所有依赖文件的目录部分和文件部分(不存在同一文件)。
$(+D)
$(+F)
分别表示所有依赖文件的目录部分和文件部分(可存在重复文件)。
$(?D)
$(?F)
分别表示被更新的依赖文件的目录部分和文件部分。
Ⅲ linux shell: 帮我解释下这个makefile每一行的意思嘛
CC=gcc //指定编译器为gcc编译器
CFLAGS //指定编译选项
CFILES=$(wildcard*.c) //wildcard是扩展通配符,匹配当前目录下所有.c文件(文件包含路径)
OBJS=$(CFILES:%c=%o) //生成文件格式,把CFILES匹配的所有.c文件名改为.o文件名
all:hello //all 目标依赖于hello
hello : $(OBJS) //hello 目标依赖于$(OBJS)包含的文件,生成$(OBJS)的规则如下。
$(CC) ...... //展开就是用gcc生成可执行程序。gcc -o hello $(OBJS)
.c.o:
$(CC) -c $< //利用gcc编译c源文件为.o格式的目标文件
clean:
rm -rf hello *.o //清理生成文件命令。
-----------------------------------------
实际上,makefile文件就是把手动编译的过程写入了这个文件。
Ⅳ Linux的makefile中有连接脚本和没连接脚本的区别
在Makefile可以调用shell脚本,但是Makefile和shell脚本是不同的。本文试着归纳一下Makefile和shell脚本的不同。
1、
shell中所有引用以$打头的变量其后要加{},而在Makefile中的变量是以$打头的后加()。实例如下:
Makefile
PATH="/data/"
SUBPATH=$(PATH)
Shell
PATH="/data/"
SUBPATH=${PATH}
2、Makefile中所有以$打头的单词都会被解释成Makefile中的变量。如果你需要调用shell中的变量(或者正则表达式中锚定句位$),都需要加两个$符号($$)。实例如下:
PATH="/data/"
all:
echo
${PATH}
echo
$$PATH例子中的第一个${PATH}引用的是Makefile中的变量,而不是shell中的PATH环境变量,后者引用的事Shell中的PATH环境变量。
3、通配符区别
shell
中通配符*表示所有的字符
Makefile
中通配符%表示所有的字符
4、在Makefile中只能在target中调用Shell脚本,其他地方是不能输出的。比如如下代码就是没有任何输出:
VAR="Hello"
echo
"$VAR"
all:
.....以上代码任何时候都不会输出,没有在target内,如果上述代码改为如下:
VAR="Hello"
all:
echo
"$VAR"
.....以上代码,在make
all的时候将会执行echo命令。
5、在Makefile中执行shell命令,一行创建一个进程来执行。这也是为什么很多Makefile中有很多行的末尾都是“;
\”,以此来保证代码是一行而不是多行,这样Makefile可以在一个进程中执行,例如:
SUBDIR=src
example
all:
@for
subdir
in
$(SUBDIR);
\
do\
echo
"building
";
\
done上述可以看出for循环中每行都是以”;
\”结尾的。
6、获取当前目录
PATH=`pwd`
注意是``,不是''
推荐你看或者linux就该这么学,具体关于这一章地址3w(dot)linuxprobe(dot)com.
Ⅳ Linux下shell脚本怎么实现运行某个文件的makefile
make工具就知道阿,makefile文件里描述了编译参数等信息
Ⅵ Makefiel和shell的区别
一句2句说不清楚,他们是2样东西,语法有相似之处,各有各的语法。bash shell script是/bin/bash这个工具可以理解并执行的命令的集合。一个脚本包括一个或者多个命令(并非全是一行一行简单的命令,还有循环,分支,函数等等)
#!/bin/bash
date
cat a.txt
echo "hello world"
这是个简单的bash shell 脚本。
看看下面最简单的一个makefile文件sy1.mk,运行cat sy1.mk显示一下它,注意echo的左边必须是一个Tab键,不是8个空格:
$ cat sy1.mk
all:
echo "hello makefile"
运行命令make -f <文件名>:
$ make -f sy1.mk
echo "hello makefile"
hello makefile
makefile文件是被/usr/bin/make或者/bin/make (或者 /usr/bin/gmake)能理解并且运行(严格说,还不能完全说“运行”)的文本文件。
编译大型软件,例如Android (你可以下载andoid全套代码,网上可以查到步骤),一般离不开makefile,也离不开shell;在linux/unix下做软件开发(不管大型软件还是很小的软件),做linux系统维护,搭建linux使用和开发环境,一般离不开shell。
学会shell和makefile不是一天2天的事,网上免费的资料很多。
供参考,谢谢!
Ⅶ 在linux下如何执行另一个文件夹下的makefile
可以在主Makefile文件中直接写
all:
cd /Path/To/src1 && make
cd /Path/To/src2 && make
......
注意命令直接要使用 “&&”符号连接,尤其是在声明一些环境变量的时候,例如
export GNUMAKE=/bin/gmake && cd /Path/To/src && make
Ⅷ Linux makefile&shell的一个问题
ar 命令是用来将若干 .o 文件打包成(静态)库文件。 按照习惯,库文件后缀名都是 .a
crv 分别是 ar 命令的三个参数,cr的意思是创建指定.a文件(如果不存在),并将.o文件加入到这个.a文件中。 v 的意思是让 ar 命令在执行的时候打印更多的提示信息。
ar crv abc.a $(OBJ) 就是将 abc.o 打包到库文件 abc.a 中的意思。
更多信息可以 man ar 来看到。
Ⅸ linux Makefile文件中 KERNELDIR = /lib/moles/$(shell uname -r)/build什么意思
你说的是编译内核模块的Makefile是吗?KERNELDIR指的是内核库文件的路径,你的代码中使用的是内核提供的函数,而这些函数也是有具体实现的,在连接成一个内核模块时要说明这些库文件在哪里,方便链接程序把它们连接成一个完成的模块。“?=”:如果这个KERNELDIR为空说明你没有指定内核库文件的路径,那么它就会给KERNELDIR赋值,因为顶层Makefile通过这个环境变量知道内核库文件在哪里。KERNELDIR=/lib/moles/$(shell uname -r)/build;其中 shell uname -r 说的是调用shell里头的uname指令 你可以uname -r看看呢是什么,他表示的是内核版本号。一般来说我们构造内核树时,它把内核库统一保存在/lib/moles/内核版本号/build目下。还有不清楚的请提问,呵呵。Ⅹ Linux基础中,shell脚本和makefile文件的差别是什么啊,求详细点嘛
你可以认为makefile是shell脚本“派生”出来的。最朴素的makefile可以完全通过gcc等语句实现,在这种情况下也就是shell脚本了。但是为了方便,makefile引入了大量的语法用来使编译链接变得简单,所以和shell脚本还是不同的。
可以参考:http://apps.hi..com/share/detail/31232485