How to write rule that gets all items referenced in a given makefile

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How to write rule that gets all items referenced in a given makefile

Adrian Muresan
Is there a built-in function to extract all the prerequisites for target in a makefile?


I could probably make a rule that will parse the makefile as a textfile from the shell but since `make` already parses the targets and prereqs I'm hoping there's a built-in way.
_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Paul Smith-20
On Tue, 2016-07-05 at 16:50 +0000, Adrian Muresan wrote:
> Is there a built-in function to extract all the prerequisites for
> target in a makefile?

It's not clear exactly what you want to do, but no, there is no built-
in function that provides this information.

Of course, from within a recipe you can use the $^ automatic variable,
which contains all the prerequisites of the current target.

> I could probably make a rule that will parse the makefile as a
> textfile from the shell but since `make` already parses the targets
> and prereqs I'm hoping there's a built-in way.

It's not that simple in all cases: for example, make won't attempt to
resolve suffix and pattern rules until it finds a target that needs to
use that rule to build, and so the complete set of prerequisites can't
be known until that time.

Similarly, new prerequisites could be added to an existing target at
any time, so any list of prerequisites obtained before all makefiles
are parsed will always be suspect.

_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Adrian Muresan
I hoped to spare you details but here goes:


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, implicitly, for `make` to think I have a dummy rule for each file 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=$@


Yes, I know that the gcc `-M` options do exactly that but I need to keep my makefile modifications to a minimum.


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 var 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. However, I do NOT see "echo header xyz" being executed.

Example:

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 = $@


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 I make it non-terminal - no double colon - then the rule doesn't apply to built-in types like `.cpp` . . . unless I undefine the built-in types that are caught by this 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?





======================================================================
It's not clear exactly what you want to do, but no, there is no built-
in function that provides this information.

Of course, from within a recipe you can use the $^ automatic variable,
which contains all the prerequisites of the current target.

> I could probably make a rule that will parse the makefile as a
> textfile from the shell but since `make` already parses the targets
> and prereqs I'm hoping there's a built-in way.

It's not that simple in all cases: for example, make won't attempt to
resolve suffix and pattern rules until it finds a target that needs to
use that rule to build, and so the complete set of prerequisites can't
be known until that time.

Similarly, new prerequisites could be added to an existing target at
any time, so any list of prerequisites obtained before all makefiles
are parsed will always be suspect.
_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Tim Murphy-4
You might want to use makes -p option (--print-data-base) to print out the
targets and prereqs that it has read.   The format of this output is
simplified - all variables etc are expanded - so in python it's very easy
to parse.

Regards,

Tim

On 5 July 2016 at 23:42, Adrian Muresan <[hidden email]> wrote:

> I hoped to spare you details but here goes:
>
>
> 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, implicitly, for `make` to think I have a dummy rule for each
> file 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=$@
>
>
> Yes, I know that the gcc `-M` options do exactly that but I need to keep
> my makefile modifications to a minimum.
>
>
> 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 var
> 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. However, I do NOT see
> "echo header xyz" being executed.
>
> Example:
>
> 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 = $@
>
>
> 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 I make it non-terminal - no double colon - then the rule doesn't apply
> to built-in types like `.cpp` . . . unless I undefine the built-in types
> that are caught by this 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?
>
>
>
>
>
> ======================================================================
> It's not clear exactly what you want to do, but no, there is no built-
> in function that provides this information.
>
> Of course, from within a recipe you can use the $^ automatic variable,
> which contains all the prerequisites of the current target.
>
> > I could probably make a rule that will parse the makefile as a
> > textfile from the shell but since `make` already parses the targets
> > and prereqs I'm hoping there's a built-in way.
>
> It's not that simple in all cases: for example, make won't attempt to
> resolve suffix and pattern rules until it finds a target that needs to
> use that rule to build, and so the complete set of prerequisites can't
> be known until that time.
>
> Similarly, new prerequisites could be added to an existing target at
> any time, so any list of prerequisites obtained before all makefiles
> are parsed will always be suspect.
> _______________________________________________
> Help-make mailing list
> [hidden email]
> https://lists.gnu.org/mailman/listinfo/help-make
>
_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Adrian Muresan
Yes, I am using it and yes the info it gives is very useful, parseable and excellent in general.

The problem is that this information is only outputted by `make` AFTER the makefile is finished executing whereas I need to access this information - via some function that apparently doesn't exist - BEFORE the makefile rules start executing so that I can create rules that act on his information.

As it stands, I'd have to run my build twice: once to get the info and another time to use the info.

Given my esoteric task, it's not unreasonable for me to do this.

1. Make all
2. Parse output, generate whatever rules I need -> Generated_Rules.mk
3. Make all MAKEFILES=Generated_Rules.mk

> On Jul 5, 2016, at 11:44 PM, Tim Murphy <[hidden email]> wrote:
>
> You might want to use makes -p option (--print-data-base) to print out the targets and prereqs that it has read.   The format of this output is simplified - all variables etc are expanded - so in python it's very easy to parse.
>
> Regards,
>
> Tim

_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Tim Murphy-4
Ok, so you want the state of make just after parsing finishes.  Without
patching make or modifying every rule I think your plan for using the
printed database is the best you can manage.   The database output is
quicker to parse than your original makefile usually.

If your makefiles use $(shell) then that might possibly cause trouble with
this scheme.

Regards,

Tim

On 6 July 2016 at 07:13, Adrian Muresan <[hidden email]> wrote:

> Yes, I am using it and yes the info it gives is very useful, parseable and
> excellent in general.
>
> The problem is that this information is only outputted by `make` AFTER the
> makefile is finished executing whereas I need to access this information -
> via some function that apparently doesn't exist - BEFORE the makefile rules
> start executing so that I can create rules that act on his information.
>
> As it stands, I'd have to run my build twice: once to get the info and
> another time to use the info.
>
> Given my esoteric task, it's not unreasonable for me to do this.
>
> 1. Make all
> 2. Parse output, generate whatever rules I need -> Generated_Rules.mk
> 3. Make all MAKEFILES=Generated_Rules.mk
>
> > On Jul 5, 2016, at 11:44 PM, Tim Murphy <[hidden email]> wrote:
> >
> > You might want to use makes -p option (--print-data-base) to print out
> the targets and prereqs that it has read.   The format of this output is
> simplified - all variables etc are expanded - so in python it's very easy
> to parse.
> >
> > Regards,
> >
> > Tim
>
_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make
Reply | Threaded
Open this post in threaded view
|

Re: How to write rule that gets all items referenced in a given makefile

Adrian Muresan
Someone at stackoverflow gave me the answer:


    %:: null
        @:

    null:
        @:

which I pass in like so: `make all MAKEFILES=Dummy.mk`


This captures ALL the files. The double-colon is "terminal rule" (see https://www.gnu.org/software/make/manual/make#Match_002dAnything-Rules)


When I run this, for every single target I get a statement


:2: update target <target> due to: null


And in the `--print-data-base` section, there is no file that is listed as `# Not a target`, only the 68 implicit rules.


This solution appears to only work on Windows: someone said they tried this on Linux and it doesn't work

http://stackoverflow.com/questions/38250056/gnu-make-terminal-rules-and-keyword-null/38252249#comment63925596_38252249





________________________________
From: Tim Murphy <[hidden email]>
Sent: Wednesday, July 6, 2016 12:38 AM
To: Adrian Muresan
Cc: [hidden email]
Subject: Re: How to write rule that gets all items referenced in a given makefile

Ok, so you want the state of make just after parsing finishes.  Without patching make or modifying every rule I think your plan for using the printed database is the best you can manage.   The database output is quicker to parse than your original makefile usually.

If your makefiles use $(shell) then that might possibly cause trouble with this scheme.

Regards,

Tim

On 6 July 2016 at 07:13, Adrian Muresan <[hidden email]<mailto:[hidden email]>> wrote:
Yes, I am using it and yes the info it gives is very useful, parseable and excellent in general.

The problem is that this information is only outputted by `make` AFTER the makefile is finished executing whereas I need to access this information - via some function that apparently doesn't exist - BEFORE the makefile rules start executing so that I can create rules that act on his information.

As it stands, I'd have to run my build twice: once to get the info and another time to use the info.

Given my esoteric task, it's not unreasonable for me to do this.

1. Make all
2. Parse output, generate whatever rules I need -> Generated_Rules.mk
3. Make all MAKEFILES=Generated_Rules.mk

> On Jul 5, 2016, at 11:44 PM, Tim Murphy <[hidden email]<mailto:[hidden email]>> wrote:
>
> You might want to use makes -p option (--print-data-base) to print out the targets and prereqs that it has read.   The format of this output is simplified - all variables etc are expanded - so in python it's very easy to parse.
>
> Regards,
>
> Tim

_______________________________________________
Help-make mailing list
[hidden email]
https://lists.gnu.org/mailman/listinfo/help-make