首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将gnu-make规则作为函数应用

将gnu-make规则作为函数应用
EN

Stack Overflow用户
提问于 2016-07-29 15:04:26
回答 1查看 179关注 0票数 0

我想要一条作为函数运行的规则,比如gzip我所有的临时目标。我在makefile中写了这些规则:

代码语言:javascript
复制
%.file0:            
         touch $@    

%.file1: %    
         touch $@    

%.file2: %          
         touch $@    

%.gz: %    
         echo "zipping to $@" 
         touch $@  

我可以打电话

代码语言:javascript
复制
$ make -n dotted.file.file0.file1.file2.gz -f makefile
touch dotted.file.file0
touch dotted.file.file0.file1
touch dotted.file.file0.file1.file2
echo "zipping to dotted.file.file0.file1.file2.gz"
rm dotted.file.file0 dotted.file.file0.file1.file2 dotted.file.file0.file1

我的最后一个目标将被成功地压缩。然后,我可以将gzip dotted.file.file0.file1放在前面:

代码语言:javascript
复制
$ make -n dotted.file.file0.file1.gz.file2 -f makefile
touch dotted.file.file0                                                   
touch dotted.file.file0.file1                                             
echo "zipping to dotted.file.file0.file1.gz"                              
touch dotted.file.file0.file1.gz.file2                                    
rm dotted.file.file0 dotted.file.file0.file1.gz dotted.file.file0.file1

在给出规则%.file2之前,还将对该文件进行gzipped压缩。但我无法锁定几个目标:

代码语言:javascript
复制
$ make -n dotted.file.file0.file1.gz.file2.gz -f makefile
make: *** No rule to make target `dotted.file.file0.file1.gz.file2.gz'.  Stop.  

我如何做到这一点,即对多个目标应用%.gz规则?

编辑1

从另一个角度来看,我试图以这样的方式重写我的规则:

代码语言:javascript
复制
%.file0:                    
         touch $@            

%.file1: %.gz             
         touch $@            

%.file2: %.gz             
         touch $@            

%.gz: %                     
         echo "zipping to $@"
         touch $@ 

然后我打电话给make:

代码语言:javascript
复制
$ make -n dotted.file.file0.file1.file2 -f makefile
make: *** No rule to make target `dotted.file.file0.file1.file2'.  Stop.

我期望/希望gnu-make执行此命令的规则:

代码语言:javascript
复制
 - ask for the file dotted.file.file0.file1.file2
 - go to rule %.file2
 - ask for the dependency dotted.file.file0.file1.gz
 - go to rule %.gz
 - as for the dependency dotted.file.file0.file1
 - go to rule %.file1
 - as for the dependency dotted.file.file0.gz
 - go to rule %.gz
 - as for the dependency dotted.file.file0
 - go to rule %.file0
 - create file dotted.file.file0

但是,如果我只要求一条规则应用%.gz,它将在这一次起作用。

The makefile:

代码语言:javascript
复制
%.file0:                    
         touch $@            

%.file1: %.gz # !!! Notice I left this single dependency to the rule %.gz           
         touch $@            

%.file2: %  ## !!! Notice I removed the .gz here             
         touch $@            

%.gz: %                     
         echo "zipping to $@"
         touch $@ 

命令:

代码语言:javascript
复制
$make -n dotted.file.file0.file1.file2 -f makefile 
touch dotted.file.file0                      
touch dotted.file.file0.file1                      
echo "zipping to dotted.file.file0.file1.gz"          
touch dotted.file.file0.file1.gz                      
touch dotted.file.file0.file1.file2                      
rm dotted.file.file0.file1.gz dotted.file.file0 dotted.file.file0.file1
EN

回答 1

Stack Overflow用户

发布于 2016-08-02 12:01:53

第一个版本的问题是,您需要静态模式规则,而不是隐式规则。下面使用GNU执行任务,使用对awk的shell调用从指定的make目标构建*.file1*.file2*.gz目标的显式列表。它还使用foreach-eval-call组合来实例化所需的尽可能多的规则(没有菜谱),以显式地表示所有依赖关系。我必须承认,这种风格的Makefile是相当不寻常的,但你的问题也不寻常.

代码语言:javascript
复制
SUFFIXES    := file1 file2 gz

# For goal $(1) and suffix $(2), build the list of all possible stems <S> such
# that $(1) matches the ^<S>\.$(2)(\..*)? regular expression. Concatenate this
# list to the $(2) make variable.
define SPLIT_rule
$(2)    += $$(shell echo $(1) | awk -F.$(2) '{for(i=1;i<=NF;i++){for(j=1;j<=i;j++)printf("%s",$$$$j);printf(".$(2) ")}}')
endef

# For goal $(1), instantiate SPLIT_rule for each suffix.
define GOAL_rule
$(foreach suffix,$(SUFFIXES),$(eval $(call SPLIT_rule,$(1),$(suffix))))
endef

$(foreach goal,$(MAKECMDGOALS),$(eval $(call GOAL_rule,$(goal))))

# For suffix $(1), instantiate the static pattern rule.
define SUFFIX_rule
$$($(1)): %.$(1): %
endef

$(foreach suffix,$(SUFFIXES),$(eval $(call SUFFIX_rule,$(suffix))))

%.file0:
    touch $@

%.file1: %
    touch $@

%.file2: %
    touch $@

%.gz: %
    echo "zipping to $@"
    touch $@

和:

代码语言:javascript
复制
$ goal1=dotted.file.file0.file1.file2.gz
$ make -n $goal1
touch dotted.file.file0
touch dotted.file.file0.file1
touch dotted.file.file0.file1.file2
echo "zipping to dotted.file.file0.file1.file2.gz"
touch dotted.file.file0.file1.file2.gz

$ goal2=dotted.file.file0.file1.gz.file2
$ make -n $goal2
touch dotted.file.file0
touch dotted.file.file0.file1
echo "zipping to dotted.file.file0.file1.gz"
touch dotted.file.file0.file1.gz
touch dotted.file.file0.file1.gz.file2

$ goal3=dotted.file.file0.file1.gz.file2.gz
$ make -n $goal3
touch dotted.file.file0
touch dotted.file.file0.file1
echo "zipping to dotted.file.file0.file1.gz"
touch dotted.file.file0.file1.gz
touch dotted.file.file0.file1.gz.file2
echo "zipping to dotted.file.file0.file1.gz.file2.gz"
touch dotted.file.file0.file1.gz.file2.gz

$ goal4=dotted.file.file0.file1.file2
$ make -n $goal4
touch dotted.file.file0
touch dotted.file.file0.file1
touch dotted.file.file0.file1.file2

$ all="$goal1 $goal2 $goal3 $goal4"
$ make -n $all
touch dotted.file.file0
touch dotted.file.file0.file1
touch dotted.file.file0.file1.file2
echo "zipping to dotted.file.file0.file1.file2.gz"
touch dotted.file.file0.file1.file2.gz
echo "zipping to dotted.file.file0.file1.gz"
touch dotted.file.file0.file1.gz
touch dotted.file.file0.file1.gz.file2
echo "zipping to dotted.file.file0.file1.gz.file2.gz"
touch dotted.file.file0.file1.gz.file2.gz
make: 'dotted.file.file0.file1.file2' is up to date.

注意:由于所有中间层不再是隐式的,它们不会被自动删除,就像它们在第一个版本中被声明为PRECIOUS一样。这就是为什么输出中不再有rm ...的原因。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38662002

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档