2016-11-14 2 views
0

Я использую GNU Make 4.0 для компиляции кода в системе IBM i. Make необъяснимо выбирает неправильное правило для создания одного типа объекта.Почему Make игнорирует явное правило шаблона?

На этой платформе программные объекты построены из модулей, которые скомпилированы из исходного кода. Также есть команда быстрого вызова, которая создаст программу непосредственно из одного фрагмента исходного кода, создав временный модуль из исходного кода, а затем создав из него программу. Проблема, с которой я столкнулся, заключается в том, что Make использует команду shortcut (crtbndrpg) вместо двухступенчатой ​​версии (crtrpgmod + crtpgm), хотя правило назначения указывает, что программа должна быть построена из модуля, а не ярлыка ,

Существует два make-файла: общий, который описывает, как создавать объекты IBM i, и конкретный проект, который описывает зависимости объектов для всех элементов в этом проекте и include s общий. Мой общий 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)/[email protected] 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. 
+0

Зачем устанавливать правило ** crtbndrpg ** вообще? Все программы ILE RPG могут быть созданы с использованием crtrpgmod + crtpgm, даже те, которые ** могут быть созданы с помощью crtbndrpg. – user2338816

+0

Вы правы, и это направление, в котором я закончил. – smeep

ответ

3

Ваш пример еще трудно читать: создание минимального примера, как правило, лучше всего (то есть, построить пример, который использует touch и т.д. для создания файлов, и Безразлично» t зависит от вашей среды).

Кроме того, использование $(eval ...) внутри рецепта для создания назначения переменной переменной немного запутанно. Не думайте, что только потому, что вы делаете это в рецепте, есть какая-то область охвата: эти переменные по-прежнему назначены глобально.

В любом случае, проблема заключается в том, что у вас есть два пути для создания цели, которая соответствует %.PGM:

%.PGM: %.RPGLE 
%.PGM: 

Вы, видимо, хотите использовать второй, но если стебель правило сопоставления по шаблону имеет равную длину (здесь оба имеют один и тот же стебель, .PGM), тогда make всегда будет выбирать первый шаблон, который вы определяете, чтобы он всегда выбирал первый, если он может.

Таким образом, он всегда будет использовать crtbndrpg, чтобы построить эту цель, если make может вычислить, как построить %.RPGLE, чтобы соответствие шаблону совпадало.

+0

Спасибо. Вы правы, это слишком сложно. Я изо всех сил пытался создать общий пример, но в будущем я буду уверен, что мне удастся. Учитывая правила '% .c:% .b','% .b:% .a' и '% .c:% .a', есть ли какой-либо возможный способ управления тем, какое правило вступит в силу для определения типа 'xyz.c: xyz.b' или' xyz.c: xyz.a'? У нас есть некоторые элементы, которые должны быть созданы с помощью правила shortcut '% .c:% .a', но другие, которые должны использовать два шага'% .c:% .a' plus '% .c:%. b'. Как мы можем сказать, что использовать? – smeep

+0

Попробуйте добавить другое правило без рецепта в xpmake, чтобы отменить нежелательное правило от IBMiMake, например '% .PGM:% .RPGLE'. – jaeheung

+1

Если вы никогда не хотите использовать один из шаблонов в данном файле makefile, вы можете удалить его, как говорит jaeheung. Если вам нужны все шаблоны в одном и том же make-файле для разных вещей, вы не можете его оставить. Он не может просто понять, что вы хотите сделать; он всегда будет использовать тот же алгоритм для поиска правил для каждой цели. В этом случае вам нужно создать явное правило, возможно, статическое правило шаблонов, для целей, которые не используют «стандартное» поведение. – MadScientist

0

Я не уверен, что они опущены в процессе упрощения, но ваши явные правила не имеют рецептов. Правила шаблонов без рецепта означают отмену любых существующих неявных правил. https://www.gnu.org/software/make/manual/html_node/Canceling-Rules.html

+1

Это только отменяет правило шаблона, если правило шаблона не имеет рецепта. Здесь ваши шаблоны имеют рецепты. Правила без рецепта определяют дополнительные предварительные условия. Поскольку рецепта нет, нет явного правила, и make будет искать правила шаблонов, чтобы найти рецепт. – MadScientist

Смежные вопросы