为什么忽略显式模式规则?

时间:2016-11-14 21:04:19

标签: makefile ibm-midrange

我正在使用GNU Make 4.0在IBM i系统上编译代码。 Make莫名其妙地选择了错误的规则来构建一种类型的对象。

在这个平台上,程序对象是从模块构建的,模块是从源代码编译而来的。还有一个方便的快捷方式命令,它将直接从单个源代码创建程序,方法是从源代码创建一个临时模块,然后从中构建一个程序。我遇到的问题是Make使用快捷命令(crtbndrpg)而不是两步版本(crtrpgmod + crtpgm),即使目标规则指定了程序应该从模块而不是快捷方式构建。

有两个makefile:一个描述如何创建IBM i对象的通用文件,以及一个描述该项目中所有项目的对象依赖关系的项目特定文件,以及include的通用文件。我的通用makefile看起来像这样(为简单起见而编辑):

# `IBMiMake`, a generic makefile that describes how to create IBM i objects.

OBJPATH := $(CURDIR)
override OBJPATH := $(shell echo "$(OBJPATH)" | tr '[:lower:]' '[:upper:]')

%.MODULE: %.RPGLE
    $(eval crtcmd := crtrpgmod module($(OBJLIB)/$*) srcstmf('$<') $(CRTRPGMODFLAGS))
    @system "$(crtcmd)" > $(LOGPATH)/$(notdir $<).log

%.PGM: %.RPGLE
    $(eval crtcmd := crtbndrpg pgm($(OBJLIB)/$*) srcstmf('$<') $(CRTBNDRPGFLAGS))
    system "$(crtcmd)" >$(LOGPATH)/$(notdir $<).log 2>&1

%.PGM:
    $(eval crtcmd := crtpgm pgm($(OBJLIB)/$*) module($(basename $(filter %.MODULE,$(notdir $^)))) $(CRTPGMFLAGS))
    system "$(crtcmd)" >$(LOGPATH)/$@.log 2>&1

特定于项目的makefile如下所示(为简单起见,也进行了编辑):

# `xpmake`, to create objects in this project.
ROOTDIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
IBMIMAKE := $(ROOTDIR)/../SDE/IBMiMake
include $(IBMIMAKE)

# AB2001.B.MODULE -- CRTRPGMOD
AB2001.B.MODULE: AB2001.B.RPGLE

# AB2001.B.PGM -- CRTPGM
AB2001.B.PGM: AB2001.B.MODULE

构建有问题的对象:

bash-4.2$ make AB2001.B.PGM OBJPATH:='/qsys.lib/xp33make.lib' -f xp33make/xpmake -d --no-builtin-rules

应该发生什么:首先应该使用crtrpgmod命令创建模块。然后应该使用crtpgm命令创建程序。但是,它不是通过crtpgm创建程序,而是出于某种原因尝试使用crtbndrpg命令直接从源代码构建程序。我唯一能想到的是,也许Make看到AB2001.B.MODULE作为中间文件,并选择绕过crtrpgmod步骤。这可能是真的吗?如何让我遵守我的规则而不是试图过度思考?

这是输出:

GNU Make 4.0
Built for powerpc-ibm-aix5.3.0.0
Copyright (C) 1988-2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Reading makefile 'xp33make/xpmake'...
Reading makefile '/home/SMEEP/Source/xp33make/../SDE/IBMiMake' (search path) (no ~ expansion)...
Updating makefiles....
 Considering target file '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
  Looking for an implicit rule for '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
  No implicit rule found for '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
  Finished prerequisites of target file '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
 No need to remake target '/home/SMEEP/Source/xp33make/../SDE/IBMiMake'.
 Considering target file 'xp33make/xpmake'.
  Looking for an implicit rule for 'xp33make/xpmake'.
  No implicit rule found for 'xp33make/xpmake'.
  Finished prerequisites of target file 'xp33make/xpmake'.
 No need to remake target 'xp33make/xpmake'.
Updating goal targets....
Considering target file 'AB2001.B.PGM'.
 File 'AB2001.B.PGM' does not exist.
 Looking for an implicit rule for 'AB2001.B.PGM'.
 Trying pattern rule with stem 'AB2001.B'.
 Trying implicit prerequisite 'AB2001.B.CLLE'.
 Trying pattern rule with stem 'AB2001.B'.
 Trying implicit prerequisite 'AB2001.B.RPGLE'.
 Found an implicit rule for 'AB2001.B.PGM'.
  Considering target file 'AB2001.B.RPGLE'.
   Looking for an implicit rule for 'AB2001.B.RPGLE'.
   No implicit rule found for 'AB2001.B.RPGLE'.
   Finished prerequisites of target file 'AB2001.B.RPGLE'.
  No need to remake target 'AB2001.B.RPGLE'; using VPATH name '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
  Considering target file 'AB2001.B.MODULE'.
   Looking for an implicit rule for 'AB2001.B.MODULE'.
   Trying pattern rule with stem 'AB2001.B'.
   Trying implicit prerequisite 'AB2001.B.C'.
   Trying pattern rule with stem 'AB2001.B'.
   Trying implicit prerequisite 'AB2001.B.CLLE'.
   Trying pattern rule with stem 'AB2001.B'.
   Trying implicit prerequisite 'AB2001.B.RPGLE'.
   Found prerequisite 'AB2001.B.RPGLE' as VPATH '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'
   Found an implicit rule for 'AB2001.B.MODULE'.
    Pruning file '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
    Pruning file '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE'.
   Finished prerequisites of target file 'AB2001.B.MODULE'.
   Prerequisite '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE' is older than target 'AB2001.B.MODULE'.
   Prerequisite '/home/SMEEP/Source/xp33make/AB2001.B.RPGLE' is older than target 'AB2001.B.MODULE'.
  No need to remake target 'AB2001.B.MODULE'; using VPATH name '/QSYS.LIB/XP33MAKE.LIB/AB2001.B.MODULE'.
 Finished prerequisites of target file 'AB2001.B.PGM'.
Must remake target 'AB2001.B.PGM'.
system "crtbndrpg pgm(XP33MAKE/AB2001.B) srcstmf('/home/SMEEP/Source/xp33make/AB2001.B.RPGLE')" >/home/SMEEP/Source/xp33make/Logs/2016-11-14_11.42.55-Mon/AB2001.B.RPGLE.log 2>&1
Putting child 30016df0 (AB2001.B.PGM) PID 1155363 on the chain.
Live child 30016df0 (AB2001.B.PGM) PID 1155363 
Reaping losing child 30016df0 PID 1155363 
/home/SMEEP/Source/xp33make/../SDE/IBMiMake:476: recipe for target 'AB2001.B.PGM' failed
Removing child 30016df0 PID 1155363 from chain.

2 个答案:

答案 0 :(得分:3)

您的示例仍然难以阅读:创建一个最小的示例通常是最好的(也就是说,构建一个使用touch等创建文件的示例,并且不依赖于您的环境。)

此外,在配方中使用$(eval ...)来创建make变量赋值有点令人困惑。不要以为仅仅因为你在配方中执行此操作就会涉及某种范围:这些变量仍然是全局分配的。

无论如何,问题在于您有两种方法可以构建匹配%.PGM的目标:

%.PGM: %.RPGLE
%.PGM:

你显然想要使用第二个,但是如果匹配模式规则的词干具有相同的长度(这里都有相同的词干,.PGM)那么make将始终选择第一个您定义的模式,如果可以,它将始终选择第一个模式。

因此,只要crtbndrpg可以找出如何构建make,它就会始终使用%.RPGLE来构建该目标,以便模式规则匹配。

答案 1 :(得分:0)

我不确定在简化过程中是否省略了它们,但您的明确规则缺少其配方。 没有配方的模式规则意味着取消任何现有的隐式规则。 https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html