Makefile中嵌入一段shell脚本及函数列表

您所在的位置:网站首页 makefile怎么传递参数 Makefile中嵌入一段shell脚本及函数列表

Makefile中嵌入一段shell脚本及函数列表

2023-08-12 11:32| 来源: 网络整理| 查看: 265

Makefile中需要在编译前进行一些处理,shell可以方便完成。以下为在Makefile中使用shell需要注意的一些事项:

makefile和shell区别变量引用

shell中所有引用以$打头的变量其后要加{},而在Makefile中的变量是以$打头的后加()。如下:

Makefile PATH="/data/" SUBPATH=$(PATH) Shell PATH="/data/" SUBPATH=${PATH}引用shell变量

Makefile中所有以$打头的单词都会被解释成Makefile中的变量。如果需要调用shell中的变量(或者正则表达式中锚定句位$),都需要加两个$符号($$)。如下:

PATH="/data/" all: echo $(PATH) echo $$PATH

第一个$(PATH)引用的是Makefile中的变量,而不是shell中的PATH环境变量,后者引用的是Shell中的PATH环境变量。

通配符区别

shell 中通配符*表示所有的字符;Makefile 中通配符%表示所有的字符

打印输出

在Makefile中只能在target中调用Shell脚本,其他地方是不能输出的。比如如下代码就是没有任何输出:

VAR="Hello" echo "$VAR" all:

以上代码任何时候都不会输出,没有在target内,如果上述代码改为如下:

VAR="Hello" all: echo "$VAR"

以上代码,在make all的时候将会执行echo命令。

代码片段

Makefile中的shell,每一行是一个进程,不同行之间变量值不能传递。所以,Makefile中的shell不管多长也要写在一行在Makefile中执行shell命令,一行创建一个进程来执行。不同行之间变量值不能传递。这也是为什么很多Makefile中有很多行的末尾都是“;\”,以此来保证代码是一行而不是多行,这样Makefile可以在一个进程中执行,例如:

SUBDIR=src example all: @for subdir in $(SUBDIR); \ #shell代码开始 do\ echo "building "; \ done

上述可以看出for循环中每行都是以”; \”结尾的。

shell代码范围

在Makefile文件的目标项冒号后的另起一行的代码才是shell代码。

xx = xx1 #这里时makefile代码 yy:xx = xx2 #这是是makefile代码,makefile允许变量赋值时,'='号两边留空格 yy: xx=xx3 #只有这里是shell代码 ,shell不允许‘=’号两边有空格哦。 有一个例外: xx=$(shell 这里的代码也是shell代码)makefile总的反引号`

反引号括起来的字符串被shell解释为命令行,在执行时,shell首先执行该命令行,并以它的标准输出结果取代整个反引号(包括两个反引号)部分

PATH=`pwd` TODAY=`date` #等同于 PATH=$(shell pwd) TODAY=$(shell date)实例

获取当前目录

TOPDIR:=$(shell pwd)

获取日期

DATE:=$(shell date +%Y%m%d)

获取源文件列表

SRC += $(shell find . -iname "*.c" | grep -v "./opensource/*") SRC += $(shell find . -iname "*.cpp") PRE_SRC=$(shell find -name "*.c" | xargs grep "HANDLER" | awk -F ':' '{print $$1}' | sort -u) #注意awk中使用的是 $$1

Makefile打印输出

print_version: @echo $(BR2_VERSION_FULL)

Makefile嵌入脚本

env: sh $(SRC_PATH)/scripts/connect.sh find $(SRC_PATH) -name "sysinfo.o" | xargs rm -f signalpre: sed -i 's/HANDLER/HANDLER HANDLERX/g' $(LIB_PATH)/include/core.h @mkdir -p $(SRC_PATH)/output/signalpres @echo "\033[031msignale handler processor...\033[0m" @for f in $(PRE_SRC); do \ OBJ=$(SRC_PATH)/output/signalpres/`basename $$f|sed -e 's/\.c/\.i/'`; \ $(CC) $(CFLAGS) -E $$f -o $$OBJ;\ echo -n ".";\ done sed -i 's/HANDLER HANDLERX/HANDLER/g' $(LIB_PATH)/include/core.h echo "\n" prepare_config: @chmod +x scripts/proj.sh @scripts/proj.sh @chmod +x scripts/theme.sh @scripts/theme.sh

Makefile中的exec执行脚本

format: @echo "Makeing format..."; @find -name "*.c" -exec dos2unix -qU 2>d2utmp1 {} \; @find -name "*.h" -exec dos2unix -qU 2>d2utmp1 {} \; # @find -name "*.c" -exec indent -npro -kr -i8 -sob -l120 -ss -ncs {} \; @find -name "*~" -exec rm {} \; @find -name "d2utmp*" -exec rm {} \; @find -name "deps*" -exec rm {} \;

循环处理文件行

cat config_tmp | while read line do echo "${line}" MACRO=$(echo ${line} | awk -F ' ' '{print $2}') VALUE=$(echo ${line} | awk -F ' ' '{print $3}') echo "Macro: $MACRO Value: $VALUE\n" #cat "$SIGNALE_HANDLER_FILE" | sed -e "s/$MACRO/$VALUE/g" > signal_tmp sed -i "s/$MACRO/$VALUE/g" ${SIGNALE_HANDLER_FILE} done

grep反选

cat $CONFIG_FILE | sed -s '/^$/d' | grep -v -e "LangName" -e "__CONFIG_H__" -e "#endif" -e "//" > config_tmp

Makefile依赖规则

OBJS=$(addprefix $(SRC_PATH)/objects/, $(addsuffix .o, $(basename $(notdir $(SRC))))) deps: $(SRC) @-rm -f deps; @for f in $(SRC); do \ OBJ=$(SRC_PATH)/objects/`basename $$f|sed -e 's/\.c/\.o/'`; \ echo $$OBJ: $$f>> deps; \ echo ' @echo -e "compiling \033[032m[$(CC)]\033[0m": ' $$f >> deps; \ echo ' $(CC) $$(CFLAGS) -c -o $$@ $$^'>> deps; \ done

Makefile模式规则

%.d: %.c @set -e; rm -f $@; \ $(CC) -M $(CPPFLAGS) $< > $@.$$$$; \ sed 's,\($*\)\.o[ : ]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$

这个规则的意思是,所有的[.d]文件依赖于[.c]文件,“rm -f $@”的意思是删除所有的目标,也就是[.d]文件,第二行的意思是,为每个依赖文件“$所包含的表达式。每一次会返回一个字符串,循环过程中,的所返回的每个字符串会以空格分隔,最后当整个循环结束时,所返回的每个字符串所组成的整个字符串(以空格分隔)将会是foreach函数的返回值。

所以,最好是一个变量名,可以是一个表达式,而中一般会使用这个参数来依次枚举中的单词。举个例子:

names := a b c d files := $(foreach n,$(names),$(n).o)

上面的例子中,$(name)中的单词会被挨个取出,并存到变量“n”中,“$(n).o”每次根据“$(n)”计算出一个值,这些值以空格分隔,最后作为foreach函数的返回,所以,$(files)的值是“a.o b.o c.o d.o”。

注意,foreach中的参数是一个临时的局部变量,foreach函数执行完后,参数的变量将不在作用,其作用域只在foreach函数当中。

if 函数

if函数很像GNU的make所支持的条件语句——ifeq,if函数的语法是:

$(if ,)

或是

$(if ,,)call函数

call函数是唯一一个可以用来创建新的参数化的函数。你可以写一个非常复杂的表达式,这个表达式中,你可以定义许多参数,然后你可以用call函数来向这个表达式传递参数。其语法是:

$(call ;,;,;,;...)

当make执行这个函数时,;参数中的变量,如$(1),$(2),$(3)等,会被参数< parm1>;,;,;依次取代。而;的返回值就是 call函数的返回值。例如:

reverse = $(1) $(2) foo = $(call reverse,a,b)

那么,foo的值就是“a b”。当然,参数的次序是可以自定义的,不一定是顺序的,如:

reverse = $(2) $(1) foo = $(call reverse,a,b)

此时的foo的值就是“b a”。

origin函数

origin函数不像其它的函数,他并不操作变量的值,他只是告诉你你的这个变量是哪里来的?其语法是:

$(origin ;)

注意,;是变量的名字,不应该是引用。所以你最好不要在;中使用“$”字符。Origin函数会以其返回值来告诉你这个变量的“出生情况”,下面,是origin函数的返回值:

“undefined” 如果;从来没有定义过,origin函数返回这个值“undefined”。 “default” 如果;是一个默认的定义,比如“CC”这个变量,这种变量我们将在后面讲述。 “environment” 如果;是一个环境变量,并且当Makefile被执行时,“-e”参数没有被打开。 “file” 如果;这个变量被定义在Makefile中。 “command line” 如果;这个变量是被命令行定义的。 “override” 如果;是被override指示符重新定义的。 “automatic” 如果;是一个命令运行中的自动化变量。关于自动化变量将在后面讲述。

这些信息对于我们编写Makefile是非常有用的,例如,假设我们有一个Makefile其包了一个定义文件Make.def,在 Make.def中定义了一个变量“bletch”,而我们的环境中也有一个环境变量“bletch”,此时,我们想判断一下,如果变量来源于环境,那么我们就把之重定义了,如果来源于Make.def或是命令行等非环境的,那么我们就不重新定义它。于是,在我们的Makefile中,我们可以这样写:

ifdef bletch ifeq "$(origin bletch)" "environment" bletch = barf, gag, etc. endif endifshell函数

它的参数应该就是操作系统Shell的命令。它和反引号`是相同的功能。这就是说,shell函数把执行操作系统命令后的输出作为函数返回。于是,我们可以用操作系统命令以及字符串处理命令awk,sed等等命令来生成一个变量,如:

contents := $(shell cat foo) files := $(shell echo *.c)

注意,这个函数会新生成一个Shell程序来执行命令,所以你要注意其运行性能,如果你的Makefile中有一些比较复杂的规则,并大量使用了这个函数,那么对于你的系统性能是有害的。特别是Makefile的隐晦的规则可能会让你的shell函数执行的次数比你想像的多得多。

自动化变量

$@ 表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,”$@”就是匹配于目标中模式定义的集合。

$% 仅当目标是函数库文件中,表示规则中的目标成员名。例如,如果一个目标是”foo.a(bar.o)”,那么,”$%”就是 “bar.o”,”$@”就是”foo.a”。如果目标不是函数库文件(Unix下是[.a],Windows下是[.lib]),那么,其值为空。

$< 依赖目标中的第一个目标名字。如果依赖目标是以模式(即”%”)定义的,那么”$



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3