当前位置: 安卓之星 -> Linux开发 -> [Makefile应用]中间层Makefile的写法

[Makefile应用]中间层Makefile的写法

作者:网络 发表于: 2016-08-17 点击: 348 次

       主要内容为:编写一个中间层的Makefile,并对其进行一些重构,比如为相应的Makefile规则的命令添加出错推出处理。
       Makefile与shell的关系可以看下面的两篇文章:
*Makefile与shell脚本区别,网址:http://blog.chinaunix.net/uid-20672257-id-3345593.html
*Makefile与Shell的问题,网址:http://blog.csdn.net/absurd/article/details/636418
       中间层的Makefile的原则是尽量透明,不要添加一些额外的变量进去,防止影响整个Makefile的层次结构。

一、
       比如,当前目录现有如下目录,在各自的目录下均有自己的Makefile,那作为中间层的Makefile只需要进入相应的目录即可。
# ls
gate ground_sense keys leds pwm wiegand
       写法如下:
# cat Makefile
# create by fantity 2012-11-28 v1
target := gate ground_sense keys leds pwm wiegand
.PHONY: $(target) all
all:$(target)
$(target):
 $(MAKE) -C [email protected]
 这里要注意的地方有
1、“:=”,不是“=”,“:=”是将变量直接展开,可防止递归调用。
2、要将$(target)声明称伪目标,否则编译器会将其当作目录。

二、
       添加上install,clean等规则之后,如下:
# cat Makefile
#creat by fantity 2012-11-29 v2
target := gate ground_sense keys leds pwm wiegand
.PHONY: all clean install
all:
 @for p in $(target);do $(MAKE) -C $$p || exit $$?;done
clean install:
 @for p in $(target);do $(MAKE) [email protected] -C $$p || exit $$?;done
       这里要注意的地方有:
1、变量p的值是要传给shell去执行的,而Makefile传给shell时会剥离一个$,所以这里需要写两个$$。
2、|| exit $$?,检查命令的执行状态,出错退出。
3、[email protected]指代目标列表,指定那个目标就会执行那个目标,并不会全部编译。
       An AND list has the form
command1 && command2
       command2 is executed if, and only if, command1 returns an exit status of zero.
       An OR list has the form
command1 || command2
       command2 is executed if and only if command1 returns a non-zero exit status. The return status of AND and OR lists is the exit  status of the last command executed in the list.

三、
# cat Makefile
# creat by fantity 2012-11-29 v3
# directory of driver
driver_target := gate ground_sense keys leds pwm wiegand
# directory of driver test program
target := gate ground_sense keys leds pwm wiegand eeprom
test_target := $(target:%=%/test)

.PHONY: all driver driver_test clean clean_driver clean_driver_test install install_driver install_driver_test
all:driver driver_test
driver:
 @for p in $(driver_target);do $(MAKE) -C $$p || exit $$?;done
driver_test:
 @for p in $(test_target);do $(MAKE) -C $$p || exit $$?;done
clean:clean_driver clean_driver_test
install:install_driver install_driver_test
clean_driver install_driver
 @for p in $(driver_target);do $(MAKE) $(subst _driver,,[email protected]) -C $$p || exit $$?;done
clean_driver_test install_driver_test:
 @for p in $(test_target);do $(MAKE) $(subst _driver_test,,[email protected]) -C $$p || exit $$?;done
       这里要注意的地方有:
1、$(target:%=%/test),为变量target的成员添加后缀/test。
2、$(subst _driver_test,,[email protected]),搜索目标列表,将列表中的_driver_test替换去掉。

四、
       对底层Makefile进行重构,将其相同的部分提取出来,作为公共的规则文件,供底层Makefile调用,减少代码的维护量。
底层Makefile内容为:
# cat Makefile
RULES_PATH ?= $(shell pwd)/..
include $(RULES_PATH)/driver_rules.mk
       针对不同模块需要修改的文件:
# cat Kbuild
obj-m := gate_char.o
       如果是多个ko文件:
# cat Kbuild
obj-m := device.o driver.o
       规则文件:
# cat driver_rules.mk 
KERNELDIR ?= /second/ezsdk/board-support/linux-2.6.37-psp04.04.00.01
PWD := $(shell pwd)
all:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm modules
.PHONY:clean install
clean:
 $(MAKE) -C $(KERNELDIR) M=$(PWD) CROSS_COMPILE=arm-none-linux-gnueabi- ARCH=arm clean
install:
 @mkdir -p $(TARGET_FS_DIR)/driver
 @cp -f *.ko $(TARGET_FS_DIR)/driver
       需要注意的是:
1、?=是在变量为空时,才对变量赋值。可以用来防止多次复制。
2、Make中的包含include与C语言中的比较类似,执行到包含语句时,会跳转到被包含文件将其展开并执行,然后回到原处接着执行。

五、
       对Makefile进一步简化
# modified by fantity 2012-12-14

# add the directory of driver
driver_target := button char led motor dm814x_pwm
test_target := button led motor dm814x_pwm

all:driver driver_test
clean:driver_clean driver_test_clean
install:driver_install driver_test_install

driver driver_clean driver_install:
 for p in $(driver_target);do $(MAKE) $(subst driver_,,$(filter driver_%,[email protected])) -C $$p || exit 1;done
driver_test driver_test_clean driver_test_install:
 for p in $(test_target);do $(MAKE) $(subst driver_test_,,$(filter driver_%,[email protected])) -C $$p || exit 1;done
这里使用了filter,用来过滤带有指定字符串的变量。

相关文章

相关文章

赶快留言冒泡

  • 评论 (0)
  • 引用通告 (0)
目前还没有任何评论.
目前还没有任何Trackbacks和Pingbacks.
吐个泡浮上去.