summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorcoco875 <59367621+coco875@users.noreply.github.com>2024-08-28 01:47:39 +0200
committerGitHub <noreply@github.com>2024-08-27 17:47:39 -0600
commita1f0d32d666c07d0754d97f107a5be59153768fd (patch)
treefcc84d9daa940274be8cf76715be902d93338e64 /tools
parentbb3cbe0500197f894c83230a9a170a2cbe7aa3e8 (diff)
Update decomp clang (#67)
* Update menus.c (#634) * Update common_data.yml (#635) * Renames for screenId and other changes (#636) * screenId renames * Rename surface map to collision mesh (#637) * Rename some stack vars (#638) * Fix syntax error (#639) * Rename some stack vars * Update collision.c * Collision Documentation (#640) * Collision related renames * update doxygen (#649) * change bool (#644) Co-authored-by: MegaMech <MegaMech@users.noreply.github.com> * Update (#642) * Delete trig_tables_bss.c (#650) * fix typo audio (#656) * fix typo src actor (#657) Co-authored-by: MegaMech <MegaMech@users.noreply.github.com> * fix typo include (#658) * fix course (#659) * fix typo debug (#660) * fix typo data (#661) * replace number with const (#665) * fix typo buffers (#655) * fix typo buffers * tweak ld file * rename to sMemoryPool * add a warning --------- * fix typo src (#654) * fix typo src * fix non matcing * Update code_80091750.c --------- * fix typo racing (#653) * fix typo racing * get it match * replace G_LINE3D to G_QUAD --------- * fix typo src (#652) * fix ending typo (#651) * Action more info when it doesn't match and fix first diff (#662) * Update linux-compile.yml * fix first-diff * Update first-diff.py --------- * document texture of kart (#663) * document texture of kart * change screenPlayerId to screenId * some documentation around object * Revert "some documentation around object" This reverts commit cbb39078e036bf2a417bed67359e910213acab28. * more rename --------- * Make evaluate_collision_players_palm_tree better (#667) This matches just the same as before, but using those two casts instead of shifts seems more likely to be accurate to the original source code Signed-off-by: Gabriel Ravier <gabravier@gmail.com> * add fedora instruciton (#666) * start documenting animation (#668) * start documenting animation * Update course_data.c * change comment * update libultra asm (#648) * update libultra asm * fix gcc __osThreadTail --------- * Document Vehicles (#641) * start doc collision * fix merge * finish rename fonction related to vehicle * document around waypoint of vehicle * make some modification * make some change and rename one * copy_ to oldPos * doc smoke ferry and train * some rename * fix some renaming * precise index * rename a funciton * simplify waypoint_vehicles * change some name * change some name * rename move_to_point_direction * fix some conflict * Update code_80005FD0.c * Update code_80005FD0.h --------- * Label a save info loop (#645) * save info * more gcc progress * fix a value and do a rename (#669) * update clang and add action (#664) * update clang and add action * try clang on course folder only * forget two file * Update course_displaylists.inc.c * forget few other file * Update course_vertices.inc.c * format all code while get it match * second pass * format other dir * disable clang format on bad ido code * fix some tabulation * revert format on tool dir * Update clang-format.yml * ignore gbi.h * add some read me instruction * fix error * format and fixing error * Update README.md --------- * Update linkonly_generator.py (#670) * format more file * update * fix compilation issue * remove course_metadata folder * re add course metadata folder * fix banshee bordwalk crash * fix windows eurk * Update CMakeLists.txt ---------
Diffstat (limited to 'tools')
m---------tools/decomp-permuter0
-rw-r--r--tools/format.py204
-rw-r--r--tools/linkonly_generator.py2
3 files changed, 205 insertions, 1 deletions
diff --git a/tools/decomp-permuter b/tools/decomp-permuter
-Subproject 8fca51b0280fed8cf612d33261d6929e5a22899
+Subproject 082a8d98953683a615d42505a7b87435ab6fabe
diff --git a/tools/format.py b/tools/format.py
new file mode 100644
index 000000000..e326fd056
--- /dev/null
+++ b/tools/format.py
@@ -0,0 +1,204 @@
+#!/usr/bin/env python3
+
+import argparse
+import glob
+import multiprocessing
+import os
+import re
+import shutil
+import subprocess
+import sys
+import tempfile
+from functools import partial
+from typing import List
+
+
+# clang-format, clang-tidy and clang-apply-replacements default version
+# This specific version is used when available, for more consistency between contributors
+CLANG_VER = 14
+
+# Clang-Format options (see .clang-format for rules applied)
+FORMAT_OPTS = "-i -style=file"
+
+# Clang-Tidy options (see .clang-tidy for checks enabled)
+TIDY_OPTS = "-p ."
+TIDY_FIX_OPTS = "--fix --fix-errors"
+
+# Clang-Apply-Replacements options (used for multiprocessing)
+APPLY_OPTS = ""
+
+# Compiler options used with Clang-Tidy
+# Normal warnings are disabled with -Wno-everything to focus only on tidying
+INCLUDES = "-Iinclude -Ibuild/us -Ibuild/us/include -Isrc -Isrc/racing -Isrc/ending -I. -Iinclude/libc"
+DEFINES = "-DVERSION_US=1 -DF3DEX_GBI=1 -DF3D_OLD=1"
+COMPILER_OPTS = f"-fno-builtin -std=gnu90 -m32 -Wno-everything {INCLUDES} {DEFINES}"
+
+
+def get_clang_executable(allowed_executables: List[str]):
+ for executable in allowed_executables:
+ try:
+ subprocess.check_call(
+ [executable, "--version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ return executable
+ except FileNotFoundError or subprocess.CalledProcessError:
+ pass
+ return None
+
+
+def get_tidy_version(tidy_executable: str):
+ tidy_version_run = subprocess.run(
+ [tidy_executable, "--version"], stdout=subprocess.PIPE, universal_newlines=True)
+ match = re.search(r"LLVM version ([0-9]+)", tidy_version_run.stdout)
+ return int(match.group(1))
+
+
+CLANG_FORMAT = get_clang_executable([f"clang-format-{CLANG_VER}", "clang-format"])
+if CLANG_FORMAT is None:
+ sys.exit(f"Error: clang-format-{CLANG_VER} not found")
+
+CLANG_TIDY = get_clang_executable([f"clang-tidy-{CLANG_VER}", "clang-tidy"])
+if CLANG_TIDY is None:
+ sys.exit(f"Error: neither clang-tidy-{CLANG_VER} nor clang-tidy found")
+
+CLANG_APPLY_REPLACEMENTS = get_clang_executable(
+ [f"clang-apply-replacements-{CLANG_VER}", "clang-apply-replacements"])
+
+# Try to detect the clang-tidy version and add --fix-notes for version 13+
+# This is used to ensure all fixes are applied properly in recent versions
+if get_tidy_version(CLANG_TIDY) >= 13:
+ TIDY_FIX_OPTS += " --fix-notes"
+
+
+def list_chunks(list: List, chunk_length: int):
+ for i in range(0, len(list), chunk_length):
+ yield list[i: i + chunk_length]
+
+
+def run_clang_format(files: List[str]):
+ exec_str = f"{CLANG_FORMAT} {FORMAT_OPTS} {' '.join(files)}"
+ subprocess.run(exec_str, shell=True)
+
+
+def run_clang_tidy(files: List[str]):
+ exec_str = f"{CLANG_TIDY} {TIDY_OPTS} {TIDY_FIX_OPTS} {' '.join(files)} -- {COMPILER_OPTS}"
+ subprocess.run(exec_str, shell=True,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+
+def run_clang_tidy_with_export(tmp_dir: str, files: List[str]):
+ (handle, tmp_file) = tempfile.mkstemp(suffix=".yaml", dir=tmp_dir)
+ os.close(handle)
+
+ exec_str = f"{CLANG_TIDY} {TIDY_OPTS} --export-fixes={tmp_file} {' '.join(files)} -- {COMPILER_OPTS}"
+ subprocess.run(exec_str, shell=True,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+
+def run_clang_apply_replacements(tmp_dir: str):
+ exec_str = f"{CLANG_APPLY_REPLACEMENTS} {APPLY_OPTS} {tmp_dir}"
+ subprocess.run(exec_str, shell=True)
+
+
+def add_final_new_line(file: str):
+ # https://backreference.org/2010/05/23/sanitizing-files-with-no-trailing-newline/index.html
+ # "gets the last character of the file pipes it into read, which will exit with a nonzero exit
+ # code if it encounters EOF before newline (so, if the last character of the file isn't a newline).
+ # If read exits nonzero, then append a newline onto the file using echo (if read exits 0,
+ # that satisfies the ||, so the echo command isn't run)." (https://stackoverflow.com/a/34865616)
+ exec_str = f"tail -c1 {file} | read -r _ || echo >> {file}"
+ subprocess.run(exec_str, shell=True)
+
+
+def format_files(src_files: List[str], extra_files: List[str], nb_jobs: int):
+ if nb_jobs != 1:
+ print(f"Formatting files with {nb_jobs} jobs")
+ else:
+ print(f"Formatting files with a single job (consider using -j to make this faster)")
+
+ # Format files in chunks to improve performance while still utilizing jobs
+ file_chunks = list(list_chunks(src_files, (len(src_files) // nb_jobs) + 1))
+
+ print("Running clang-format...")
+ # clang-format only applies changes in the given files, so it's safe to run in parallel
+ with multiprocessing.get_context("fork").Pool(nb_jobs) as pool:
+ pool.map(run_clang_format, file_chunks)
+
+ print("Running clang-tidy...")
+ if nb_jobs > 1:
+ # clang-tidy may apply changes in #included files, so when running it in parallel we use --export-fixes
+ # then we call clang-apply-replacements to apply all suggested fixes at the end
+ tmp_dir = tempfile.mkdtemp()
+
+ try:
+ with multiprocessing.get_context("fork").Pool(nb_jobs) as pool:
+ pool.map(partial(run_clang_tidy_with_export, tmp_dir), file_chunks)
+
+ run_clang_apply_replacements(tmp_dir)
+ finally:
+ shutil.rmtree(tmp_dir)
+ else:
+ run_clang_tidy(src_files)
+
+ print("Adding missing final new lines...")
+ # Adding final new lines is safe to do in parallel and can be applied to all types of files
+ with multiprocessing.get_context("fork").Pool(nb_jobs) as pool:
+ pool.map(add_final_new_line, src_files + extra_files)
+
+ print("Done formatting files.")
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Format files in the codebase to enforce most style rules")
+ parser.add_argument("files", metavar="file", nargs="*")
+ parser.add_argument(
+ "--show-paths",
+ dest="show_paths",
+ action="store_true",
+ help="Print the paths to the clang-* binaries used",
+ )
+ parser.add_argument(
+ "-j",
+ dest="jobs",
+ type=int,
+ nargs="?",
+ default=1,
+ help="number of jobs to run (default: 1 without -j, number of cpus with -j)",
+ )
+ args = parser.parse_args()
+
+ if args.show_paths:
+ import shutil
+
+ print("CLANG_FORMAT ->", shutil.which(CLANG_FORMAT))
+ print("CLANG_TIDY ->", shutil.which(CLANG_TIDY))
+ print("CLANG_APPLY_REPLACEMENTS ->",
+ shutil.which(CLANG_APPLY_REPLACEMENTS))
+
+ nb_jobs = args.jobs or multiprocessing.cpu_count()
+ if nb_jobs > 1:
+ if CLANG_APPLY_REPLACEMENTS is None:
+ sys.exit(
+ f"Error: neither clang-apply-replacements-{CLANG_VER} nor clang-apply-replacements found (required to use -j)"
+ )
+ default_list_folder = [
+ "include",
+ "data",
+ "courses",
+ "src"
+ ]
+ if args.files:
+ files = args.files
+ extra_files = []
+ else:
+ files = []
+ for folder in default_list_folder:
+ files += glob.glob(f"{folder}*/**/*.c", recursive=True)+ glob.glob(f"{folder}*/**/*.cpp", recursive=True) + glob.glob(f"{folder}*/**/*.h", recursive=True)
+ files = [x for x in files if "assets" not in x]
+ extra_files = glob.glob("assets/**/*.xml", recursive=True)
+
+ format_files(files, extra_files, nb_jobs)
+
+
+if __name__ == "__main__":
+ main() \ No newline at end of file
diff --git a/tools/linkonly_generator.py b/tools/linkonly_generator.py
index fe2aa073b..b478f524e 100644
--- a/tools/linkonly_generator.py
+++ b/tools/linkonly_generator.py
@@ -315,7 +315,7 @@ course_name = sys.argv[1]
# This depends on the texture lists in each courses/<course_name_here>/course_offsets.c
# look like: `{gTexture6447C4, 0x0106, 0x0800, 0x0},`
-texture_regex = re.compile(r"{(\S+),\s+\S+,\s+(\S+),\s+\S+}")
+texture_regex = re.compile(r"{\s*(\S+),\s+\S+,\s+(\S+),\s+\S+\s*}")
h_string = ""
c_string = ""