Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement: configuration summary printing #757

Closed
tp-m opened this issue Sep 5, 2016 · 17 comments · Fixed by #4649
Closed

Enhancement: configuration summary printing #757

tp-m opened this issue Sep 5, 2016 · 17 comments · Fixed by #4649

Comments

@tp-m
Copy link
Member

tp-m commented Sep 5, 2016

Many configure scripts have something like this at the end:

echo $PACKAGE configuration summary:
echo
echo Installation Prefix .............. : ${prefix}
echo GStreamer API version ............ : $GST_VERSION
echo VA-API version ................... : $VA_VERSION_STR
echo Video encoding ................... : $(yesno $USE_ENCODERS)
echo Video outputs .................... : $VIDEO_OUTPUTS

It would be nice if we had dedicated API for this in Meson. It would provide two features:

  • booleans printed as yes|no by default, though possibility to pass alternative strings would be nice to have too
  • formatting the output so that it's nicely in two columns (so would have to collect all config summary statements to figure out width first)

API-wise it could be something like:

summary_message('Foo', value)
summary_message('Bar', other_value)

or

print_summary([
  ['Foo', value],
  ['Bar', value],
])
@inigomartinez
Copy link
Contributor

Although I do agree that the proposed approach may cover almost all cases, there are some different ones.

Based on my what I've seen on different packages, usually the summary prints different options values which are split in different sections. There are also some packages that might also show messages with different values.

For example:

System paths:
  prefix: /tmp/nm
  exec_prefix: ${prefix}
  systemdunitdir: /tmp/nm/lib/system/system
  nmbinary: ${sbindir}/NetworkManager
  nmconfdir: ${sysconfdir}/NetworkManager
  nmlibdir: ${prefix}/lib/NetworkManager
  nmdatadir: ${datadir}/NetworkManager
  nmstatedir: ${localstatedir}/lib/NetworkManager
  nmrundir: ${runstatedir}/NetworkManager

Platform:
  session tracking: systemd-logind, consolekit
  suspend/resume: systemd
  policykit: yes (permissive modify.system) (default: main.auth-polkit=yes)
  polkit agent: yes
  selinux: yes
  systemd-journald: yes (default: logging.backend=journal)
  hostname persist: default
  libaudit: yes (default: logging.audit=true)

Features:
  wext: yes
  wifi: yes
  ppp: yes ${exec_prefix}/lib/pppd/2.4.5
  modemmanager-1: yes
  ofono: yes
  concheck: yes
  libteamdctl: yes
  ovs: yes
  libnm-glib: yes
  nmcli: yes
  ...

Following the first proposal, I would extend it with the following changes:

summary_message('Foo', [value1, value2])
summary_section('FooBar')
summary_message('Bar', [value1, value2, value3])

As you can see, some values has also descriptions ((default: logging.backend=journal)) which is not covered by this extension.

Using the other proposal would be something like this:

print_summary([
  ['Foo', foo_options],
  ['FooBar, ['Bar', bar_options]]
])

@bruce-richardson
Copy link
Contributor

bruce-richardson commented Aug 29, 2018

Also for consideration, is how to manage printing out of lists of components, potentially with 20+ items in the list. For example, in DPDK, we have dozens of drivers in multiple categories, which would make listing them vertically as yes/no infeasible. Therefore I think we may want to have different types of summary sections, for example, "yes-no", "name-value" or "component-list". The former two are shown as above, while latter would be configured by e.g:

foo=summary_section('Foo Components', type: list)
foreach item:components
   ...
   if build
      add_summary_component(foo, item)
   endif
endforeach

Then at the end of the meson run the summary list would include a horiztonal list, word-wrapped appropriately:

Foo Components:
    comp1 comp2 comp3 ... compX
    compX+1 ..... compN

I'm also assuming that the APIs are designed for calling throughout the various meson files, and that summary printing is only done at the end?

@jpakkane
Copy link
Member

Something like that yes but preferably something simpler:

delayed_status_message('Some setting', 'its value')

@tp-m
Copy link
Member Author

tp-m commented Aug 29, 2018

I think the concept of summaries being sub-divided into sections of sort is an essential requirement, so something super-simple probably won't cut it. This is the kind of thing that starts out simple but may need to be tweaked and extended later, so doing something object-based from the start might make sense?

s = summary()
platform = s.add_section('Platform')
platform.add('selinux', opt_selinux)
s.print()

Alternatively, one could do away with the summary() object and have it implicit in Meson:

platform = add_summary_section('Platform')
platform.add('selinux', opt_selinux)

or just use

platform = meson.add_summary_section('Platform')
platform.add('selinux', opt_selinux)

instead and rely on Meson printing it automatically at the end if any have been registered.

I would assume that anything related to this API is either automatically delayed to the end or to the moment some .print() or .summarise() function is called, so don't think that would have to be part of the API.

@jpakkane
Copy link
Member

Or possibly something like:

final_status_message(type : 'Thingy name',
  value : 'its value',
  section : 'Platform')

Section can be empty, all those would be grouped in one.

@xclaesse
Copy link
Member

Maybe a bit crazy idea, but I'm wondering if this summary message could be partly automatic, based on 'feature' options. Most of the time what's interesting to know in the summary is if it found "auto" features, right?

When doing dependency('foo', required : get_option('an-auto-feature-option')) we could remember if the result was found and generate a report at the end for each option of type feature.

@dcbaker
Copy link
Member

dcbaker commented Dec 17, 2018

I've gotten multiple requests for this feature so I'm looking into adding it. What about using a dict for the summary?

@dcbaker dcbaker self-assigned this Dec 17, 2018
@tp-m
Copy link
Member Author

tp-m commented Dec 17, 2018

Not sure if doing something just based on feature options is enough. There are many things which are not decided/covered by feature options (manual detection of things; combos etc.).

@dcbaker: How would a dict work exactly? Would it be a dict per section or a dict with sub-dicts or?

I still think explicit/non-clever API is best, because whatever we do we will inevitably want to extend it in future. But I haven't seen how you want to use dicts of course. Can you give examples?

@dcbaker
Copy link
Member

dcbaker commented Dec 17, 2018

I agree, non-clever is best: I'm imagining something like:

sec1 = {'foo' : true, 'bar' : 'thing'}
sec2 = { 'boo' : 1, 'arb' : ['some', 'things']}
summary(
  'Section 1 options' : sec1,
  'Section 2 options' : sec2,
)

With summary taking keyword arguments for each section, with the argument as the name, and it would print something like:

Section 1 options:
  foo = true
  bar = 'thing'

Section 2 options:
  boo = 1
  arb = ['some', 'things']

@dcbaker
Copy link
Member

dcbaker commented Dec 17, 2018

Or better yet, just use a single nested dictionary:

sec1 = {'foo' : true, 'bar' : 'thing'}
sec2 = { 'boo' : 1, 'arb' : ['some', 'things']}
summary({
  'Section 1 options' : sec1,
  'Section 2 options' : sec2,
})

Have I mentioned it's annoying that lists are mutable but dicts are immutable?

@dcbaker
Copy link
Member

dcbaker commented Dec 17, 2018

I think it should also be okay to pass an unnested dict which is probably useful for simpler projects.

dcbaker added a commit to dcbaker/meson that referenced this issue Dec 17, 2018
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This is a very simple function that takes a single dictionary as an
argument, that dictionary may define scalar or container values which
will be printed as summaries. It treats nested dictionaries as another
level of configuration options, which allows grouping options together.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}

summary({
  'Backend' : 'OpenGL',
  'Server' : sec1,
  'Client' : sec2,
})
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
```

Fixes mesonbuild#757
dcbaker added a commit to dcbaker/meson that referenced this issue Dec 17, 2018
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This is a very simple function that takes a single dictionary as an
argument, that dictionary may define scalar or container values which
will be printed as summaries. It treats 1 leve of nested dictionaries as
another level of configuration options, which allows grouping options
together.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}
...
sec3 = {'with' : {'mesa' : true, 'gbm' : false}}

summary({
  'Backend' : 'OpenGL',
  'Server' : sec1,
  'Client' : sec2,
  'Misc' : sec3,
})
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
  Misc:
    with = {'mesa : true, 'gbm' : false}
```

Fixes mesonbuild#757
dcbaker added a commit to dcbaker/meson that referenced this issue Dec 17, 2018
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This function can be called one per project (so subprojects can call it
as well), and takes up to a single positional argument, and an unlimited
number of free form keyword arguments, the values of which must be
dictionaries. At the end of the configuration phase all of the
information passed to the summary function is printed, separating the
main project from each subproject, and printing the group information.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}
...
sec3 = {'with' : {'mesa' : true, 'gbm' : false}}

summary(
  {'Backend' : 'OpenGL'},
  'Server' : sec1,
  'Client' : sec2,
  'Misc' : sec3,
)
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
  Misc:
    with = {'mesa : true, 'gbm' : false}
```

Fixes mesonbuild#757
@jpakkane
Copy link
Member

There is also #4643...

@dcbaker
Copy link
Member

dcbaker commented Dec 18, 2018

I'm not opposed to 4643, but I like my approach better :)

For my use, 100% of the reason to have this is to print the configuration summary at the end of the configuration, (what auto options got selected, what's turned on, etc). From that point of view building a data structure (dict) of key value pairs and letting meson do the formatting for me is better than having to manually do the formatting in strings.

Also different, though possibly solvable, is that my solution integrates subproject messages into the final summary, but separates them in a way that is (hopefully) clear.

Oh, and mine makes it easy to group like things because it doesn't depend on the order that the function is called in. even with end_message I'm almost certainly going to have to store all of the messages anyway and loop over them at the end of the program due to the complex nature of mesa.

@dcbaker
Copy link
Member

dcbaker commented Dec 18, 2018

I'm going to go try both of them in mesa and see how they work out.

@dcbaker
Copy link
Member

dcbaker commented Dec 18, 2018

Okay, I wired up prototypes of both in mesa, and here's my take away:
My summary approach required a little more typing, but was much more flexible. In particular it allows you to set the state as you go, even when the order of the meson.build file doesn't match the order you want the summary printed in. The end_message approach was less typing overall, but proved to be awkward to work with, as it prints messages in the order it's called in, which means you either end up tracking state or just calling `end_message at the end of the meson.build anyway (I ended up with the latter).

In mesa I want to group the summary into groups like "core options", "dri drivers", "gallium", "vulkan drivers", "window systems", "llvm", but some of those thing are intermixed. When you use an auto option, for example, we might need to figure out the drivers, then the platforms, then gallium state trackers (dx, opengl, opencl, media). Or I might figure out the dri drivers, then the gallium drivers, then other dri settings.

Here's the two patches for reference:
summary
end_message

@tp-m
Copy link
Member Author

tp-m commented Dec 18, 2018

The end_message() idea has a certain simplicity, but I don't know if it can deliver on what I was after.

Half the job of the function is formatting IMHO, nice indentation, perhaps even column spacing, maybe more. I quite like the summary() suggestion, but haven't tried to put it into use yet.

@dcbaker
Copy link
Member

dcbaker commented Dec 19, 2018

The summary() implementation needs a bit more work ATM. It's basically just enough POC to try the API and some very basic formatting. I'm planning to spend a bit more time after lunch polishing it.

dcbaker added a commit to dcbaker/meson that referenced this issue Dec 20, 2018
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This function can be called one per project (so subprojects can call it
as well), and takes up to a single positional argument, and an unlimited
number of free form keyword arguments, the values of which must be
dictionaries. At the end of the configuration phase all of the
information passed to the summary function is printed, separating the
main project from each subproject, and printing the group information.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}
...
sec3 = {'with' : {'mesa' : true, 'gbm' : false}}

summary(
  {'Backend' : 'OpenGL'},
  Server : sec1,
  Client : sec2,
  Misc : sec3,
)
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
  Misc:
    with = {'mesa : true, 'gbm' : false}
```

Fixes mesonbuild#757
dcbaker added a commit to dcbaker/meson that referenced this issue Dec 20, 2018
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This function can be called one per project (so subprojects can call it
as well), and takes up to a single positional argument, and an unlimited
number of free form keyword arguments, the values of which must be
dictionaries. At the end of the configuration phase all of the
information passed to the summary function is printed, separating the
main project from each subproject, and printing the group information.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}
...
sec3 = {'with' : {'mesa' : true, 'gbm' : false}}

summary(
  {'Backend' : 'OpenGL'},
  Server : sec1,
  Client : sec2,
  Misc : sec3,
)
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
  Misc:
    with = {'mesa : true, 'gbm' : false}
```

Fixes mesonbuild#757
dcbaker added a commit to dcbaker/meson that referenced this issue Feb 1, 2019
This has been requested multiple times in the mesa/xorg community, and
apparently in the GStreamer community as well.

This function can be called one per project (so subprojects can call it
as well), and takes up to a single positional argument, and an unlimited
number of free form keyword arguments, the values of which must be
dictionaries. At the end of the configuration phase all of the
information passed to the summary function is printed, separating the
main project from each subproject, and printing the group information.

For example:

```meson
sec1 = {'driver' : 'foobar', 'OS' : 'Linux', 'API' : 1.7}
...
sec2 = {'driver' : 'dive comp', 'OS' : 'Minix', 'API' : 1.1.2}
...
sec3 = {'with' : {'mesa' : true, 'gbm' : false}}

summary(
  {'Backend' : 'OpenGL'},
  Server : sec1,
  Client : sec2,
  Misc : sec3,
)
```

Which would print something like:

```txt
Configuration Summary:
  Backend = OpenGL
  Server:
    driver = foobar
    OS = Linux
    API = 1.7
  Client:
    driver = dive comp
    OS = Minix
    API = 1.1.2
  Misc:
    with = {'mesa : true, 'gbm' : false}
```

Fixes mesonbuild#757
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 9, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 9, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 9, 2019
xclaesse pushed a commit to xclaesse/meson that referenced this issue Dec 9, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 9, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to xclaesse/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to xclaesse/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to xclaesse/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 10, 2019
xclaesse pushed a commit to xclaesse/meson that referenced this issue Dec 11, 2019
xclaesse pushed a commit to dcbaker/meson that referenced this issue Dec 11, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 11, 2019
xclaesse added a commit to xclaesse/meson that referenced this issue Dec 12, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 12, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 12, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 12, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 12, 2019
xclaesse added a commit to dcbaker/meson that referenced this issue Dec 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants