JamitLabs / Accio

A dependency manager driven by SwiftPM that works for iOS/tvOS/watchOS/macOS projects.
MIT License
664 stars 32 forks source link

Is it possible to choose if the generated framework for a dependency is static or dynamic? #48

Closed acecilia closed 4 years ago

acecilia commented 5 years ago

Hi :)

Just discovered Accio, sounds very promising. My question is: is it possible to choose which kind of framework to generate for a dependency, dynamic or static?

Let me add some context to the question. Recently, there is an ongoing conversation in the community about which are better: dynamic or static frameworks (see for example https://github.com/ReactiveX/RxSwift/pull/1960). Seems like static frameworks allow for faster launch times and smaller app bundles (as static linking allows to remove unused symbols). At the moment, when using Carthage, the author of the dependency is the one configuring the Xcode project and selecting how the framework is going to be generated: dynamic or static. Consumers of the dependencies have to rely on hacks in order to generate a static framework.

As mentioned here:

Consumer should decide how they want to consume the library not the library authors. Library authors should decide on the API and code only.

Is this possible with Accio?

Thanks, Andres

Jeehut commented 5 years ago

Short answer: Nope, currently this is not supported.

And actually, I wasn't aware of the fact that the framework authors could decide to make a library static using Carthage, I always thought it's always dynamic. If there's an easy way of altering an Xcode project to produce a static framework rather than a dynamic framework, we could definitely add this feature into Accio though. We are already doing quite some corrections in the XcodeProjectIntegrationService and could add an option to explicitly change the framework type to static or dynamic if specified via a parameter, which would need to be defined also.

Could you please explain the steps necessary to set the framework type? Is there even a simple way? And would you be up to implementing the change and posting a PR? I'll be on vacation the coming weeks, so I might only be able to have a cursory look and comment. But @fredpi, @JensK611 and @mrylmz might be able to help in the meantime.

acecilia commented 5 years ago

Yes. I will look into it as soon as I find some time :)

Short answer:

We may have all the necessary things to make this happen :)

Long answer:

/// A library's product can either be statically or dynamically linked. It /// is recommended to not declare the type of library explicitly to let the /// Swift Package Manager choose between static or dynamic linking depending /// on the consumer of the package.

Seems the SPM allows the consumer to specify how the linking happens, but I did not fully understand how yet. I will need to look into it.

xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
trap 'rm -f "$xcconfig"' INT TERM HUP EXIT
echo "MACH_O_TYPE = staticlib" >> $xcconfig
export XCODE_XCCONFIG_FILE="$xcconfig"
carthage bootstrap --platform ios --no-use-binaries
andrewtheis commented 5 years ago

Carthage also supports downloading prebuilt static frameworks (these are built in Objective-C, as Swift will not support static frameworks until module stability in 5.1). For example a Cartfile can declare:

binary "https://dl.google.com/dl/firebase/ios/carthage/FirebaseAnalyticsBinary.json" == 6.1.0

In the JSON file you see a list of prebuilt frameworks for each version:

{
  "6.0.0":"https://dl.google.com/dl/firebase/ios/carthage/6.0.0/Analytics-597265ca9352ba4a.zip",
  "6.1.0":"https://dl.google.com/dl/firebase/ios/carthage/6.1.0/Analytics-dba70a4b2638700a.zip",
  // ...
}

Carthage just downloads these frameworks for you. They do not need to be added to the Carthage Copy Frameworks phase as they are linked/copied as part of Xcode's normal build process.

As far as I can tell, SPM does not support this in the manifest, so Accio may need to add a supplementary file that it scans for this case.

acecilia commented 5 years ago

@andrewtheis Swift static frameworks are already supported. From here: Since version 0.30.0 Carthage project rolls out support for statically linked frameworks written in Swift or Objective-C

From what I researched so far, you are right, SPM does not support specifying if the produced framework should be static or dynamic, and Accio will need to get that information somehow.

mrylmz commented 5 years ago

Maybe we have to check the part for copy frameworks build phase to fully support the statically linked frameworks with carthage. The only investigation we have to do is configuring the static linkage of the libraries correctly inside the project

Adding support to SPM based project could possibly be more difficult.

Jeehut commented 5 years ago

So, how would the consumer of a package specify if it is integrated as a static or dynamic framework? I didn't quite get this from the above comments ... other than that, it reads like we could support this. Is anyone up to implement it?

acecilia commented 5 years ago

So, how would the consumer of a package specify if it is integrated as a static or dynamic framework?

@Dschee I think there is no final decision on this yet. For now, what seems to be the main proposal is to introduce an accio.yml/accio.swift configuration file

EDIT: I just created https://github.com/JamitLabs/Accio/issues/54 in order to look into this

fredpi commented 4 years ago

Closing this, as Accio is now deprecated.