diff --git a/docs/file_format/custom_options.md b/docs/file_format/custom_options.md index 7e28bde..e0efe7c 100644 --- a/docs/file_format/custom_options.md +++ b/docs/file_format/custom_options.md @@ -15,6 +15,7 @@ handled by the C preprocessor or in Rust with its features. - [Usage](#usage) - [Path replacement](#path-replacement) - [Example](#example) + - [Conditional inclusion and exclusion of file entries](#conditional-inclusion-and-exclusion-of-file-entries) ## How does this work? @@ -121,3 +122,14 @@ combinations: - `build/eu1.1/src/boot/boot_main_pal.o` - `build/eu1.1/src/boot/dmadata.o` - `build/eu1.1/src/boot/util.o` + +### Conditional inclusion and exclusion of file entries + +Custom options can be used to conditionally include or conditionally exclude +certain files. + +Check the [`include_if_any`](file.md#include_if_any), +[`include_if_all`](file.md#include_if_all), +[`exclude_if_any`](file.md#exclude_if_any) and +[`exclude_if_all`](file.md#exclude_if_all) fields of [`file.md`](file.md) for +more information. diff --git a/docs/file_format/file.md b/docs/file_format/file.md index 6a3ae45..23c2173 100644 --- a/docs/file_format/file.md +++ b/docs/file_format/file.md @@ -34,6 +34,18 @@ Every attribute listed is optional unless explicitly stated. - [Example](#example-5) - [`dir`](#dir) - [Example](#example-6) + - [`include_if_any`](#include_if_any) + - [Example](#example-7) + - [Valid values](#valid-values-7) + - [`include_if_all`](#include_if_all) + - [Example](#example-8) + - [Valid values](#valid-values-8) + - [`exclude_if_any`](#exclude_if_any) + - [Example](#example-9) + - [Valid values](#valid-values-9) + - [`exclude_if_all`](#exclude_if_all) + - [Example](#example-10) + - [Valid values](#valid-values-10) ## `path` @@ -268,3 +280,151 @@ segments: - { path: lib_memory.o } - { path: aud_samples.o } ``` + +## `include_if_any` + +Allows to conditionally include this entry depending on the current [custom +options](custom_options.md). + +Expects a list of key-value tuples. This entry will be emitted into the +generated files only if at least one of the given tuples matches the current +custom options. If none of the elements of this list matches any custom option +then this whole entry will be omitted. + +This conditional behavior is only applied if this field is present and not empty. + +### Example + +```yaml +settings: + base_path: build + +segments: + - name: boot + files: + - { path: src/boot/boot_main.o } + - { path: src/boot/util.o } + + # This entry will be emitted only if `version` is `jpn1.0` + - { path: src/boot/expansion_required.o, include_if_any: [[version, jpn1.0]] } + + # This entry will be emitted only if `version` is either `pal1.0`, `pal1.1` or `pal1.2` + - { path: src/boot/language_selector.o, include_if_any: [[version, pal1.0], [version, pal1.1], [version, pal1.2]] } + + # This whole group will be emitted only if `compiler` is `kmc` + - kind: group + dir: lib/libkmc + include_if_any: [[compiler, kmc]] + files: + - { path: memmove.o } + - { path: memset.o } + - { path: strcpy.o } + - { path: mmuldi3.o } + + # This whole group will be emitted only if `compiler` is `modern_gcc` + - kind: group + dir: lib + include_if_any: [[compiler, modern_gcc]] + files: + - { path: libgcc.a } +``` + +### Valid values + +A list of two-tuples of strings. + +## `include_if_all` + +Allows to conditionally include this entry depending on the current [custom +options](custom_options.md). + +Expects a list of key-value tuples. This entry will be emitted into the +generated files only if all the given tuples matches the current custom options. +If at least one of the elements of this list does not matches any custom option +then this whole entry will be omitted. + +This conditional behavior is only applied if this field is present and not empty. + +### Example + +```yaml +settings: + base_path: build + +segments: + - name: boot + files: + - { path: src/boot/boot_main.o } + - { path: src/boot/util.o } + + # This entry will be emitted only if `compiler` is `modern_gcc` and `modding` is `true` + - { path: src/boot/is_viewer.o, include_if_all: [[compiler, modern_gcc], [modding, true]] } +``` + +### Valid values + +A list of two-tuples of strings. + +## `exclude_if_any` + +Allows to conditionally exclude this entry depending on the current [custom +options](custom_options.md). + +Expects a list of key-value tuples. This entry won't be emitted into the +generated files only if at least one of the given tuples matches the current +custom options. If none of the elements of this list matches any custom option +then this entry will be normally emitted. + +This conditional behavior is only applied if this field is present and not empty. + +### Example + +```yaml +settings: + base_path: build + +segments: + - name: boot + files: + - { path: src/boot/boot_main.o } + - { path: src/boot/util.o } + + # This entry will be emitted only if `compiler` is not `modern_gcc` and `compiler` is not `kmc` + - { path: src/libultra/libc/ll.o, exclude_if_any: [[compiler, modern_gcc], [compiler, kmc]] } +``` + +### Valid values + +A list of two-tuples of strings. + +## `exclude_if_all` + +Allows to conditionally exclude this entry depending on the current [custom +options](custom_options.md). + +Expects a list of key-value tuples. This entry will not be emitted into the +generated files only if all the given tuples matches the current custom options. +If at least one of the elements of this list does match any custom option then +this whole entry will be normally emitted. + +This conditional behavior is only applied if this field is present and not empty. + +### Example + +```yaml +settings: + base_path: build + +segments: + - name: boot + files: + - { path: src/boot/boot_main.o } + - { path: src/boot/util.o } + + # This entry won't be emitted only if `compiler` is `modern_gcc` and `modding` is `true` + - { path: src/boot/is_viewer.o, exclude_if_all: [[compiler, modern_gcc], [modding, true]] } +``` + +### Valid values + +A list of two-tuples of strings. diff --git a/slinky/tests/integration_test.rs b/slinky/tests/integration_test.rs index 26b1546..e32acc3 100644 --- a/slinky/tests/integration_test.rs +++ b/slinky/tests/integration_test.rs @@ -12,6 +12,9 @@ fn set_custom_options(document: &mut Document) { document .custom_options .insert("version".into(), "us".into()); + document + .custom_options + .insert("compiler".into(), "modern_gcc".into()); } fn check_ld_generation(yaml_path: &Path, ld_path: &Path) -> Result<(), SlinkyError> { diff --git a/tests/regen_tests.sh b/tests/regen_tests.sh index 27e6bfb..6884584 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 --custom-options version=us + cargo run --release -- $filepath -o $output --custom-options version=us -c compiler=modern_gcc 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 -c version=us + cargo run --release -- $filepath -o $output --partial-linking -c version=us -c compiler=modern_gcc done diff --git a/tests/test_cases/conditional_includes.ld b/tests/test_cases/conditional_includes.ld index 6016c05..2b001a5 100644 --- a/tests/test_cases/conditional_includes.ld +++ b/tests/test_cases/conditional_includes.ld @@ -26,6 +26,7 @@ SECTIONS build/us/src/boot/file24.o(.text*); build/us/src/boot/file28.o(.text*); build/us/src/boot/file29.o(.text*); + build/us/lib/libgcc.a:*(.text*); . = ALIGN(., 0x10); boot_TEXT_END = .; boot_TEXT_SIZE = ABSOLUTE(boot_TEXT_END - boot_TEXT_START); @@ -47,6 +48,7 @@ SECTIONS build/us/src/boot/file24.o(.data*); build/us/src/boot/file28.o(.data*); build/us/src/boot/file29.o(.data*); + build/us/lib/libgcc.a:*(.data*); . = ALIGN(., 0x10); boot_DATA_END = .; boot_DATA_SIZE = ABSOLUTE(boot_DATA_END - boot_DATA_START); @@ -68,6 +70,7 @@ SECTIONS build/us/src/boot/file24.o(.rodata*); build/us/src/boot/file28.o(.rodata*); build/us/src/boot/file29.o(.rodata*); + build/us/lib/libgcc.a:*(.rodata*); . = ALIGN(., 0x10); boot_RODATA_END = .; boot_RODATA_SIZE = ABSOLUTE(boot_RODATA_END - boot_RODATA_START); @@ -89,6 +92,7 @@ SECTIONS build/us/src/boot/file24.o(.sdata*); build/us/src/boot/file28.o(.sdata*); build/us/src/boot/file29.o(.sdata*); + build/us/lib/libgcc.a:*(.sdata*); . = ALIGN(., 0x10); boot_SDATA_END = .; boot_SDATA_SIZE = ABSOLUTE(boot_SDATA_END - boot_SDATA_START); @@ -119,6 +123,7 @@ SECTIONS build/us/src/boot/file24.o(.sbss*); build/us/src/boot/file28.o(.sbss*); build/us/src/boot/file29.o(.sbss*); + build/us/lib/libgcc.a:*(.sbss*); . = ALIGN(., 0x10); boot_SBSS_END = .; boot_SBSS_SIZE = ABSOLUTE(boot_SBSS_END - boot_SBSS_START); @@ -140,6 +145,7 @@ SECTIONS build/us/src/boot/file24.o(.scommon*); build/us/src/boot/file28.o(.scommon*); build/us/src/boot/file29.o(.scommon*); + build/us/lib/libgcc.a:*(.scommon*); . = ALIGN(., 0x10); boot_SCOMMON_END = .; boot_SCOMMON_SIZE = ABSOLUTE(boot_SCOMMON_END - boot_SCOMMON_START); @@ -161,6 +167,7 @@ SECTIONS build/us/src/boot/file24.o(.bss*); build/us/src/boot/file28.o(.bss*); build/us/src/boot/file29.o(.bss*); + build/us/lib/libgcc.a:*(.bss*); . = ALIGN(., 0x10); boot_BSS_END = .; boot_BSS_SIZE = ABSOLUTE(boot_BSS_END - boot_BSS_START); @@ -182,6 +189,7 @@ SECTIONS build/us/src/boot/file24.o(COMMON*); build/us/src/boot/file28.o(COMMON*); build/us/src/boot/file29.o(COMMON*); + build/us/lib/libgcc.a:*(COMMON*); . = ALIGN(., 0x10); bootCOMMON_END = .; bootCOMMON_SIZE = ABSOLUTE(bootCOMMON_END - bootCOMMON_START); diff --git a/tests/test_cases/conditional_includes.yaml b/tests/test_cases/conditional_includes.yaml index 53a1801..e9a4540 100644 --- a/tests/test_cases/conditional_includes.yaml +++ b/tests/test_cases/conditional_includes.yaml @@ -35,3 +35,19 @@ segments: - { path: src/boot/file27.o, include_if_any: [[version, jp], [modding, true]], exclude_if_any: [[version, us]] } - { path: src/boot/file28.o, include_if_any: [[version, us], [modding, true]], exclude_if_any: [[version, jp]] } - { path: src/boot/file29.o, include_if_any: [[version, jp], [modding, true]], include_if_all: [[version, us]], exclude_if_any: [[version, jp]] } + + - kind: group + dir: lib/libkmc + include_if_any: [[compiler, kmc]] + files: + - { path: memmove.o } + - { path: memset.o } + - { path: strcpy.o } + - { path: mmuldi3.o } + + - kind: group + dir: lib + include_if_any: [[compiler, modern_gcc]] + files: + - { path: libgcc.a } +