Xcodegen: Using frameworks with Carthage dependencies with playgrounds

Created on 17 Feb 2019  Â·  1Comment  Â·  Source: yonaskolb/XcodeGen

XcodeGen 2.2.0, Xcode 10.1.

I can't get frameworks with framework and Carthage dependencies working with Xcode playgrounds. This might not be a XcodeGen issue at all, but it's possible XcodeGen could be doing something to help along here. I don't know the solution.

I have an iOS app split into frameworks where some of the frameworks depend on each other. The frameworks work fine in a playground. If I add Carthage dependencies into the mix, they stop working in the playground. In the application target they both work fine.

Here's a project.yml that works fine:

name: MyTestProject
options:
  xcodeVersion: "1000"
  bundleIdPrefix: "fi.juripakaste.xcodegentest.2f0d"
settingGroups:
  default:
    SWIFT_VERSION: 4.2
targets:
  MyFramework:
    platform: iOS
    type: framework
    sources:
      - path: MyFramework/Sources
        name: "My Framework"
    dependencies:
      - target: MyBaseFramework
    settings:
      groups: [default]

  MyBaseFramework:
    platform: iOS
    type: framework
    sources:
      - path: MyBaseFramework/Sources
        name: "My Base Framework"
    settings:
      groups: [default]

  MyApplication:
    platform: iOS
    type: application
    sources:
      - path: MyApplication/Sources
        name: "App (2f0d)"
    dependencies:
      - target: MyFramework
      - target: MyBaseFramework
    settings:
      groups: [default]

Here's a project.yml where MyFramework won't work in playground (notice MyFramework depends on Differ):

name: MyTestProject
options:
  xcodeVersion: "1000"
  bundleIdPrefix: "fi.juripakaste.xcodegentest.2f1d"
settingGroups:
  default:
    SWIFT_VERSION: 4.2
targets:
  MyFramework:
    platform: iOS
    type: framework
    sources:
      - path: MyFramework/Sources
        name: "My Framework"
    dependencies:
      - carthage: Differ
      - target: MyBaseFramework
    settings:
      groups: [default]

  MyBaseFramework:
    platform: iOS
    type: framework
    sources:
      - path: MyBaseFramework/Sources
        name: "My Base Framework"
    settings:
      groups: [default]

  MyApplication:
    platform: iOS
    type: application
    sources:
      - path: MyApplication/Sources
        name: "My Application (2f1d)"
    dependencies:
      - target: MyFramework
      - target: MyBaseFramework
    settings:
      groups: [default]

In both cases I've opened the generated project, done a Save As Workspace…, then added a playground to the workspace. In both cases I have a public struct Bar in MyFramework that uses public struct Foo from MyBaseFramework. With the latter project, where I have the Carthage dependency, trying to instantiate a Bar in the playground results in this message:

error: Couldn't lookup symbols:
  MyFramework.Bar.init(field: MyBaseFramework.Foo) -> MyFramework.Bar
  type metadata for MyFramework.Bar

So the first question is slightly in the Stack Overflow territory: any ideas how to make this work? And second: is this a problem with XcodeGen or in how I've set up my project?

Most helpful comment

My workaround is here:

...
aggregateTargets:
  CopyFrameworksForPlayground:
    buildScripts:
      - script: cp -rv "${SRCROOT}/Carthage/Build/iOS/" "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
targets:
  Playground: # create fake framework to just adding reference to playground to project and avoid including to app bundle
    type: framework
    platform: iOS
    sources:
      - Playground.playground
  App:
    type: application
    platform: iOS
    ...

Add the aggregateTarget that has the script copies carthage projects to frameworks folder. Unfortunately we have to run that aggregateTarget when carthage dependencies changed.

My idea is to make it possible to describe something like a target for a playground on a spec.

targets:
  Playground:
    type: playground
    sources: [Playground.playground]
    dependencies:
      - carthage: Kingfisher
      - carthage: Alamofire

But this may not be a good idea. I think this behavior is a problem with Xcode and should be fixed by Apple.

>All comments

My workaround is here:

...
aggregateTargets:
  CopyFrameworksForPlayground:
    buildScripts:
      - script: cp -rv "${SRCROOT}/Carthage/Build/iOS/" "${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"
targets:
  Playground: # create fake framework to just adding reference to playground to project and avoid including to app bundle
    type: framework
    platform: iOS
    sources:
      - Playground.playground
  App:
    type: application
    platform: iOS
    ...

Add the aggregateTarget that has the script copies carthage projects to frameworks folder. Unfortunately we have to run that aggregateTarget when carthage dependencies changed.

My idea is to make it possible to describe something like a target for a playground on a spec.

targets:
  Playground:
    type: playground
    sources: [Playground.playground]
    dependencies:
      - carthage: Kingfisher
      - carthage: Alamofire

But this may not be a good idea. I think this behavior is a problem with Xcode and should be fixed by Apple.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pvinis picture pvinis  Â·  6Comments

TheInkedEngineer picture TheInkedEngineer  Â·  4Comments

thecb4 picture thecb4  Â·  3Comments

toshi0383 picture toshi0383  Â·  3Comments

lukewakeford picture lukewakeford  Â·  6Comments