diff options
| author | coco875 <59367621+coco875@users.noreply.github.com> | 2024-08-28 01:47:39 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-08-27 17:47:39 -0600 |
| commit | a1f0d32d666c07d0754d97f107a5be59153768fd (patch) | |
| tree | fcc84d9daa940274be8cf76715be902d93338e64 /tools | |
| parent | bb3cbe0500197f894c83230a9a170a2cbe7aa3e8 (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-permuter | 0 | ||||
| -rw-r--r-- | tools/format.py | 204 | ||||
| -rw-r--r-- | tools/linkonly_generator.py | 2 |
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 = "" |
