bugmake - Bugs: bug #64571, Add option to print targets

 
 

bug #64571: Add option to print targets

Submitter:  Tim <timmmm>
Submitted:  Sat 19 Aug 2023 05:49:19 PM UTC
Votes: 102
 
Severity:  3 - Normal Item Group:  Enhancement
Status:  Fixed Privacy:  Public
Assigned to:  psmith Open/Closed:  Closed
Component Version:  4.4.1 Operating System:  Any
Fixed Release:  SCM Triage Status:  Medium Effort
* Mandatory Fields

Add a New Comment Rich Markup
   

Jump to the original submission

Tue 09 Jan 2024 10:02:09 AM UTC, comment #18: 

Amazing, thank you Paul!

And I agree with David A. Wheeler - this option makes sense for things like command line autocomplete. JSON makes sense for things like IDE integration.

Tim <timmmm>
Tue 09 Jan 2024 04:35:16 AM UTC, comment #17: 

I pushed an implementation to Git.

Paul D. Smith <psmith>
Group administrator
Mon 08 Jan 2024 07:23:25 PM UTC, comment #16: 

I think it's important to identify "what is the use case" before adding options. I think there are two different use cases that are getting conflated. I suggest supporting two different options for the two cases.

1. "Give me the list of targets of this makefile, e.g., for better autocompletion". I think using JSON or even CSV for this use case would be a terrible idea. I strongly recommend a special option that simply gives a list of targets, one per line, enabling easy processing. Trivial tools can handle this format, and including any other data about the targets would just slow down interactive processing without being useful.

2. "Provide full post-processed make database to support complex analysis". Here I think JSON or CSV is plausible, with JSON being more flexible (and thus probably the better choice). You can implement a simple "dump JSON" or use a more complex format language. The trade-off is simple: a format language lets you only output the data that matters, but now you have to devise and implement the format language. In this case, I think the format language is NOT worth it - just do a JSON data dump. If you need to process the make database in detail, you're going to need to do some fancier processing anyway; the format language will never be enough. It's much easier and more future-proof if you don't implement the format language. Modern systems can process huge makefiles without fuss. JSON processing is widely available, so while POSIX by itself doesn't have tools for it, I don't think that's a problem. Tools like jq are widely available, and you can build your own if you want to. You could add the format language later if I'm wrong, and you can't eliminate the format language later if I'm right.

So: Just add two options:

1. Dump all targets, one per line.
2. Dump entire processed database in JSON format.

David A. Wheeler <dwheeler>
Mon 08 Jan 2024 06:10:39 PM UTC, comment #15: 

Just to point out, GNU Make doesn't provide any support for autocompletion in its package.  Any autocompletion that is available is provided by other packages, for example the bash-completion package:


$ head -n1 /usr/share/bash-completion/completions/make
# bash completion for GNU make                             -*- shell-script -*-

$ dpkg -S /usr/share/bash-completion/completions/make
bash-completion: /usr/share/bash-completion/completions/make


As far as I'm aware this package is part of the standard system installation on many/most GNU/Linux distributions.

So it's not a matter of someone installing make vs. jq.  It's a matter of whether the maintainers of these generic packages are willing to write completion scripts which require other non-standard packages to be installed before they can be of use, or whether they will simply continue to use their current workarounds because they don't want to make that requirement.

If the latter then this request has failed its intended audience, I expect.

Also getting jq for Windows etc. is less simple, although I don't know if those platforms have any use for it anyway.

Paul D. Smith <psmith>
Group administrator
Mon 08 Jan 2024 05:30:44 PM UTC, comment #14: 

I think JSON would be a good solution.

> (b) these tools (like jq for example) are not part of most standard systems and so can't be relied on to exist everywhere,


It's no harder to install `jq` than it is to install `make` these days, even on relatively ancient distros. I don't see why this would be an issue.

> (c) jq, at least, is somewhat tricky to use correctly especially if you want to do matching etc.


I don't particularly like its syntax but it's not especially difficult, and let's face it most people are going to be googling "how to print make targets" and copy/pasting the first stack-overflow page.

On the other hand, maybe it is over-complicating things.

Tim <timmmm>
Sun 07 Jan 2024 10:34:42 PM UTC, comment #13: 

It depends on what you mean by "this context".  If what we are suggesting is to use this new JSON output format so that we don't need to create an option to print targets, then it's very relevant since the goal of this option is to provide input for tools that want to list the possible goal targets (for command line completion or IDEs).

I think that the way it will have to work is that we don't try to rebuild makefiles when listing targets.  I don't see any feasible alternative given the use-case referred to here.  This means that the list of targets may be incomplete in some situations but it should be rare that a target you'd really want to add to the command line would not be listed, except in the most extreme cases.

Paul D. Smith <psmith>
Group administrator
Sun 07 Jan 2024 08:38:05 PM UTC, comment #12: 

Wow, that's great stuff from Tim. I was really re-treading his steps there, even with the same flag name `--print-data-base-json`!

Definitely valid limitations of nested JSON, very tricky to parse without the right tools. However, in this context, is that an issue? If JSON output is opt in with `--format json`, then it's on the caller whether or not they have the required tooling available to handle the output. I wasn't imagining that make's bash completion would be re-written building on the new JSON output. Is there a risk that would happen?

Once there's a `--format` option, then there's space for other formats (`git log` offers several bespoke formats). A new line delimited, bespoke tabular format could be added, which would be more easily parsed by standard POSIX tools, and could be a better option for reworking bash completion if this was wanted / needed.

Thank you for the information regarding `-n` and `-p`. Will need to have a think about that one (and refresh my knowledge on rebuilding make files)!

Benjamin Tilley <mrsquee>
Sun 07 Jan 2024 07:14:08 PM UTC, comment #11: 

Tim Murphy had a proposal and even a patch to generate JSON, posted to bug-make a few weeks ago: https://lists.gnu.org/archive/html/bug-make/2023-12/msg00027.html

Overall I like JSON but I'm not convinced it will be as helpful for this situation.

The problem with JSON is that (a) it requires special tools to parse it, you can't do it with traditional POSIX tools like sed or sh, (b) these tools (like jq for example) are not part of most standard systems and so can't be relied on to exist everywhere, and (c) jq, at least, is somewhat tricky to use correctly especially if you want to do matching etc.

The last point is not that bad since someone who is proficient with jq will presumably create some bash completion script one time then everyone will use it, but the first two are problematic: it would not be popular to force systems to install jq if they wanted GNU Make command completion for example.

Regarding how -p manages remaking makefiles, this is not an issue because -p already doesn't inhibit builds (that is when you add -p make will still do all its normal builds).  That's why people often use -np (the -n inhibits normal builds).  So if you ask what -n does regarding remaking makefiles, it will normally rebuild them; the -n option doesn't prevent ALL commands from running: it will for example run any command that is prefixed with "+" or contains the string "$(MAKE)" (or "${MAKE}") so that even when you run with -n you still invoke sub-makes to see what they would have built.

So, unfortunately I don't think we can look to either -p or -n for help in deciding how to handle this situation.

Regarding a putative --format option, I don't think it needs to do every single thing immediately but it should at least be clear how it might be extended to support new facilities in the future.

Paul D. Smith <psmith>
Group administrator
Sun 07 Jan 2024 06:00:05 PM UTC, comment #10: 

@psmith, just missed your comment while I was writing mine :) Seems like we were thinking in a similar direction, I agree the `--format` option is a good fit with how other tools handle this.

When I get a chunk of time, I can put in a proposal for this. Would a `--format` option need to be honoured for all `make` output for a patch to be accepted or could it be incrementally applied to other `make` invocations (i.e. other than `make -pq`) as needed / requested?

Re the remaking makefile question, do you know how the current `--print-data-base` output approaches this?

Benjamin Tilley <mrsquee>
Sun 07 Jan 2024 05:47:51 PM UTC, comment #9: 

I had a thought about how this could be approached in a different way.

As has been mentioned, we already have a lot of information available about targets (also variables and other info) via the `--print-data-base` flag. It's just that as it currently exists this information is output in a bespoke, human-readable format defined by `make`.

```
...
# Files
...
example: dep
#  Phony target (prerequisite of .PHONY).
#  Implicit rule search has not been done.
#  File does not exist.
#  File has not been updated.
#  commands to execute (from `Makefile', line 16):
...
```

This has lead to the many "regex" based, "hacky solutions" that currently exist as people manipulate this output as best they can.

Could we instead add an option to print the database in JSON (and/or another structured format), so that the querying can be done using existing tools for manipulating said format, i.e. `jq` for JSON.

More UNIX-y than trying to guess what a sensible default would be for the new option. It can print everything that's in the current `--print-data-base` option, just in a new format that users can query better.

E.g. assuming a `--print-data-base-json` output for the example above of something like

```
{
  ...
  "files": [
    {
      "target": "example",
      "prerequisites": [
        "dep"
      ],
      "is_target": true,
      "phony": true,
      ...
    },
    ...
  ],
  ...
}
```

You could get phony targets with `make -pq | jq '.files[] | select(.phony == true) | .target'`. The `jq` query language can be a little enigmatic for longer queries, but I would argue it's more readable than regex. Also, the structured natured of the output would give users more confidence that they're actually getting everything that they're querying for, and haven't missed something just because they're not familiar with the current bespoke format of `--print-data-base`.

For your use case @timmmm, you'd do something like `make -pq | jq '.files[] | select(.is_target == true) | .target'` to get all the things that are actual targets. And not just prerequisites or implicit rules, etc.

The structure of the output and the names of the properties could follow what already exists in the `print_data_base` function:

```
  print_variable_data_base ();
  print_dir_data_base ();
  print_rule_data_base ();
  print_file_data_base ();
  print_vpath_data_base ();
  strcache_print_stats ("#");
```

e.g.

```
{
  "variables: [...],
  "directories": [...],
  "rules": [...],
  "files": [...],
  "vpath": [...],
  "stats": [...]
}
```

From looking at the source code, it seems that "rules" are actually only implicit rules, and other user defined targets and prerequisites always appear in "files". Can you confirm that @psmith?

Thoughts? I'm happy to put some time into getting an example working for further discussion if there's enough interest in the approach?

Benjamin Tilley <mrsquee>
Sun 07 Jan 2024 05:39:37 PM UTC, comment #8: 

Let me just say up-front that my biggest concern with this is going in the direction you suggest:

> I guess you can always add flags to refine the behaviour later if necessary


Just... no.  I won't introduce an entire family of options that tweak and customize this output in various ways.

If someone feels the need for this level of customization then I think the only way forward is to introduce a kind of "format syntax" that will allow users to provide customized output (a well-known example of this is Git's "git log --format" option but there are many examples that predate it).  Ideally this syntax would be sufficient to generate, for example, the current print database output (a default syntax), and allow users to change it.  This would be quite a bit of work and I don't plan to work on it, but if someone else wants to please provide a proposal on -email is unavailable- and we can discuss the details.

Given the parameters laid out (used to generate targets for command-line completion) it seems like:

  • We definitely want to print targets with no recipe (all: often, for example)
  • We definitely want to print phony targets
  • We don't want to perform recursion into sub-makes, or any other "normal" recipes


In addition it seems like we would also want the following:

  • Don't show builtin targets (these are basically suffix rules)
  • Don't show special targets like .PHONY, .SILENT, .PRECIOUS, etc.


The big open question is what to do about remaking makefiles ( https://www.gnu.org/software/make/manual/html_node/Remaking-Makefiles.html ).  If we do not do this then in some situations some targets which you could build, will not show up in the list (because they are defined in a makefile that will be remade but was not).  But if we DO do this then the output generated by make will first be any output created when remaking makefiles, followed by the list of targets, which would mess up any utility trying to parse the output.

Paul D. Smith <psmith>
Group administrator
Sat 06 Jan 2024 09:16:00 PM UTC, comment #7: 

To be honest I'm not sure I know enough about Make to answer in detail, but generally people want to know targets for which they might actually type `make thetarget`, so:

> I assume users only care about explicit targets, not implicit targets (patterns etc.)


Yeah, we don't want to see a list of `.o` files.

> Are people hoping to see all possible targets that the makefile could build, even intermediate targets?


Yes. It's pretty common to have an "all" target that builds everything, so if you don't show intermediate targets then it would just print "all" which is not very helpful.

> Do people want to see phony targets?


Yes.

> Only targets that have recipes, or all prerequisites as well (a prerequisite is also considered a target by make of course)?


Not 100% sure what this one means, sorry!

> I suppose we can just do whatever is simple and if people aren't happy with the results they can revert to whatever they were doing before.


Sounds like a good plan to me! I guess you can always add flags to refine the behaviour later if necessary, but hopefully that won't be required.

I guess it might be worth us constructing a concrete test Makefile and deciding what it would show?

Tim <timmmm>
Sat 06 Jan 2024 06:46:53 PM UTC, comment #6: 

I have asked below, and I'm still waiting for an answer.  Until there's some agreement on the answer, I don't see how we can move forward no matter how many "hacky solutions" exist in the wild.

In fact, the more "hacky solutions" there are the LESS likely it is that any specific facility we implement inside GNU Make, will be correct for all or even most of the uses people have.

What exactly should this new option do?  It's easy enough to say "print the targets" but that is TOO simplistic.

I assume users only care about explicit targets, not implicit targets (patterns etc.)  Are people hoping to see all possible targets that the makefile could build, even intermediate targets?  That pretty much can't be done.

Do people want to see phony targets?  Only targets that have recipes, or all prerequisites as well (a prerequisite is also considered a target by make of course)?

I suppose we can just do whatever is simple and if people aren't happy with the results they can revert to whatever they were doing before.

Paul D. Smith <psmith>
Group administrator
Thu 04 Jan 2024 08:03:33 AM UTC, comment #5: 

This is definitely a (implicitly) highly requested feature.

As Tim has already explained, users are currently using tons of hacky solutions which are not 100% reliable.

Having an "official" targets list created by 'make' itself shall be the trustable and reliable option since it would be coming from the "true source" -- make's internal target parsing engine.

Miguel Moreno <mamorenor>
Thu 16 Nov 2023 09:10:59 AM UTC, comment #4: 


> I'm just not really that convinced that the simplest thing is going to be useful to people.


People are already using hacky regexes which are even less useful.

> even internal ones etc


Yeah there were some internal targets that I didn't want to show but couldn't figure out how to do it. If you can help that would be great!

> Even in the comments below someone suggested "especially for phony targets"


I think they meant targets that are marked as phony, not the .PHONY target itself?

> make -pn | sed -n 's/^\([^#][^=]*:\).*/\1/p;'


Hacks like this not working is what finally motivated me to write this patch.

Try it in this directory: https://github.com/riscv-software-src/riscv-tests/tree/master/isa

Regex version output: https://gist.github.com/Timmmm/519aeee5f24658855f2f6fb9359643e3
My patch output: https://gist.github.com/Timmmm/85acf0ab3f00c9a1780579946823d1bb

I feel like I may have missed the point you're making here though. (Note I'm not remotely a Make expert!)

> I'm just skeptical that this wouldn't degenerate into a morass of conflicting requests for new features.


Maybe. But this is clearly a highly demanded feature just for auto-complete/discovery. Seems mean to deny it just because people might ask for other things too.

Tim <timmmm>
Wed 01 Nov 2023 01:57:43 PM UTC, comment #3: 

This is the right place for patches.  I did look at this patch; it's not quite right (IIRC) but of course it could be adjusted relatively straightforwardly.

The hard thing about this request is not the code.  The hard thing is the design.  I'm just not really that convinced that the simplest thing is going to be useful to people.

GNU Make is used by so many people for so many things, and I'm leery of creating some new facility that ends up being "not really right" for what people want to do, but that then must be maintained forever going forward.

First of all, of course there's no way to show any target that is created by an implicit rule (well this could be possible but would be a lot of work; we'd have to have a mode where we resolve all targets without actually building anything).

Second, it will show explicit targets... but ALL of them, even internal ones etc.  Even in the comments below someone suggested "especially for phony targets"... well, now are we suggesting that we want not just one option but some kind of suite of options that can choose different types of target output based on various criteria?  It just feels unpleasant.

Here's an experiment you can run in your makefile environment:


$ make -pn | sed -n 's/^\([^#][^=]*:\).*/\1/p;'


What do you get out of this?  This is "more or less" what a simple implementation of "show all explicit targets" would generate (you can ignore the suffix rules sprinkled through the output).

Is that really what people are looking for?  I'm just skeptical that this wouldn't degenerate into a morass of conflicting requests for new features.

Paul D. Smith <psmith>
Group administrator
Wed 01 Nov 2023 10:27:46 AM UTC, comment #2: 

@mrsquee yeah I also found it confusing since there are some open patches but "Submit new" is disabled with no clue why. I think I read somewhere that they want you to just submit bugs with a patch attached, so that's what I did. Very unintuitive.

Tim <timmmm>
Tue 31 Oct 2023 09:14:06 PM UTC, comment #1: 

I'm also interested in this feature. I often find when coming back to an old project I want a quick way to list the possible targets so that I remember what `make` invocation I should run. Especially for .PHONY targets that are just performing some admin in the repo.

@projectmaintainers I've not used savannah before - what is the best way to raise a possible feature like this. It's currently in the bug list, so maybe it's not in the right place for attacting comments and upvotes? :)

Benjamin Tilley <mrsquee>
Sat 19 Aug 2023 05:49:19 PM UTC, original submission:  

A lot of people would like to be able to print all the targets contained in a Makefile. Here's the most popular StackOverflow question about it:

https://stackoverflow.com/questions/4219255/how-do-you-get-the-list-of-targets-in-a-makefile

It has 316 upvotes and 30 bad answers at the moment. The only good option is if you are using CMake, then it provides `make help` which lists the main targets. But this doesn't help in the general case.

The rest of the answers are some variant of "use a regex" which is a terrible idea (now you have two problems) and doesn't work for targets with computed names.

I figured that rather than writing terrible regexes 30 times it can't be that hard to actually add this feature to Make.

I have attached a patch that seems to do the job. I'm not sure I put the call to `print_all_targets()` at the right point in `main()` - to be honest I couldn't really follow the code. Maybe you can tell me if it's correct and merge it if so?

Thanks!

Tim <timmmm>

 

(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:
   
   
Comment:
   

Attached Files

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -email is unavailable- added by dwheeler (Posted a comment)
  • -email is unavailable- added by mamorenor (Posted a comment)
  • -email is unavailable- added by mamorenor (Voted in favor of this item)
  • -email is unavailable- added by psmith (Posted a comment)
  • -email is unavailable- added by timmmm (Voted in favor of this item)
  • -email is unavailable- added by mrsquee (Posted a comment)
  • -email is unavailable- added by timmmm (Submitted the item)
  •  

    There are 102 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.

     

    Follow 9 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2024-01-09 psmith StatusNone Fixed
        Assigned toNone psmith
        Open/ClosedOpen Closed
        Operating SystemNone Any
        Fixed ReleaseNone SCM
        Triage StatusNone Medium Effort
    2024-01-04 mamorenor Carbon-Copy- Added mamorenor
    2023-11-01 timmmm Carbon-Copy- Added timmmm
    2023-08-19 timmmm Attached File- Added Add-flag-to-print-all-targets.patch, #55063

    Back to the top

    Powered by Savane 3.12.
    Corresponding source code