1
votes

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.

2
So you are actually asking how to make every header file in the working directory a prerequisite of... some target. Is that right? - Beta
@Beta no not a prereq. I want to make EVERY file that make is aware of to have an empty rule i.e. AnyFile: SO THAT the rule that I define in ImplTarget.mk. - Bob
@Beta if some file, like a .cpp already has a rule, the additional "empty rule" will have no effect. - Bob
@Beta I'm trying to accomplish what gcc -E -M -Mp accomplishes but in particular, what the -MP flag accomplishes: in addition to emitting a rule that states what headers a .cpp is dependent on, it ADDITIONALLy emits those same headers one line at a time as an empty target i.e. header file followed by colon. Example is header1:, header2:. - Bob

2 Answers

0
votes

This may take a few iterations. Try:

%.h: null
    @echo header xyz = $@

%: null
    @echo other xyz= $@

null:
    @:
0
votes

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.