Skip to content

removeSourceFile finds the Sources build phase entry by its comment, so a .mm added by 4.0.0 leaves its entry behind #202

Open

Description

@YevheniiKotyrlo

Split out of #200, as suggested there: this is its removeSourceFile half.

Summary

removeSourceFile deletes the file's PBXBuildFile by the file's name, but finds its entry in the Sources build phase by comment: longComment(file), "<name> in <group>", with the group the running version detects for the file's type. An entry commented any other way stays in the build phase, pointing at a PBXBuildFile that no longer exists.

An upgrade is enough to get there. 4.0.0 doesn't map .mm, so it comments a .mm's build file in Resources; master, which maps it since #199, looks for in Sources. So a plugin's .mm that cordova-ios added with 4.0.0 and removes with a release that includes #199 leaves its entry in the Sources build phase. Once #201 lands, the same happens to a .c, .cpp, .cc or .cxx that 4.0.0 added.

Steps to reproduce

  1. Download the gist https://gist.github.com/YevheniiKotyrlo/83e2ad5c1e82e506fe82cea69371b9d2 into an empty folder: package.json, which depends on xcode from this repository at 354a163 and on xcode@4.0.0 as xcode-4.0.0, and repro.js.
  2. Add the repository's test project beside them and install:
    curl -sSfLO https://raw.githubusercontent.com/apache/cordova-node-xcode/354a1631d0a448531e4cc0aee8ca60c89262d1f1/test/parser/projects/full.pbxproj
    npm install
    npm 12 fetches the git dependency only with --allow-git=root.
  3. Run node repro.js full.pbxproj. It adds Plugins/com.example.plugin/Plain.mm with addSourceFile(path, {}) and removes it with removeSourceFile(path), as cordova-ios does for a plugin's <source-file> (install, uninstall): first with master for both, then adding with 4.0.0. It prints the build file and build phase lines each addition wrote, and every line still naming Plain.mm after the removal.

Expected: nothing names Plain.mm after the removal, whichever version added it.

Actual: when 4.0.0 added it, the Sources build phase keeps Plain.mm in Resources, whose uuid is defined nowhere:

== added by master, removed by master
added:   F27FAA5682EF4239A600E77C /* Plain.mm in Sources */ = {isa = PBXBuildFile; fileRef = 72327B084AD0454E92716875 /* Plain.mm */; };
added:   F27FAA5682EF4239A600E77C /* Plain.mm in Sources */,
removed: nothing names Plain.mm
== added by xcode@4.0.0, removed by master
added:   F6903D0DF1184805B24735FB /* Plain.mm in Resources */ = {isa = PBXBuildFile; fileRef = 6B24BFC6BB1E4C748A7A0220 /* Plain.mm */; };
added:   F6903D0DF1184805B24735FB /* Plain.mm in Resources */,
removed: F6903D0DF1184805B24735FB /* Plain.mm in Resources */,    <- F6903D0DF1184805B24735FB is defined nowhere

The uuids are random, so they differ from run to run. Node 26.12.1 on Windows 11; xcode from master at 354a163. What Xcode does with the leftover entry I haven't checked.

Reading

lib/pbxProject.js at 354a163: removeSourceFile calls removeFromPbxBuildFileSection, which deletes every PBXBuildFile whose fileRef_comment is the file's basename and records its uuid on file.uuid, then removeFromPbxSourcesBuildPhase, which splices the first entry whose comment === longComment(file). Matching the entry by the uuid removeFromPbxBuildFileSection just found would remove it whatever its comment says. removeFromPbxResourcesBuildPhase, removeFromPbxFrameworksBuildPhase, removeFromPbxCopyfilesBuildPhase and removeFromPbxEmbedFrameworksBuildPhase match by longComment the same way.

Activity

  1. breautek commented on Nov 6, 2026

    @breautek
    Contributor

    If I understand correctly, sources that was added pre #199 were sources that was not mapped, so they defaulted to the Resource Group.

    Post #199 attempting to remove these sources attempt to remove them from the Sources group and because these extensions are now properly mapped to the Sources group it will not find the file reference to remove, as the actual file reference is in the Resources group.

  2. YevheniiKotyrlo commented on Nov 6, 2026

    @YevheniiKotyrlo
    Author

    Yes, except that the file reference is found and removed, and so is its PBXBuildFile. What it misses is the file's entry in the Sources build phase: 4.0.0 added it there with the comment Plain.mm in Resources, and since #199 removeSourceFile looks for Plain.mm in Sources, so the entry stays, pointing at a PBXBuildFile that no longer exists.

  3. self-assigned this
    on Nov 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions