Skip to content

chore(cli): split crates/perry/src/commands/compile.rs (9k lines, run_with_parse_cache is 7.6k) #1105

Description

@proggeramlug

Part of #1097.

Current state

crates/perry/src/commands/compile.rs is 9,007 lines. The function run_with_parse_cache spans lines 1171 → 8765 (~7.6k lines) — that is, almost the entire file is one function: the full compile pipeline (parse → HIR → transform → link → bundle → sign → audit manifest) in a single linear scope.

There are some helpers around it (target_bundle_section, package_name_for_path, inject_ios_deeplinks, lookup_bundle_id_from_info_plist, emit_harmonyos_arkts_stubs, read_app_metadata, write_audit_manifest, collect_native_archives_for_lock, for_each_native_library_package, derive_target_key, rust_target_triple) but they're a small fraction.

The pipeline isn't conceptually one thing — it's parse, then HIR-lower, then transform, then codegen, then link, then bundle/sign per target. Each phase has its own concerns that today share one stack frame and one set of let-bound locals.

Proposed split

This one is higher-effort than the other seven because it requires extracting state into a CompileState struct (or threading the existing CompilationContext through more aggressively) so each phase can be a function. The payoff is large — making the compile pipeline navigable is worth a focused effort — but the work isn't pure file-moves the way the others can be.

Suggested phasing:

  1. PR 1 — pure helper extraction (no API change to run_with_parse_cache): pull the obvious sub-routines (TypeScript-checking pass, source-map emission, audit-manifest assembly, dependency-lock writing, native-archive scanning) out into private functions still defined in compile.rs. This is mechanical and reviewable.

  2. PR 2 — phase functions: define a struct CompilePipeline { ... } holding the long-lived state (parse cache, HIR modules, codegen settings, target info, etc.) and convert each phase to impl CompilePipeline { fn parse(&mut self), fn lower(&mut self), fn transform(&mut self), fn codegen(&mut self), fn link(&mut self), fn bundle(&mut self) }. run_with_parse_cache becomes a ~50-line orchestrator.

  3. PR 3 — split into directory module crates/perry/src/commands/compile/:

    • compile/mod.rspub fn run, pub fn run_with_parse_cache, the CompilePipeline orchestrator
    • compile/parse.rs — parsing + parse-cache integration
    • compile/lower.rs — driving HIR lowering across modules
    • compile/transform.rs — running transform passes
    • compile/codegen.rs — driving codegen + the rayon parallel chunking
    • compile/link.rs — invoking cc/ld
    • compile/bundle_ios.rs / compile/bundle_macos.rs / compile/bundle_android.rs / compile/bundle_harmonyos.rs — per-target bundling
    • compile/sign.rs — codesigning, entitlements, provisioning
    • compile/audit.rswrite_audit_manifest
    • compile/metadata.rsread_app_metadata, lookup_bundle_id_from_info_plist, package_bundle_id_from_input, target_bundle_section, toml_string, toml_build_number, package_name_for_path, rust_target_triple
    • compile/native_libs.rscollect_native_archives_for_lock, for_each_native_library_package, derive_target_key
    • compile/ios_deeplinks.rsinject_ios_deeplinks
    • compile/harmonyos_arkts.rsemit_harmonyos_arkts_stubs

Acceptance

Per-PR conventions from #1097. Plus, because this is the CLI entry point, smoke-test each major target before merging the final PR:

  • cargo run --release -- some.ts -o out && ./out
  • cargo run --release -- some.ts --target ios-simulator -o out
  • Optionally android/harmonyos if the local toolchain is set up

Metadata

Metadata

Assignees

Labels

toolingDeveloper tooling, CI, tests, or release infrastructure

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions