Cargo manifest and "unused manifest key": allow other tools to extend the manifest

I would like to build an external tool that reuse most of the existing manifest, but needs a few extra keys on the [[example]] targets

it would be something like:

[[example]]
name = "my_example"
path = "examples/category/subcategory/my_example.rs"
display-name = "My Example"
description = "Example of an example"
wasm-support = true

and my tool would parse the manifest to be able to work on the examples.

This is already possible, but very noisy when running a standard cargo command as it will warn for each unknown key, for each example. I could create an external file that would copy the example table, but that would mean I'll have to keep both in sync. And I have more than a hundred example...

While I could silence cargo with --quiet, this removes all messages from cargo and is not easy to communicate to users.

I would like to be able to declare keys that are unknown to cargo but shouldn't warn as they are used by another tool.

Would it be possible to add an ignore-unused-keys entry in the config.toml file that would silence the warnings for the given keys?

ignore-unused-keys = [
    "example.*.display-name",
    "example.*.description",
    "example.*.wasm-support",
]

Cargo would then be able to ignore those keys if they are effectively not used by cargo. If they are, they should issue a warning along the lines of "key declared as unused by cargo is actually used".

The metadata field is explicitly intended for this.

It's not directly associated with a particular example, though.

7 Likes

Another challenge with blessing the use of unused keys is it creates compatibility issues. If cargo started to use that key then an upgrade can either cause problems from silent behavior changes to manifest parse failures.

It might be interesting to add more metadata tables. As for compatibility within a metadata table, its the wild west but generally people namespace their content in it (example).

1 Like

Thanks! I missed the metadata field. It could work, but it would be a bit painful to add.

Would it make sense to add a metadata field to each target? I looked a little into cargo source, adding the field to the struct TomlTarget is enough to silence the warning. Anything else I should look into, or would that be an interesting PR?

On the less proactive track cargo could warn in this case, or special prefixes could be reserved for metadata-esque usage.

Perhaps instead there could be a convention for adding target-specific metadata under the existing metadata field, which wouldn't require any changes to Cargo.

[metadata.target.target-triple-here] seems straightforward enough, and matches the toplevel [target] table

1 Like

I would go an entirely different route, and to the extent of trying to deprecate the existing metadata field. That said my opinions on this are perhaps even irrationally strong...

The way that I would try and do this is via the toml -> json translation path that exists for toml. Augmenting cargo itself to do more than the bare minimum json translation for the keys that it knows about. Teaching cargo to output json-ld and provide a json-ld schema for a linked data implementation of cargo manifests.

Users who need additional keys beyond what cargo knows about would have to provide a schema for their keys and and use a json-ld manifest instead. (Because it seems unlikely that a toml to json-ld mechanism could actually be realized or standardized within toml).

The existing metadata keys could be encoded as json-ld json literals At one point I had started an RFC for this, but it seemed as though the rfc process was undergoing transition. I'm still interested in pursing it if there is interest from the cargo team, and most of the changes don't seem user visible besides the additional manifest type for manifests using keys with a custom schema. The rest being basically a lot of plumbing, and internal organization to define things like a cargo schema.

It is at least a thought on a different way we could move forward that isn't metadata keys.

The downside is it doesn't logically group things.

There is a bit of a usability gap between

[[example]]
name = "my_example"
path = "examples/category/subcategory/my_example.rs"
display-name = "My Example"
description = "Example of an example"
wasm-support = true

and

[[example]]
name = "my_example"
path = "examples/category/subcategory/my_example.rs"

[[example.metadata.some-tool]]
display-name = "My Example"
description = "Example of an example"
wasm-support = true

and

[[example]]
name = "my_example"
path = "examples/category/subcategory/my_example.rs"

[metadata.example.my_example.some-tool]
display-name = "My Example"
description = "Example of an example"
wasm-support = true
2 Likes

I was using "target" as in compilation target, not platform target.

You could consider the "target_type.target_name" (so example.my_example) would be a "double" uniquely identifying the target but that means a lot of repetition whereas TOML lets you specify a new table referring to the example just above easily as shown by @epage second example.

The second example should use [example.metadata.some-tool]. Specifically reserving the metadata key like this in all tables seems a plausible approach (though there are some non-table values I could see wanting to attach metadata to, like sub-values of features).