Skip to content

Commit 02c7f10

Browse files
authored
Merge pull request #1104 from oliver-butterley/config-file-updates
feat: refactor Charon.toml to use Cargo.toml and add support for start_from, hide_marker_traits
2 parents 7941319 + a7cdb5e commit 02c7f10

7 files changed

Lines changed: 66 additions & 45 deletions

File tree

charon/src/bin/charon/cli.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ pub struct Cli {
1313
pub enum Charon {
1414
/// Runs charon on a single rust file (and the modules it references, if any).
1515
Rustc(RustcArgs),
16-
/// Runs charon on a cargo project.
16+
/// Runs charon on a cargo project. If a `[package.metadata.charon]` section is present in
17+
/// `Cargo.toml`, options are also read from it.
1718
Cargo(CargoArgs),
1819
/// Print the path to the rustc toolchain used by charon.
1920
ToolchainPath(ToolchainPathArgs),
Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,31 @@
1-
//! Processing of the contents of a `Charon.toml` file.
1+
//! Processing of the contents of `[package.metadata.charon]` in `Cargo.toml`.
22
use charon_lib::options::CliOpts;
33
use serde::Deserialize;
4-
use std::path::PathBuf;
54

6-
/// The struct used to define the options available in `Charon.toml` files.
5+
/// The struct used to define the options available under `[package.metadata.charon]` in
6+
/// `Cargo.toml`. These all mirror the corresponding cli option.
77
#[derive(Debug, Deserialize)]
88
pub struct TomlConfig {
99
#[serde(default)]
10-
pub charon: CharonTomlConfig,
10+
pub extract_opaque_bodies: bool,
1111
#[serde(default)]
12-
pub rustc: RustcTomlConfig,
13-
}
14-
15-
/// The struct used to define the options available in `Charon.toml` files. These all mirror the
16-
/// corresponding cli option.
17-
#[derive(Debug, Default, Deserialize)]
18-
pub struct CharonTomlConfig {
12+
pub start_from: Vec<String>,
1913
#[serde(default)]
20-
pub extract_opaque_bodies: bool,
14+
pub start_from_if_exists: Vec<String>,
15+
#[serde(default)]
16+
pub start_from_attribute: Option<String>,
17+
#[serde(default)]
18+
pub start_from_pub: bool,
19+
#[serde(default)]
20+
pub hide_marker_traits: bool,
2121
#[serde(default)]
2222
pub include: Vec<String>,
2323
#[serde(default)]
2424
pub opaque: Vec<String>,
2525
#[serde(default)]
2626
pub exclude: Vec<String>,
27+
#[serde(default)]
28+
pub rustc: RustcTomlConfig,
2729
}
2830

2931
#[derive(Debug, Default, Deserialize)]
@@ -36,23 +38,29 @@ impl TomlConfig {
3638
/// Applies the options specified in the toml file to the cli options. In case of conflict, cli
3739
/// options take precedence.
3840
pub(crate) fn apply(self, mut config: CliOpts) -> CliOpts {
39-
config.extract_opaque_bodies |= self.charon.extract_opaque_bodies;
40-
config.include.extend(self.charon.include);
41-
config.opaque.extend(self.charon.opaque);
42-
config.exclude.extend(self.charon.exclude);
41+
config.extract_opaque_bodies |= self.extract_opaque_bodies;
42+
config.start_from.extend(self.start_from);
43+
config
44+
.start_from_if_exists
45+
.extend(self.start_from_if_exists);
46+
if config.start_from_attribute.is_none() {
47+
config.start_from_attribute = self.start_from_attribute;
48+
}
49+
config.start_from_pub |= self.start_from_pub;
50+
config.hide_marker_traits |= self.hide_marker_traits;
51+
config.include.extend(self.include);
52+
config.opaque.extend(self.opaque);
53+
config.exclude.extend(self.exclude);
4354
config.rustc_args.extend(self.rustc.flags);
4455
config
4556
}
4657
}
4758

48-
/// Read `./Charon.toml` if there is such a file.
59+
/// Read `[package.metadata.charon]` from `./Cargo.toml` if present.
4960
pub(crate) fn read_toml() -> Option<TomlConfig> {
50-
trace!("Reading options from the `Charon.toml` file");
51-
let path = PathBuf::from("./Charon.toml");
52-
if path.exists() {
53-
let contents = std::fs::read_to_string(path).unwrap();
54-
Some(toml::from_str(&contents).unwrap())
55-
} else {
56-
None
57-
}
61+
trace!("Reading options from `[package.metadata.charon]` in `Cargo.toml`");
62+
let contents = std::fs::read_to_string("./Cargo.toml").ok()?;
63+
let full: toml::Value = toml::from_str(&contents).ok()?;
64+
let charon_meta = full.get("package")?.get("metadata")?.get("charon")?.clone();
65+
Some(charon_meta.try_into().unwrap())
5866
}

charon/tests/cargo/toml.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ fn UNIT_METADATA()
4949
// Full name: UNIT_METADATA
5050
const UNIT_METADATA: () = UNIT_METADATA()
5151

52-
// Full name: test_cargo_toml::main
53-
fn main()
52+
// Full name: test_cargo_toml::included::run
53+
pub fn run()
5454
{
5555
let _0: (); // return
5656
let _1: bool; // anonymous local

charon/tests/cargo/toml/Cargo.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@ name = "test-cargo-toml"
55
version = "0.1.0"
66
authors = ["Son Ho <hosonmarc@gmail.com>"]
77
edition = "2021"
8+
9+
[package.metadata.charon]
10+
extract_opaque_bodies = true
11+
start_from = ["crate::included"]
12+
13+
[package.metadata.charon.rustc]
14+
flags = ["--cfg", "abc"]

charon/tests/cargo/toml/Charon.toml

Lines changed: 0 additions & 5 deletions
This file was deleted.
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
11
#![allow(unexpected_cfgs)]
2-
// The `cfg` is here to test that we correctly passed rustc flags from the `Charon.toml`. The call
3-
// to `is_some` is here to exercice the `extract_opaque_bodies` option.
2+
3+
// `[cfg(abc)]` is here to test that we correctly passed rustc flags from `[package.metadata.charon.rustc]`:
4+
// without `--cfg abc`, `main` does not exist and the build fails.
5+
// The call to `is_some` exercises the `extract_opaque_bodies` option.
6+
#[cfg(abc)]
7+
pub mod included {
8+
pub fn run() {
9+
let _ = Some(false).is_some();
10+
}
11+
}
12+
13+
// Must NOT appear in the output: `start_from = ["crate::included"]` filters this out.
14+
pub mod excluded {
15+
pub fn unreachable() -> u32 {
16+
42
17+
}
18+
}
19+
420
#[cfg(abc)]
521
fn main() {
6-
let _ = Some(false).is_some();
22+
included::run();
723
}

docs/usage.md

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,9 @@ provides various options and flags to tweak its behaviour: you can display a
99
detailed documentation with `--help`.
1010
In particular, you can pretty-print the translated crate with both `--print-ullbc` and `--print-llbc`, depending on the Charon intermediate representation you wish to use.
1111

12-
If there is a `Charon.toml` file at the root of your project, `charon` will also take options from it.
13-
The file supports the same options at the cli interface, except for the options that relate to
14-
input/output like `--print-llbc`. Example `Charon.toml`:
15-
```toml
16-
[charon]
17-
extract_opaque_bodies = true
18-
[rustc]
19-
flags = ["--cfg", "abc"]
20-
```
12+
Charon supports per-crate configuration via the `[package.metadata.charon]` section in `Cargo.toml`.
13+
The exact list can be found by looking at `src/bin/charon/toml_config.rs`.
14+
If an option is set both as a CLI flag and as a toml value and we can't merge them, the CLI flag wins.
2115

2216
**Remark**: because Charon is compiled with Rust nightly (this is a requirement to implement a rustc
2317
driver), it will build your crate with Rust nightly. You can find the nightly version pinned for

0 commit comments

Comments
 (0)