Add `code_size`, `data_size` to generated `config.json`

Also simplify project config generation by skipping default fields
This commit is contained in:
Luke Street 2023-09-14 17:24:00 -04:00
parent 59a4eb33d0
commit 400fb7fa7f
4 changed files with 55 additions and 15 deletions

2
Cargo.lock generated
View File

@ -331,7 +331,7 @@ dependencies = [
[[package]]
name = "decomp-toolkit"
version = "0.5.1"
version = "0.5.2"
dependencies = [
"anyhow",
"ar",

View File

@ -3,7 +3,7 @@ name = "decomp-toolkit"
description = "Yet another GameCube/Wii decompilation toolkit."
authors = ["Luke Street <luke@street.dev>"]
license = "MIT OR Apache-2.0"
version = "0.5.1"
version = "0.5.2"
edition = "2021"
publish = false
build = "build.rs"

View File

@ -142,6 +142,12 @@ pub struct ConfigArgs {
#[inline]
fn bool_true() -> bool { true }
#[inline]
fn is_true(b: &bool) -> bool { *b }
#[inline]
fn is_default<T: Default + PartialEq>(t: &T) -> bool { t == &T::default() }
mod path_slash_serde {
use std::path::PathBuf;
@ -187,51 +193,56 @@ mod path_slash_serde_option {
pub struct ProjectConfig {
#[serde(flatten)]
pub base: ModuleConfig,
#[serde(with = "path_slash_serde_option", default)]
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
pub selfile: Option<PathBuf>,
#[serde(skip_serializing_if = "is_default")]
pub selfile_hash: Option<String>,
/// Version of the MW `.comment` section format.
/// If not present, no `.comment` sections will be written.
#[serde(skip_serializing_if = "is_default")]
pub mw_comment_version: Option<u8>,
/// Disables some time-consuming analysis passes.
/// Useful when the symbols file is already created.
#[serde(default)]
#[serde(default, skip_serializing_if = "is_default")]
pub quick_analysis: bool,
#[serde(default)]
#[serde(default, skip_serializing_if = "is_default")]
pub modules: Vec<ModuleConfig>,
// Analysis options
#[serde(default = "bool_true")]
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub detect_objects: bool,
#[serde(default = "bool_true")]
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub detect_strings: bool,
#[serde(default = "bool_true")]
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub write_asm: bool,
/// Specifies the start of the common BSS section.
#[serde(skip_serializing_if = "is_default")]
pub common_start: Option<u32>,
/// Disables all analysis passes that yield new symbols,
/// and instead assumes that all symbols are known.
#[serde(default)]
#[serde(default, skip_serializing_if = "is_default")]
pub symbols_known: bool,
/// Fills gaps between symbols with
#[serde(default = "bool_true")]
#[serde(default = "bool_true", skip_serializing_if = "is_true")]
pub fill_gaps: bool,
}
#[derive(Serialize, Deserialize, Debug, Clone)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
pub struct ModuleConfig {
/// Object name. If not specified, the file name without extension will be used.
#[serde(skip_serializing_if = "is_default")]
pub name: Option<String>,
#[serde(with = "path_slash_serde")]
pub object: PathBuf,
#[serde(skip_serializing_if = "is_default")]
pub hash: Option<String>,
#[serde(with = "path_slash_serde_option", default)]
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
pub splits: Option<PathBuf>,
#[serde(with = "path_slash_serde_option", default)]
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
pub symbols: Option<PathBuf>,
#[serde(with = "path_slash_serde_option", default)]
#[serde(with = "path_slash_serde_option", default, skip_serializing_if = "is_default")]
pub map: Option<PathBuf>,
/// Forces the given symbols to be active in the linker script.
#[serde(default)]
#[serde(default, skip_serializing_if = "is_default")]
pub force_active: Vec<String>,
}
@ -262,6 +273,8 @@ pub struct OutputUnit {
pub object: PathBuf,
pub name: String,
pub autogenerated: bool,
pub code_size: u32,
pub data_size: u32,
}
#[derive(Serialize, Deserialize, Debug, Clone, Default)]
@ -797,6 +810,8 @@ fn split_write_obj(
object: out_path.clone(),
name: unit.name.clone(),
autogenerated: unit.autogenerated,
code_size: split_obj.code_size(),
data_size: split_obj.data_size(),
});
if let Some(parent) = out_path.parent() {
DirBuilder::new().recursive(true).create(parent)?;

View File

@ -293,4 +293,29 @@ impl ObjInfo {
.filter(|(_, _, _, split)| split.unit == unit)
.all(|(_, _, _, split)| split.autogenerated)
}
/// Calculate the total size of all code sections.
pub fn code_size(&self) -> u32 {
self.sections
.iter()
.filter(|(_, section)| section.kind == ObjSectionKind::Code)
.map(|(_, section)| section.size as u32)
.sum()
}
/// Calculate the total size of all data sections, including common BSS symbols.
pub fn data_size(&self) -> u32 {
self.sections
.iter()
.filter(|(_, section)| section.kind != ObjSectionKind::Code)
.map(|(_, section)| section.size as u32)
.chain(
// Include common symbols
self.symbols
.iter()
.filter(|&symbol| symbol.flags.is_common())
.map(|s| s.size as u32),
)
.sum()
}
}