From bd211881cc5ee8e12da80b95c3225e6d15ad4f32 Mon Sep 17 00:00:00 2001 From: angie Date: Thu, 11 Jul 2024 16:49:29 -0400 Subject: [PATCH] Path replacement support and add custom-options Closes #51 --- Cargo.lock | 5 +- docs/file_format/custom_options.md | 121 ++++++++++++++++++ slinky-cli/Cargo.toml | 1 + slinky-cli/src/main.rs | 39 +++++- slinky/src/document.rs | 79 +++++++++++- slinky/src/error.rs | 6 + slinky/src/linker_writer.rs | 109 +++++++++++----- slinky/src/partial_linker_writer.rs | 8 +- slinky/tests/integration_test.rs | 50 +++++--- tests/regen_tests.sh | 4 +- tests/test_cases/drmario64.yaml | 152 +++++++++++----------- tests/test_cases/makerom_zelda_like.ld | 154 +++++++++++------------ tests/test_cases/makerom_zelda_like.yaml | 2 +- 13 files changed, 518 insertions(+), 212 deletions(-) create mode 100644 docs/file_format/custom_options.md diff --git a/Cargo.lock b/Cargo.lock index 6bc8b2c..67f5a70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -290,9 +290,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", @@ -431,6 +431,7 @@ name = "slinky-cli" version = "0.1.0" dependencies = [ "clap", + "regex", "slinky", ] diff --git a/docs/file_format/custom_options.md b/docs/file_format/custom_options.md new file mode 100644 index 0000000..854fdda --- /dev/null +++ b/docs/file_format/custom_options.md @@ -0,0 +1,121 @@ +# Custom options + +The custom options are key-value pairs specified by the user at runtime that +allow generating different linker scripts from the same input yaml file. + +This is somewhat similar to "conditional compilation" on compiled programing +languages, kind of similar to what would be done in C with build-time defines +handled by the C preprocessor or in Rust with its features. + +## Table of contents + +- [Custom options](#custom-options) + - [Table of contents](#table-of-contents) + - [How does this work?](#how-does-this-work) + - [Usage](#usage) + - [Path replacement](#path-replacement) + - [Example](#example) + +## How does this work? + +The user can provide any number of key-value pairs when using slinky (either via +the CLI or the API) and use them to affect the generation of the linker script +and other files generated by slinky. This pairs will be used by slinky to +perform textual string replacement, affect which entries are emitted, etc. + +## Usage + +In the context of the CLI, the custom options are specified with the +`--custom-options key=value` long flag or the `-c key=value` short flag. + +Multiple options can be set by passing the flag multiple times (i.e. +`-c key1=value1 -c key2=value2 -c key3=value1 -c key2=value3`) or by passing +multiple pairs separated by a comma (`,`) to the same flag (i.e. +`-c key1=value1,key2=value2,key3=value1,key2=value3`) + +Keys are unique. If the same key is given multiple times to the CLI then the +last key-value pair corresponding to this key is used. Values may be duplicated +among different keys. + +Keys must be simple strings, containing only ASCII alphanumeric characters or +underscore characters (`_`). Keys should not start with a numeric character. +Keys should be composed of at least 1 character. This rules are similar to the +ones imposed to C identifiers like variables. The following regular expression +matches this restriction: `[a-zA-Z_][a-zA-Z0-9_]*`. + +If one or more custom option are passed that are not referenced by the input +yaml file then they are simply ignored. + +The following subsections show how this custom options can affect the linker +script generation. + +### Path replacement + +The path replacement feature allows to insert a custom key into a path in the +input yaml and let slinky replace the given key with the passed custom value. +This feature is specially useful when a single yaml file is wanted to be used +among different versions of the same project by changing the build paths. + +slinky searches paths for strings contained within curly braces like `{key}`. +The key and the braces are replaced with the corresponding value to the given +key. Because of this, if a `{KEY}` is used on any path then a custom option pair +containing the given `KEY` must be passed to slinky, otherwise it will refuse to +generate the linker script and emit an error. + +A `{key}` used in path replacement can't cross each component boundary of the +given path (each component being separated by `/`). In other words, something +like `base_path: build/ga{exam/ple}me/` is not valid, but +`base_path: build/{example}/game/`, `base_path: build/ga{example}me/`, +`target_path: build/{example}/game.{version}.elf` are valid. + +#### Example + +Say we have a yaml file like the following: + +```yaml +settings: + base_path: build/{version} + target_path: build/{version}/game.{version}.elf + +segments: + - name: header + files: + - { path: src/rom_header/rom_header.o } + - { path: "asm/{version}/data/ipl3.o" } # needs to be fenced in quotes + - { path: src/entry/entry.o } + + - name: boot + files: + - { path: "src/boot/boot_main_{region}.o" } # needs to be fenced in quotes + - { path: src/boot/dmadata.o } + - { path: src/boot/util.o } +``` + +This yaml file requires two custom options to be passed, `version` and `region`, +so if any of those are missing when invoking slinky then it will produce an +error. + +Now we'll list what the each path expands to by using a few custom option +combinations: + +- `--custom-option version=us -c region=ntsc` + - `target_path`: `build/us/game.us.elf` + - `header` segment: + - `build/us/src/rom_header/rom_header.o` + - `build/asm/us/data/ipl3.o` + - `build/us/src/entry/entry.o` + - `boot` segment: + - `build/us/src/boot/boot_main_ntsc.o` + - `build/us/src/boot/dmadata.o` + - `build/us/src/boot/util.o` + +- `--custom-option version=eu1.1,region=pal` + - `target_path`: `build/eu1.1/game.eu1.1.elf` + - `header` segment: + - `build/eu1.1/src/rom_header/rom_header.o` + - `build/asm/eu1.1/data/ipl3.o` + - `build/eu1.1/src/entry/entry.o` + - `boot` segment: + - `build/eu1.1/src/boot/boot_main_pal.o` + - `build/eu1.1/src/boot/dmadata.o` + - `build/eu1.1/src/boot/util.o` diff --git a/slinky-cli/Cargo.toml b/slinky-cli/Cargo.toml index ad530f5..620a50f 100644 --- a/slinky-cli/Cargo.toml +++ b/slinky-cli/Cargo.toml @@ -10,4 +10,5 @@ edition = "2021" [dependencies] clap = { version = "4.5.1", features = ["derive"] } +regex = "1.10.5" slinky = { path = "../slinky", version = "0.1.0" } diff --git a/slinky-cli/src/main.rs b/slinky-cli/src/main.rs index 54f818e..6b807c1 100644 --- a/slinky-cli/src/main.rs +++ b/slinky-cli/src/main.rs @@ -1,9 +1,10 @@ /* SPDX-FileCopyrightText: © 2024 decompals */ /* SPDX-License-Identifier: MIT */ -use std::path::PathBuf; +use std::{error::Error, path::PathBuf}; use clap::Parser; +use regex::Regex; // TODO: Add program description to cli @@ -21,20 +22,50 @@ struct Cli { /// Requires both `partial_scripts_folder` and `partial_build_segments_folder` YAML settings to be set. #[arg(short, long, default_value_t = false)] partial_linking: bool, + + #[arg(short = 'c', long, value_parser = parse_key_val::, value_delimiter = ',')] + custom_options: Vec<(String, String)>, +} + +// Taken from https://github.com/clap-rs/clap/blob/f5965e586292d31b2a2cbd83f19d145180471012/examples/typed-derive.rs#L48 +/// Parse a single key-value pair +fn parse_key_val(s: &str) -> Result<(T, U), Box> +where + T: std::str::FromStr, + T::Err: Error + Send + Sync + 'static, + U: std::str::FromStr, + U::Err: Error + Send + Sync + 'static, +{ + let pos = s + .find('=') + .ok_or_else(|| format!("invalid KEY=value: no `=` found in `{s}`"))?; + Ok((s[..pos].parse()?, s[pos + 1..].parse()?)) } fn main() { let cli = Cli::parse(); // TODO: don't use expect? - let document = slinky::Document::read_file(&cli.input).expect("Error while parsing input file"); + let mut document = + slinky::Document::read_file(&cli.input).expect("Error while parsing input file"); // println!("settings {:#?}", document.settings); + let regex_identifier = Regex::new(r"[a-zA-Z_][a-zA-Z0-9_]*").unwrap(); + + document.custom_options.reserve(cli.custom_options.len()); + for (key, value) in &cli.custom_options { + if !regex_identifier.is_match(key) { + // TODO: is there a better alternative than a plain panic? + panic!("Invalid key for custom option: '{}'", key); + } + document.custom_options.insert(key.into(), value.into()); + } + if cli.partial_linking { let mut writer = slinky::PartialLinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments).expect(""); let output_path = cli .output @@ -48,7 +79,7 @@ fn main() { } else { let mut writer = slinky::LinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments).expect("ah?"); if let Some(output_path) = cli.output { writer diff --git a/slinky/src/document.rs b/slinky/src/document.rs index 9b09d4b..a61f450 100644 --- a/slinky/src/document.rs +++ b/slinky/src/document.rs @@ -1,7 +1,11 @@ /* SPDX-FileCopyrightText: © 2024 decompals */ /* SPDX-License-Identifier: MIT */ -use std::{fs, path::Path}; +use std::{ + collections::HashMap, + fs, + path::{Path, PathBuf}, +}; use serde::Deserialize; @@ -17,6 +21,8 @@ pub struct Document { pub vram_classes: Vec, pub segments: Vec, + + pub custom_options: HashMap, } impl Document { @@ -41,6 +47,76 @@ impl Document { document_serial.unserialize() } + + fn get_custom_option_value( + &self, + custom_option: &str, + original_path: &Path, + ) -> Result<&str, SlinkyError> { + match self.custom_options.get(custom_option) { + None => Err(SlinkyError::CustomOptionInPathNotProvided { + path: original_path.into(), + custom_option: custom_option.into(), + }), + Some(val) => Ok(val), + } + } + + /// Replace all the `{key}` instances on the `path` argument with the corresponding value specified on the global `custom_options`. + /// + /// If the `key` is not present on the custom options then it returns an error. + pub(crate) fn escape_path(&self, path: &Path) -> Result { + let mut new_path = PathBuf::new(); + + for component in path.iter() { + // &OsStr is dumb so we convert each component into &str, hopefully the conversion isn't noticeable on runtime + if let Some(c) = component.to_str() { + if c.starts_with('{') && c.ends_with('}') { + // left/{thingy}/right + + let custom_option = &c[1..c.len() - 1]; + + new_path.push(self.get_custom_option_value(custom_option, path)?); + } else if !c.contains('{') || !c.contains('}') { + // No replacement at all + new_path.push(component); + } else { + // There may be one or more replacements, so we need to look for all of them. + + let mut new_component = String::new(); + let mut within_replacment = false; + let mut custom_option = String::new(); + + for character in c.chars() { + if within_replacment { + if character == '}' { + new_component += + self.get_custom_option_value(&custom_option, path)?; + + within_replacment = false; + custom_option.clear(); + } else { + custom_option.push(character); + } + } else { + // Haven't found a replacement yet, continue searching + if character == '{' { + within_replacment = true; + } else { + new_component.push(character); + } + } + } + + new_path.push(new_component) + } + } else { + new_path.push(component); + } + } + + Ok(new_path) + } } #[derive(Deserialize, PartialEq, Debug)] @@ -87,6 +163,7 @@ impl DocumentSerial { settings, vram_classes, segments, + custom_options: HashMap::new(), }) } } diff --git a/slinky/src/error.rs b/slinky/src/error.rs index d98122c..73d208c 100644 --- a/slinky/src/error.rs +++ b/slinky/src/error.rs @@ -40,4 +40,10 @@ pub enum SlinkyError { #[error("At least one of the following options should be provided: {fields}")] MissingAnyOfOptionalFields { fields: String }, + + #[error("Path '{path}' referenced custom option {custom_option}, but it was not provided")] + CustomOptionInPathNotProvided { + path: PathBuf, + custom_option: String, + }, } diff --git a/slinky/src/linker_writer.rs b/slinky/src/linker_writer.rs index 613c788..47324ad 100644 --- a/slinky/src/linker_writer.rs +++ b/slinky/src/linker_writer.rs @@ -60,18 +60,21 @@ impl<'a> LinkerWriter<'a> { s } - pub fn add_all_segments(&mut self, segments: &[Segment]) { + pub fn add_all_segments(&mut self, segments: &[Segment]) -> Result<(), SlinkyError> { if self.d.settings.single_segment_mode { + // TODO: change assert to proper error assert!(segments.len() == 1); - self.add_single_segment(&segments[0]); + self.add_single_segment(&segments[0])?; } else { self.begin_sections(); for segment in segments { - self.add_segment(segment); + self.add_segment(segment)?; } self.end_sections(); } + + Ok(()) } pub fn begin_sections(&mut self) { @@ -171,7 +174,7 @@ impl<'a> LinkerWriter<'a> { self.buffer.finish(); } - pub fn add_segment(&mut self, segment: &Segment) { + pub fn add_segment(&mut self, segment: &Segment) -> Result<(), SlinkyError> { assert!(!self.single_segment); let style = &self.d.settings.linker_symbols_style; @@ -227,12 +230,12 @@ impl<'a> LinkerWriter<'a> { .write_symbol(&main_seg_sym_start, &format!("ADDR(.{})", segment.name)); // Emit alloc segment - self.write_segment(segment, &segment.alloc_sections, false); + self.write_segment(segment, &segment.alloc_sections, false)?; self.buffer.write_empty_line(); // Emit noload segment - self.write_segment(segment, &segment.noload_sections, true); + self.write_segment(segment, &segment.noload_sections, true)?; self.write_sym_end_size( &main_seg_sym_start, @@ -259,9 +262,11 @@ impl<'a> LinkerWriter<'a> { } self.buffer.write_empty_line(); + + Ok(()) } - pub fn add_single_segment(&mut self, segment: &Segment) { + pub fn add_single_segment(&mut self, segment: &Segment) -> Result<(), SlinkyError> { assert!(self.buffer.is_empty()); // Make sure this function is called only once @@ -277,16 +282,18 @@ impl<'a> LinkerWriter<'a> { } // Emit alloc segment - self.write_single_segment(segment, &segment.alloc_sections, false); + self.write_single_segment(segment, &segment.alloc_sections, false)?; self.buffer.write_empty_line(); // Emit noload segment - self.write_single_segment(segment, &segment.noload_sections, true); + self.write_single_segment(segment, &segment.noload_sections, true)?; self.buffer.write_empty_line(); self.end_sections(); + + Ok(()) } } @@ -330,18 +337,20 @@ impl LinkerWriter<'_> { dst: &mut impl Write, target_path: &Path, ) -> Result<(), SlinkyError> { - if let Err(e) = write!(dst, "{}:", target_path.display()) { + let escaped_target_path = self.d.escape_path(target_path)?; + if let Err(e) = write!(dst, "{}:", escaped_target_path.display()) { return Err(SlinkyError::FailedWrite { description: e.to_string(), - contents: target_path.display().to_string(), + contents: escaped_target_path.display().to_string(), }); } for p in &self.files_paths { - if let Err(e) = write!(dst, " \\\n {}", p.display()) { + let escaped_p = self.d.escape_path(p)?; + if let Err(e) = write!(dst, " \\\n {}", escaped_p.display()) { return Err(SlinkyError::FailedWrite { description: e.to_string(), - contents: p.display().to_string(), + contents: escaped_p.display().to_string(), }); } } @@ -354,10 +363,11 @@ impl LinkerWriter<'_> { } for p in &self.files_paths { - if let Err(e) = writeln!(dst, "{}:", p.display()) { + let escaped_p = self.d.escape_path(p)?; + if let Err(e) = writeln!(dst, "{}:", escaped_p.display()) { return Err(SlinkyError::FailedWrite { description: e.to_string(), - contents: p.display().to_string(), + contents: escaped_p.display().to_string(), }); } } @@ -600,7 +610,13 @@ impl LinkerWriter<'_> { self.write_sections_kind_end(segment, noload); } - fn emit_file(&mut self, file: &FileInfo, segment: &Segment, section: &str, base_path: &Path) { + fn emit_file( + &mut self, + file: &FileInfo, + segment: &Segment, + section: &str, + base_path: &Path, + ) -> Result<(), SlinkyError> { let style = &self.d.settings.linker_symbols_style; let wildcard = if segment.wildcard_sections { "*" } else { "" }; @@ -611,25 +627,33 @@ impl LinkerWriter<'_> { let mut path = base_path.to_path_buf(); path.extend(&file.path); - self.buffer - .writeln(&format!("{}({}{});", path.display(), section, wildcard)); - if !self.files_paths.contains(&path) { - self.files_paths.insert(path); + let escaped_path = self.d.escape_path(&path)?; + + self.buffer.writeln(&format!( + "{}({}{});", + escaped_path.display(), + section, + wildcard + )); + if !self.files_paths.contains(&escaped_path) { + self.files_paths.insert(escaped_path); } } FileKind::Archive => { let mut path = base_path.to_path_buf(); path.extend(&file.path); + let escaped_path = self.d.escape_path(&path)?; + self.buffer.writeln(&format!( "{}:{}({}{});", - path.display(), + escaped_path.display(), file.subfile, section, wildcard )); - if !self.files_paths.contains(&path) { - self.files_paths.insert(path); + if !self.files_paths.contains(&escaped_path) { + self.files_paths.insert(escaped_path); } } FileKind::Pad => { @@ -650,13 +674,20 @@ impl LinkerWriter<'_> { new_base_path.extend(&file.dir); for file_of_group in &file.files { - self.emit_file(file_of_group, segment, section, &new_base_path); + self.emit_file(file_of_group, segment, section, &new_base_path)?; } } } + + Ok(()) } - fn emit_section(&mut self, segment: &Segment, section: &str, sections: &[String]) { + fn emit_section( + &mut self, + segment: &Segment, + section: &str, + sections: &[String], + ) -> Result<(), SlinkyError> { let mut base_path = PathBuf::new(); base_path.extend(&self.d.settings.base_path); @@ -688,16 +719,23 @@ impl LinkerWriter<'_> { .sort_unstable_by_key(|&k| sections.iter().position(|s| s == k)); for k in sections_to_emit_here { - self.emit_file(file, segment, k, &base_path); + self.emit_file(file, segment, k, &base_path)?; } } else { // No need to mess with section ordering, just emit the file - self.emit_file(file, segment, section, &base_path); + self.emit_file(file, segment, section, &base_path)?; } } + + Ok(()) } - fn write_segment(&mut self, segment: &Segment, sections: &[String], noload: bool) { + fn write_segment( + &mut self, + segment: &Segment, + sections: &[String], + noload: bool, + ) -> Result<(), SlinkyError> { self.write_segment_start(segment, noload); if let Some(fill_value) = segment.fill_value { @@ -707,7 +745,7 @@ impl LinkerWriter<'_> { for (i, section) in sections.iter().enumerate() { self.write_section_symbol_start(segment, section); - self.emit_section(segment, section, sections); + self.emit_section(segment, section, sections)?; self.write_section_symbol_end(segment, section); @@ -717,9 +755,16 @@ impl LinkerWriter<'_> { } self.write_segment_end(segment, noload); + + Ok(()) } - fn write_single_segment(&mut self, segment: &Segment, sections: &[String], noload: bool) { + fn write_single_segment( + &mut self, + segment: &Segment, + sections: &[String], + noload: bool, + ) -> Result<(), SlinkyError> { self.write_sections_kind_start(segment, noload); for (i, section) in sections.iter().enumerate() { @@ -740,7 +785,7 @@ impl LinkerWriter<'_> { self.buffer.writeln(&format!("FILL(0x{:08X});", fill_value)); } - self.emit_section(segment, section, sections); + self.emit_section(segment, section, sections)?; self.buffer.end_block(); self.write_section_symbol_end(segment, section); @@ -751,5 +796,7 @@ impl LinkerWriter<'_> { } self.write_sections_kind_end(segment, noload); + + Ok(()) } } diff --git a/slinky/src/partial_linker_writer.rs b/slinky/src/partial_linker_writer.rs index a0691da..2dc186c 100644 --- a/slinky/src/partial_linker_writer.rs +++ b/slinky/src/partial_linker_writer.rs @@ -27,7 +27,7 @@ impl<'a> PartialLinkerWriter<'a> { } } - pub fn add_all_segments(&mut self, segments: &[Segment]) { + pub fn add_all_segments(&mut self, segments: &[Segment]) -> Result<(), SlinkyError> { self.main_writer.begin_sections(); self.partial_writers.reserve(segments.len()); @@ -37,7 +37,7 @@ impl<'a> PartialLinkerWriter<'a> { partial_writer.set_emit_sections_kind_symbols(false); partial_writer.set_emit_section_symbols(false); - partial_writer.add_single_segment(segment); + partial_writer.add_single_segment(segment)?; self.partial_writers .push((partial_writer, segment.name.clone())); @@ -59,10 +59,12 @@ impl<'a> PartialLinkerWriter<'a> { files: Vec::new(), dir: PathBuf::new(), }]; - self.main_writer.add_segment(&reference_segment); + self.main_writer.add_segment(&reference_segment)?; } self.main_writer.end_sections(); + + Ok(()) } pub fn export_linker_script_to_files(&self, path: &Path) -> Result<(), SlinkyError> { diff --git a/slinky/tests/integration_test.rs b/slinky/tests/integration_test.rs index 20401b8..26b1546 100644 --- a/slinky/tests/integration_test.rs +++ b/slinky/tests/integration_test.rs @@ -5,12 +5,22 @@ use std::fs; use std::path::{Path, PathBuf}; use rstest::rstest; +use slinky::{Document, SlinkyError}; -fn check_ld_generation(yaml_path: &Path, ld_path: &Path) { - let document = slinky::Document::read_file(yaml_path).expect("unable to read original file"); +fn set_custom_options(document: &mut Document) { + // We are lazy and use the same version for every test case + document + .custom_options + .insert("version".into(), "us".into()); +} + +fn check_ld_generation(yaml_path: &Path, ld_path: &Path) -> Result<(), SlinkyError> { + let mut document = + slinky::Document::read_file(yaml_path).expect("unable to read original file"); + set_custom_options(&mut document); let mut writer = slinky::LinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments)?; let expected_ld_contents = fs::read_to_string(ld_path).expect("unable to read expected ld file"); @@ -19,13 +29,17 @@ fn check_ld_generation(yaml_path: &Path, ld_path: &Path) { expected_ld_contents, writer.export_linker_script_to_string().unwrap() ); + + Ok(()) } -fn check_d_generation(yaml_path: &Path, ld_path: &Path) { - let document = slinky::Document::read_file(yaml_path).expect("unable to read original file"); +fn check_d_generation(yaml_path: &Path, ld_path: &Path) -> Result<(), SlinkyError> { + let mut document = + slinky::Document::read_file(yaml_path).expect("unable to read original file"); + set_custom_options(&mut document); let mut writer = slinky::LinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments)?; let expected_d_contents = fs::read_to_string(ld_path).expect("unable to read expected d file"); @@ -36,13 +50,17 @@ fn check_d_generation(yaml_path: &Path, ld_path: &Path) { .export_dependencies_file_to_string(target_path) .unwrap() ); + + Ok(()) } -fn check_symbols_header_generation(yaml_path: &Path, ld_path: &Path) { - let document = slinky::Document::read_file(yaml_path).expect("unable to read original file"); +fn check_symbols_header_generation(yaml_path: &Path, ld_path: &Path) -> Result<(), SlinkyError> { + let mut document = + slinky::Document::read_file(yaml_path).expect("unable to read original file"); + set_custom_options(&mut document); let mut writer = slinky::LinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments)?; let expected_h_contents = fs::read_to_string(ld_path).expect("unable to read expected h file"); @@ -50,27 +68,29 @@ fn check_symbols_header_generation(yaml_path: &Path, ld_path: &Path) { expected_h_contents, writer.export_symbol_header_to_string().unwrap() ); + + Ok(()) } #[rstest] fn test_simple_linker_script_generation(#[files("../tests/test_cases/*.ld")] ld_path: PathBuf) { let yaml_path = ld_path.with_extension("yaml"); - check_ld_generation(&yaml_path, &ld_path); + check_ld_generation(&yaml_path, &ld_path).expect(""); } #[rstest] fn test_dependency_d_generation(#[files("../tests/test_cases/*.d")] d_path: PathBuf) { let yaml_path = d_path.with_extension("yaml"); - check_d_generation(&yaml_path, &d_path); + check_d_generation(&yaml_path, &d_path).expect(""); } #[rstest] fn test_symbols_header_generation(#[files("../tests/test_cases/*.h")] h_path: PathBuf) { let yaml_path = h_path.with_extension("yaml"); - check_symbols_header_generation(&yaml_path, &h_path); + check_symbols_header_generation(&yaml_path, &h_path).expect(""); } #[rstest] @@ -88,7 +108,7 @@ fn test_partial_linking_script_generation( let document = slinky::Document::read_file(&yaml_path).expect("unable to read original file"); let mut writer = slinky::PartialLinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments).expect(""); let expected_ld_contents = fs::read_to_string(ld_path).expect("unable to read expected ld file"); @@ -125,7 +145,7 @@ fn test_partial_linking_d_generation(#[files("../tests/partial_linking/*.d")] d_ let document = slinky::Document::read_file(&yaml_path).expect("unable to read original file"); let mut writer = slinky::PartialLinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments).expect(""); let expected_d_contents = fs::read_to_string(d_path).expect("unable to read expected d file"); @@ -168,7 +188,7 @@ fn test_partial_linking_symbols_header_generation( let document = slinky::Document::read_file(&yaml_path).expect("unable to read original file"); let mut writer = slinky::PartialLinkerWriter::new(&document); - writer.add_all_segments(&document.segments); + writer.add_all_segments(&document.segments).expect(""); let expected_h_contents = fs::read_to_string(h_path).expect("unable to read expected h file"); diff --git a/tests/regen_tests.sh b/tests/regen_tests.sh index 6828bb8..27e6bfb 100755 --- a/tests/regen_tests.sh +++ b/tests/regen_tests.sh @@ -13,7 +13,7 @@ for filepath in tests/test_cases/*.yaml; do stem="${filename%.*}" output=tests/test_cases/$stem.ld echo Generating $output - cargo run --release -- $filepath -o $output + cargo run --release -- $filepath -o $output --custom-options version=us done for filepath in tests/partial_linking/*.yaml; do @@ -21,5 +21,5 @@ for filepath in tests/partial_linking/*.yaml; do stem="${filename%.*}" output=tests/partial_linking/$stem.ld echo Generating $output - cargo run --release -- $filepath -o $output --partial-linking + cargo run --release -- $filepath -o $output --partial-linking -c version=us done diff --git a/tests/test_cases/drmario64.yaml b/tests/test_cases/drmario64.yaml index b1fca1f..73b567c 100644 --- a/tests/test_cases/drmario64.yaml +++ b/tests/test_cases/drmario64.yaml @@ -1,8 +1,8 @@ settings: - base_path: build/us + base_path: build/{version} d_path: tests/test_cases/drmario64.d - target_path: build/us/drmario64.us.elf + target_path: build/{version}/drmario64.{version}.elf sections_allowlist: # mips debug sections @@ -69,7 +69,7 @@ segments: - name: ipl3 files: - - { path: asm/us/data/ipl3.o } + - { path: "asm/{version}/data/ipl3.o" } - name: entry fixed_vram: 0x80000400 @@ -272,7 +272,7 @@ segments: - { path: src/libkmc/ctype.o } # end of libkmc - - { path: asm/us/data/boot/8001B640.bss.o } + - { path: "asm/{version}/data/boot/8001B640.bss.o" } - name: dma_table files: @@ -285,7 +285,7 @@ segments: - { path: src/main_segment/joy.o } - { path: src/main_segment/audio/sound.o } - - { path: asm/us/data/main_segment/audio/sound.bss.o } + - { path: "asm/{version}/data/main_segment/audio/sound.bss.o" } - { path: src/main_segment/graphic.o } - { path: src/main_segment/graphics/static.o } @@ -296,31 +296,31 @@ segments: - { path: src/main_segment/main1x.o } - { path: src/main_segment/vr_init.o } - - { path: asm/us/data/main_segment/vr_init.bss.o } + - { path: "asm/{version}/data/main_segment/vr_init.bss.o" } - { path: src/main_segment/aiset.o } - - { path: asm/us/data/main_segment/aiset.data.o } - - { path: asm/us/data/main_segment/aiset.bss.o } + - { path: "asm/{version}/data/main_segment/aiset.data.o" } + - { path: "asm/{version}/data/main_segment/aiset.bss.o" } - { path: src/main_segment/record.o } - - { path: asm/us/data/main_segment/record.bss.o } + - { path: "asm/{version}/data/main_segment/record.bss.o" } - { path: src/main_segment/unused/020D10.o } - - { path: asm/us/data/main_segment/unused/020D10.data.o } - - { path: asm/us/data/main_segment/unused/020D10.bss.o } + - { path: "asm/{version}/data/main_segment/unused/020D10.data.o" } + - { path: "asm/{version}/data/main_segment/unused/020D10.bss.o" } - { path: src/main_segment/game_etc.o } - - { path: asm/us/data/main_segment/game_etc.data.o } - - { path: asm/us/data/main_segment/game_etc.bss.o } + - { path: "asm/{version}/data/main_segment/game_etc.data.o" } + - { path: "asm/{version}/data/main_segment/game_etc.bss.o" } - { path: src/main_segment/screen_print/printer.o } - { path: src/main_segment/screen_print/printf_impl.o } - - { path: asm/us/data/main_segment/0750C0.data.o } + - { path: "asm/{version}/data/main_segment/0750C0.data.o" } - { path: src/main_segment/screen_print/debug_print.o } - - { path: asm/us/data/main_segment/screen_print/debug_print.bss.o } + - { path: "asm/{version}/data/main_segment/screen_print/debug_print.bss.o" } - { path: src/main_segment/debug_menu.o } - - { path: asm/us/data/main_segment/debug_menu.bss.o } + - { path: "asm/{version}/data/main_segment/debug_menu.bss.o" } - { path: src/main_segment/028820.o } @@ -336,24 +336,24 @@ segments: - { path: src/main_segment/dm_virus_init.o } - { path: src/main_segment/dm_game_main.o } - - { path: asm/us/data/main_segment/dm_game_main.data.o } - - { path: asm/us/data/main_segment/dm_game_main.bss.o } + - { path: "asm/{version}/data/main_segment/dm_game_main.data.o" } + - { path: "asm/{version}/data/main_segment/dm_game_main.bss.o" } - { path: src/main_segment/dm_manual_main.o } - - { path: asm/us/data/main_segment/dm_manual_main.bss.o } + - { path: "asm/{version}/data/main_segment/dm_manual_main.bss.o" } - { path: src/main_segment/dm_title_main.o } - - { path: asm/us/data/main_segment/dm_title_main.data.o } - - { path: asm/us/data/main_segment/dm_title_main.bss.o } + - { path: "asm/{version}/data/main_segment/dm_title_main.data.o" } + - { path: "asm/{version}/data/main_segment/dm_title_main.bss.o" } - - { path: asm/us/data/main_segment/08F1C0.data.o } + - { path: "asm/{version}/data/main_segment/08F1C0.data.o" } - { path: src/main_segment/main_story.o } - - { path: asm/us/data/main_segment/main_story.data.o } - - { path: asm/us/data/main_segment/main_story.bss.o } + - { path: "asm/{version}/data/main_segment/main_story.data.o" } + - { path: "asm/{version}/data/main_segment/main_story.bss.o" } - { path: src/main_segment/lws.o } - - { path: asm/us/data/main_segment/lws.bss.o } + - { path: "asm/{version}/data/main_segment/lws.bss.o" } - { path: src/main_segment/calc.o } - { path: src/main_segment/unused/065080.o } # weird alignment @@ -361,7 +361,7 @@ segments: - { path: src/main_segment/unused/066080.o } - { path: src/main_segment/replay.o } - - { path: asm/us/data/main_segment/replay.bss.o } + - { path: "asm/{version}/data/main_segment/replay.bss.o" } - { path: src/main_segment/066580.o } @@ -377,12 +377,12 @@ segments: - { path: lib/libmus/src/lib_memory.o } - { path: lib/libmus/src/aud_samples.o } - - { path: asm/us/data/rsp/rspboot.o } - - { path: asm/us/data/rsp/aspMain.o } - - { path: asm/us/data/rsp/f3dex2.o } - - { path: asm/us/data/rsp/s2dex.o } + - { path: "asm/{version}/data/rsp/rspboot.o" } + - { path: "asm/{version}/data/rsp/aspMain.o" } + - { path: "asm/{version}/data/rsp/f3dex2.o" } + - { path: "asm/{version}/data/rsp/s2dex.o" } - - { path: asm/us/data/main_segment/800E9BB0.bss.o } + - { path: "asm/{version}/data/main_segment/800E9BB0.bss.o" } - name: buffer1 files: @@ -400,188 +400,188 @@ segments: - name: n64_wave_tables files: - - { path: asm/us/data/n64_wave_tables.o } + - { path: "asm/{version}/data/n64_wave_tables.o" } - name: n64_ptr_tables_v2 files: - - { path: asm/us/data/n64_ptr_tables_v2.o } + - { path: "asm/{version}/data/n64_ptr_tables_v2.o" } - name: segment_172130 files: - - { path: asm/us/data/segment_172130.o } + - { path: "asm/{version}/data/segment_172130.o" } - name: segment_172D60 files: - - { path: asm/us/data/segment_172D60.o } + - { path: "asm/{version}/data/segment_172D60.o" } - name: segment_1750C0 files: - - { path: asm/us/data/segment_1750C0.o } + - { path: "asm/{version}/data/segment_1750C0.o" } - name: segment_177420 files: - - { path: asm/us/data/segment_177420.o } + - { path: "asm/{version}/data/segment_177420.o" } - name: segment_179620 files: - - { path: asm/us/data/segment_179620.o } + - { path: "asm/{version}/data/segment_179620.o" } - name: segment_17B790 files: - - { path: asm/us/data/segment_17B790.o } + - { path: "asm/{version}/data/segment_17B790.o" } - name: segment_17C1E0 files: - - { path: asm/us/data/segment_17C1E0.o } + - { path: "asm/{version}/data/segment_17C1E0.o" } - name: segment_17D130 files: - - { path: asm/us/data/segment_17D130.o } + - { path: "asm/{version}/data/segment_17D130.o" } - name: segment_17E090 files: - - { path: asm/us/data/segment_17E090.o } + - { path: "asm/{version}/data/segment_17E090.o" } - name: segment_181840 files: - - { path: asm/us/data/segment_181840.o } + - { path: "asm/{version}/data/segment_181840.o" } - name: segment_184FF0 files: - - { path: asm/us/data/segment_184FF0.o } + - { path: "asm/{version}/data/segment_184FF0.o" } - name: segment_186FF0 files: - - { path: asm/us/data/segment_186FF0.o } + - { path: "asm/{version}/data/segment_186FF0.o" } - name: segment_188FF0 files: - - { path: asm/us/data/segment_188FF0.o } + - { path: "asm/{version}/data/segment_188FF0.o" } - name: segment_189D40 files: - - { path: asm/us/data/segment_189D40.o } + - { path: "asm/{version}/data/segment_189D40.o" } - name: segment_18CB40 files: - - { path: asm/us/data/segment_18CB40.o } + - { path: "asm/{version}/data/segment_18CB40.o" } - name: segment_18DB90 files: - - { path: asm/us/data/segment_18DB90.o } + - { path: "asm/{version}/data/segment_18DB90.o" } - name: segment_18F160 files: - - { path: asm/us/data/segment_18F160.o } + - { path: "asm/{version}/data/segment_18F160.o" } - name: segment_1906E0 files: - - { path: asm/us/data/segment_1906E0.o } + - { path: "asm/{version}/data/segment_1906E0.o" } - name: segment_1911D0 files: - - { path: asm/us/data/segment_1911D0.o } + - { path: "asm/{version}/data/segment_1911D0.o" } - name: segment_1936C0 files: - - { path: asm/us/data/segment_1936C0.o } + - { path: "asm/{version}/data/segment_1936C0.o" } - name: segment_1937F0 files: - - { path: asm/us/data/segment_1937F0.o } + - { path: "asm/{version}/data/segment_1937F0.o" } - name: segment_194070 files: - - { path: asm/us/data/segment_194070.o } + - { path: "asm/{version}/data/segment_194070.o" } - name: segment_194150 files: - - { path: asm/us/data/segment_194150.o } + - { path: "asm/{version}/data/segment_194150.o" } - name: segment_194910 files: - - { path: asm/us/data/segment_194910.o } + - { path: "asm/{version}/data/segment_194910.o" } - name: segment_195290 files: - - { path: asm/us/data/segment_195290.o } + - { path: "asm/{version}/data/segment_195290.o" } - name: segment_game_etc files: - - { path: asm/us/data/segment_game_etc.o } + - { path: "asm/{version}/data/segment_game_etc.o" } - name: segment_menu_bg files: - - { path: asm/us/data/segment_menu_bg.o } + - { path: "asm/{version}/data/segment_menu_bg.o" } - name: segment_menu_bg2 files: - - { path: asm/us/data/segment_menu_bg2.o } + - { path: "asm/{version}/data/segment_menu_bg2.o" } - name: segment_coffee01 files: - - { path: asm/us/data/segment_coffee01.o } + - { path: "asm/{version}/data/segment_coffee01.o" } - name: segment_title_all files: - - { path: asm/us/data/segment_title_all.o } + - { path: "asm/{version}/data/segment_title_all.o" } - name: segment_title_bmp files: - - { path: asm/us/data/segment_title_bmp.o } + - { path: "asm/{version}/data/segment_title_bmp.o" } - name: segment_waku files: - - { path: asm/us/data/segment_waku.o } + - { path: "asm/{version}/data/segment_waku.o" } - name: segment_waku2 files: - - { path: asm/us/data/segment_waku2.o } + - { path: "asm/{version}/data/segment_waku2.o" } - name: segment_story_bg01 files: - - { path: asm/us/data/segment_story_bg01.o } + - { path: "asm/{version}/data/segment_story_bg01.o" } - name: segment_story_bg02 files: - - { path: asm/us/data/segment_story_bg02.o } + - { path: "asm/{version}/data/segment_story_bg02.o" } - name: segment_story_bg03 files: - - { path: asm/us/data/segment_story_bg03.o } + - { path: "asm/{version}/data/segment_story_bg03.o" } - name: segment_story_bg04 files: - - { path: asm/us/data/segment_story_bg04.o } + - { path: "asm/{version}/data/segment_story_bg04.o" } - name: segment_story_bg05 files: - - { path: asm/us/data/segment_story_bg05.o } + - { path: "asm/{version}/data/segment_story_bg05.o" } - name: segment_story_bg07 files: - - { path: asm/us/data/segment_story_bg07.o } + - { path: "asm/{version}/data/segment_story_bg07.o" } - name: segment_story_bg08 files: - - { path: asm/us/data/segment_story_bg08.o } + - { path: "asm/{version}/data/segment_story_bg08.o" } - name: segment_story_bg09 files: - - { path: asm/us/data/segment_story_bg09.o } + - { path: "asm/{version}/data/segment_story_bg09.o" } - name: segment_story_bg10 files: - - { path: asm/us/data/segment_story_bg10.o } + - { path: "asm/{version}/data/segment_story_bg10.o" } - name: segment_story_bg11 files: - - { path: asm/us/data/segment_story_bg11.o } + - { path: "asm/{version}/data/segment_story_bg11.o" } diff --git a/tests/test_cases/makerom_zelda_like.ld b/tests/test_cases/makerom_zelda_like.ld index ebc7320..1a9f693 100644 --- a/tests/test_cases/makerom_zelda_like.ld +++ b/tests/test_cases/makerom_zelda_like.ld @@ -10,25 +10,25 @@ SECTIONS { FILL(0x00000000); _makeromSegmentDataStart = .; - build/makerom/header.o(.data*); - build/makerom/ipl3.o(.data*); - build/makerom/entry.o(.data*); + build/us/makerom/header.o(.data*); + build/us/makerom/ipl3.o(.data*); + build/us/makerom/entry.o(.data*); . = ALIGN(., 0x10); _makeromSegmentDataEnd = .; _makeromSegmentDataSize = ABSOLUTE(_makeromSegmentDataEnd - _makeromSegmentDataStart); _makeromSegmentTextStart = .; - build/makerom/header.o(.text*); - build/makerom/ipl3.o(.text*); - build/makerom/entry.o(.text*); + build/us/makerom/header.o(.text*); + build/us/makerom/ipl3.o(.text*); + build/us/makerom/entry.o(.text*); . = ALIGN(., 0x10); _makeromSegmentTextEnd = .; _makeromSegmentTextSize = ABSOLUTE(_makeromSegmentTextEnd - _makeromSegmentTextStart); _makeromSegmentRoDataStart = .; - build/makerom/header.o(.rodata*); - build/makerom/ipl3.o(.rodata*); - build/makerom/entry.o(.rodata*); + build/us/makerom/header.o(.rodata*); + build/us/makerom/ipl3.o(.rodata*); + build/us/makerom/entry.o(.rodata*); . = ALIGN(., 0x10); _makeromSegmentRoDataEnd = .; _makeromSegmentRoDataSize = ABSOLUTE(_makeromSegmentRoDataEnd - _makeromSegmentRoDataStart); @@ -43,33 +43,33 @@ SECTIONS { FILL(0x00000000); _makeromSegmentSbssStart = .; - build/makerom/header.o(.sbss*); - build/makerom/ipl3.o(.sbss*); - build/makerom/entry.o(.sbss*); + build/us/makerom/header.o(.sbss*); + build/us/makerom/ipl3.o(.sbss*); + build/us/makerom/entry.o(.sbss*); . = ALIGN(., 0x10); _makeromSegmentSbssEnd = .; _makeromSegmentSbssSize = ABSOLUTE(_makeromSegmentSbssEnd - _makeromSegmentSbssStart); _makeromSegmentScommonStart = .; - build/makerom/header.o(.scommon*); - build/makerom/ipl3.o(.scommon*); - build/makerom/entry.o(.scommon*); + build/us/makerom/header.o(.scommon*); + build/us/makerom/ipl3.o(.scommon*); + build/us/makerom/entry.o(.scommon*); . = ALIGN(., 0x10); _makeromSegmentScommonEnd = .; _makeromSegmentScommonSize = ABSOLUTE(_makeromSegmentScommonEnd - _makeromSegmentScommonStart); _makeromSegmentBssStart = .; - build/makerom/header.o(.bss*); - build/makerom/ipl3.o(.bss*); - build/makerom/entry.o(.bss*); + build/us/makerom/header.o(.bss*); + build/us/makerom/ipl3.o(.bss*); + build/us/makerom/entry.o(.bss*); . = ALIGN(., 0x10); _makeromSegmentBssEnd = .; _makeromSegmentBssSize = ABSOLUTE(_makeromSegmentBssEnd - _makeromSegmentBssStart); _makeromSegmentCOMMONStart = .; - build/makerom/header.o(COMMON*); - build/makerom/ipl3.o(COMMON*); - build/makerom/entry.o(COMMON*); + build/us/makerom/header.o(COMMON*); + build/us/makerom/ipl3.o(COMMON*); + build/us/makerom/entry.o(COMMON*); . = ALIGN(., 0x10); _makeromSegmentCOMMONEnd = .; _makeromSegmentCOMMONSize = ABSOLUTE(_makeromSegmentCOMMONEnd - _makeromSegmentCOMMONStart); @@ -91,25 +91,25 @@ SECTIONS { FILL(0x00000000); _bootSegmentTextStart = .; - build/boot/boot_main.o(.text*); + build/us/boot/boot_main.o(.text*); . = ALIGN(., 0x10); _bootSegmentTextEnd = .; _bootSegmentTextSize = ABSOLUTE(_bootSegmentTextEnd - _bootSegmentTextStart); _bootSegmentDataStart = .; - build/boot/boot_main.o(.data*); + build/us/boot/boot_main.o(.data*); . = ALIGN(., 0x10); _bootSegmentDataEnd = .; _bootSegmentDataSize = ABSOLUTE(_bootSegmentDataEnd - _bootSegmentDataStart); _bootSegmentRoDataStart = .; - build/boot/boot_main.o(.rodata*); + build/us/boot/boot_main.o(.rodata*); . = ALIGN(., 0x10); _bootSegmentRoDataEnd = .; _bootSegmentRoDataSize = ABSOLUTE(_bootSegmentRoDataEnd - _bootSegmentRoDataStart); _bootSegmentSdataStart = .; - build/boot/boot_main.o(.sdata*); + build/us/boot/boot_main.o(.sdata*); . = ALIGN(., 0x10); _bootSegmentSdataEnd = .; _bootSegmentSdataSize = ABSOLUTE(_bootSegmentSdataEnd - _bootSegmentSdataStart); @@ -124,25 +124,25 @@ SECTIONS { FILL(0x00000000); _bootSegmentSbssStart = .; - build/boot/boot_main.o(.sbss*); + build/us/boot/boot_main.o(.sbss*); . = ALIGN(., 0x10); _bootSegmentSbssEnd = .; _bootSegmentSbssSize = ABSOLUTE(_bootSegmentSbssEnd - _bootSegmentSbssStart); _bootSegmentScommonStart = .; - build/boot/boot_main.o(.scommon*); + build/us/boot/boot_main.o(.scommon*); . = ALIGN(., 0x10); _bootSegmentScommonEnd = .; _bootSegmentScommonSize = ABSOLUTE(_bootSegmentScommonEnd - _bootSegmentScommonStart); _bootSegmentBssStart = .; - build/boot/boot_main.o(.bss*); + build/us/boot/boot_main.o(.bss*); . = ALIGN(., 0x10); _bootSegmentBssEnd = .; _bootSegmentBssSize = ABSOLUTE(_bootSegmentBssEnd - _bootSegmentBssStart); _bootSegmentCOMMONStart = .; - build/boot/boot_main.o(COMMON*); + build/us/boot/boot_main.o(COMMON*); . = ALIGN(., 0x10); _bootSegmentCOMMONEnd = .; _bootSegmentCOMMONSize = ABSOLUTE(_bootSegmentCOMMONEnd - _bootSegmentCOMMONStart); @@ -164,33 +164,33 @@ SECTIONS { FILL(0x00000000); _codeSegmentTextStart = .; - build/src/code/main.o(.text*); - build/src/code/z_game_over.o(.text*); - build/src/code/z_message_PAL.o(.text*); + build/us/src/code/main.o(.text*); + build/us/src/code/z_game_over.o(.text*); + build/us/src/code/z_message_PAL.o(.text*); . = ALIGN(., 0x10); _codeSegmentTextEnd = .; _codeSegmentTextSize = ABSOLUTE(_codeSegmentTextEnd - _codeSegmentTextStart); _codeSegmentDataStart = .; - build/src/code/main.o(.data*); + build/us/src/code/main.o(.data*); . = ALIGN(., 0x10); _codeSegmentDataEnd = .; _codeSegmentDataSize = ABSOLUTE(_codeSegmentDataEnd - _codeSegmentDataStart); _codeSegmentRoDataStart = .; - build/src/code/main.o(.rodata*); - build/src/code/z_game_over.o(.data*); - build/src/code/z_game_over.o(.rodata*); - build/src/code/z_message_PAL.o(.data*); - build/src/code/z_message_PAL.o(.rodata*); + build/us/src/code/main.o(.rodata*); + build/us/src/code/z_game_over.o(.data*); + build/us/src/code/z_game_over.o(.rodata*); + build/us/src/code/z_message_PAL.o(.data*); + build/us/src/code/z_message_PAL.o(.rodata*); . = ALIGN(., 0x10); _codeSegmentRoDataEnd = .; _codeSegmentRoDataSize = ABSOLUTE(_codeSegmentRoDataEnd - _codeSegmentRoDataStart); _codeSegmentSdataStart = .; - build/src/code/main.o(.sdata*); - build/src/code/z_game_over.o(.sdata*); - build/src/code/z_message_PAL.o(.sdata*); + build/us/src/code/main.o(.sdata*); + build/us/src/code/z_game_over.o(.sdata*); + build/us/src/code/z_message_PAL.o(.sdata*); . = ALIGN(., 0x10); _codeSegmentSdataEnd = .; _codeSegmentSdataSize = ABSOLUTE(_codeSegmentSdataEnd - _codeSegmentSdataStart); @@ -205,33 +205,33 @@ SECTIONS { FILL(0x00000000); _codeSegmentSbssStart = .; - build/src/code/main.o(.sbss*); - build/src/code/z_game_over.o(.sbss*); - build/src/code/z_message_PAL.o(.sbss*); + build/us/src/code/main.o(.sbss*); + build/us/src/code/z_game_over.o(.sbss*); + build/us/src/code/z_message_PAL.o(.sbss*); . = ALIGN(., 0x10); _codeSegmentSbssEnd = .; _codeSegmentSbssSize = ABSOLUTE(_codeSegmentSbssEnd - _codeSegmentSbssStart); _codeSegmentScommonStart = .; - build/src/code/main.o(.scommon*); - build/src/code/z_game_over.o(.scommon*); - build/src/code/z_message_PAL.o(.scommon*); + build/us/src/code/main.o(.scommon*); + build/us/src/code/z_game_over.o(.scommon*); + build/us/src/code/z_message_PAL.o(.scommon*); . = ALIGN(., 0x10); _codeSegmentScommonEnd = .; _codeSegmentScommonSize = ABSOLUTE(_codeSegmentScommonEnd - _codeSegmentScommonStart); _codeSegmentBssStart = .; - build/src/code/main.o(.bss*); - build/src/code/z_game_over.o(.bss*); - build/src/code/z_message_PAL.o(.bss*); + build/us/src/code/main.o(.bss*); + build/us/src/code/z_game_over.o(.bss*); + build/us/src/code/z_message_PAL.o(.bss*); . = ALIGN(., 0x10); _codeSegmentBssEnd = .; _codeSegmentBssSize = ABSOLUTE(_codeSegmentBssEnd - _codeSegmentBssStart); _codeSegmentCOMMONStart = .; - build/src/code/main.o(COMMON*); - build/src/code/z_game_over.o(COMMON*); - build/src/code/z_message_PAL.o(COMMON*); + build/us/src/code/main.o(COMMON*); + build/us/src/code/z_game_over.o(COMMON*); + build/us/src/code/z_message_PAL.o(COMMON*); . = ALIGN(., 0x10); _codeSegmentCOMMONEnd = .; _codeSegmentCOMMONSize = ABSOLUTE(_codeSegmentCOMMONEnd - _codeSegmentCOMMONStart); @@ -255,25 +255,25 @@ SECTIONS { FILL(0x00000000); _gameplay_keepSegmentTextStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.text*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.text*); . = ALIGN(., 0x10); _gameplay_keepSegmentTextEnd = .; _gameplay_keepSegmentTextSize = ABSOLUTE(_gameplay_keepSegmentTextEnd - _gameplay_keepSegmentTextStart); _gameplay_keepSegmentDataStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.data*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.data*); . = ALIGN(., 0x10); _gameplay_keepSegmentDataEnd = .; _gameplay_keepSegmentDataSize = ABSOLUTE(_gameplay_keepSegmentDataEnd - _gameplay_keepSegmentDataStart); _gameplay_keepSegmentRoDataStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.rodata*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.rodata*); . = ALIGN(., 0x10); _gameplay_keepSegmentRoDataEnd = .; _gameplay_keepSegmentRoDataSize = ABSOLUTE(_gameplay_keepSegmentRoDataEnd - _gameplay_keepSegmentRoDataStart); _gameplay_keepSegmentSdataStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.sdata*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.sdata*); . = ALIGN(., 0x10); _gameplay_keepSegmentSdataEnd = .; _gameplay_keepSegmentSdataSize = ABSOLUTE(_gameplay_keepSegmentSdataEnd - _gameplay_keepSegmentSdataStart); @@ -288,25 +288,25 @@ SECTIONS { FILL(0x00000000); _gameplay_keepSegmentSbssStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.sbss*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.sbss*); . = ALIGN(., 0x10); _gameplay_keepSegmentSbssEnd = .; _gameplay_keepSegmentSbssSize = ABSOLUTE(_gameplay_keepSegmentSbssEnd - _gameplay_keepSegmentSbssStart); _gameplay_keepSegmentScommonStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.scommon*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.scommon*); . = ALIGN(., 0x10); _gameplay_keepSegmentScommonEnd = .; _gameplay_keepSegmentScommonSize = ABSOLUTE(_gameplay_keepSegmentScommonEnd - _gameplay_keepSegmentScommonStart); _gameplay_keepSegmentBssStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(.bss*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(.bss*); . = ALIGN(., 0x10); _gameplay_keepSegmentBssEnd = .; _gameplay_keepSegmentBssSize = ABSOLUTE(_gameplay_keepSegmentBssEnd - _gameplay_keepSegmentBssStart); _gameplay_keepSegmentCOMMONStart = .; - build/assets/objects/gameplay_keep/gameplay_keep.o(COMMON*); + build/us/assets/objects/gameplay_keep/gameplay_keep.o(COMMON*); . = ALIGN(., 0x10); _gameplay_keepSegmentCOMMONEnd = .; _gameplay_keepSegmentCOMMONSize = ABSOLUTE(_gameplay_keepSegmentCOMMONEnd - _gameplay_keepSegmentCOMMONStart); @@ -330,25 +330,25 @@ SECTIONS { FILL(0x00000000); _gameplay_dangeon_keepSegmentTextStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.text*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.text*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentTextEnd = .; _gameplay_dangeon_keepSegmentTextSize = ABSOLUTE(_gameplay_dangeon_keepSegmentTextEnd - _gameplay_dangeon_keepSegmentTextStart); _gameplay_dangeon_keepSegmentDataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.data*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.data*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentDataEnd = .; _gameplay_dangeon_keepSegmentDataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentDataEnd - _gameplay_dangeon_keepSegmentDataStart); _gameplay_dangeon_keepSegmentRoDataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.rodata*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.rodata*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentRoDataEnd = .; _gameplay_dangeon_keepSegmentRoDataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentRoDataEnd - _gameplay_dangeon_keepSegmentRoDataStart); _gameplay_dangeon_keepSegmentSdataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sdata*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sdata*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentSdataEnd = .; _gameplay_dangeon_keepSegmentSdataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentSdataEnd - _gameplay_dangeon_keepSegmentSdataStart); @@ -363,25 +363,25 @@ SECTIONS { FILL(0x00000000); _gameplay_dangeon_keepSegmentSbssStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sbss*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sbss*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentSbssEnd = .; _gameplay_dangeon_keepSegmentSbssSize = ABSOLUTE(_gameplay_dangeon_keepSegmentSbssEnd - _gameplay_dangeon_keepSegmentSbssStart); _gameplay_dangeon_keepSegmentScommonStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.scommon*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.scommon*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentScommonEnd = .; _gameplay_dangeon_keepSegmentScommonSize = ABSOLUTE(_gameplay_dangeon_keepSegmentScommonEnd - _gameplay_dangeon_keepSegmentScommonStart); _gameplay_dangeon_keepSegmentBssStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.bss*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.bss*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentBssEnd = .; _gameplay_dangeon_keepSegmentBssSize = ABSOLUTE(_gameplay_dangeon_keepSegmentBssEnd - _gameplay_dangeon_keepSegmentBssStart); _gameplay_dangeon_keepSegmentCOMMONStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(COMMON*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(COMMON*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentCOMMONEnd = .; _gameplay_dangeon_keepSegmentCOMMONSize = ABSOLUTE(_gameplay_dangeon_keepSegmentCOMMONEnd - _gameplay_dangeon_keepSegmentCOMMONStart); @@ -405,25 +405,25 @@ SECTIONS { FILL(0x00000000); _gameplay_dangeon_keepSegmentTextStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.text*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.text*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentTextEnd = .; _gameplay_dangeon_keepSegmentTextSize = ABSOLUTE(_gameplay_dangeon_keepSegmentTextEnd - _gameplay_dangeon_keepSegmentTextStart); _gameplay_dangeon_keepSegmentDataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.data*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.data*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentDataEnd = .; _gameplay_dangeon_keepSegmentDataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentDataEnd - _gameplay_dangeon_keepSegmentDataStart); _gameplay_dangeon_keepSegmentRoDataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.rodata*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.rodata*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentRoDataEnd = .; _gameplay_dangeon_keepSegmentRoDataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentRoDataEnd - _gameplay_dangeon_keepSegmentRoDataStart); _gameplay_dangeon_keepSegmentSdataStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sdata*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sdata*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentSdataEnd = .; _gameplay_dangeon_keepSegmentSdataSize = ABSOLUTE(_gameplay_dangeon_keepSegmentSdataEnd - _gameplay_dangeon_keepSegmentSdataStart); @@ -438,25 +438,25 @@ SECTIONS { FILL(0x00000000); _gameplay_dangeon_keepSegmentSbssStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sbss*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.sbss*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentSbssEnd = .; _gameplay_dangeon_keepSegmentSbssSize = ABSOLUTE(_gameplay_dangeon_keepSegmentSbssEnd - _gameplay_dangeon_keepSegmentSbssStart); _gameplay_dangeon_keepSegmentScommonStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.scommon*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.scommon*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentScommonEnd = .; _gameplay_dangeon_keepSegmentScommonSize = ABSOLUTE(_gameplay_dangeon_keepSegmentScommonEnd - _gameplay_dangeon_keepSegmentScommonStart); _gameplay_dangeon_keepSegmentBssStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.bss*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(.bss*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentBssEnd = .; _gameplay_dangeon_keepSegmentBssSize = ABSOLUTE(_gameplay_dangeon_keepSegmentBssEnd - _gameplay_dangeon_keepSegmentBssStart); _gameplay_dangeon_keepSegmentCOMMONStart = .; - build/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(COMMON*); + build/us/assets/objects/gameplay_dangeon_keep/gameplay_dangeon_keep.o(COMMON*); . = ALIGN(., 0x10); _gameplay_dangeon_keepSegmentCOMMONEnd = .; _gameplay_dangeon_keepSegmentCOMMONSize = ABSOLUTE(_gameplay_dangeon_keepSegmentCOMMONEnd - _gameplay_dangeon_keepSegmentCOMMONStart); diff --git a/tests/test_cases/makerom_zelda_like.yaml b/tests/test_cases/makerom_zelda_like.yaml index 7e73296..94e837f 100644 --- a/tests/test_cases/makerom_zelda_like.yaml +++ b/tests/test_cases/makerom_zelda_like.yaml @@ -1,5 +1,5 @@ settings: - base_path: build + base_path: build/{version} subalign: null linker_symbols_style: makerom