Skip to content

feat(ios): manage generated modulemaps in CLI-controlled directory instead of node_modules#6063

Open
edusperoni wants to merge 2 commits into
mainfrom
feat/dont-write-ios-node-modules
Open

feat(ios): manage generated modulemaps in CLI-controlled directory instead of node_modules#6063
edusperoni wants to merge 2 commits into
mainfrom
feat/dont-write-ios-node-modules

Conversation

@edusperoni

@edusperoni edusperoni commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

PR Checklist

What is the current behavior?

When preparing an iOS plugin that ships a static library (.a) with headers, the CLI generates a module.modulemap and writes it into node_modules — next to the plugin's headers at node_modules/{plugin}/platforms/ios/.../include/{lib}/module.modulemap. This mutates node_modules, which should be treated as immutable (it breaks clean/reproducible installs, dirties caches, and is the iOS counterpart to the Android side writing generated .aars back into node_modules).

What is the new behavior?

The generated modulemap is now written into a CLI-managed directory under the platform root — platforms/ios/.plugins/{lib}/module.modulemap — and never into node_modules.

  • generateModulemap() writes to the new .plugins location and references the plugin's headers in place via relative paths (header "<relative path back to node_modules>"), so no headers are copied or linked and node_modules is left untouched. It now returns a boolean indicating whether a modulemap was produced.
  • addStaticLibrary() adds the .plugins/{lib} directory to HEADER_SEARCH_PATHS so clang discovers the module from the new location; removeStaticLibs() removes it symmetrically on plugin removal.
  • No iOS runtime change is required: the runtime/metadata generator discovers modulemaps purely through HEADER_SEARCH_PATHS, which the CLI controls — so this works on any iOS runtime version.

Tests for generateModulemap were updated to cover the new output location, the relative header paths, and the boolean return value.

Summary by CodeRabbit

  • Refactor
    • Reorganized iOS static-library module.modulemap generation into a dedicated CLI-managed directory under the iOS project root.
    • Updated modulemap handling so stale files are removed when headers are missing, and Xcode header search paths are adjusted only when a modulemap is actually produced.
    • Improved dynamic framework binary path detection to align with updated path construction behavior.
  • Tests
    • Updated modulemap-related static library tests to match the new output location and updated generation outcomes.

@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 935d672b-823a-4b22-a5cc-cd9664586db7

📥 Commits

Reviewing files that changed from the base of the PR and between 1cb741c and 60a7b36.

📒 Files selected for processing (1)
  • lib/services/ios-project-service.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/services/ios-project-service.ts

📝 Walkthrough

Walkthrough

IOSProjectService now writes C/C++ modulemaps for static libraries into a CLI-managed directory (GENERATED_PLUGINS_DIR_NAME) under the iOS platform project root instead of the headers folder. generateModulemap is reworked to accept a target directory, return a boolean, and clean up stale files. Header search path additions and removals are updated accordingly, and tests reflect the new paths and return value.

Changes

Modulemap CLI-managed directory refactor

Layer / File(s) Summary
GENERATED_PLUGINS_DIR_NAME constant and isDynamicFramework path fixes
lib/services/ios-project-service.ts
Adds the GENERATED_PLUGINS_DIR_NAME constant and updates isDynamicFramework to build .xcframework and non-.xcframework binary paths via path.join.
generateModulemap rework
lib/services/ios-project-service.ts
generateModulemap now accepts a modulemapDir argument, ensures that directory exists, writes module.modulemap into it, removes a stale modulemap when no header files are present, and returns a boolean indicating success.
Static library add/remove wiring
lib/services/ios-project-service.ts
Static library preparation calls generateModulemap with the CLI-managed directory and adds it to Xcode header search paths only when the call returns true; removal deletes that same directory from header search paths.
Tests for new modulemap directory and boolean return
test/ios-project-service.ts
Tests target modulemapDir under <projectPath>/.plugins/<libraryName>, use path.relative for expected header entries, assert generateModulemap returns false after headers are deleted, and verify that reading module.modulemap from modulemapDir throws.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 No more maps tucked in headers' lair,
The CLI now picks a spot with care.
.plugins awaits each module's scroll,
A boolean returned to show control.
Paths joined just right, the test agrees—
The rabbit hops with tidy ease! 🗺️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and accurately reflects the main change: moving generated modulemaps from node_modules to a CLI-controlled directory.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/services/ios-project-service.ts`:
- Around line 1739-1745: The call to this.$fs.readDirectory(headersFolderPath)
will throw an error if the headersFolderPath directory does not exist, and there
is no guard to prevent this. Add an existence check using this.$fs.getFsStats or
a similar method before calling readDirectory to verify that headersFolderPath
exists and is a directory. If the directory does not exist, handle it gracefully
by returning an empty array or skipping the operation, so the filter operation
on headerFiles can proceed safely without throwing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 637c453c-b36e-4c97-848f-92ccf6eb636f

📥 Commits

Reviewing files that changed from the base of the PR and between 86cb6a5 and 1cb741c.

📒 Files selected for processing (2)
  • lib/services/ios-project-service.ts
  • test/ios-project-service.ts

Comment thread lib/services/ios-project-service.ts
A plugin can ship a static lib (.a) without an include/{lib} headers
folder. Check the headers dir exists before readDirectory so we bail out
gracefully (clean up any stale modulemap, return false) instead of
throwing. Addresses PR review feedback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant