GNU make-将每个先决条件转换为目标(隐式) [英] GNU make - transform every prerequisite into target (implicitly)

查看:75
本文介绍了GNU make-将每个先决条件转换为目标(隐式)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我还有另一个类似make的工具,该工具在解析我的makefile之后将XML生成为工件,然后将使用Python进行进一步处理.

如果我可以让make认为每个前提条件都是一个实际目标,那么它会为我简化很多事情-因为那是另一种工具 会将每个文件归类为作业".

这是我的makefile文件的一部分:

.obj/eventlookupmodel.o: C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h \
        C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h \
        C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h \
        ...

我希望make认为我对每个先决条件都有一个虚拟规则,如下所示:

C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h: 
     @echo target pre= $@

 C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h: 
    @echo target pre=$@

C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp :
    @echo target pre=$@

C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h:
    @echo target pre=$@

我不在乎规则的确切形式,只是每个文件都被视为实际目标.

我传递此规则的方法是像这样设置MAKEFILES变量

make all MAKEFILES=Dummy.mk

,其中Dummy.mk包含此规则,这样我就不会修改Makefile.

到目前为止,我已经尝试了以下方法.

Dummy.mk:

%.h: 
    @echo header xyz = $@

%: 
    @echo other xyz= $@

这部分起作用.

我运行make all --trace --print-data-base MAKEFILES=Dummy.mk,我可以看到 make确实将%.h:规则绑定"到头文件.在--print-data-base section中,我看到该规则已分配给头文件.

C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef.h:
#  Implicit rule search has been done.
#  Implicit/static pattern stem: 'C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef'
#  Last modified 2016-05-27 12:39:16
#  File has been updated.
#  Successfully updated.
#  recipe to execute (from '@$(QMAKE) top_builddir=C:/Users/User1/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/ top_srcdir=C:/Users/User1/Desktop/A/HMI_FORGF/ -Wall CONFIG+=release CONFIG+=qnx_build_release_with_symbols CONFIG+=rtc_build -o Makefile C:/Users/User1/Desktop/A/HMI_FORGF/src/HmiLogging/HmiLogging.pro
', line 2):
@echo header xyz = $@

但是,我没有看到"echo header xyz $ @"规则正在执行.

关于%:规则,既不对.cpp文件执行该规则,也不在--print-data-base节中对其进行绑定". 但是,它是对没有后缀的现有目标进行绑定和执行的.

all: library binary

binary: | library
ifs:    | library

对于%:规则,此行为的原因是由于 10.5.5任何匹配模式规则:如果您没有将任何匹配规则标记为终止,则该规则为非终止.非终结符任何匹配规则不能应用于指示特定数据类型的文件名.如果某些不匹配的隐式规则目标与之匹配,则文件名指示一种特定的数据类型.

如果我将其设置为非终结符-不能使用双冒号-则该规则不适用于.cpp之类的内置类型,除非我取消定义会否定我的%:规则的内置规则.

如果我将其设置为终端,则除非其先决条件,否则它不适用确实存在".但是.h.cpp从技术上讲没有先决条件.我可以创建一个虚拟文件并将其作为先决条件吗?

注意:这与gcc -M生成无关.是的,-M选项在特定情况下有助于头文件和源文件,但是此问题是针对在启动make时makefile中已经存在的更通用的目标和先决条件的. >

解决方案

尝试为头文件生成静态模式规则.请参阅以下答案之一:忽略不存在的先决条件. /p>

静态模式规则仅适用于目标文件的明确列表,如下所示:

$(OBJECTS): %.o: %.c
    *recipe here*

其中,变量OBJECTS在makefile中较早时定义为目标文件列表(用空格分隔),例如:

OBJECTS := src/fileA.c src/fileB.c src/fileC.c

请注意,您可以使用各种make实用程序功能来构建目标文件列表.例如$(wildcard pattern)$(addsuffix)

还应确保配方接触"头文件以更改时间戳.

我发现使用静态模式规则而不是模式规则可以解决make不能构建不存在的先决条件或删除所需文件的问题.


这里是使用wildcard将文件从一个目录复制到另一个目录的示例.

# Copy images to build/images
img_files := $(wildcard src/images/*.png src/images/*.gif src/images/*.jpg \
src/images/*.mp3)

build_images := $(subst src/,$(BUILD_DIR)/,$(img_files))
$(build_images): $(BUILD_DIR)/images/% : src/images/%
    mkdir -p $(dir $@)
    cp -v -a $< $@

还有其他make函数(例如addprefix)可用于生成更复杂的文件规范.

I have another make-like tool that produces an XML as an artifact after parsing my makefile which I'll then further process with Python.

It'd simplify things for me - a lot - if I could have make consider every single prerequisite to be an actual target because then this other tool will classify each and every file as a "job".

This is a fragment of my makefile:

.obj/eventlookupmodel.o: C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h \
        C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h \
        C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h \
        ...

I'd want for make to think I have a dummy rule for each prerequisite such as below:

C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qvariant.h: 
     @echo target pre= $@

 C:/Users/User1/Desktop/A/PROJ/qt5binaries/include/QtCore/qabstractitemmodel.h: 
    @echo target pre=$@

C:/Users/User1/Desktop/A/PROJ/src/AL2HMIBridge/LookupModels/eventlookupmodel.cpp :
    @echo target pre=$@

C:\Users\User1\Desktop\A\PROJ\src\AL2HMIBridge\LookupModels\eventlookupmodel.h:
    @echo target pre=$@

I don't care about the exact form of the rule just that each file is considered an actual target.

My method of passing in this rule would be by setting the MAKEFILES variable like so

make all MAKEFILES=Dummy.mk

with Dummy.mk containing this rule so that I do not modify the makefiles.

I've tried the following so far.

Dummy.mk:

%.h: 
    @echo header xyz = $@

%: 
    @echo other xyz= $@

This partially works.

I run make all --trace --print-data-base MAKEFILES=Dummy.mk and I can see that make does "bind" the %.h: rule to the header files. In the --print-data-base section, I see that rule being assigned to the header files.

C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef.h:
#  Implicit rule search has been done.
#  Implicit/static pattern stem: 'C:/Users/User1/Desktop/A/QNX_SDK/target/qnx6/usr/include/stddef'
#  Last modified 2016-05-27 12:39:16
#  File has been updated.
#  Successfully updated.
#  recipe to execute (from '@$(QMAKE) top_builddir=C:/Users/User1/Desktop/A/HMI_FORGF/src/../lib/armle-v7/release/ top_srcdir=C:/Users/User1/Desktop/A/HMI_FORGF/ -Wall CONFIG+=release CONFIG+=qnx_build_release_with_symbols CONFIG+=rtc_build -o Makefile C:/Users/User1/Desktop/A/HMI_FORGF/src/HmiLogging/HmiLogging.pro
', line 2):
@echo header xyz = $@

However, I do NOT see the "echo header xyz $@"-rule being executed.

Regarding the %: rule, it is neither executed for the .cpp files nor "bound" to them in the --print-data-base section. However, it is bound and executed for existing targets which have no suffix i.e.

all: library binary

binary: | library
ifs:    | library

For the %: rule, the reason for this behavior is because of 10.5.5 Match-Anything Pattern Rules: If you do not mark the match-anything rule as terminal, then it is non-terminal. A non-terminal match-anything rule cannot apply to a file name that indicates a specific type of data. A file name indicates a specific type of data if some non-match-anything implicit rule target matches it.

If I make it non-terminal - no double colon - then the rule doesn't apply to built-in types like .cppunless I un-define the built-in rules that negate my intended %: rule.

If I make it terminal, "it does not apply unless its prerequisites actually exist". But a .h or .cpp doesn't technically have prerequisites; can I just create a dummy file and have that as its prerequisite?

NOTE: This has NOTHING to do with gcc -M generation. Yes the -M option would help in the specific case of header and source files but this question is for more generic targets and prerequisites that already exist in the makefile when make is launched.

解决方案

Try generating static pattern rules for the header files. See one of the answers to Make ignoring Prerequisite that doesn't exist.

Static pattern rules only apply to an explicit list of target files like this:

$(OBJECTS): %.o: %.c
    *recipe here*

where the variable OBJECTS is defined earlier in the makefile to be a list of target files (separated by spaces), for example:

OBJECTS := src/fileA.c src/fileB.c src/fileC.c

Note that you can use the various make utility functions to build that list of target files. For example, $(wildcard pattern), $(addsuffix), etc.

You should also ensure that the recipe "touches" the header file to change the timestamp.

I've found that using static pattern rules instead of pattern rules fixes problems where make doesn’t build prerequisites that don’t exist, or deletes files that you want.


Here is an example of using wildcard to copy files from one directory to another.

# Copy images to build/images
img_files := $(wildcard src/images/*.png src/images/*.gif src/images/*.jpg \
src/images/*.mp3)

build_images := $(subst src/,$(BUILD_DIR)/,$(img_files))
$(build_images): $(BUILD_DIR)/images/% : src/images/%
    mkdir -p $(dir $@)
    cp -v -a $< $@

There are other make functions like addprefix that could be used to generate a more complex file specification.

这篇关于GNU make-将每个先决条件转换为目标(隐式)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆