apollographql / apollo-ios

📱  A strongly-typed, caching GraphQL client for iOS, written in Swift.
https://www.apollographql.com/docs/ios/
MIT License
3.89k stars 728 forks source link

Codegen output and BUILD_LIBRARY_FOR_DISTRIBUTION #3271

Closed jimisaacs closed 1 year ago

jimisaacs commented 1 year ago

Use case

Question / suggestion, do you have any test cases for Codegen output that builds with BUILD_LIBRARY_FOR_DISTRIBUTION? If not, could it be added?

An internal team has been working through issues that they have been having related to this.

Describe the solution you'd like

So far, I think this might equate to requiring the option to output enums with @frozen.

BobaFetters commented 1 year ago

@jimisaacs We don't currently have that but we can get that added and see what other adjustments we need to make as a result.

jimisaacs commented 1 year ago

@jimisaacs We don't currently have that but we can get that added and see what other adjustments we need to make as a result.

Thanks! FYI, I'd like to retract that @frozen comment, but it would still be good to double check the stance on things. i.e. expect consumers to handle @unknown cases, for client and codegen.

BobaFetters commented 1 year ago

@jimisaacs Been looking into this some, made myself a test project with a framework scheme to generate code into and run xcbuild commands with BUILD_LIBRARY_FOR_DISTRIBUTION enabled. Have a working example which I will attach if you would like to take a look. Although I was wondering if you could provide a little more detail/sample of how you all are trying to accomplish this so i can make sure I am covering different possible setups when I start converting this into some tests. CodegenOutputTest.zip

jimisaacs commented 1 year ago

Thanks you @BobaFetters! I will look more closely when I get a chance.

FYI, we were able to support that internal team mentioned by implementing @unknown for all enums everywhere (client and codegen), among a few other things. Such as, removing scoped imports (not supported for distributed frameworks). Using @_exported for custom scalars that were type aliases. Most importantly, ensuring the shared schema module is as small as we can make it, given the framework still uses internal shared libraries, but is also meant for distribution.

I think maybe what will be useful with what you have going here, is just ensuring that it builds with all things, or least as many features as possible, related to Apollo in use. This way it will 1. Ensure the Apollo client and codegen packages can be used in a distributed framework just fine, and 2. Allow for Apollo to provide some strong guidance in this use case.

BobaFetters commented 1 year ago

@jimisaacs Glad you were able to get it working, the example I posted is pretty bare bones, basically just getting some output from code generation compiling successfully into a framework. A few things I want to clarify with you to make sure I am understanding correctly:

Want to make sure I am fully understanding what you had to do to get it working so I know what needs to be documented and given as guidance vs what we can actually implement or potentially change to just make this process work easier.

jimisaacs commented 1 year ago

Yeah, I reread my last comment and it's pretty ambiguous as to the reasons, i.e. sounds like I'm saying it's in a Apollo packages themselves. No, it's just things that the internal team have to do in internal frameworks that utilized the Apollo packages.

Are you packaging the apollo-ios package in a framework with the codegen output, or having separate frameworks, or what is that structure like?

There is only one framework that is distributed, which links statically against packages that use both apollo-ios, and output from apollo-ios-codegen (no external dependencies once distributed). Basically the framework provides a non-GQL domain specific interface, while internally it links against all things GraphQL. In terms of Apollo usage, there is a target for generated operations, a shared schema package, and direct use of ApolloClient and all it's parts.

For the @unknown and scoped imports, were these things you need to change in the consuming code, or in the Apollo code that is part of the framework?

Consuming code. Any switch of OperationType, CachePolicy, or any enum output by codegen.

Similar question for the @_exported was this in consuming code or Apollo code? I know we do @_exported for ApollAPI in a lot of the generated files in the codegen output, although not in the custom scalar files.

We have quite a few custom scalars, all of them use typealiases to Foundation types, it turns out to use typealiases will require either to use @_exported on Foundation, or wrap the types. Otherwise it's a warning stating that it will be an error in Swift 6, or it will error now if you build with warnings-as-errors (we do this a lot).

BobaFetters commented 1 year ago

@jimisaacs Thanks for the clarification, I think a good starting point for us is to turn the test project I have into a codegen test to ensure that generated code can be properly compiled into a distribution framework, and then starting an FAQ or similar style doc that can gather information on things to look out for and tips etc when using apollo-ios or the generated code as a framework that we can continue to add to as needed.

I also think we could explore ways to expand on the test over time to help cover more aspects of this type of setup.