Skip to content

Ensure static frameworks are embedded by default - #1628

Merged
yonaskolb merged 1 commit into
yonaskolb:masterfrom
daltonclaybrook:dalton/embed-static-frameworks
Jul 16, 2026
Merged

Ensure static frameworks are embedded by default#1628
yonaskolb merged 1 commit into
yonaskolb:masterfrom
daltonclaybrook:dalton/embed-static-frameworks

Conversation

@daltonclaybrook

Copy link
Copy Markdown
Contributor

Resolves #1627

@yonaskolb yonaskolb left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Thanks @daltonclaybrook. I added that the previous behaviour happens on older declared xcode versions.

@yonaskolb
yonaskolb merged commit 4c62889 into yonaskolb:master Jul 16, 2026
3 checks passed
@marcos-strava

Copy link
Copy Markdown

Hi @daltonclaybrook and @yonaskolb this PR seems to have broken our project somehow. Our project is large and complex with dozens of xcodegen files, so it's unclear what we need to update in our xcodegen files to get this back on track.

The associated issue describes that since Xcode 15 the embed setting maybe have been happening automatically, but clearly something in our project isn't doing it 😅

Do you have some notes or suggestions of what needs to change ideally?

@daltonclaybrook

Copy link
Copy Markdown
Contributor Author

Hey @marcos-strava, Sorry you're having issues. I'd love to help you get to the bottom of this, but I need more information. I assume you're using static frameworks (type: framework.static) in your project? Are you seeing an error message? Is the build failing? Is the app crashing at runtime? Is it failing app store validation? What exactly do you mean by "broken our project somehow"?

@marcos-strava

marcos-strava commented Jul 28, 2026

Copy link
Copy Markdown

Hey @marcos-strava, Sorry you're having issues. I'd love to help you get to the bottom of this, but I need more information. I assume you're using static frameworks (type: framework.static) in your project? Are you seeing an error message? Is the build failing? Is the app crashing at runtime? Is it failing app store validation? What exactly do you mean by "broken our project somehow"?

Sorry should've been more transparent from the start! Yeah I first noticed an issue because we were setting up a new CI machine, so we ran the usual brew install xcodegen. It wasn't clear at the time, but two issues kept happening. When running one of our fastlane lanes that creates an adhoc build, we were noticing compile issues like:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/bitcode_strip ....
ld: file cannot be open()ed, errno=2 path=strip

This was also annoying but we fixed it by setting STRIP_BITCODE_FROM_COPIED_FILES: NO on our main app target. Then after this, the build > archive succeeded and a signed IPA was created, but then the app refused to install to device and looked like an empty icon:
image

This is where we currently are. We've identified that it's the latest 2.46.0 Xcodegen version because if we revert back to even 2.45.4, we don't have either of the issues above^.

As far as project settings a lot of our static targets actually still look like:

ActivitySave:
    platform: iOS
    type: framework
    sources:
      - Sources/ActivitySave
    settings:
      INFOPLIST_FILE: Libraries/Shared/Plists/Framework-Info.plist
      APPLICATION_EXTENSION_API_ONLY: false
      MACH_O_TYPE: staticlib

For dynamic libraries, those usually look like

AttributionInterface:
    platform: iOS
    type: framework
    sources: [Sources/AttributionInterface]
    settings:
      INFOPLIST_FILE: Libraries/Shared/Plists/Framework-Info.plist
      APPLICATION_EXTENSION_API_ONLY: NO
      MACH_O_TYPE: mh_dylib

We then have our main app target:

Strava:
    type: application
    platform: iOS
    sources:
      .....
    dependencies:
      - target: ActivitySave
      - target: AttributionInterface
        embed: true

Any ideas?

@daltonclaybrook

daltonclaybrook commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

I'd suggest explicitly passing embed: false for ActivitySave:

- target: ActivitySave
  embed: false

When you have more time, you could try using type: framework.static and removing MACH_O_TYPE: staticlib. Maybe this is what's tripping Xcode up.

@marcos-strava

Copy link
Copy Markdown

I'd suggest explicitly passing embed: false for ActivitySave:


- target: ActivitySave

  embed: false

When you have more time, you could try using type: framework and removing MACH_O_TYPE: staticlib. Maybe this is what's tripping Xcode up.

Does MACH_O_TYPE default to static lib when omitted?

Ill give it a shot, but we have about 300+ targets so it's hard to know what are all the places that need to change. Are you familiar with any project settings that can help here?

@marcos-strava

Copy link
Copy Markdown

Okay after several Claude assisted attempts, we had to:

  1. Add the following build settings to our main app target:
STRIP_BITCODE_FROM_COPIED_FILES: false
REMOVE_STATIC_EXECUTABLES_FROM_EMBEDDED_BUNDLES: true
  1. We had to make all MACH_O_TYPE: staticlib dependencies (including those that get transitively linked) be embed:false in the main target AND other extension targets (watch, widget, etc) as @daltonclaybrook had suggested. This was probably the most frustrating one because it took a lot of trial and error. Fastlane did not output any errors during archiving and only failed to install and/or launch. It really was only because Claude could analyze the logs in ~/Library/Logs/gym to know which dependencies were linked and it compared it against a pre 2.46.0 log file we had.
- target: ActivityDataCorrection
        embed: false

We're now validating that the changes we made here won't break pre 2.46.0 versions, but even then this change was not in the 2.46.0 change log and should possibly be considered a breaking change imo. Hopefully it helps others who find this PR.

@daltonclaybrook

daltonclaybrook commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Does MACH_O_TYPE default to static lib when omitted?

@marcos-strava Sorry, I mis-typed my original message (which I've now edited). MACH_O_TYPE: staticlib is the default when you use type: framework.static, not type: framework. I'd suggest changing all your targets currently using type: framework with explicit MACH_O_TYPE: staticlib to type: framework.static and omitting MACH_O_TYPE.

After you've made this change, I'd be curious to know if using embed: false is no longer necessary.

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.

Default embed behavior for framework.static targets is incorrect

3 participants