decompctx: Automatic includes from cflags, respect #pragma once
Resolves #23, #43
This commit is contained in:
parent
065fc7b715
commit
d34e7c95db
|
@ -18,58 +18,63 @@ from typing import List
|
|||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
root_dir = os.path.abspath(os.path.join(script_dir, ".."))
|
||||
src_dir = os.path.join(root_dir, "src")
|
||||
include_dirs = [
|
||||
os.path.join(root_dir, "include"),
|
||||
# Add additional include directories here
|
||||
]
|
||||
include_dirs: List[str] = [] # Set with -I flag
|
||||
|
||||
include_pattern = re.compile(r'^#\s*include\s*[<"](.+?)[>"]')
|
||||
guard_pattern = re.compile(r"^#\s*ifndef\s+(.*)$")
|
||||
once_pattern = re.compile(r"^#\s*pragma\s+once$")
|
||||
|
||||
defines = set()
|
||||
deps = []
|
||||
|
||||
|
||||
def import_h_file(in_file: str, r_path: str, deps: List[str]) -> str:
|
||||
def import_h_file(in_file: str, r_path: str) -> str:
|
||||
rel_path = os.path.join(root_dir, r_path, in_file)
|
||||
if os.path.exists(rel_path):
|
||||
return import_c_file(rel_path, deps)
|
||||
return import_c_file(rel_path)
|
||||
for include_dir in include_dirs:
|
||||
inc_path = os.path.join(include_dir, in_file)
|
||||
if os.path.exists(inc_path):
|
||||
return import_c_file(inc_path, deps)
|
||||
return import_c_file(inc_path)
|
||||
else:
|
||||
print("Failed to locate", in_file)
|
||||
return ""
|
||||
|
||||
|
||||
def import_c_file(in_file: str, deps: List[str]) -> str:
|
||||
def import_c_file(in_file: str) -> str:
|
||||
in_file = os.path.relpath(in_file, root_dir)
|
||||
deps.append(in_file)
|
||||
out_text = ""
|
||||
|
||||
try:
|
||||
with open(in_file, encoding="utf-8") as file:
|
||||
out_text += process_file(in_file, list(file), deps)
|
||||
out_text += process_file(in_file, list(file))
|
||||
except Exception:
|
||||
with open(in_file) as file:
|
||||
out_text += process_file(in_file, list(file), deps)
|
||||
out_text += process_file(in_file, list(file))
|
||||
return out_text
|
||||
|
||||
|
||||
def process_file(in_file: str, lines: List[str], deps: List[str]) -> str:
|
||||
def process_file(in_file: str, lines: List[str]) -> str:
|
||||
out_text = ""
|
||||
for idx, line in enumerate(lines):
|
||||
guard_match = guard_pattern.match(line.strip())
|
||||
if idx == 0:
|
||||
guard_match = guard_pattern.match(line.strip())
|
||||
if guard_match:
|
||||
if guard_match[1] in defines:
|
||||
break
|
||||
defines.add(guard_match[1])
|
||||
else:
|
||||
once_match = once_pattern.match(line.strip())
|
||||
if once_match:
|
||||
if in_file in defines:
|
||||
break
|
||||
defines.add(in_file)
|
||||
print("Processing file", in_file)
|
||||
include_match = include_pattern.match(line.strip())
|
||||
if include_match and not include_match[1].endswith(".s"):
|
||||
out_text += f'/* "{in_file}" line {idx} "{include_match[1]}" */\n'
|
||||
out_text += import_h_file(include_match[1], os.path.dirname(in_file), deps)
|
||||
out_text += import_h_file(include_match[1], os.path.dirname(in_file))
|
||||
out_text += f'/* end "{include_match[1]}" */\n'
|
||||
else:
|
||||
out_text += line
|
||||
|
@ -100,10 +105,19 @@ def main():
|
|||
"--depfile",
|
||||
help="""Dependency file""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-I",
|
||||
"--include",
|
||||
help="""Include directory""",
|
||||
action="append",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
deps = []
|
||||
output = import_c_file(args.c_file, deps)
|
||||
if args.include is None:
|
||||
exit("No include directories specified")
|
||||
global include_dirs
|
||||
include_dirs = args.include
|
||||
output = import_c_file(args.c_file)
|
||||
|
||||
with open(os.path.join(root_dir, args.output), "w", encoding="utf-8") as f:
|
||||
f.write(output)
|
||||
|
|
|
@ -176,7 +176,9 @@ class ProjectConfig:
|
|||
True # Generate compile_commands.json for clangd
|
||||
)
|
||||
self.extra_clang_flags: List[str] = [] # Extra flags for clangd
|
||||
self.scratch_preset_id: Optional[int] = None # Default decomp.me preset ID for scratches
|
||||
self.scratch_preset_id: Optional[int] = (
|
||||
None # Default decomp.me preset ID for scratches
|
||||
)
|
||||
|
||||
# Progress output, progress.json and report.json config
|
||||
self.progress = True # Enable report.json generation and CLI progress output
|
||||
|
@ -380,7 +382,7 @@ def generate_build_ninja(
|
|||
decompctx = config.tools_dir / "decompctx.py"
|
||||
n.rule(
|
||||
name="decompctx",
|
||||
command=f"$python {decompctx} $in -o $out -d $out.d",
|
||||
command=f"$python {decompctx} $in -o $out -d $out.d $includes",
|
||||
description="CTX $in",
|
||||
depfile="$out.d",
|
||||
deps="gcc",
|
||||
|
@ -809,10 +811,8 @@ def generate_build_ninja(
|
|||
else:
|
||||
extra_cflags.insert(0, "-lang=c")
|
||||
|
||||
cflags_str = make_flags_str(cflags)
|
||||
if len(extra_cflags) > 0:
|
||||
extra_cflags_str = make_flags_str(extra_cflags)
|
||||
cflags_str += " " + extra_cflags_str
|
||||
all_cflags = cflags + extra_cflags
|
||||
cflags_str = make_flags_str(all_cflags)
|
||||
used_compiler_versions.add(obj.options["mw_version"])
|
||||
|
||||
# Add MWCC build rule
|
||||
|
@ -836,11 +836,21 @@ def generate_build_ninja(
|
|||
|
||||
# Add ctx build rule
|
||||
if obj.ctx_path is not None:
|
||||
include_dirs = []
|
||||
for flag in all_cflags:
|
||||
if (
|
||||
flag.startswith("-i ")
|
||||
or flag.startswith("-I ")
|
||||
or flag.startswith("-I+")
|
||||
):
|
||||
include_dirs.append(flag[3:])
|
||||
includes = " ".join([f"-I {d}" for d in include_dirs])
|
||||
n.build(
|
||||
outputs=obj.ctx_path,
|
||||
rule="decompctx",
|
||||
inputs=src_path,
|
||||
implicit=decompctx,
|
||||
variables={"includes": includes},
|
||||
)
|
||||
|
||||
# Add host build rule
|
||||
|
@ -1358,9 +1368,21 @@ def generate_objdiff_config(
|
|||
unit_config["base_path"] = obj.src_obj_path
|
||||
unit_config["metadata"]["source_path"] = obj.src_path
|
||||
|
||||
cflags = obj.options["cflags"]
|
||||
# Filter out include directories
|
||||
def keep_flag(flag):
|
||||
return (
|
||||
not flag.startswith("-i ")
|
||||
and not flag.startswith("-i-")
|
||||
and not flag.startswith("-I ")
|
||||
and not flag.startswith("-I+")
|
||||
and not flag.startswith("-I-")
|
||||
)
|
||||
|
||||
all_cflags = list(
|
||||
filter(keep_flag, obj.options["cflags"] + obj.options["extra_cflags"])
|
||||
)
|
||||
reverse_fn_order = False
|
||||
for flag in cflags:
|
||||
for flag in all_cflags:
|
||||
if not flag.startswith("-inline "):
|
||||
continue
|
||||
for value in flag.split(" ")[1].split(","):
|
||||
|
@ -1369,20 +1391,11 @@ def generate_objdiff_config(
|
|||
elif value == "nodeferred":
|
||||
reverse_fn_order = False
|
||||
|
||||
# Filter out include directories
|
||||
def keep_flag(flag):
|
||||
return not flag.startswith("-i ") and not flag.startswith("-I ")
|
||||
|
||||
cflags = list(filter(keep_flag, cflags))
|
||||
|
||||
compiler_version = COMPILER_MAP.get(obj.options["mw_version"])
|
||||
if compiler_version is None:
|
||||
print(f"Missing scratch compiler mapping for {obj.options['mw_version']}")
|
||||
else:
|
||||
cflags_str = make_flags_str(cflags)
|
||||
if len(obj.options["extra_cflags"]) > 0:
|
||||
extra_cflags_str = make_flags_str(obj.options["extra_cflags"])
|
||||
cflags_str += " " + extra_cflags_str
|
||||
cflags_str = make_flags_str(all_cflags)
|
||||
unit_config["scratch"] = {
|
||||
"platform": "gc_wii",
|
||||
"compiler": compiler_version,
|
||||
|
|
Loading…
Reference in New Issue