0

When I look all over the place for a simple thing and can't find it, it makes me wonder whether I'm doing something completely the wrong way. I have used frameworks where you type make targetname where targetname is not known by the makefile, so it has to pick up targetname as a makefile variable and figure out its dependencies from there. I'm trying to do that, but I can't figure out how, and apparently no one does this, because I can't find anyone talking about how to do it. They talk about everything else under the sun, but not how to get make hooplah to execute using hooplah.html as the top-level target.

A lot of searching and guessing has gotten me as far as the failing makefile below, and I'm so frustrated that here I am risking life and limb by asking a question on SO. In case it keeps me from harm, I'll mention that I've read this SO answer, and this, this, and this, as well as digging through a number of pages in the GNU makefile documentation, all to no avail.

I want to type make page-72 on the command line and get make to treat page-72.html as its top-level dependency throughout the makefile, not just in the top-level rule. The other rules need to know about page-72.html, but I can't figure out how to give them the information.

I've read about MAKECMDGOALS, but it looks like that's only useful for checking for specific target names; I'm looking for something that will allow any target name and treat it as an output filename. Below is what I have. It shows me page-72 due to the % target, and the $@.html dependency works, but no variable I have found yet allows the $@.html rule to know the name of the target that was specified on the command line.

%: $@.html
    @echo "Top: dollar-at = $@"

$@.html:
    @echo "html: $@, $%, $<, $?, $^, $+, $|, $*"

I get the following output:

html: .html, , , , , , , 
Top: dollar-at = makefile
Top: dollar-at = index

Am I getting this conceptually wrong? Is it just not done this way? Bonus points if anyone can help me get rid of Top: dollar-at = makefile. Cheers

SaganRitual
  • 3,143
  • 2
  • 24
  • 40

1 Answers1

2

Yes, you are getting it completely wrong :).

In none of the places you looked did anyone attempt to use an automatic variable such as $@ in a prerequisite list as you've done above, and in fact that cannot work. Automatic variables are only set within the recipe of a rule, not within the prerequisite list.

As a result, after make expands your targets and prerequisites the $@ variable is unset there and it expands to the empty string. So your rules look like this:

%: .html
        @echo "Top: dollar-at = $@"

.html:
        @echo "html: $@, $%, $<, $?, $^, $+, $|, $*"

Maybe that helps explain why you're getting the output you see.

In a pattern rule the stem (the part that matches the % pattern) must be the same in the target and prerequisite.

You want to write your rule like this:

%: %.html
        @echo "Top: dollar-at = $@"

%.html:
        @echo "html: $@, $%, $<, $?, $^, $+, $|, $*"

However, I really don't understand what you're trying to do. I don't know what you mean by a "top level dependency throughout the makefile". And I don't see, from the example you've given, how you expect make to build a x.html file.

To write a makefile, you need to create for yourself a set of steps that say: I want to build this target. To build it, it will use these prerequisites. And given those prerequisites, it will use this set of commands. Then, you repeat that recursively for any of the prerequisites that need to be built. You don't have to write rules for source files (things that don't have to be built). They already exist.

Once you have that set of steps it's pretty straightforward to turn them into makefile rules.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
  • I want to be able to type `make page-72` and have my makefile create `page-72.html`, `page-72.pdf`, `page-72.md`, etc. I understand dependencies and rules. I understand variables, and even magic variables in make. But I can't figure out how to carry `page-72` from the command line through all the steps of creating the different file types. – SaganRitual Nov 27 '18 at 13:29
  • The above set of rules in my sample will successfully allow you to run `make page-72` and it generates `page-72.html`. You can make new rules for other types, like: `%: %.html %.pdf %.md ; @echo done`. I guess at this point, it would be good if you described what the actual problem you are having (if you use the makefile and run `make page-72`, what happens? What about what happened wasn't what you wanted? – MadScientist Nov 27 '18 at 13:52
  • Your makefile is exactly what I needed. Make is almost as hard as regex. Thanks much for your help! – SaganRitual Nov 27 '18 at 14:25