Carthage: Automate copy-frameworks arguments — quite error prone

Created on 17 Feb 2016  Â·  10Comments  Â·  Source: Carthage/Carthage

The README reads:

4. On your application targets’ “Build Phases” settings tab, click the “+” icon and choose “New Run Script Phase”. Create a Run Script with the following contents:

/usr/local/bin/carthage copy-frameworks
and add the paths to the frameworks you want to use under “Input Files”, e.g.:

$(SRCROOT)/Carthage/Build/iOS/Box.framework
$(SRCROOT)/Carthage/Build/iOS/Result.framework
$(SRCROOT)/Carthage/Build/iOS/ReactiveCocoa.framework
This script works around an App Store submission bug triggered by universal binaries and ensures that necessary bitcode-related files and dSYMs are copied when archiving.

This can be quite a chore for Carthage users. This additional step makes maintaining the Xcode project quite error prone. For instance, it's possible to run and debug your app on the Simulator without a copy-framework step. Linker errors due to frameworks not being found (they weren't copied) would show up only when you're debugging on the device.

Provided this workaround will stick around (!), is there any way for copy-frameworks to get smart, and basically figure out from Cartfile that it should probably go and copy those dependencies' build .framework artefacts to save the developer from having to maintain this Run Build Phase?

Or, is this not Carthage's responsibility, because it's 'flexible'?

enhancement help wanted

Most helpful comment

Has anyone tried the following:

https://github.com/lvillani/carthage-copy-frameworks

It is suppose to automate the build phase and include all frameworks with one line.

All 10 comments

TBH I'm not sure why it was done that way. But having Carthage do it does seem like it'd be preferable if possible.

Provided this workaround will stick around (!), is there any way for copy-frameworks to get smart, and basically figure out from Cartfile that it should probably go and copy those dependencies' build .framework

That's a good idea. In practice, however, I think that assumes an ideal scenario. If you consider projects with multiple targets of different platforms, with Carthage dependencies that may or may not be for all platforms, and targets that may not want all dependencies... this wouldn't work so well.

I suppose if we can cross-check Cartfile with the list of linked frameworks in each target that should be accurate.

But @fatuhoku you're totally right. However, if you think about it, what's error prone is Xcode's configuration itself. Copying frameworks is necessary whether you use Carthage or not. The fact that this is done with copy-frameworks in the case of fat Carthage frameworks is just due to a century-old bug (excuse my perception problem again... I meant to say lack of a feature) that won't remove unnecessary slices from .frameworks.

To me, it would simplify everything if Carthage just built separate frameworks for the device vs the simulator instead of having to smash them together and then pull them apart again.

You can use the $(PLATFORM_NAME) macro to get "iOS" vs "iOS Simulator" and so forth, so it would only require minor updates to build settings for users.

Has anyone tried the following:

https://github.com/lvillani/carthage-copy-frameworks

It is suppose to automate the build phase and include all frameworks with one line.

Yes @zirinisp, I just tried the carthage-copy-frameworks and it works for me!
Could be worth mentioning in the README or somehow integrate this into Carthage

I uses the following Ruby script

#!/usr/bin/env ruby

command = "/usr/local/bin/carthage copy-frameworks"
frameworks_path = File.join(ARGV.first || ".", "Carthage/Build/iOS")
frameworks = Dir.entries(frameworks_path)
  .select { |entry| File.extname(entry) == ".framework" }
  .map { |framework| File.join(frameworks_path, framework) }
env_vars = frameworks.each_with_index
  .map { |framework, index| "SCRIPT_INPUT_FILE_#{index}=#{framework}" }
  .join(" ")
`SCRIPT_INPUT_FILE_COUNT=#{frameworks.count} #{env_vars} #{command}`

and then call it through a run script phase like

$SRCROOT/script/copy_frameworks $SRCROOT

I have created a github project with a single python script here. You still have to provide Input Files in the build-phase setup, but you can provide only the frameworks build directly by projects in your Cartfile. Any dependecies of those frameworks are determined automatically using otool -L

Ref: #2477

Anybody coming across this issue nowadays, please checkout my comment here.

Closing because integrating XCFrameworks does not require carthage copy-frameworks: https://github.com/Carthage/Carthage#migrating-a-project-from-framework-bundles-to-xcframeworks

Was this page helpful?
0 / 5 - 0 ratings