Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WEB-749] ReactiveExtensions and ReactiveSwift to SPM #1745

Merged
merged 9 commits into from Oct 19, 2022

Conversation

msadoon
Copy link
Contributor

@msadoon msadoon commented Oct 11, 2022

πŸ“² What

Our final two Carthage dependency Reactive-Extensions and ReactiveSwift needs to move to SPM.

πŸ€” Why

Part of a platform upgrade to move all our dependencies away from Carthage and shell scripts building for non-M1 architectures to more dependable Swift Package Manager. Context.

πŸ›  How

This requires us making our internal ReactiveExtensions library SPM compatible. Here is the diff on the changes, but essentially what that requires is:

  • creating a top level Package.swift file.
  • Put all library files inside a Sources directory. Put tests inside a Tests directory.
  • For some reason in the package library we need to import Foundation in 3 files (KsrDebounce.swift, KsrDelay.swift, WithLatestFrom.swift) not sure why exactly, but seeing as this is the most basic of dependencies provided by Apple and the foundation for almost every other framework/library in existence on iOS, it is safe.
  • use swift package dump-package to validate Package.swift

The above were changes to the ReactiveExtensions repo to make it SPM compatible. After importing that library via SPM into our Kickstarter project, we include ReactiveExtensions into our main app target Kickstarter-iOS, Library-iOS, Kickstarter-Framework-iOS and KsApi. We also include ReactiveExtensions-TestHelpers into the test targets of the aforementioned libraries.

As for ReactiveSwift we tried to use the included dependency within ReactiveExtensions instead of importing it via SPM separately but ended up with this strange linking error not being able to link it it through the RE package.

ld: warning: directory not found for option '-F/Users/mubarak/Desktop/Kickstarter/ios-oss/Carthage/Build/iOS'
Undefined symbols for architecture x86_64:
  "(extension in ReactiveSwift):ReactiveSwift.ReactiveExtensionsProvider.reactive.getter : ReactiveSwift.Reactive<A>", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "protocol witness table for ReactiveSwift.QueueScheduler : ReactiveSwift.Scheduler in ReactiveSwift", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "(extension in ReactiveSwift):ReactiveSwift.Reactive<A where A: __C.NSURLSession>.data(with: Foundation.URLRequest) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error>", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.start(on: ReactiveSwift.Scheduler) -> ReactiveSwift.SignalProducer<A, B>", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.flatMap<A>(ReactiveSwift.FlattenStrategy, (A) -> ReactiveSwift.SignalProducer<A1, B>) -> ReactiveSwift.SignalProducer<A1, B>", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.map<A>((A) -> A1) -> ReactiveSwift.SignalProducer<A1, B>", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_JSONResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?) -> ReactiveSwift.SignalProducer<Any, KsApi.ErrorEnvelope> in NSURLSession.o
      KsApi.Service.decodeModel<A where A: Swift.Decodable>(data: Foundation.Data) -> ReactiveSwift.SignalProducer<A?, KsApi.ErrorEnvelope> in Service+DecodeHelpers.o
  "type metadata accessor for ReactiveSwift.QueueScheduler", referenced from:
      one-time initialization function for (scheduler in _EE2FFDFE3F55EAB482860367DB4D56EC) in NSURLSession.o
  "ReactiveSwift.SignalProducer.first() -> Swift.Result<A, B>?", referenced from:
      (extension in KsApi):KsApi.ApolloClientType.data<A where A1: Swift.Decodable>(from: ReactiveSwift.SignalProducer<A1, KsApi.ErrorEnvelope>) -> A1? in MockGraphQLClient.o
      (extension in KsApi):KsApi.ApolloClientType.error<A where A1: Swift.Decodable>(from: ReactiveSwift.SignalProducer<A1, KsApi.ErrorEnvelope>) -> KsApi.ErrorEnvelope? in MockGraphQLClient.o
  "protocol witness table for __C.NSURLSession : ReactiveSwift.ReactiveExtensionsProvider in ReactiveSwift", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.flatMapError<A where A1: Swift.Error>((B) -> ReactiveSwift.SignalProducer<A, A1>) -> ReactiveSwift.SignalProducer<A, A1>", referenced from:
      KsApi.Service.incrementVideoCompletion(forProject: KsApi.Project) -> ReactiveSwift.SignalProducer<KsApi.VoidEnvelope, KsApi.ErrorEnvelope> in Service.o
      KsApi.Service.incrementVideoStart(forProject: KsApi.Project) -> ReactiveSwift.SignalProducer<KsApi.VoidEnvelope, KsApi.ErrorEnvelope> in Service.o
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.init(value: A) -> ReactiveSwift.SignalProducer<A, B>", referenced from:
      static KsApi.ClientSecretEnvelope.envelopeProducer(from: KsApi.GraphAPI.CreateSetupIntentMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.ClientSecretEnvelope, KsApi.ErrorEnvelope> in ClientSecretEnvelope.o
      static KsApi.ErroredBackingsEnvelope.producer(from: KsApi.GraphAPI.FetchUserBackingsQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.ErroredBackingsEnvelope, KsApi.ErrorEnvelope> in ErroredBackingsEnvelope.o
      static KsApi.ProjectAndBackingEnvelope.envelopeProducer(from: KsApi.GraphAPI.FetchBackingQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.ProjectAndBackingEnvelope, KsApi.ErrorEnvelope> in ProjectAndBackingEnvelope.o
      static KsApi.WatchProjectResponseEnvelope.producer(from: KsApi.GraphAPI.WatchProjectMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.WatchProjectResponseEnvelope, KsApi.ErrorEnvelope> in WatchProjectResponseEnvelope+WatchProjectMutation.Data.o
      static KsApi.CreatePaymentSourceEnvelope.producer(from: KsApi.GraphAPI.CreatePaymentSourceMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.CreatePaymentSourceEnvelope, KsApi.ErrorEnvelope> in CreatePaymentSourceEnvelope+CreatePaymentSourceMutation.Data.o
      static KsApi.Project.projectProducer(from: KsApi.GraphAPI.FetchAddOnsQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.Project, KsApi.ErrorEnvelope> in Project+FetchAddOnsQueryData.o
      static KsApi.CategoryEnvelope.envelopeProducer(from: KsApi.GraphAPI.FetchCategoryQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.CategoryEnvelope, KsApi.ErrorEnvelope> in CategoryEnvelope+FetchCategoryQueryData.o
      ...
  "ReactiveSwift.SignalProducer.on(starting: (() -> ())?, started: (() -> ())?, event: ((ReactiveSwift.Signal<A, B>.Event) -> ())?, failed: ((B) -> ())?, completed: (() -> ())?, interrupted: (() -> ())?, terminated: (() -> ())?, disposed: (() -> ())?, value: ((A) -> ())?) -> ReactiveSwift.SignalProducer<A, B>", referenced from:
      KsApi.MockService.fetchProject(projectParam: KsApi.Param, configCurrency: Swift.String?) -> ReactiveSwift.SignalProducer<(project: KsApi.Project, backingId: Swift.Int?), KsApi.ErrorEnvelope> in MockService.o
  "nominal type descriptor for ReactiveSwift.Signal.Observer", referenced from:
      _symbolic _____y4Data_____Qz______G 13ReactiveSwift6SignalC8ObserverC 6Apollo16GraphQLOperationP 5KsApi13ErrorEnvelopeV in ApolloClient+RAC.o
  "ReactiveSwift.QueueScheduler.__allocating_init(qos: Dispatch.DispatchQoS, name: Swift.String, targeting: __C.OS_dispatch_queue?) -> ReactiveSwift.QueueScheduler", referenced from:
      one-time initialization function for (scheduler in _EE2FFDFE3F55EAB482860367DB4D56EC) in NSURLSession.o
  "ReactiveSwift.SignalProducer.init(error: B) -> ReactiveSwift.SignalProducer<A, B>", referenced from:
      static KsApi.ClientSecretEnvelope.envelopeProducer(from: KsApi.GraphAPI.CreateSetupIntentMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.ClientSecretEnvelope, KsApi.ErrorEnvelope> in ClientSecretEnvelope.o
      static KsApi.ErroredBackingsEnvelope.producer(from: KsApi.GraphAPI.FetchUserBackingsQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.ErroredBackingsEnvelope, KsApi.ErrorEnvelope> in ErroredBackingsEnvelope.o
      static KsApi.ProjectAndBackingEnvelope.envelopeProducer(from: KsApi.GraphAPI.FetchBackingQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.ProjectAndBackingEnvelope, KsApi.ErrorEnvelope> in ProjectAndBackingEnvelope.o
      static KsApi.WatchProjectResponseEnvelope.producer(from: KsApi.GraphAPI.WatchProjectMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.WatchProjectResponseEnvelope, KsApi.ErrorEnvelope> in WatchProjectResponseEnvelope+WatchProjectMutation.Data.o
      static KsApi.CreatePaymentSourceEnvelope.producer(from: KsApi.GraphAPI.CreatePaymentSourceMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.CreatePaymentSourceEnvelope, KsApi.ErrorEnvelope> in CreatePaymentSourceEnvelope+CreatePaymentSourceMutation.Data.o
      static KsApi.Project.projectProducer(from: KsApi.GraphAPI.FetchAddOnsQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.Project, KsApi.ErrorEnvelope> in Project+FetchAddOnsQueryData.o
      static KsApi.ClearUserUnseenActivityEnvelope.producer(from: KsApi.GraphAPI.ClearUserUnseenActivityMutation.Data) -> ReactiveSwift.SignalProducer<KsApi.ClearUserUnseenActivityEnvelope, KsApi.ErrorEnvelope> in ClearUserUnseenActivityEnvelope+ClearUserUnseenActivityMutation.Data.o
      ...
  "nominal type descriptor for ReactiveSwift.SignalProducer", referenced from:
      _symbolic __________yx_____GIeggo_ 10Foundation4DataV 13ReactiveSwift14SignalProducerV 5KsApi13ErrorEnvelopeV in Service+RequestHelpers.o
      _symbolic _____y_____7project_SiSg9backingIdt_____G 13ReactiveSwift14SignalProducerV 5KsApi7ProjectV AD13ErrorEnvelopeV in MockService.o
      _symbolic _____y_____7project_SiSg9backingIdt_____Gz_Xx 13ReactiveSwift14SignalProducerV 5KsApi7ProjectV AD13ErrorEnvelopeV in MockService.o
      _symbolic __________y__________GIeggo_ 5KsApi8GraphAPIO27CreatePaymentSourceMutationC4DataV 13ReactiveSwift14SignalProducerV AA0efG8EnvelopeV AA05ErrorN0V in Service.o
      _symbolic __________y__________GIeggo_ 5KsApi8GraphAPIO21CreateBackingMutationC4DataV 13ReactiveSwift14SignalProducerV AA0eF8EnvelopeV AA05ErrorM0V in Service.o
      _symbolic __________y__________GIeggo_ 5KsApi8GraphAPIO25CreateSetupIntentMutationC4DataV 13ReactiveSwift14SignalProducerV AA20ClientSecretEnvelopeV AA05ErrorP0V in Service.o
      _symbolic __________y__________GIeggo_ 5KsApi8GraphAPIO31ClearUserUnseenActivityMutationC4DataV 13ReactiveSwift14SignalProducerV AA0efgH8EnvelopeV AA05ErrorO0V in Service.o
      ...
  "ReactiveSwift.Signal.Observer.send(value: A) -> ()", referenced from:
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.fetch<A where A: Apollo.GraphQLQuery>(query: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.perform<A where A: Apollo.GraphQLMutation>(mutation: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Foundation.Data?, __C.NSURLResponse?, Swift.Error?) -> () in closure #1 (ReactiveSwift.Signal<(Foundation.Data, __C.NSURLResponse), Swift.Error>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):__C.NSURLSession.(rac_dataWithRequest in _EE2FFDFE3F55EAB482860367DB4D56EC)(_: Foundation.URLRequest, uploading: Foundation.URL, named: Swift.String) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error> in NSURLSession.o
  "ReactiveSwift.Signal.Observer.sendCompleted() -> ()", referenced from:
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.fetch<A where A: Apollo.GraphQLQuery>(query: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.perform<A where A: Apollo.GraphQLMutation>(mutation: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Foundation.Data?, __C.NSURLResponse?, Swift.Error?) -> () in closure #1 (ReactiveSwift.Signal<(Foundation.Data, __C.NSURLResponse), Swift.Error>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):__C.NSURLSession.(rac_dataWithRequest in _EE2FFDFE3F55EAB482860367DB4D56EC)(_: Foundation.URLRequest, uploading: Foundation.URL, named: Swift.String) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error> in NSURLSession.o
  "static ReactiveSwift.SignalProducer.empty.getter : ReactiveSwift.SignalProducer<A, B>", referenced from:
      static KsApi.CategoryEnvelope.envelopeProducer(from: KsApi.GraphAPI.FetchCategoryQuery.Data) -> ReactiveSwift.SignalProducer<KsApi.CategoryEnvelope, KsApi.ErrorEnvelope> in CategoryEnvelope+FetchCategoryQueryData.o
      KsApi.MockService.addNewCreditCard(input: KsApi.CreatePaymentSourceInput) -> ReactiveSwift.SignalProducer<KsApi.CreatePaymentSourceEnvelope, KsApi.ErrorEnvelope> in MockService.o
      KsApi.MockService.addPaymentSheetPaymentSource(input: KsApi.CreatePaymentSourceSetupIntentInput) -> ReactiveSwift.SignalProducer<KsApi.CreatePaymentSourceEnvelope, KsApi.ErrorEnvelope> in MockService.o
      KsApi.MockService.cancelBacking(input: KsApi.CancelBackingInput) -> ReactiveSwift.SignalProducer<KsApi.EmptyResponseEnvelope, KsApi.ErrorEnvelope> in MockService.o
      KsApi.MockService.changeEmail(input: KsApi.ChangeEmailInput) -> ReactiveSwift.SignalProducer<KsApi.EmptyResponseEnvelope, KsApi.ErrorEnvelope> in MockService.o
      KsApi.MockService.changePassword(input: KsApi.ChangePasswordInput) -> ReactiveSwift.SignalProducer<KsApi.EmptyResponseEnvelope, KsApi.ErrorEnvelope> in MockService.o
      KsApi.MockService.createBacking(input: KsApi.CreateBackingInput) -> ReactiveSwift.SignalProducer<KsApi.CreateBackingEnvelope, KsApi.ErrorEnvelope> in MockService.o
      ...
  "ReactiveSwift.Signal.Observer.send(error: B) -> ()", referenced from:
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.fetch<A where A: Apollo.GraphQLQuery>(query: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Swift.Result<Apollo.GraphQLResult<A.Data>, Swift.Error>) -> () in closure #1 (ReactiveSwift.Signal<A.Data, KsApi.ErrorEnvelope>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):Apollo.ApolloClient.perform<A where A: Apollo.GraphQLMutation>(mutation: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      closure #1 (Foundation.Data?, __C.NSURLResponse?, Swift.Error?) -> () in closure #1 (ReactiveSwift.Signal<(Foundation.Data, __C.NSURLResponse), Swift.Error>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):__C.NSURLSession.(rac_dataWithRequest in _EE2FFDFE3F55EAB482860367DB4D56EC)(_: Foundation.URLRequest, uploading: Foundation.URL, named: Swift.String) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error> in NSURLSession.o
  "ReactiveSwift.Lifetime.observeEnded(() -> ()) -> ReactiveSwift.Disposable?", referenced from:
      closure #1 (ReactiveSwift.Signal<(Foundation.Data, __C.NSURLResponse), Swift.Error>.Observer, ReactiveSwift.Lifetime) -> () in (extension in KsApi):__C.NSURLSession.(rac_dataWithRequest in _EE2FFDFE3F55EAB482860367DB4D56EC)(_: Foundation.URLRequest, uploading: Foundation.URL, named: Swift.String) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error> in NSURLSession.o
  "ReactiveSwift.FlattenStrategy.concat.unsafeMutableAddressor : ReactiveSwift.FlattenStrategy", referenced from:
      (extension in KsApi):__C.NSURLSession.rac_dataResponse(_: Foundation.URLRequest, uploading: (url: Foundation.URL, name: Swift.String)?, and: KsApi.ErrorHandler?) -> ReactiveSwift.SignalProducer<Foundation.Data, KsApi.ErrorEnvelope> in NSURLSession.o
  "ReactiveSwift.SignalProducer.init((ReactiveSwift.Signal<A, B>.Observer, ReactiveSwift.Lifetime) -> ()) -> ReactiveSwift.SignalProducer<A, B>", referenced from:
      (extension in KsApi):Apollo.ApolloClient.fetch<A where A: Apollo.GraphQLQuery>(query: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      (extension in KsApi):Apollo.ApolloClient.perform<A where A: Apollo.GraphQLMutation>(mutation: A) -> ReactiveSwift.SignalProducer<A.Data, KsApi.ErrorEnvelope> in ApolloClient+RAC.o
      (extension in KsApi):__C.NSURLSession.(rac_dataWithRequest in _EE2FFDFE3F55EAB482860367DB4D56EC)(_: Foundation.URLRequest, uploading: Foundation.URL, named: Swift.String) -> ReactiveSwift.SignalProducer<(Foundation.Data, __C.NSURLResponse), Swift.Error> in NSURLSession.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Without spending too much time on it, already been about a day, safest is to import it via SPM and include it in all targets with ReactiveExtensions. This affects the app size and we've already increased it by about 25% by moving the existing Carthage dependencies over. It will increase more with these two big dependencies now moved as well. This means longer install times and longer app start times. But with our newer initiatives to remove existing unused features in the app, we can start to look at things like optimizing app size and build times. Especially for noticeably long start times from first install and subsequent launches.

The strong argument for this change (and the reason we did all this platform work) is that developer efficiency is increased substantially due to all builds now working on M1 processors. It's actually twice as fast as a non-M1 MBP after a clean + build.

2019 Intel i9 8-Core 32GB

Screen Shot 2022-10-13 at 8 11 13 PM

2021 M1 Pro 16GB

Screen Shot 2022-10-13 at 8 11 35 PM

The size/launch time increase seem to be worth it, but we'll do more testing and follow up.

βœ… Acceptance criteria

  • Ensure long start times are not noticeable from first install.

⏰ TODO

  • Bug related to import ReactiveExtensions in KsApi Service+RequestHelpers file...
  • Fix broken tests

…ough SPM, included ReactiveSwift as a dependency. Almost build except for a few import ReactiveExtensions (could not find) build errors.
@msadoon msadoon changed the title [WEB] ReactiveExtensions to SPM [WEB-749] ReactiveExtensions to SPM Oct 11, 2022
@msadoon msadoon self-assigned this Oct 11, 2022
@msadoon msadoon added this to the release-5.6.0 milestone Oct 11, 2022
@msadoon msadoon added the WIP label Oct 11, 2022
@msadoon msadoon changed the title [WEB-749] ReactiveExtensions to SPM [WEB-749] ReactiveExtensions and ReactiveSwift to SPM Oct 14, 2022
@scottkicks
Copy link
Contributor

scottkicks commented Oct 17, 2022

@msadoon I went ahead and addressed the outstanding issues for this as I was testing on my M1.

  1. First I added missing import UIKit statements in MessageThreadCellViewModelTests.swift and MessageCellViewModelTests.swift

  2. I also made some updates to each test target

  • ReactiveExtensions-TestHelpers did not need to be in KsApiTests
  • Library-iOSTests and Kickstarter-Framework-iOSTests require all 3 libraries to be linked (ReactiveSwift, ReactiveExtensions, and ReactiveExtensions-TestHelpers)

Comment on lines 7252 to 7265
1998BCAD28F60EB700D04077 /* ReactiveExtensions */,
1905787E28F8CD5E00428375 /* ReactiveSwift */,
6047E6F928FDC104003A55A0 /* ReactiveExtensions */,
6047E6FB28FDC1B1003A55A0 /* ReactiveSwift */,
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure why these IDs changed because the same libraries are linked. It should be ok.

Copy link
Contributor Author

@msadoon msadoon Oct 18, 2022

Choose a reason for hiding this comment

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

Usually ID's change when libraries are added and removed, wouldn't worry too much about this as they generated by XCode, not us.

@codecov
Copy link

codecov bot commented Oct 17, 2022

Codecov Report

Merging #1745 (b4eaba1) into main (63e5d5e) will increase coverage by 0.00%.
The diff coverage is n/a.

@@           Coverage Diff           @@
##             main    #1745   +/-   ##
=======================================
  Coverage   85.38%   85.38%           
=======================================
  Files        1275     1275           
  Lines      115181   115181           
  Branches    30453    30454    +1     
=======================================
+ Hits        98350    98352    +2     
+ Misses      15778    15776    -2     
  Partials     1053     1053           
Impacted Files Coverage Ξ”
...iOS/Features/Help/ViewModel/HelpWebViewModel.swift 100.00% <ΓΈ> (ΓΈ)
KsApi/models/Project.swift 80.16% <ΓΈ> (ΓΈ)
...iewModels/ActivitySampleBackingCellViewModel.swift 80.00% <ΓΈ> (ΓΈ)
...ViewModels/ActivitySampleFollowCellViewModel.swift 93.33% <ΓΈ> (ΓΈ)
...iewModels/ActivitySampleProjectCellViewModel.swift 88.57% <ΓΈ> (ΓΈ)
Library/ViewModels/AddNewCardViewModel.swift 98.15% <ΓΈ> (ΓΈ)
Library/ViewModels/BetaToolsViewModel.swift 75.96% <ΓΈ> (ΓΈ)
Library/ViewModels/CommentCellViewModel.swift 100.00% <ΓΈ> (ΓΈ)
Library/ViewModels/CommentRepliesViewModel.swift 100.00% <ΓΈ> (ΓΈ)
Library/ViewModels/CommentsViewModel.swift 99.42% <ΓΈ> (ΓΈ)
... and 29 more

πŸ“£ We’re building smart automated test selection to slash your CI/CD build times. Learn more

@scottkicks scottkicks marked this pull request as ready for review October 17, 2022 18:09
@msadoon msadoon force-pushed the feature/reactive-swift-extensions-spm branch from b4cffd4 to 16910fe Compare October 18, 2022 17:17
…rk-iOS

Because KsApi includes ReactiveSwift and ReactiveExtensions, and Library includes KsApi and KickstarterFramework-iOS includes Library-iOS, there is no need to include RE and RS in either Library-iOS or KickstarterFramework-iOS.
@msadoon
Copy link
Contributor Author

msadoon commented Oct 18, 2022

@msadoon I went ahead and addressed the outstanding issues for this as I was testing on my M1.

1. First I added missing `import UIKit` statements in `MessageThreadCellViewModelTests.swift` and `MessageCellViewModelTests.swift`

2. I also made some updates to each test target


* `ReactiveExtensions-TestHelpers` did not need to be in `KsApiTests`

* `Library-iOSTests` and `Kickstarter-Framework-iOSTests` require all 3 libraries to be linked (`ReactiveSwift`, `ReactiveExtensions`, and `ReactiveExtensions-TestHelpers`)

Hey @scottkicks, appreciate your investigation here, and I did do some digging on my own before your commit was pushed and found that the changes in your commit were not the root of the issues.

  1. MessageThreadCellViewModelTests.swift and MessageCellViewModelTests.swift both did need changes, but import Foundation was needed not import UIKit. This doesn't really matter in our case, because we import UIKit in Library-iOSTests elsewhere, but as a general rule let's try to keep the import sizes small (UIKit kit includes all of Foundation) because if/when we import a library for the first time there is a cost to compiling that entire library. With that thinking, why should we increase our build times unless we require UIKit classes. In this case both these files only require URL which is found directly in Foundation.

  2. Good call on Test-Helpers not needing to be in KsApiTests. Left that out, but Library-iOSTests only needs ReactiveExtensions and ReactiveExtensions-TestHelpers not ReactiveSwift. Similarly, Kickstarter-FrameworkiOSTests does not need ReactiveExtensions or ReactiveSwift.

Also worth noting that Kickstarter-FrameworkiOS and Library-iOS do not require ReactiveExtensions or ReactiveSwift in the Link Binary with Libraries phase in order to have the app build and run on simulator or to have the tests pass on CI. We already include those libraries inside KsApi which gets linked to Kickstarter-FrameworkiOS. We only include these because they cause a linking error when building to device.

All of that to say I was curious as to how the build system worked, and while not understanding most of the lower level details, watching this WWDC video (12:54) on the iOS build system gave me the impression that keeping our build phases as minimized as possible gives us faster build times by parallelizing our build dependencies as much as possible. So saying "include the library" might cause unneeded lookups for the build system everytime if its not needed.

@msadoon msadoon removed the WIP label Oct 18, 2022
@scottkicks
Copy link
Contributor

scottkicks commented Oct 19, 2022

@msadoon Ah yea ok. I was going to check out the WWDC video as well. I was finding it strange that CI tests would pass with those extra libraries being linked, but locally they would fail for me. I don't fully understand the lower level details either, but your explanation makes sense πŸ‘ Thanks for writing this extra info out.

Running locally now to verify the changes and will approve once done.

Copy link
Contributor

@scottkicks scottkicks left a comment

Choose a reason for hiding this comment

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

πŸŽ‰πŸŽ‰

@msadoon msadoon merged commit bb76488 into main Oct 19, 2022
@msadoon msadoon deleted the feature/reactive-swift-extensions-spm branch October 19, 2022 13:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants