You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+38-91Lines changed: 38 additions & 91 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,63 +1,42 @@
1
1
# GenerateInterface
2
2
3
-
A command-line tool that automatically generates Swift interface modules from compiled module interfaces using SourceKit and SwiftSyntax.
3
+
Auto-generate Swift interface modules from compiled modules using SourceKit and SwiftSyntax - eliminating unnecessary recompilation in modular iOS codebases.
4
4
5
-
## The Problem
5
+
## Why?
6
6
7
-
In large modular iOS codebases, modules often depend on each other's full implementations even when they only need access to the public API. This means changing an implementation detail in one module can trigger recompilation of all dependent modules, slowing down builds significantly.
7
+
In large modular iOS projects, changing an implementation detail in one module triggers recompilation of every dependent module. **Interface modules** break this chain by exposing only the public API surface - dependents import the lightweight interface instead of the full implementation.
8
8
9
-
**Interface modules** solve this by extracting a module's public API surface into a separate, lightweight module. Dependents import the interface module instead of the full implementation, so implementation changes no longer cascade rebuilds across the dependency graph.
9
+
Maintaining these by hand is tedious and error-prone. This tool automates the entire process.
10
10
11
-
Creating and maintaining these interface modules by hand is tedious and error-prone. This tool automates the process.
11
+
## What it does
12
12
13
-
## What It Does
14
-
15
-
Given a module name and its compiler arguments, the tool:
16
-
17
-
1.**Extracts the module interface** via SourceKit (the same engine Xcode uses for code completion and indexing)
18
-
2.**Rewrites the interface** using SwiftSyntax - strips private/internal imports (prefixed with `_`), removes `some`/`any` type erasure wrappers, simplifies member type syntax, filters out builder classes, and merges duplicate extensions
19
-
3.**Replaces declarations** with their original source versions when available (preserving doc comments, attributes, and formatting)
20
-
4.**Creates the interface module directory** with a `Sources/` folder
21
-
5.**Rewrites import statements** across the codebase (`import Module` -> `import ModuleInterface`)
22
-
6.**Updates Project.swift** to register the new interface module with the correct dependencies (Tuist-specific)
13
+
- Extracts the public module interface via SourceKit (`source.request.editor.open.interface`)
The script builds the tool, compiles a sample Swift module via SPM, extracts compiler arguments, and runs the tool. Use `--write` to execute the full pipeline, or omit it to preview with `--print-only`.
55
-
56
-
After running with `--write`, you'll see:
57
-
-`libraries/business/UserProfileInterface/` created with `Sources/`
58
-
-`Project.swift` updated with the new interface module declaration
The JSON output is keyed by module name, then by source file path. Each entry contains a `swiftASTCommandArguments` array. Extract those arguments, remove`-module-name` and the module name itself, and write one argument per line to a file:
80
+
Parse `swiftASTCommandArguments`, removing`-module-name` and the module name:
106
81
107
82
```bash
108
-
# Using jq as an example (the Ruby wrapper does this automatically)
-**SourceKittenFramework** - sends a `source.request.editor.open.interface` request to Xcode's SourceKit daemon, which returns the full public interface of a compiled module (the same text you see in Xcode's "Generated Interface" view)
156
-
-**SwiftSyntax** - parses and rewrites the generated interface at the AST level, ensuring transformations are structurally correct rather than fragile string replacements
101
+
## How it works
157
102
158
-
The `ProjectRewriter` manipulates Tuist's `Module(...)` declarations via SwiftSyntax to add the new interface module definition, update dependency lists, and wire up test support targets.
103
+
-**SourceKit** returns the full public interface of a compiled module (same as Xcode's "Generated Interface" view)
104
+
-**SwiftSyntax** parses and rewrites the interface at the AST level - structurally correct transformations, not string replacements
105
+
-**ProjectRewriter** manipulates Tuist `Module(...)` declarations to register the new interface module and update dependencies
159
106
160
107
## Limitations
161
108
162
-
-The `Project.swift` rewriting is specific to a Tuist project structure using `Module(...)` declarations with `kind`, `moduleDependencies`, and `features` parameters. You may need to adapt `ProjectRewriter.swift` for your project's conventions.
163
-
-The Ruby wrapper assumes an Xcode workspace-based project. Adjust if using a different build system.
164
-
- Builder class filtering (`classes inheriting from Builder are excluded`) is project-specific behavior.
109
+
-`Project.swift` rewriting is specific to Tuist projects using `Module(...)` declarations with `kind`, `moduleDependencies`, and `features` parameters - adapt `ProjectRewriter.swift` for other conventions
110
+
- Ruby wrapper assumes an Xcode workspace-based project
111
+
- Builder class filtering is project-specific behavior
0 commit comments