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

Weaken the dependency on XCTest #146

Merged
merged 5 commits into from Sep 7, 2015

Conversation

briancroom
Copy link
Member

I had some good success working on what seems like a great solution to #144. The weak linking seems to be working successfully. The process dies with a dylib error the instant that you try to instantiate NimbleXCTestHandler without the XCTest framework+lib around, so I added some code to prevent that form happening. We could potentially try to add a non-crashing fallback assertion handler for this situation as well.

Thoughts? @jeffh @tjarratt

@tjarratt
Copy link

This is really awesome! It looks like the build failed because CircleCI doesn't support the latest swift compiler (but I'm not 100% sure).

@briancroom
Copy link
Member Author

Would it make sense to apply this to a different branch (master?) instead?

@jeffh
Copy link
Member

jeffh commented Jul 12, 2015

Don't worry about CircleCI, it doesn't support Swift 2.0 yet, so it's always red for the swift-2.0 branch. I manually run the tests before merging in PRs. The master branch is for stable swift (1.2).

Hey @briancroom, are you doing something special to get Nimble working without XCTest? I've tried importing Nimble as an app dependency in a demo app as an example (using carthage or cocoapods), but it doesn't work. libswiftXCTest is still required.

$ otool -L /Users/jeff/Library/Developer/Xcode/DerivedData/Nimble-ejlspkozrikyvdavdrwfoyknlvax/Build/Products/Debug-iphoneos/Nimble.framework/Nimble
/Users/jeff/Library/Developer/Xcode/DerivedData/Nimble-ejlspkozrikyvdavdrwfoyknlvax/Build/Products/Debug-iphoneos/Nimble.framework/Nimble (architecture armv7):
    @rpath/Nimble.framework/Nimble (compatibility version 1.0.0, current version 1.0.0)
    @rpath/libswiftXCTest.dylib (compatibility version 0.0.0, current version 0.0.0)
    /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1223.1.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1223.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1223.1.0)
    @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftCoreGraphics.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftCoreImage.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftDarwin.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftDispatch.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftFoundation.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftObjectiveC.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftSecurity.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftUIKit.dylib (compatibility version 0.0.0, current version 0.0.0)
/Users/jeff/Library/Developer/Xcode/DerivedData/Nimble-ejlspkozrikyvdavdrwfoyknlvax/Build/Products/Debug-iphoneos/Nimble.framework/Nimble (architecture arm64):
    @rpath/Nimble.framework/Nimble (compatibility version 1.0.0, current version 1.0.0)
    @rpath/libswiftXCTest.dylib (compatibility version 0.0.0, current version 0.0.0)
    /System/Library/Frameworks/Foundation.framework/Foundation (compatibility version 300.0.0, current version 1223.1.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1223.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation (compatibility version 150.0.0, current version 1223.1.0)
    @rpath/libswiftCore.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftCoreGraphics.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftCoreImage.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftDarwin.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftDispatch.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftFoundation.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftObjectiveC.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftSecurity.dylib (compatibility version 0.0.0, current version 0.0.0)
    @rpath/libswiftUIKit.dylib (compatibility version 0.0.0, current version 0.0.0)

@briancroom
Copy link
Member Author

That's interesting, @jeffh, I hadn't tried running inspecting the Nimble binary with otool. I've done some more digging, and it seems that the -L command reports linked dylibs without any indication of whether they are weakly referenced or not, however if you use -l to get the list of load commands, then you can see the distinction:

...
Load command 10
          cmd LC_LOAD_WEAK_DYLIB
      cmdsize 72
         name @rpath/XCTest.framework/Versions/A/XCTest (offset 24)
   time stamp 2 Wed Dec 31 19:00:02 1969
      current version 8131.5.0
compatibility version 1.0.0
Load command 11
          cmd LC_LOAD_WEAK_DYLIB
      cmdsize 56
         name @rpath/libswiftXCTest.dylib (offset 24)
   time stamp 2 Wed Dec 31 19:00:02 1969
      current version 0.0.0
compatibility version 0.0.0
Load command 12
          cmd LC_LOAD_DYLIB
      cmdsize 96
         name /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (offset 24)
   time stamp 2 Wed Dec 31 19:00:02 1969
      current version 1223.1.0
compatibility version 300.0.0
...

I have also pushed a branch that shows an example of using Nimble without XCTest to briancroom/Nimble@0d3721f

To be fair, I haven't attempted this with pulling in the framework via Cocoapods or Carthage yet. I'm anticipating that Carthage will work, but it may take some additional work to get Cocoapods to build it correctly.

@briancroom
Copy link
Member Author

Ah, I see...there's more going on here than I realized. The example app I linked to was included in the Nimble workspace. It links with a copy of the Nimble framework that isn't embedded in the final app, which meant that swift-stdlib-tool didn't scan Nimble when it decides which Swift libraries to copy in.

I tested it with Carthage now and encountered the same problem that @jeffh saw, presumably. swift-stdlib-tool copies libswiftXCTest.dylib into the app bundle, because it sees that Nimble can take advantage of it, but then the app crashes on launch because that dylib is strongly linked to XCTest.framework. I tried adding a Run Script to delete libswiftXCTest.dylib, but the Swift libs aren't copied until after the script executes.

I'm going to need to experiment a bit more to determine what other approaches may be feasible to work around this.

@briancroom
Copy link
Member Author

A couple more findings...

  • When using this with Carthage, the app will launch and execute as expected if I manually delete libswiftXCTest.dylib from the app bundle after Xcode finishes making the build, however I haven't been able to figure out a way to make this work as part of a standard Xcode Run action
  • I'm intending to file a Radar on swift-stdlib-tool asking for more flexible handling of weakly linked libraries, or some other way to modify the handling of the XCTest support lib
  • Because of these issues, I've lost a lot of confidence in using weak linking as a solution to Using Nimble without XCTest #144, unfortunately

@briancroom
Copy link
Member Author

A couple updates:

  • I rebased this against the latest on the swift-2.0 branch
  • I was able to get this working for iOS and Mac apps using Nimble as a Carthage-built framework by adding a post-build scheme action running a script[1] that deletes the copy of libswiftXCTest.dylib that swift-stdlib-tool copies into the bundle. This would only be a requirement for people trying to use Nimble without XCTest.
  • This patch set seems to me to align with @modocache's stated goal of trying to loosen Quick's coupling with XCTest.

[1]

rm "${SWIFT_STDLIB_TOOL_DESTINATION_DIR}/libswiftXCTest.dylib"

@briancroom
Copy link
Member Author

@jeffh I've pushed a usage example of this: https://github.com/briancroom/NimbleWithCarthageExample

@jeffh
Copy link
Member

jeffh commented Aug 13, 2015

Hey @briancroom, would this script be safe to run in always or does this cause surprising failures when XCTest should automatically be linked, but isn't? I'm wondering if this is something more automatic or documentation that needs to mention how to run Nimble without XCTest.

Sorry, I haven't been spending significant time on Nimble since it's annoying that Xcode 7 beta 5 crashes on Nimble's test suite.

@briancroom
Copy link
Member Author

Thanks for bringing up documentation @jeffh. I've added a section to the README indicating how this works.

@modocache
Copy link
Member

This is really cool! 👍

Code looks good to me, but I'll defer to @jeffh to merge. If this is the direction Nimble is taking, I'd love to explore whether Quick could also use weak linking.

@jeffh
Copy link
Member

jeffh commented Aug 17, 2015

Hey @briancroom,

In Xcode 7 beta 5, it doesn't seem like 'SWIFT_STDLIB_TOOL_DESTINATION_DIR' exists?

@briancroom
Copy link
Member Author

@jeffh I just gave it another try on beta 5 and it seemed to be working. If the script isn't finding the environment variable, maybe check to make sure that you selected the right target in the script's "Provide build settings from" dropdown? When working on this, I was putting the following line in the script to see what I had available:

export > /tmp/out.txt

Do you see the expected build settings env vars from that?

@jeffh
Copy link
Member

jeffh commented Aug 26, 2015

Oh never mind, I configured it incorrectly. My bad. But I still seem to get failure when running. This could be because I'm now running Xcode 7 beta 6.

screen shot 2015-08-26 at 1 31 50 am

Sorry for the long turnaround. I've also uploaded my repo that I've been using to test: https://github.com/jeffh/NimbleCocoaPodsExample.

I'll raise this issue to a higher priority so I can respond more regularly.

Brian Croom added 4 commits September 2, 2015 13:33
This allows using Nimble without pulling XCTest into your process.
When strongly linking XCTest, Cocoapods automatically adds a
framework search path to allow the framework to be found. When
weakly linking, it must be manually specified.
@briancroom
Copy link
Member Author

Hey @jeffh , thanks for that repo. That was useful for testing just now. I just found some time to get this rebased to include the new commits on the swift-2.0 branch. After doing so, I was able to get your example repo working by using the following Podfile:

platform :ios, '8.0'

use_frameworks!

target 'NimbleCocoaPodsExample' do
  pod 'Nimble', :path => '../TestingTools/Nimble' #:git => 'https://github.com/briancroom/Nimble', :branch => 'weakly-link-xctest'
end

target 'NimbleCocoaPodsExampleTests' do
  pod 'Quick', :git => 'https://github.com/Quick/Quick', :tag => 'v0.6.0'
  pod 'Nimble', :path => '../TestingTools/Nimble' #:git => 'https://github.com/briancroom/Nimble', :branch => 'weakly-link-xctest'
end

When you get a few minutes, could you take another look?

@jeffh
Copy link
Member

jeffh commented Sep 3, 2015

I'll take a look tonight. Thanks.


Sent from my iPhone

On Wed, Sep 2, 2015 at 10:56 AM, Brian Croom notifications@github.com
wrote:

Hey Jeff, thanks for that repo. That was useful for testing just now. I just found some time to get this rebased to include the new commits on the swift-2.0 branch. After doing so, I was able to get your example repo working by using the following Podfile:

platform :ios, '8.0'
use_frameworks!
target 'NimbleCocoaPodsExample' do
  pod 'Nimble', :path => '../TestingTools/Nimble' #:git => 'https://github.com/briancroom/Nimble', :branch => 'weakly-link-xctest'
end
target 'NimbleCocoaPodsExampleTests' do
  pod 'Quick', :git => 'https://github.com/Quick/Quick', :tag => 'v0.6.0'
  pod 'Nimble', :path => '../TestingTools/Nimble' #:git => 'https://github.com/briancroom/Nimble', :branch => 'weakly-link-xctest'
end

When you get a few minutes, could you take another look?

Reply to this email directly or view it on GitHub:
#146 (comment)

jeffh added a commit that referenced this pull request Sep 7, 2015
@jeffh jeffh merged commit 8baefcc into Quick:swift-2.0 Sep 7, 2015
@jeffh
Copy link
Member

jeffh commented Sep 7, 2015

Thanks @briancroom, I've gotten it to work. Although, I'm not sure if it was cache cleaning, cocoapods update, or xcode update that's related to the original issues i've been having.

@briancroom
Copy link
Member Author

🎉 Thanks @jeffh for seeing this through! Also to @tjarratt for the initial inspiration.

@briancroom briancroom deleted the weakly-link-xctest branch January 20, 2016 18:37
Megal pushed a commit to Megal/Nimble that referenced this pull request Jul 31, 2019
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

4 participants