Add `ldscript_template` option to project config

This commit is contained in:
Luke Street 2023-09-23 07:56:49 -04:00
parent 400fb7fa7f
commit 610a2e56b9
4 changed files with 36 additions and 8 deletions

2
Cargo.lock generated
View File

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

View File

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

View File

@ -244,6 +244,8 @@ pub struct ModuleConfig {
/// Forces the given symbols to be active in the linker script. /// Forces the given symbols to be active in the linker script.
#[serde(default, skip_serializing_if = "is_default")] #[serde(default, skip_serializing_if = "is_default")]
pub force_active: Vec<String>, pub force_active: Vec<String>,
#[serde(skip_serializing_if = "is_default")]
pub ldscript_template: Option<PathBuf>,
} }
impl ModuleConfig { impl ModuleConfig {
@ -821,7 +823,17 @@ fn split_write_obj(
} }
// Generate ldscript.lcf // Generate ldscript.lcf
fs::write(&out_config.ldscript, generate_ldscript(obj, &module_config.force_active)?)?; let ldscript_template = if let Some(template) = &module_config.ldscript_template {
Some(fs::read_to_string(template).with_context(|| {
format!("Failed to read linker script template '{}'", template.display())
})?)
} else {
None
};
fs::write(
&out_config.ldscript,
generate_ldscript(obj, ldscript_template.as_deref(), &module_config.force_active)?,
)?;
if config.write_asm { if config.write_asm {
debug!("Writing disassembly"); debug!("Writing disassembly");
@ -1556,6 +1568,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None, symbols: None,
map: None, map: None,
force_active: vec![], force_active: vec![],
ldscript_template: None,
}, },
selfile: None, selfile: None,
selfile_hash: None, selfile_hash: None,
@ -1590,6 +1603,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None, symbols: None,
map: None, map: None,
force_active: vec![], force_active: vec![],
ldscript_template: None,
}); });
} }
Some(ext) if ext.eq_ignore_ascii_case(OsStr::new("sel")) => { Some(ext) if ext.eq_ignore_ascii_case(OsStr::new("sel")) => {
@ -1605,6 +1619,7 @@ fn config(args: ConfigArgs) -> Result<()> {
symbols: None, symbols: None,
map: None, map: None,
force_active: vec![], force_active: vec![],
ldscript_template: None,
}); });
} }
_ => bail!("Unknown file extension: '{}'", path.display()), _ => bail!("Unknown file extension: '{}'", path.display()),

View File

@ -9,9 +9,16 @@ use crate::obj::{ObjInfo, ObjKind};
#[inline] #[inline]
const fn align_up(value: u32, align: u32) -> u32 { (value + (align - 1)) & !(align - 1) } const fn align_up(value: u32, align: u32) -> u32 { (value + (align - 1)) & !(align - 1) }
pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<String> { const LCF_TEMPLATE: &str = include_str!("../../assets/ldscript.lcf");
const LCF_PARTIAL_TEMPLATE: &str = include_str!("../../assets/ldscript_partial.lcf");
pub fn generate_ldscript(
obj: &ObjInfo,
template: Option<&str>,
force_active: &[String],
) -> Result<String> {
if obj.kind == ObjKind::Relocatable { if obj.kind == ObjKind::Relocatable {
return generate_ldscript_partial(obj, force_active); return generate_ldscript_partial(obj, template, force_active);
} }
let origin = obj.sections.iter().map(|(_, s)| s.address).min().unwrap(); let origin = obj.sections.iter().map(|(_, s)| s.address).min().unwrap();
@ -66,7 +73,8 @@ pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<Strin
let last_section_name = obj.sections.iter().next_back().unwrap().1.name.clone(); let last_section_name = obj.sections.iter().next_back().unwrap().1.name.clone();
let last_section_symbol = format!("_f_{}", last_section_name.trim_start_matches('.')); let last_section_symbol = format!("_f_{}", last_section_name.trim_start_matches('.'));
let out = include_str!("../../assets/ldscript.lcf") let out = template
.unwrap_or(LCF_TEMPLATE)
.replace("$ORIGIN", &format!("{:#X}", origin)) .replace("$ORIGIN", &format!("{:#X}", origin))
.replace("$SECTIONS", &section_defs) .replace("$SECTIONS", &section_defs)
.replace("$LAST_SECTION_SYMBOL", &last_section_symbol) .replace("$LAST_SECTION_SYMBOL", &last_section_symbol)
@ -77,7 +85,11 @@ pub fn generate_ldscript(obj: &ObjInfo, force_active: &[String]) -> Result<Strin
Ok(out) Ok(out)
} }
pub fn generate_ldscript_partial(obj: &ObjInfo, force_active: &[String]) -> Result<String> { pub fn generate_ldscript_partial(
obj: &ObjInfo,
template: Option<&str>,
force_active: &[String],
) -> Result<String> {
let mut force_files = Vec::with_capacity(obj.link_order.len()); let mut force_files = Vec::with_capacity(obj.link_order.len());
for unit in &obj.link_order { for unit in &obj.link_order {
let obj_path = obj_path_for_unit(&unit.name); let obj_path = obj_path_for_unit(&unit.name);
@ -92,7 +104,8 @@ pub fn generate_ldscript_partial(obj: &ObjInfo, force_active: &[String]) -> Resu
} }
} }
let out = include_str!("../../assets/ldscript_partial.lcf") let out = template
.unwrap_or(LCF_PARTIAL_TEMPLATE)
.replace("$FORCEACTIVE", &force_active.join("\n ")); .replace("$FORCEACTIVE", &force_active.join("\n "));
Ok(out) Ok(out)
} }