Skip to content

Commit f7478eb

Browse files
committed
Use quote crate for creating Config struct instead of debug impls
1 parent 2d7e064 commit f7478eb

File tree

3 files changed

+83
-33
lines changed

3 files changed

+83
-33
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,16 +60,21 @@ optional = true
6060
llvm-tools-build = { version = "0.1", optional = true, package = "llvm-tools" }
6161
toml = { version = "0.5.1", optional = true }
6262
serde = { version = "1.0", features = ["derive"], optional = true}
63+
quote = { version = "1.0", optional = true}
64+
proc-macro2 = { version = "1.0", optional = true}
6365

6466
[features]
6567
default = []
6668
builder = ["argh", "thiserror", "displaydoc", "anyhow", "llvm-tools", "json", "fatfs", "gpt"]
6769
runner = ["anyhow"]
6870
bios_bin = ["binary", "rsdp"]
6971
uefi_bin = ["binary", "uefi"]
70-
binary = ["llvm-tools-build", "x86_64", "toml", "xmas-elf", "usize_conversions", "log", "conquer-once", "spinning_top", "serde", "font8x8"]
7172
recursive_page_table = []
7273
map_physical_memory = []
74+
binary = [
75+
"llvm-tools-build", "x86_64", "toml", "xmas-elf", "usize_conversions", "log", "conquer-once",
76+
"spinning_top", "serde", "font8x8", "quote", "proc-macro2",
77+
]
7378

7479
[profile.dev]
7580
panic = "abort"

build.rs

Lines changed: 75 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fn main() {
88

99
#[cfg(feature = "binary")]
1010
mod binary {
11-
use std::fmt;
11+
use quote::quote;
1212

1313
pub fn main() {
1414
use llvm_tools_build as llvm_tools;
@@ -207,17 +207,21 @@ mod binary {
207207
Ok(path)
208208
if Path::new(&path).file_name().and_then(|s| s.to_str()) != Some("Cargo.toml") =>
209209
{
210-
format!(
211-
"compile_error!(\"The given `--kernel-manifest` path `{}` does not \
212-
point to a `Cargo.toml`\")",
210+
let err = format!(
211+
"The given `--kernel-manifest` path `{}` does not \
212+
point to a `Cargo.toml`",
213213
path,
214-
)
214+
);
215+
quote! { compile_error!(#err) }
215216
}
216217
Ok(path) if !Path::new(&path).exists() => {
217-
format!(
218-
"compile_error!(\"The given `--kernel-manifest` path `{}` does not exist`\")",
219-
path,
220-
)
218+
let err = format!(
219+
"The given `--kernel-manifest` path `{}` does not exist.",
220+
path
221+
);
222+
quote! {
223+
compile_error!(#err);
224+
}
221225
}
222226
Ok(path) => {
223227
println!("cargo:rerun-if-changed={}", path);
@@ -245,22 +249,28 @@ mod binary {
245249
.unwrap_or_else(|| toml::Value::Table(toml::map::Map::new()));
246250

247251
config_table
248-
.try_into::<Config>()
249-
.map(|c| format!("{:?}", c))
252+
.try_into::<ParsedConfig>()
253+
.map(|c| quote! { #c })
250254
.unwrap_or_else(|err| {
251-
format!(
252-
"compile_error!(\"failed to parse bootloader config in {}:\n\n{}\")",
255+
let err = format!(
256+
"failed to parse bootloader config in {}:\n\n{}",
253257
path,
254-
err.to_string().escape_default(),
255-
)
258+
err.to_string().escape_default()
259+
);
260+
quote! {
261+
compile_error!(#err);
262+
}
256263
})
257264
} else {
258-
format!(
259-
"compile_error!(\"no bootloader dependency in {}\n\n The \
260-
`--kernel-manifest` path should point to the `Cargo.toml` \
261-
of the kernel.\")",
262-
path,
263-
)
265+
let err = format!(
266+
"no bootloader dependency in {}\n\n The \
267+
`--kernel-manifest` path should point to the `Cargo.toml` \
268+
of the kernel.",
269+
path
270+
);
271+
quote! {
272+
compile_error!(#err);
273+
}
264274
}
265275
}
266276
};
@@ -269,13 +279,13 @@ mod binary {
269279
let file_path = out_dir.join("bootloader_config.rs");
270280
let mut file = File::create(file_path).expect("failed to create bootloader_config.rs");
271281
file.write_all(
272-
format!(
273-
"mod parsed_config {{
282+
quote::quote! {
283+
mod parsed_config {
274284
use crate::config::Config;
275-
pub const CONFIG: Config = {};
276-
}}",
277-
config,
278-
)
285+
pub const CONFIG: Config = #config;
286+
}
287+
}
288+
.to_string()
279289
.as_bytes(),
280290
)
281291
.expect("write to bootloader_config.rs failed");
@@ -294,10 +304,11 @@ mod binary {
294304
///
295305
/// This copy is needed because we can't derive Deserialize in the `src/config.rs`
296306
/// module itself, since cargo currently unifies dependencies (the `toml` crate enables
297-
/// serde's standard feature).
307+
/// serde's standard feature). Also, it allows to separate the parsing special cases
308+
/// such as `AlignedAddress` more cleanly.
298309
#[derive(Debug, serde::Deserialize)]
299310
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
300-
struct Config {
311+
struct ParsedConfig {
301312
#[serde(default)]
302313
pub map_physical_memory: bool,
303314
#[serde(default)]
@@ -312,11 +323,43 @@ mod binary {
312323
pub framebuffer_address: Option<AlignedAddress>,
313324
}
314325

326+
/// Convert to tokens suitable for initializing the `Config` struct.
327+
impl quote::ToTokens for ParsedConfig {
328+
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
329+
fn optional(value: Option<impl quote::ToTokens>) -> proc_macro2::TokenStream {
330+
value.map(|v| quote!(Some(#v))).unwrap_or(quote!(None))
331+
}
332+
333+
let map_physical_memory = self.map_physical_memory;
334+
let map_page_table_recursively = self.map_page_table_recursively;
335+
let map_framebuffer = self.map_framebuffer;
336+
let kernel_stack_size = optional(self.kernel_stack_size);
337+
let physical_memory_offset = optional(self.physical_memory_offset);
338+
let recursive_index = optional(self.recursive_index);
339+
let kernel_stack_address = optional(self.kernel_stack_address);
340+
let boot_info_address = optional(self.boot_info_address);
341+
let framebuffer_address = optional(self.framebuffer_address);
342+
343+
tokens.extend(quote! { Config {
344+
map_physical_memory: #map_physical_memory,
345+
map_page_table_recursively: #map_page_table_recursively,
346+
map_framebuffer: #map_framebuffer,
347+
kernel_stack_size: #kernel_stack_size,
348+
physical_memory_offset: #physical_memory_offset,
349+
recursive_index: #recursive_index,
350+
kernel_stack_address: #kernel_stack_address,
351+
boot_info_address: #boot_info_address,
352+
framebuffer_address: #framebuffer_address,
353+
}});
354+
}
355+
}
356+
357+
#[derive(Debug, Clone, Copy)]
315358
struct AlignedAddress(u64);
316359

317-
impl fmt::Debug for AlignedAddress {
318-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319-
write!(f, "{}", self.0)
360+
impl quote::ToTokens for AlignedAddress {
361+
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
362+
self.0.to_tokens(tokens);
320363
}
321364
}
322365

0 commit comments

Comments
 (0)