Skip to content

MLXHuggingFace: consider a macro-free path — its macros pull swift-syntax into consumer build graphs #339

@roryford

Description

@roryford

First — thanks for the v3 decoupling work in #118; the tokenizer/downloader seams are exactly what downstream SDKs need.

One follow-up cost we measured: the MLXHuggingFace product's only content is freestanding convenience macros (#huggingFaceTokenizerLoader(), #hubDownloader(), …), implemented in the MLXHuggingFaceMacros macro target. Depending on the product therefore compiles swift-syntax in every consumer graph.

Measured impact (ManifoldKit, an Apple-platforms LLM SDK wrapping MLXLLM/MLXVLM): in our default build the macro chain accounted for 103 swift-syntax compile tasks, 248 build tasks total, and ~24% of build CPU (794.7s → 601.8s user after removal). We worked around it by hand-inlining the macro expansion and dropping the product: roryford/ManifoldKit#1746

The expansions don't depend on the call site. TokenizerLoaderMacro/TokenizerAdaptorMacro/DownloaderMacro each expand to a fixed bridge type (TransformersLoader, TokenizerBridge, HubBridge). Ordinary public types would provide identical functionality with no swift-syntax involvement, e.g.:

// instead of: using: #huggingFaceTokenizerLoader()
using: HuggingFaceTokenizerLoader()

Suggestions (any subset helps):

  1. Export the bridge types as plain public API in MLXHuggingFace (macros could remain as sugar, or be deprecated).
  2. If the macros stay, consider raising the swift-syntax floor to 602.0.0 — swift.org's signed prebuilts are keyed per swift-syntax tag + exact toolchain, and 600.0.1/601.0.1 artifacts are no longer published for current toolchains (verified: on Swift 6.3.2 / Xcode 26.5, a 600.x resolution silently falls back to the full ~212-task source compile, while 603.0.1 resolves to a prebuilt and builds in seconds). A downstream package pinning 600.x also drags the unified resolution below the prebuilt floor for everyone in the graph.
  3. Alternatively, move the macro layer into a separate opt-in product so MLXHuggingFace consumers who only need the bridges don't carry the macro target.

Happy to open a PR for option 1 (plain bridge types + macro deprecation) if that direction is agreeable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions