Skip to content

Conversation

@paul-han-n
Copy link

Summary

This pull request addresses several Xcode compatibility issues related to file system synchronized groups, Swift package references, and build phase serialization. These fixes ensure that generated project files match Xcode's expected format and maintain proper compatibility with Xcode 15+.

Changes

1. Unicode NFD Normalization for Xcode Compatibility

File: lib/xcodeproj/project/object.rb

Added Unicode NFD (Normalization Form Decomposed) normalization to the ascii_plist_annotation method. This ensures that special characters in display names are properly normalized to match Xcode's internal representation.

Why: Xcode internally uses NFD normalization for strings. Without this normalization, projects with non-ASCII characters (e.g., accented characters, Korean, Japanese) may experience compatibility issues or display inconsistencies when opened in Xcode.

2. Improved Swift Package URL Parsing

File: lib/xcodeproj/project/object/swift_package_remote_reference.rb

Enhanced the extract_package_name method to correctly handle various Git repository URL formats:

  • HTTPS URLs: https://github.com/owner/repo.gitrepo
  • SSH URLs: git@github.com:owner/repo.gitrepo
  • Custom registry URLs: domain.xyzxyz

Why: Previous implementation didn't correctly parse all URL formats, leading to inconsistent package naming in project files. The improved parser ensures consistent and correct package names across different repository URL schemes.

3. Fixed displayName for File System Synchronized Exception Sets

File: lib/xcodeproj/project/object/file_system_synchronized_exception_set.rb

Changed the displayName for exception sets from descriptive strings to Xcode's internal class names:

  • PBXFileSystemSynchronizedBuildFileExceptionSet for build file exceptions
  • PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet for build phase membership exceptions

Why: Xcode uses the class name as the display name for these objects, not descriptive strings. Using descriptive names caused project file format mismatches.

Added: Support for attributes_by_relative_path attribute in PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet to match Xcode's data model.

4. Remove Empty Exception Arrays from File System Synchronized Root Groups

File: lib/xcodeproj/project/object/file_system_synchronized_root_group.rb

Added to_hash_as method that excludes empty exceptions arrays from serialization.

Why: Xcode doesn't serialize empty exception arrays in PBXFileSystemSynchronizedRootGroup objects. Including them creates unnecessary diff noise and doesn't match Xcode's output format. Related to #1012.

5. Use Full Path in XCLocalSwiftPackageReference Annotations

File: lib/xcodeproj/project/object/swift_package_local_reference.rb

Changed annotation from using File.basename(display_name) to using the full display_name path.

Why: Xcode uses the full relative path in annotations for local Swift package references, not just the basename. This ensures the annotation matches Xcode's format exactly.

6. Ensure inputPaths and outputPaths Always Present in Shell Script Build Phases

File: lib/xcodeproj/project/object/build_phase.rb

Modified PBXShellScriptBuildPhase serialization to always include inputPaths and outputPaths arrays, even when empty.

Why: Xcode always serializes these fields as empty arrays when not set, rather than omitting them. This prevents unnecessary project file changes when the project is opened and saved in Xcode.

Testing

These changes have been tested to ensure:

  • Generated project files match Xcode's format exactly
  • Projects can be opened and modified in Xcode without generating spurious diffs
  • Unicode characters in file/folder names are handled correctly
  • All Swift package URL formats are parsed correctly
  • File system synchronized groups serialize properly

Compatibility

  • No breaking changes to the public API
  • Maintains backward compatibility with existing projects
  • Improves forward compatibility with Xcode 15+

Related Issues

paul-han-n and others added 9 commits November 28, 2025 01:51
Remove File.basename() wrapper to preserve the complete display_name
path in ascii_plist_annotation output instead of just the base filename.
- Handle https:// and git@ prefixed URLs by extracting last path component
- For other formats, split by dot and use last component
- Supports both GitHub and custom registry URL formats
…patibility

- Add encoding check before unicode_normalize to prevent errors
- Only normalize UTF-8 and US-ASCII encoded strings
- Ensures compatibility with xcode which uses NFD
- Prevents Encoding::CompatibilityError for non-Unicode encodings
…ference

Xcode uses only the part before the first dot when generating
annotation names for remote Swift package references.
e.g., socket.io-client-swift -> socket
fix: extract package name before first dot for XCRemoteSwiftPackageReference
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.

2 participants