react: 16.3.2
react-native: 0.55.3
react-viro: 2.6.0
Device: iPhone 5s
I'm building a 2DReact-VR Hybrid application, by adding Viro to an existing React Native application. Android is working perfectly, but I'm running into some issues building it for iOS.
When I build without use_frameworks!, the app crashes immediately on startup with this, which makes sense:
dyld: Library not loaded: @rpath/AWSCore.framework/AWSCore
Referenced from: /private/var/containers/Bundle/Application/BB364BB5-18FD-44E2-B846-B49F515D37AF/yesfitclient.app/Frameworks/ViroKit.framework/ViroKit
Reason: image not found
However, when I add use_frameworks! to my Pod file, I get numerous new build errors from other libraries. My assumption is these other libraries do not support use_frameworks!. Here is the output from my pod update command. The frameworks mentioned may or may not be related to the libraries that produce build errors:
[!] The 'Pods-yesfitclient' target has transitive dependencies that include static binaries:
(AppsFlyerLib.framework,
GoogleMapsBase.framework,
GoogleMaps.framework,
GoogleMapsCore.framework)
My first build error is from Stripe. In another post, I've read there are build issues with Google Maps and Firebase in conjunction with use_frameworks!, both of which I use. The effort for me to go and fix all of these new errors seems massive and potentially fruitless.
Ideally, I'd like a workaround for not having to use use_frameworks!, because my only alternative is spending the next several days trouble-shooting these other libraries that are failing, which may or may not yield success. It looks like some people have had success with use_frameworks!, but success seems to be related to how many other libraries are in the Pod file and how compatible they are.
Does anyone have a workaround for this? I converted to using Cocoa Pods a while back and haven't run into any issues with it until now.
Hi @grahamyesfit,
This seems to be a perennial problem with Cocoapods. We used to not use_frameworks! but that introduced issues in that we would end up compiling our dependencies into our libraries which would cause conflicts with others if they used the same libraries (ie. two versions of the AWS SDK).
Unfortunately, your dependencies seem to not support use_frameworks!.
The current dependency tree that we have in Cocoapods is the following (taken from the Podfile.lock).
- AWSCore (2.6.12)
- AWSDynamoDB (2.6.12):
- AWSCore (= 2.6.12)
- GoogleToolboxForMac/Defines (2.1.0)
- GoogleToolboxForMac/Logger (2.1.0):
- GoogleToolboxForMac/Defines (= 2.1.0)
- GTMSessionFetcher/Core (1.1.6)
- GVRAudioSDK (1.120.0)
- GVRSDK (1.120.0):
- GoogleToolboxForMac/Logger (= 2.1.0)
- GTMSessionFetcher/Core (= 1.1.6)
- ViroKit (1.0):
- AWSDynamoDB (~> 2.6.7)
- GVRAudioSDK (= 1.120.0)
- GVRSDK (= 1.120.0)
- ViroReact (1.0)
One workaround is to not use Cocoapods for our frameworks and instead manually include it into your project alongside the following framework files. At the end of the day, Cocoapods copies a static lib (.a file) and headers into the ios/Pods/ directory, then if use_frameworks! is enabled, then Cocoapods creates .framework files out of them. The .framework products are just glorified directories anyways.
Based on that fact, you can either 1) manually create frameworks out of each dependency 2) Use the Pod project with only the .framework targets and add it to your own target before creating a new Pod project without our dependencies.
We haven't tried it ourselves, but this might work for you.
Here's also another GitHub issue where others ran into issues with use_frameworks!: https://github.com/viromedia/viro/issues/144
We'll keep this issue in mind to see if there's something we can do to properly support both "types" of Pods.
Thanks,
Thanks for the detailed reply, @achuvm.
Both of your suggestions intrigue me, but I have some follow up questions:
1) If I manually create frameworks out of each dependency, where do I get the source code for each from? Is it a case of finding each GitHub repository and simply cloning the source into my own Frameworks folder? Are there other steps (e.g. header path changes) to be made when using this approach?
2) Can you provide more guidance on how I would configure a "two-pod" approach? This seems like it might be cleaner than the first suggestion, but my experience with Cocoapods is minimal. Are you suggesting I remove use_frameworks! and Viro from my pod file, then create another pod project with a pod file that includes use_frameworks! and Viro? How do I make two pod files run?
Thanks for the link to the other GitHub issue: I've been down that road. I managed to include the AWS dependencies described there, and now I'm getting a run-time error that GTMSessionFetcher can't be found. I included the following in my pod file, but that doesn't seem to be enough:
pod 'GTMSessionFetcher/Core', '1.1.6'
pod 'GoogleToolboxForMac/Logger', '2.1.0'
pod 'GoogleToolboxForMac/Defines', '2.1.0'
Hi @grahamyesfit,
1) Rather than going to each individual GitHub, you can simply take advantage of CocoaPods. When you run pod install there's a Pods directory created with all the headers + static library (.a files) that you need. The tricky thing is that you'll need to "create" frameworks out of each collection of headers and static library (this used to be a thing people had to do before Framework targets were supported by Xcode, but I'm unable to find a good guide).
ie.
~/workspace/ViroSample/ios/Pods$ ls
AWSCore GVRAudioSDK Headers Pods.xcodeproj
AWSDynamoDB GVRSDK Local Podspecs Target Support Files
GTMSessionFetcher GoogleToolboxForMac Manifest.lock
2) This one was more hypothetical, but the way CocoaPods works is that they create an Xcode project named Pods and add all your dependencies to it. Then they create a workspace that includes your Xcode project and the new Pods project and link them together through the project settings (this part is a bit more ambiguous to myself). So I was thinking, if you create 1 Pods project with just the use_frameworks! files, and then move/rename the project so it's no longer associated with CocoaPods (because each project is only allowed 1 CocoaPods file, etc). Then you should be able to treat the extracted Pods project as just another project that you have and can include in your workspace with your original project and the non-use_frameworks! CocoaPods project.
Thinking about this more, you can maybe do 1) easier by instead manually linking all your non-use_frameworks! libraries to your project and add the header paths to the Header Search Paths of your original project.
If you don't mind, can you post your Podfile so we can take a look at your other dependencies? I may have some time to take a look at one or two solutions above.
Hope that helps,
Thanks again, @achuvm.
So for (1), would I take my non-use_frameworks! pods out of my pod file completely?
Sure, here's my pod file, in all its glory:
# Uncomment the next line to define a global platform for your project
platform :ios, '9.3'
inhibit_all_warnings!
#pre_install do |installer|
# workaround for CocoaPods/CocoaPods#3289
# Pod::Installer::Xcode::TargetValidator.send(:define_method, :verify_no_static_framework_transitive_dependencies) {}
#end
target 'yesfitclient' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
#use_frameworks!
#inherit! :search_paths
# Pods for yesfitclient
pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga/yoga.podspec'
pod 'React', :path => '../node_modules/react-native', :subspecs => [
'Core',
'DevSupport',
'RCTAnimation',
'RCTActionSheet',
'RCTGeolocation',
'RCTLinkingIOS',
'RCTSettings',
'RCTVibration',
'RCTImage',
'RCTNetwork',
'RCTText',
'RCTWebSocket'
# Add any other subspecs you want to use in your project
]
pod 'Stripe', '~> 11.2.0'
pod 'GoogleMaps'
pod 'Firebase/Core'
pod 'Firebase/Messaging'
pod 'react-native-maps', path: '../node_modules/react-native-maps'
pod 'react-native-google-maps', path: '../node_modules/react-native-maps'
#pod 'react-native-streetview', path: '../node_modules/react-native-streetview'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'Intercom'
pod 'react-native-intercom', :path => '../node_modules/react-native-intercom'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'react-native-appsflyer', :path => '../node_modules/react-native-appsflyer'
pod 'ViroReact', :path => '../node_modules/react-viro/ios/'
pod 'ViroKit', :path => '../node_modules/react-viro/ios/dist/ViroRenderer/'
#pod 'RNBackgroundGeolocation', :path => '../node_modules/react-native-background-geolocation-android'
#pod 'RNBackgroundFetch', :path => '../node_modules/react-native-background-fetch'
#pod 'PayPal-iOS-SDK'
#For Viro
pod 'GTMSessionFetcher/Core', '1.1.6'
pod 'GoogleToolboxForMac/Logger', '2.1.0'
pod 'GoogleToolboxForMac/Defines', '2.1.0'
#pod 'AWSCore', '~> 2.6.7'
#pod 'AWSDynamoDB', '~> 2.6.7'
target 'yesfitclient-tvOSTests' do
inherit! :search_paths
# Pods for testing
end
target 'yesfitclientTests' do
inherit! :search_paths
# Pods for testing
end
post_install do |installer|
system(". ./pod_post_install.sh")
installer.pods_project.targets.each do |target|
if target.name == 'react-native-google-maps'
target.build_configurations.each do |config|
config.build_settings['CLANG_ENABLE_MODULES'] = 'No'
end
end
if target.name == "React"
target.remove_from_project
end
if target.name == 'yoga'
# Workaround: react-native v0.52 bug issue #17274
# node_modules/react-native/ReactCommon/yoga/yoga/YGNodePrint.cpp:208:46: Implicit conversion loses integer
# precision: 'size_type' (aka 'unsigned long') to 'const uint32_t' (aka 'const unsigned int')
# https://github.com/facebook/react-native/issues/17274#issuecomment-356363557
target.build_configurations.each do |config|
config.build_settings['GCC_TREAT_WARNINGS_AS_ERRORS'] = 'NO'
config.build_settings['GCC_WARN_64_TO_32_BIT_CONVERSION'] = 'NO'
end
end
if target.name == "RNSVG"
target.build_configurations.each do |config|
config.build_settings['GCC_NO_COMMON_BLOCKS'] = 'NO'
end
end
end
end
end
Hi @grahamyesfit,
Yep, in that case since you'd be manually adding the dependencies, you would no longer include them in your Podfile.
Thanks for your Podfile, I'll let you know if/when I get a chance to look at it.
Hi @achuvm, gotcha, thanks. The tricky part is that not all the pods in my Podfile are npm packages. For example, Stripe, GoogleMaps and Firebase/Core. I'm not even sure where it gets those pods from.
Hi @grahamyesfit,
The way CocoaPods work is that they have a master repo with every single Pod defined by a .podspec file. When you declare a dependency, CocoaPods finds the .podspec file in the local repo on your computer at ~/.cocoapods/repos/master/ and then follows the location specified in the .podspec file to get the actual files (Headers/Source/Libraries).
ie. ~/.cocoapods/repos/master/Specs/0/3/2/WCImagePicker/0.0.3/WCImagePicker.podspec.json:
{
"name": "WCImagePicker",
"version": "0.0.3",
"summary": "简易好用的图片选择器(Simple and easy for image picker)",
"homepage": "https://github.com/MeetDay/WCImagePicker",
"license": "MIT",
"platforms": {
"ios": "9.0"
},
"source": {
"git": "https://github.com/MeetDay/WCImagePicker.git",
"tag": "0.0.3"
},
"source_files": "WCImagePicker/*.{h,m}",
"resource_bundles": {
"WCImagePicker": "WCImagePicker/*.{xib,xcassets}"
},
"frameworks": [
"Photos",
"PhotosUI"
],
"requires_arc": true
}
My advice is to simply run pod install so that CocoaPods handles the finding and downloading of the various dependencies to the <project>/ios/Pods directory in your project, then modify/package those files.
Hi @achuvm, thanks for the background info.
So let's take Stripe, for example. After a pod install, I would move the <project>/ios/Pods/Stripe folder to a new location (so that it doesn't get subsequently wiped out when I remove it from the Podfile), then add the new location to my Header Search Path? I won't need an xcodeproj for each one? What do you mean by 'modify/package'?
Thanks again for your patience in this matter, I really appreciate your assistance in this.
Hi @grahamyesfit,
Yep the steps would be:
1) pod install
2) move the dependencies to another location
3) Add the path to the header files to the Header Search Paths
4) Then find the .a file and add it to Your Project -> Build Phases -> Link Binary With Libraries, you may need to "add" the .a file to your project first.
You won't need an xcodeproj because you're manually including/linking a static library to your project. I was referring to "modify/package" if you were to instead manually link the frameworks rather than the static libraries.
Although, I suspect you may need to instead add the Stripe folder to your project and include the header files under Your Project -> Build Phases -> Headers rather than the step 3 above...
Hi @achuvm, thanks so much for the steps. I'm going to give this a try and report back.
@achuvm, this is proving to be tough. I have been to every site for the Pods that give me errors with use_frameworks, which is most of them. I've been working on this for nearly a day now and I'm still not able to build. My Pod file is almost empty. It doesn't feel right that I'm changing the whole structure of my project to support Viro, when everything else prior was working perfectly. I might have to put this on hold until Viro find a way to support users who can't use use_frameworks.
You mentioned you might look into properly supporting both "types" of Pods - is this something that might actually happen? If so, what kind of time frame? VR and AR are a big part of the future of our App, and Viro is by far the best framework out there for this. I really really want to use Viro, but I'm on Day 4 of trying to get it integrated and I'm running out of time.
Hi @grahamyesfit,
This issue is something that we do want to help you resolve (whether we go through CocoaPods or not). Unfortunately, we don't yet have a timeframe for a fix, but we may be able to get you a one-off fix within the next week. Let us know what deadlines you may have and we'll see if we can get you something before then.
Thanks,
Hi @achuvm, awesome, I appreciate your attention in this matter. A one-off fix would be fantastic, just so that I can continue to move forward. I don't have a specific deadline, but the sooner the better so that I can tell my CEO we're a go on VR/AR (he's very enthusiastic about your platform). Essentially, you're the premium platform for VR/AR and I'm excited about developing a partnership with Viro.
HI @grahamyesfit, @achuvm created a one-off fix for viro-react that does not use framworks. I've tested it myself and it seems to work! Instructions on how to use it are below:
1) To use, first delete your current react-viro package, from your project root run:rm -rf node_modules/react-viro from the command line.
2) Download the patched react-viro from here: https://s3-us-west-2.amazonaws.com/viro/viro_2_6_1_static_lib/react-viro-2.6.1.tgz.
3) Install the tgz file. Run npm install <path_to_file>/react-viro-2-6.1.tgz
4) Your podfile will need to be modified(remove the use_frameworks! line). We tested this with the following dependencies:
pod 'Stripe', '~> 11.2.0'
pod 'GoogleMaps'
pod 'Firebase/Core'
pod 'Firebase/Messaging'
pod 'ViroReact', :path => '../node_modules/react-viro/ios/'
pod 'ViroKit', :path => '../node_modules/react-viro/ios/dist/ViroRenderer/'
5) Run pod install to properly install the pods.
The above worked for us. Hopefully this works for you. Let us know if you run into any issues. Thanks!
Hi @achuvm and @VikAdvani, what can I say? You guys are bloody awesome. It works! Thank you so much for figuring this out for me. I just successfully got a VR view on my iPhone!
The only thing I had to change was to set Enable Bitcode No, when previously it was Yes. I'm not sure if this will affect anything else, like the store release.
Thank you so much!
Hi @achuvm and @VikAdvani, this solution worked awesomely on my Mac, but when I commit it to Buddy Build, I get a lot of errors. I've attached the logs in case you can see something obvious.
buddybuild_build_220_logs.txt
buddybuild_xcodebuild_220_logs.txt
@achuvm and @VikAdvani, I have more information. I set the Deployment Target of my xCode project to 9.3 (to match my Podfile) and I set the target to Release, and now when I build locally on my Mac, I get around 200 errors similar to this. I think it's the Release setting that's throwing it all off:
Undefined symbols for architecture
armv7"VROFBXLoader::loadFBXFromResource(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, VROResourceType, std::__1::shared_ptr<VRONode>, std::__1::function<void (std::__1::shared_ptr<VRONode>, bool)>)", referenced from:
-[VRT3DObject didSetProps:] in libViroReact.a(VRT3DObject.o)
"VROPolygon::createPolygon(std::__1::vector<VROVector3f, std::__1::allocator<VROVector3f> >, float, float, float, float)", referenced from:
-[VRTPolygon updateGeometry] in libViroReact.a(VRTPolygon.o)
"VROBox::setWidth(float)", referenced from:
-[VRTBox setWidth:] in libViroReact.a(VRTBox.o)
"VROBox::createBox(float, float, float)", referenced from:
-[VRTBox initWithBridge:] in libViroReact.a(VRTBox.o)
"VROScene::getControllerPresenter()", referenced from:
-[VRTController sceneWillAppear] in libViroReact.a(VRTController.o)
"VRONodeCamera::setFieldOfViewY(float)", referenced from:
-[VRTCamera setFieldOfView:] in libViroReact.a(VRTCamera.o)
"VRONodeCamera::setPosition(VROVector3f)", referenced from:
-[VRTCamera setPosition:] in libViroReact.a(VRTCamera.o)
"VROPortalFrame::~VROPortalFrame()", referenced from:
std::__1::__compressed_pair_elem<VROPortalFrame, 1, false>::~__compressed_pair_elem() in libViroReact.a(VRTPortal.o)
"VROPortalFrame::VROPortalFrame()", referenced from:
std::__1::shared_ptr<VROPortalFrame> std::__1::shared_ptr<VROPortalFrame>::make_shared<>() in libViroReact.a(VRTPortal.o)
@VikAdvani , thanks a lot, I have the same issue, now it's solved :)
@chaendler: are you able to build a Release configuration?
@achuvm, @VikAdvani: still no luck for me building a Release configuration. Do you have any ideas for me?
@grahamyesfit, @brittanyyesfit I'm looking into it. I'm able to reproduce the issues where release fails. It seems it's related to armv7 not being including in the binary. I'll update this issue(likely with a new one off patch) when fixed :)
Hi @grahamyesfit, @brittanyyesfit, @chaendler. I've updated the fix with a new .tgz that should work with release as well. Please let me know if you have any issues. Thanks!
Here is the link: https://s3-us-west-2.amazonaws.com/viro/viro_2_6_1_static_lib_5_18_18/react-viro-2.6.1.tgz
@VikAdvani, worked like a charm. Thank you so much.
Any idea when this will get an official release so we don't have to install the pre-built tgz?
Hi @taylesworth,
Unfortunately we don't yet have a set timeline for this, but we are actively working on this.
The issue here is that the creation of static libraries vs frameworks requires us to completely change how we link our renderer to our bridge. As a result, we aren't currently able to create both types of artifacts using the same project. In the meantime, we'll have to manually make changes to our project in order to create the static libraries (in the .tgz file).
Thanks,
@achuvm Thanks for the update. It's great to know you are actively working on a solution.
Any news on this? We are working on a project using viro 2.7.3 and are having trouble creating a release build in xCode. @VikAdvani can we maybe get a patched 2.7.3 tgz with support for release builds and without frameworks?
Hi @augustsjogren, we have a new section in our documentation called "Integrating w/o use_frameworks! (Cocoapods)". You can find the 2.7.3 tgz and future tgz here -> https://docs.viromedia.com/docs/no_use_frameworks
@dam00n we followed that guide and got it working fine for debug, but when trying to build a release build it didn't work. We got the error invalid bundle CFBundleSupportedPlatforms.
@augustsjogren got it, thanks for the additional info. We will take a look at this and get back to you.
Hi @augustsjogren, thanks for pointing this out. We figured out the issue. A way to get this working is to do the following.
Edit the file under node_modules/react-viro located /ios/dist/ViroRenderer/ViroKit.framework/Info.plist.
1) Find the block with keyCFBundleSupportedPlatforms and replace the value iPhoneSimulator with iPhoneOS within the
2) Do the same for block with key DTPlatformName, except in all lowercase. Replace the value iphonesimulator with iphoneos
Save the file, do a full clean and rebuild in release. You should be able to build in release now.
In our next release this will be fixed so won't have to do this manually.
@VikAdvani Thanks a lot, much appreciated! Any chance you could provide a .tgz with these changes so that we don't need to cnange this every time we delete/clean the node_modules folder?
Hi @augustsjogren, I updated the 2.7.3 tgz file on the website to include this fix, so you should be able to just pull from there :)
Link: https://s3-us-west-2.amazonaws.com/viro/viro_2_7_3_static_lib/react-viro-2.7.3.tgz
Most helpful comment
Hi @augustsjogren, I updated the 2.7.3 tgz file on the website to include this fix, so you should be able to just pull from there :)
Link: https://s3-us-west-2.amazonaws.com/viro/viro_2_7_3_static_lib/react-viro-2.7.3.tgz