diff --git a/Makefile b/Makefile index 79b08c1aa1..750267fcb2 100644 --- a/Makefile +++ b/Makefile @@ -26,9 +26,7 @@ SUBPROJ_DIR := subprojects MESON_VER := 1.10.0 MESON_DIR := $(SUBPROJ_DIR)/meson-$(MESON_VER) -MESON_SUB := $(MESON_DIR)/meson.py - -MESON ?= $(MESON_SUB) +MESON := $(MESON_DIR)/meson.py NINJA ?= ninja GIT ?= git @@ -130,12 +128,8 @@ distclean: purge: distclean rm -rf $(SKREW_DIR) -ifeq ($(MESON),$(MESON_SUB)) ! test -f $(MESON) || $(MESON) subprojects purge --confirm rm -rf $(MESON_DIR) -else - $(MESON) subprojects purge --confirm -endif update: meson skrewup $(MESON) subprojects update || true @@ -165,13 +159,12 @@ $(ROOT_INI): | $(BUILD) $(BUILD): mkdir -p -- $(BUILD) -meson: ; -ifeq ($(MESON),$(MESON_SUB)) -meson: $(MESON_SUB) -endif +meson: $(MESON) -$(MESON_SUB): +$(MESON): $(GIT) clone --depth=1 -b $(MESON_VER) https://github.com/mesonbuild/meson $(@D) + cd $(MESON_DIR) ; find ../packagefiles/meson_patch -name '*.patch' -exec $(GIT) apply {} \; + cd $(MESON_DIR) ; $(GIT) add . skrew: $(SKREW_EXE) diff --git a/docs/meson/patching.md b/docs/meson/patching.md new file mode 100644 index 0000000000..ff94e2500e --- /dev/null +++ b/docs/meson/patching.md @@ -0,0 +1,78 @@ +# Patching Meson + +We make use of a locally-cloned installation of Meson rather than asking a user +to install it themselves via a package manager. This enables us to patch Meson +for features that are slated for an upcoming release or to customize +functionality that we otherwise find desirable. + +## Rules for Patching + +1. Patches for features must be applied from a commit from the upstream Meson + repository: . The content of the patch + may be stripped down to remove changes to documentation, automated tests, etc. +2. When filing a PR to introduce your patch, provide a link to the commit or PR + in Meson's upstream repository for tracking. +3. Patches which add new features *must* have a forward-path for merging into + the main Meson release. This ensures that we do not bloat the set of patches + that we apply. +4. Patches for bug-fixes or small changes to functionality suitable for our + use-cases do not necessarily need links to upstream commits or PRs. Such + changes should be small in scope. This is a bit on the gray side and subject + to discretion from the maintainers, but it allows us to make changes to Meson + that fit our use-case but may not align with Meson's own goals. + +## Fetching a Patch + +If you already have a PR filed to the upstream Meson repository, then you may +use `tools/scripts/fetch_meson_diff.sh` to pull the content of that PR into a +local patch. The script requires a single argument, which is the GitHub PR +number. + +As an example, the following command would create +`subprojects/packagefiles/meson_patch/15402.patch`: + +```bash +./tools/scripts/fetch_meson_diff.sh 15402 +``` + +Before submitting any patches created using this script for review, you must +give the output file a meaningful name (that is, not just its PR ID). You may +also want to consider doctoring your patch, if it requires changes that are +present in the `master` branch of the Meson repository but not in our base +revision. + +## Writing a Patch + +Apply your changes to a clean, un-patched copy of the Meson installation. + +1. Modify the `Makefile`: + +```diff +$(MESON): +$(GIT) clone --depth=1 -b $(MESON_VER) https://github.com/mesonbuild/meson $(@D) +- cd $(MESON_DIR) ; find ../packagefiles/meson_patch -name '*.patch' -exec $(GIT) apply {} \; +``` + +2. Remove your current installation: + +```bash +rm -rf subprojects/meson-* +``` + +3. Run `make meson` to re-clone a fresh copy of the current base version. +4. Make your changes to the checkout and verify that they work as expected with + a small toy-example. You likely won't be able to do this with the + `pokeplatinum` build itself. +5. Stage the relevant changes with `git add`, then output them to a patch: + +```bash +git diff HEAD > ../packagefiles/meson_patch/name-of-your-patch.patch +``` + +## Additional Considerations + +1. Generally, prefix feature-patches with `feat-` and fix-patches with `fix-`. + This helps us delineate the purpose of each patch at-a-glance. +2. Provide a comment as the first line of your patch-file which links to the + upstream Meson PR, if any exists. The patch-fetching script will do this for + you automatically. diff --git a/res/battle/meson.build b/res/battle/meson.build index 626ddecd6c..c5cfad0dae 100644 --- a/res/battle/meson.build +++ b/res/battle/meson.build @@ -2,34 +2,5 @@ # to the index for the battle particles NARC. subdir('particles') -# This generator is shared by both move-specific animations (in the `moves` -# directory) and common animations (in the `scripts/common_anims` directory). -battle_anim_script_bin_gen = generator(make_script_bin_sh, - arguments: [ - '-i', relative_source_root / 'include', - '-i', relative_source_root / 'asm', - '-i', '.' / 'res' / 'text', - '-i', '.' / 'res', - '-i', '.', - '--depfile', - '--assembler', arm_none_eabi_gcc_exe.full_path(), - '--objcopy', arm_none_eabi_objcopy_exe.full_path(), - '@EXTRA_ARGS@', - '@INPUT@', - ], - depends: [ - text_banks, - c_consts_generators, - h_headers, - battle_particles_narc[1], - anim_ncer_narc_files[1], - anim_nanr_narc_files[1], - anim_ncgr_narc_files[1], - anim_nclr_narc_files[1], - ], - output: '@BASENAME@', - depfile: '@BASENAME@.d', -) - subdir('moves') subdir('scripts') diff --git a/res/battle/moves/meson.build b/res/battle/moves/meson.build index 61294b83c5..31772e315b 100644 --- a/res/battle/moves/meson.build +++ b/res/battle/moves/meson.build @@ -97,10 +97,17 @@ anim_scripts_narc = custom_target(anim_scripts_narc_name, output: [ anim_scripts_narc_name, ], - input: battle_anim_script_bin_gen.process( + input: script_bin_gen.process( anim_script_srcs, extra_args: ['--out-dir', anim_scripts_private_dir, '--parent-dir'], preserve_path_from: anim_scripts_root, + depends: [ + battle_particles_narc, + anim_ncer_narc_files, + anim_nanr_narc_files, + anim_ncgr_narc_files, + anim_nclr_narc_files, + ], ), command: [ nitroarc_exe, diff --git a/res/battle/scripts/common_anims/meson.build b/res/battle/scripts/common_anims/meson.build index b6dbf30d3d..ff40499278 100644 --- a/res/battle/scripts/common_anims/meson.build +++ b/res/battle/scripts/common_anims/meson.build @@ -65,9 +65,16 @@ anim_subscripts_narc = custom_target(anim_subscripts_narc_name, anim_subscripts_narc_name, anim_subscripts_naix_name, ], - input: battle_anim_script_bin_gen.process( + input: script_bin_gen.process( anim_subscript_files, - extra_args: [ '--out-dir', anim_subscripts_private_dir, ] + extra_args: [ '--out-dir', anim_subscripts_private_dir ], + depends: [ + battle_particles_narc, + anim_ncer_narc_files, + anim_nanr_narc_files, + anim_ncgr_narc_files, + anim_nclr_narc_files, + ], ), command: [ nitroarc_exe, diff --git a/res/field/frontier_scripts/meson.build b/res/field/frontier_scripts/meson.build index 8be78e7b59..5844d887eb 100644 --- a/res/field/frontier_scripts/meson.build +++ b/res/field/frontier_scripts/meson.build @@ -1,32 +1,4 @@ relative_build_dir = fs.relative_to(meson.current_build_dir(), meson.project_build_root()) -# -# NOTE: This is a functional copy of script_bin_gen, which is separated from the -# base generator due to an additional dependency on headers generated for -# events IDs. Meson unfortunately does not have a clean way to copy an existing -# object and tweak a single property. -# WARN: If you update this generator, you should also consider updating its parent -# in res/meson.build -frontier_script_bin_gen = generator(make_script_bin_sh, - arguments: [ - '-i', relative_source_root / 'include', - '-i', relative_source_root / 'asm', - '-i', '.' / 'res' / 'text', - '-i', '.' / 'res', - '-i', '.', - '--depfile', - '--assembler', arm_none_eabi_gcc_exe.full_path(), - '--objcopy', arm_none_eabi_objcopy_exe.full_path(), - '@EXTRA_ARGS@', - '@INPUT@', - ], - depends: [ - c_consts_generators, - frontier_particles_narc[1], - text_banks, - ], - output: '@BASENAME@', - depfile: '@BASENAME@.d', -) fr_script_target_name = 'fr_script.narc' fr_script_private_dir = relative_build_dir / fr_script_target_name + '.p' @@ -37,23 +9,27 @@ fr_script_narc = custom_target('fr_script.narc', 'fr_script.naix', ], input: [ - frontier_script_bin_gen.process(files( - 'frontier_scripts_battle_castle.s', - 'frontier_scripts_battle_factory.s', - 'frontier_scripts_battle_hall.s', - 'frontier_scripts_battle_arcade.s', - ), extra_args: ['--out-dir', fr_script_private_dir]), - copy_gen.process(files( - 'frontier_scripts_unused_04.bin', - 'frontier_scripts_unused_05.bin', - )), - script_bin_gen.process(files( - 'frontier_scripts_battle_tower_corridor.s', - 'frontier_scripts_battle_tower_corridor_multi.s', - 'frontier_scripts_battle_tower_battle_room.s', - 'frontier_scripts_battle_tower_multi_battle_room.s', - 'frontier_scripts_unknown_10.s', - ), extra_args: ['--out-dir', fr_script_private_dir]), + script_bin_gen.process( + files( + 'frontier_scripts_battle_castle.s', + 'frontier_scripts_battle_factory.s', + 'frontier_scripts_battle_hall.s', + 'frontier_scripts_battle_arcade.s', + 'frontier_scripts_battle_tower_corridor.s', + 'frontier_scripts_battle_tower_corridor_multi.s', + 'frontier_scripts_battle_tower_battle_room.s', + 'frontier_scripts_battle_tower_multi_battle_room.s', + 'frontier_scripts_unknown_10.s', + ), + extra_args: ['--out-dir', fr_script_private_dir], + depends: [frontier_particles_narc], + ), + copy_gen.process( + files( + 'frontier_scripts_unused_04.bin', + 'frontier_scripts_unused_05.bin', + ), + ), ], command: [ nitroarc_exe, diff --git a/res/field/scripts/meson.build b/res/field/scripts/meson.build index 0bc339568e..41b41af1be 100644 --- a/res/field/scripts/meson.build +++ b/res/field/scripts/meson.build @@ -1,34 +1,5 @@ relative_build_dir = fs.relative_to(meson.current_build_dir(), meson.project_build_root()) -# NOTE: This is a functional copy of script_bin_gen, which is separated from the -# base generator due to an additional dependency on headers generated for -# events IDs. Meson unfortunately does not have a clean way to copy an existing -# object and tweak a single property. -# WARN: If you update this generator, you should also consider updating its parent -# in res/meson.build -field_script_bin_gen = generator(make_script_bin_sh, - arguments: [ - '-i', relative_source_root / 'include', - '-i', relative_source_root / 'asm', - '-i', '.' / 'res' / 'text', - '-i', '.' / 'res', - '-i', '.', - '--depfile', - '--assembler', arm_none_eabi_gcc_exe.full_path(), - '--objcopy', arm_none_eabi_objcopy_exe.full_path(), - '@EXTRA_ARGS@', - '@INPUT@', - ], - depends: [ - text_banks, - c_consts_generators, - h_headers, - events_headers, - ], - output: '@BASENAME@', - depfile: '@BASENAME@.d', -) - scr_seq_target_name = 'scr_seq.narc' scr_seq_private_dir = relative_build_dir / scr_seq_target_name + '.p' @@ -1164,9 +1135,10 @@ scr_seq_narc = custom_target('scr_seq.narc', 'scr_seq.narc', 'scr_seq.naix', ], - input: field_script_bin_gen.process( + input: script_bin_gen.process( scr_seq_files, - extra_args: ['--depfile', '--out-dir', scr_seq_private_dir] + extra_args: ['--depfile', '--out-dir', scr_seq_private_dir], + depends: [events_headers], ), command: [ nitroarc_exe, diff --git a/res/meson.build b/res/meson.build index b29ad308e0..235926487c 100644 --- a/res/meson.build +++ b/res/meson.build @@ -89,8 +89,6 @@ relative_source_root = fs.relative_to(meson.project_source_root(), meson.project # *breaks* the dependency-chain if any of these files are edited. However, because # this generator produces a depfile, the build back-end will still see the correct # granular headers on which each input source file depends. -# WARN: If you update this generator, you should also consider updating its child -# in res/field/scripts/meson.build script_bin_gen = generator(make_script_bin_sh, arguments: [ '-i', relative_source_root / 'include', diff --git a/subprojects/packagefiles/meson_patch/feat-generator-process-depends.patch b/subprojects/packagefiles/meson_patch/feat-generator-process-depends.patch new file mode 100644 index 0000000000..3dc0c93053 --- /dev/null +++ b/subprojects/packagefiles/meson_patch/feat-generator-process-depends.patch @@ -0,0 +1,100 @@ +# Upstream PR: https://github.com/mesonbuild/meson/pull/15402 +diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py +index 086d195..eb93d2a 100644 +--- a/mesonbuild/backend/ninjabackend.py ++++ b/mesonbuild/backend/ninjabackend.py +@@ -2792,6 +2792,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) + exe = generator.get_exe() + infilelist = genlist.get_inputs() + extra_dependencies = self.get_target_depend_files(genlist) ++ for d in genlist.extra_depends: ++ # Add a dependency on all the outputs of this target ++ for output in d.get_outputs(): ++ extra_dependencies.append(os.path.join(self.get_target_dir(d), output)) + for curfile in infilelist: + infilename = curfile.rel_to_builddir(self.build_to_src, self.get_target_private_dir(target)) + base_args = generator.get_arglist(infilename) +diff --git a/mesonbuild/build.py b/mesonbuild/build.py +index 138f1ae..d0f65df 100644 +--- a/mesonbuild/build.py ++++ b/mesonbuild/build.py +@@ -2027,13 +2027,15 @@ class Generator(HoldableObject): + subdir: str = '', + preserve_path_from: T.Optional[str] = None, + extra_args: T.Optional[T.List[str]] = None, +- env: T.Optional[EnvironmentVariables] = None) -> 'GeneratedList': ++ env: T.Optional[EnvironmentVariables] = None, ++ extra_depends: T.Optional[T.List[GeneratedTypes]] = None) -> 'GeneratedList': + output = GeneratedList( + self, + subdir, + preserve_path_from, + extra_args=extra_args if extra_args is not None else [], +- env=env if env is not None else EnvironmentVariables()) ++ env=env if env is not None else EnvironmentVariables(), ++ extra_depends=extra_depends if extra_depends is not None else []) + + for e in files: + if isinstance(e, (CustomTarget, CustomTargetIndex)): +@@ -2069,6 +2071,7 @@ class GeneratedList(HoldableObject): + preserve_path_from: T.Optional[str] + extra_args: T.List[str] + env: T.Optional[EnvironmentVariables] ++ extra_depends: T.List[GeneratedTypes] + + def __post_init__(self) -> None: + self.name = self.generator.exe +@@ -2076,7 +2079,6 @@ class GeneratedList(HoldableObject): + self.infilelist: T.List[FileMaybeInTargetPrivateDir] = [] + self.outfilelist: T.List[str] = [] + self.outmap: T.Dict[FileMaybeInTargetPrivateDir, T.List[str]] = {} +- self.extra_depends = [] # XXX: Doesn't seem to be used? + self.depend_files: T.List[File] = [] + + if self.extra_args is None: +@@ -2085,6 +2087,9 @@ class GeneratedList(HoldableObject): + if self.env is None: + self.env: EnvironmentVariables = EnvironmentVariables() + ++ if self.extra_depends is None: ++ self.extra_depends: T.List[GeneratedTypes] = [] ++ + if isinstance(self.generator.exe, programs.ExternalProgram): + if not self.generator.exe.found(): + raise InvalidArguments('Tried to use not-found external program as generator') +diff --git a/mesonbuild/interpreter/interpreterobjects.py b/mesonbuild/interpreter/interpreterobjects.py +index 4dce3f5..c50f7d3 100644 +--- a/mesonbuild/interpreter/interpreterobjects.py ++++ b/mesonbuild/interpreter/interpreterobjects.py +@@ -1173,7 +1173,8 @@ class GeneratorHolder(ObjectHolder[build.Generator]): + 'generator.process', + KwargInfo('preserve_path_from', (str, NoneType), since='0.45.0'), + KwargInfo('extra_args', ContainerTypeInfo(list, str), listify=True, default=[]), +- ENV_KW.evolve(since='1.3.0') ++ ENV_KW.evolve(since='1.3.0'), ++ KwargInfo('depends', ContainerTypeInfo(list, (build.CustomTarget, build.CustomTargetIndex, build.GeneratedList)), listify=True, default=[], since='1.10.0'), + ) + @InterpreterObject.method('process') + def process_method(self, +@@ -1192,7 +1193,8 @@ class GeneratorHolder(ObjectHolder[build.Generator]): + '0.57.0', self.interpreter.subproject) + + gl = self.held_object.process_files(args[0], self.interpreter.subdir, +- preserve_path_from, extra_args=kwargs['extra_args'], env=kwargs['env']) ++ preserve_path_from, extra_args=kwargs['extra_args'], env=kwargs['env'], ++ extra_depends=kwargs['depends']) + + return gl + +diff --git a/mesonbuild/interpreter/kwargs.py b/mesonbuild/interpreter/kwargs.py +index 4935973..fae7087 100644 +--- a/mesonbuild/interpreter/kwargs.py ++++ b/mesonbuild/interpreter/kwargs.py +@@ -108,6 +108,7 @@ class GeneratorProcess(TypedDict): + preserve_path_from: T.Optional[str] + extra_args: T.List[str] + env: EnvironmentVariables ++ depends: T.List[T.Union[build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] + + class DependencyMethodPartialDependency(TypedDict): + diff --git a/subprojects/packagefiles/meson_patch/fix-meson-exe-stderr.patch b/subprojects/packagefiles/meson_patch/fix-meson-exe-stderr.patch new file mode 100644 index 0000000000..a63a353313 --- /dev/null +++ b/subprojects/packagefiles/meson_patch/fix-meson-exe-stderr.patch @@ -0,0 +1,15 @@ +# Upstream PR: https://github.com/mesonbuild/meson/pull/15683 +diff --git a/mesonbuild/scripts/meson_exe.py b/mesonbuild/scripts/meson_exe.py +index e928e9c..1d892c2 100644 +--- a/mesonbuild/scripts/meson_exe.py ++++ b/mesonbuild/scripts/meson_exe.py +@@ -77,6 +77,9 @@ def run_exe(exe: ExecutableSerialisation, extra_env: T.Optional[T.Dict[str, str] + print('--- stderr ---') + print(stderr.decode(encoding=encoding, errors='replace')) + return p.returncode ++ elif stderr: # Allow a wrapped subprocess to gracefully communicate warnings ++ encoding = locale.getpreferredencoding() ++ print(stderr.decode(encoding=encoding, errors='replace')) + + if exe.capture: + skip_write = False diff --git a/tools/dataproc/src/speciesproc.c b/tools/dataproc/src/speciesproc.c index c1a05f8ef4..171b79ef0b 100644 --- a/tools/dataproc/src/speciesproc.c +++ b/tools/dataproc/src/speciesproc.c @@ -730,7 +730,7 @@ static u32 get_height_decimeters(datanode_t dexdata) { datanode_t height_m = dp_objmemb(dexdata, "height_meters"); datanode_t height_i = dp_objmemb(dexdata, "height_inches"); - dp_error(&dexdata, "conflicting unit-systems given for species height; remove one before rebuilding"); + dp_warn(&dexdata, "conflicting unit-systems given for species height; metric units will be used"); dp_note(&height_m, "metric units defined here"); dp_note(&height_i, "imperial units defined here"); } @@ -748,7 +748,7 @@ static u32 get_weight_hectograms(datanode_t dexdata, enum Species species) { datanode_t weight_m = dp_objmemb(dexdata, "weight_kilograms"); datanode_t weight_i = dp_objmemb(dexdata, "weight_pounds"); - dp_error(&dexdata, "conflicting unit-systems given for species weight; remove one before rebuilding"); + dp_warn(&dexdata, "conflicting unit-systems given for species weight; metric units will be used"); dp_note(&weight_m, "metric units defined here"); dp_note(&weight_i, "imperial units defined here"); } @@ -914,7 +914,7 @@ static void emit_tutorables(datafile_t *df, size_t i) { } if (found) tutorset[idx / 8] |= (u8)(1 << (idx % 8)); - else dp_error(&move, "'%s' is not available from any move tutors", move_s); + else dp_warn(&move, "'%s' is not available from any move tutors and will be skipped", move_s); } for (size_t i = 0; i < tutorset_size; i++) fprintf(*f_tutor_sets, "0x%02X, ", tutorset[i]); diff --git a/tools/scripts/fetch_meson_diff.sh b/tools/scripts/fetch_meson_diff.sh new file mode 100755 index 0000000000..f2d24f9e51 --- /dev/null +++ b/tools/scripts/fetch_meson_diff.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash + +set -eo pipefail + +cd "$(git rev-parse --show-toplevel)" + +PR_ID=${1} +PATCH_DIR=subprojects/packagefiles/meson_patch +MESON_GIT=https://github.com/mesonbuild/meson +TARGET="${PATCH_DIR}/${PR_ID}.patch" + +FILTERED_PATCH=$(curl -fSL -X GET "${MESON_GIT}/pull/${PR_ID}.diff" \ + | sed -n '/^diff --git a\/mesonbuild/,$p') +DIFF_LINES=$(grep -n 'diff --git' <<< "${FILTERED_PATCH}") +NOT_MESONBUILD=$(grep -v 'diff --git a/mesonbuild' <<< "${DIFF_LINES}" || true) +LINE_EXCLUDE=$(head -n 1 <<< "${NOT_MESONBUILD}" | cut -d ':' -f 1) + +if [ -n "${LINE_EXCLUDE}" ]; then + FILTERED_PATCH=$(head -n "$((LINE_EXCLUDE - 1))" <<< "${FILTERED_PATCH}") +fi + +echo "# Upstream PR: ${MESON_GIT}/pull/${PR_ID}" > "${TARGET}" +echo "${FILTERED_PATCH}" >> "${TARGET}"