Skip to content

Commit

Permalink
Implement file grouping
Browse files Browse the repository at this point in the history
Fixes #34
  • Loading branch information
AngheloAlf committed Mar 2, 2024
1 parent dac24e8 commit 2eca6c4
Show file tree
Hide file tree
Showing 8 changed files with 2,192 additions and 28 deletions.
71 changes: 70 additions & 1 deletion docs/file_format/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Path to the file.

The `base_path` from settings is used as a base for the emitted path.

This field is not compatible with the [`kind`](#kind) `pad`.
This field is only compatible with the [`kind`](#kind)s `object` and `archive`.

### Example

Expand Down Expand Up @@ -57,6 +57,9 @@ segments:
- `linker_offset`: Emit a symbol between the files at a given
[`section`](#section). Both [`section`](#section) and
[`linker_offset_name`](#linker_offset_name) are required.
- `group`: Allows grouping multiple files for better organization. A group may
also have a [`dir`](#dir) field that prefixes the path of all the files from
this group. The [`files`](#files) field is required.

### Default value

Expand Down Expand Up @@ -169,3 +172,69 @@ build/src/code/collisions.o(.rodata*);
### Valid values

A dictionary (map) of non empty string as keys and values.

## `files`

Can only be used with the `group` [`kind`](#kind).

Allows to specify a list of files.

### Example

```yaml
settings:
base_path: build
segments:
- name: boot
files:
- { path: src/boot/boot_main.o }
- { path: src/boot/util.o }
- kind: group
files:
- { path: src/libkmc/fmod.o }
- { path: src/libkmc/memmove.o }
- { path: src/libkmc/memset.o }
- { path: src/libkmc/modf.o }
- { path: src/gzip/unzip.o }
```

## `dir`

Can only be used with the `group` [`kind`](#kind).

Specifies a directory that will be used as a prefix for the files listed by this
entry.

### Example

```yaml
settings:
base_path: build
segments:
- name: boot
files:
- { path: src/boot/boot_main.o }
- { path: src/boot/util.o }
- kind: group
dir: src/libultra
files:
- { path: io/conteepprobe.o }
- { path: io/conteeplongwrite.o }
- { path: io/conteeplongread.o }
- kind: group
dir: src/libmus
files:
- { path: player.o }
- { path: player_fx.o }
- { path: aud_dma.o }
- { path: aud_sched.o }
- { path: aud_thread.o }
- { path: lib_memory.o }
- { path: aud_samples.o }
```
62 changes: 54 additions & 8 deletions slinky/src/file_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ pub struct FileInfo {
pub linker_offset_name: String,

pub section_order: HashMap<String, String>,

// Used for groups
pub files: Vec<FileInfo>,
pub dir: PathBuf,
}

#[derive(Deserialize, PartialEq, Debug)]
Expand All @@ -48,6 +52,11 @@ pub(crate) struct FileInfoSerial {

#[serde(default)]
pub section_order: AbsentNullable<HashMap<String, String>>,

#[serde(default)]
pub files: AbsentNullable<Vec<FileInfoSerial>>,
#[serde(default)]
pub dir: AbsentNullable<PathBuf>,
}

impl FileInfoSerial {
Expand All @@ -66,11 +75,11 @@ impl FileInfoSerial {

(p, k)
}
FileKind::Pad | FileKind::LinkerOffset => {
// pad doesn't allow for paths
FileKind::Pad | FileKind::LinkerOffset | FileKind::Group => {
// doesn't allow paths
if self.path.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "kind: pad or kind: linker_offset".into(),
field1: "`kind: pad`, `kind: linker_offset` or `kind: group`".into(),
field2: "path".into(),
});
}
Expand All @@ -93,7 +102,7 @@ impl FileInfoSerial {
};

let subfile = match kind {
FileKind::Object | FileKind::LinkerOffset | FileKind::Pad => {
FileKind::Object | FileKind::LinkerOffset | FileKind::Pad | FileKind::Group => {
if self.subfile.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "subfile".into(),
Expand All @@ -106,7 +115,7 @@ impl FileInfoSerial {
};

let pad_amount = match kind {
FileKind::Object | FileKind::LinkerOffset | FileKind::Archive => {
FileKind::Object | FileKind::LinkerOffset | FileKind::Archive | FileKind::Group => {
if self.pad_amount.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "pad_amount".into(),
Expand All @@ -119,7 +128,7 @@ impl FileInfoSerial {
};

let section = match kind {
FileKind::Object | FileKind::Archive => {
FileKind::Object | FileKind::Archive | FileKind::Group => {
if self.section.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "section".into(),
Expand All @@ -132,7 +141,7 @@ impl FileInfoSerial {
};

let linker_offset_name = match kind {
FileKind::Object | FileKind::Pad | FileKind::Archive => {
FileKind::Object | FileKind::Pad | FileKind::Archive | FileKind::Group => {
if self.linker_offset_name.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "linker_offset_name".into(),
Expand All @@ -145,7 +154,7 @@ impl FileInfoSerial {
};

let section_order = match kind {
FileKind::Pad | FileKind::LinkerOffset => {
FileKind::Pad | FileKind::LinkerOffset | FileKind::Group => {
if self.section_order.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "section_order".into(),
Expand All @@ -159,6 +168,41 @@ impl FileInfoSerial {
.get_non_null("section_order", HashMap::default)?,
};

let files = match kind {
FileKind::Object | FileKind::Archive | FileKind::Pad | FileKind::LinkerOffset => {
if self.files.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "files".into(),
field2: "non `kind: group`".into(),
});
}
Vec::default()
}
FileKind::Group => {
let temp_vec = self.files.get("files")?;
let mut result_vec = Vec::with_capacity(temp_vec.len());

for temp in temp_vec {
result_vec.push(temp.unserialize(_settings)?);
}

result_vec
}
};

let dir = match kind {
FileKind::Object | FileKind::Archive | FileKind::Pad | FileKind::LinkerOffset => {
if self.dir.has_value() {
return Err(SlinkyError::InvalidFieldCombo {
field1: "dir".into(),
field2: "non `kind: group`".into(),
});
}
PathBuf::default()
}
FileKind::Group => self.dir.get_non_null("dir", PathBuf::default)?,
};

Ok(FileInfo {
path,
kind,
Expand All @@ -167,6 +211,8 @@ impl FileInfoSerial {
section,
linker_offset_name,
section_order,
files,
dir,
})
}
}
1 change: 1 addition & 0 deletions slinky/src/file_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum FileKind {
Archive,
Pad,
LinkerOffset,
Group,
}

impl FileKind {
Expand Down
25 changes: 18 additions & 7 deletions slinky/src/linker_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -295,21 +295,23 @@ impl LinkerWriter<'_> {
self.write_sym_end_size(seg_sym_start, seg_sym_end, seg_sym_size, ".");
}

fn emit_file(&mut self, file: &FileInfo, segment: &Segment, section: &str) {
fn emit_file(&mut self, file: &FileInfo, segment: &Segment, section: &str, base_path: &Path) {
let style = &self.settings.linker_symbols_style;

let mut path = self.settings.base_path.clone();

path.extend(&file.path);

let wildcard = if segment.wildcard_sections { "*" } else { "" };

// TODO: figure out glob support
match file.kind {
FileKind::Object => {
let mut path = base_path.to_path_buf();
path.extend(&file.path);

self.writeln(&format!("{}({}{});", path.display(), section, wildcard));
}
FileKind::Archive => {
let mut path = base_path.to_path_buf();
path.extend(&file.path);

self.writeln(&format!(
"{}:{}({}{});",
path.display(),
Expand All @@ -328,6 +330,15 @@ impl LinkerWriter<'_> {
self.write_symbol(&style.linker_offset(&file.linker_offset_name), ".");
}
}
FileKind::Group => {
let mut new_base_path = base_path.to_path_buf();

new_base_path.extend(&file.dir);

for file_of_group in &file.files {
self.emit_file(file_of_group, segment, section, &new_base_path);
}
}
}
}

Expand All @@ -345,12 +356,12 @@ impl LinkerWriter<'_> {
// Check if any other section should be placed be placed here
for (k, v) in &file.section_order {
if v == section {
self.emit_file(file, segment, k);
self.emit_file(file, segment, k, &self.settings.base_path);
}
}
}

self.emit_file(file, segment, section);
self.emit_file(file, segment, section, &self.settings.base_path);
}
}

Expand Down
4 changes: 0 additions & 4 deletions tests/input_files/drmario64.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ settings:
# misc
- .note
- .comment
sections_allowlist_extra:
- .shstrtab
- .strtab
- .symtab
sections_denylist:
- .reginfo
- .MIPS.abiflags
Expand Down
Loading

0 comments on commit 2eca6c4

Please sign in to comment.