Skip to content

addSourceFile records a .mm file as type unknown, in a build file named for Resources #198

Closed

Description

@YevheniiKotyrlo

Problem

lib/pbxFile.js maps no Objective-C++ extension: FILETYPE_BY_EXTENSION has m but no mm, and neither GROUP_BY_FILETYPE nor ENCODING_BY_FILETYPE knows sourcecode.cpp.objcpp. So addSourceFile('Untyped.mm', {}, group) writes a file reference with lastKnownFileType = unknown and fileEncoding = undefined, and the PBXBuildFile it adds to the Sources build phase is commented Untyped.mm in Resources. Passing lastKnownFileType: 'sourcecode.cpp.objcpp' fixes the type but not the encoding or the build file's group.

Xcode 27.1 still compiles an untyped .mm as Objective-C++ by its extension, so the project builds; what is wrong is the project file xcode writes.

Reproduction

With xcode installed from master at 940d6db, and the repository's own test/parser/projects/full.pbxproj:

const xcode = require('xcode');

const project = xcode.project(process.argv[2]);
project.parseSync();
const group = project.findPBXGroupKey({ name: 'Classes' });

project.addSourceFile('Plain.m', {}, group);
project.addSourceFile('Untyped.mm', {}, group);
project.addSourceFile('Typed.mm', { lastKnownFileType: 'sourcecode.cpp.objcpp' }, group);

const written = project.writeSync();
for (const line of written.split('\n')) {
  if (/\b(Plain\.m|Untyped\.mm|Typed\.mm)\b/.test(line) && /isa = PBX(FileReference|BuildFile)/.test(line)) {
    console.log(line.trim());
  }
}
const sources = project.pbxSourcesBuildPhaseObj().files.map((file) => file.comment);
console.log('Sources build phase:', sources.filter((comment) => /Plain|Typed/.test(comment)).join(', '));

node repro.js full.pbxproj (Node 26.12.1, Windows 11):

AD4216C6EB7446AAB29F9B39 /* Plain.m in Sources */ = {isa = PBXBuildFile; fileRef = 84E22FCC709E495BB2FDCC86 /* Plain.m */; };
4BC51096B73D49A48B4FEFFB /* Untyped.mm in Resources */ = {isa = PBXBuildFile; fileRef = 7A12F7DE99FF438E9EC2A936 /* Untyped.mm */; };
86294C477BE8437FA7AF65AE /* Typed.mm in Resources */ = {isa = PBXBuildFile; fileRef = F118177DC1BD4147864E3266 /* Typed.mm */; };
84E22FCC709E495BB2FDCC86 /* Plain.m */ = {isa = PBXFileReference; name = "Plain.m"; path = "Plain.m"; sourceTree = "<group>"; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; };
7A12F7DE99FF438E9EC2A936 /* Untyped.mm */ = {isa = PBXFileReference; name = "Untyped.mm"; path = "Untyped.mm"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; };
F118177DC1BD4147864E3266 /* Typed.mm */ = {isa = PBXFileReference; name = "Typed.mm"; path = "Typed.mm"; sourceTree = "<group>"; fileEncoding = undefined; lastKnownFileType = sourcecode.cpp.objcpp; explicitFileType = undefined; includeInIndex = 0; };
Sources build phase: Plain.m in Sources, Typed.mm in Resources

Expected

Each .mm typed sourcecode.cpp.objcpp with fileEncoding = 4, and its build file in Sources, as Plain.m gets for .m. 4.0.0 from npm writes the same as master.

Activity

  1. erisu commented on Oct 29, 2026

    @erisu
    Member

    @YevheniiKotyrlo
    I opened a PR and updated the mappings. I believe it resolves this ticket.
    Using your sample code, we can now see fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp for ObjC++ (.mm) source files.
    If you have any additional testing, can you test and let me know if this PR is good?

  2. YevheniiKotyrlo commented on Oct 29, 2026

    @YevheniiKotyrlo
    Author

    Thanks for picking this up so quickly! I ran the reproduction from the issue against #199 at f4a295c: Untyped.mm and Typed.mm now both get fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp, and their build files read in Sources.

    I also built a macOS command-line tool whose .mm was added with addSourceFile at that commit: Xcode 27.1 compiles it as Objective-C++, and the tool runs. It resolves the issue for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    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