Repository navigation
addSourceFile records a .mm file as type unknown, in a build file named for Resources #198
Description
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
erisu commentedon Oct 29, 2026
@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.objcppfor ObjC++ (.mm) source files.If you have any additional testing, can you test and let me know if this PR is good?
YevheniiKotyrlo commentedon Oct 29, 2026
Thanks for picking this up so quickly! I ran the reproduction from the issue against #199 at f4a295c:
Untyped.mmandTyped.mmnow both getfileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp, and their build files readin Sources.I also built a macOS command-line tool whose
.mmwas added withaddSourceFileat that commit: Xcode 27.1 compiles it as Objective-C++, and the tool runs. It resolves the issue for me.