Unable to use other configurations than Debug and Release on 0.40
compojoom opened this issue Β· 55 comments
Description
in XCode we can duplicate the default build Configurations by navigating to our Project -> info tab -> click on the plus symbol and duplicate any of the existing configs (debug, Release). Set a new name. Now when edit our scheme and tell XCode to use our new config the build process won't finish. Most probably you'll end up with this error:
fatal error: 'React/RCTBundleURLProvider.h' file not found
After staring at the screen for a day I think that the issue is that the build script is copying the React files to either debug-iphoneos or release-iphoneos instead of using the "newconfig"-iphoneos directory.
REPROPDUCTION
Steps to reproduce:
- create a new RN project:
react-native init test
-
Now open the project in XCode, click on your project in the folder tree. Then select the project -> your project and navigate to the Info tab. Duplicate one of the configurations and give it whatever name you like.
-
Edit your current scheme and select the new configuration in the "build configuration" option. Now run the project. It should fail.
-
You can repeat the same steps on RN 0.39 and it works...
Here a few screenshots of the proper screens in XCode:
And on this screen you can see that RTCBundleURLProvider.h is being copied, but to the wrong path
Solution
Don't have one yet, most probably the issue happens somewhere in runIOS.js
Additional Information
- React Native version: 0.40
- Platform: iOS
- Operating System: MacOS
I think what you are looking for is something like:
productFlavors {
development {
applicationId "io.app"
versionName "${appVersionName}-development"
}
staging {
applicationId "io.app"
versionName "${appVersionName}-staging"
}
production {
applicationId "io.app"
versionName "${appVersionName}"
}
}
check this out: 46422dd
Same Issue for me - could you find a solution @compojoom ?
@javache I think you worked on the compilation stuff. Is there an easy way to get a Staging Target up?
Thank you very much!
Just figured it out: You need to copy the Release Target in 'React' Project too with the same Name as the parent Target has. Now we need an idea how to make it less troublesome ( without touching React) or we just document it somewhere?
@K-Leon We have had the same issue with our Staging
build configuration. Adding Staging
as a configuration to the React.xcodeproj sorted our 0.40.0 build issues. Release
and Debug
worked out of the box.
This is a bug/feature of Xcode. It attempts to build sub-projects using the same configuration as the main project. If that configuration does not exist, Xcode uses the Release configuration. With the latest changes to public headers exposed by React.xcodeproj, these headers now go to the build path of the sub-project, which is configuration-dependent.
While adding a configuration with the same name works, it's not the most CI-friendly or future-proof solution. This is what I did, instead:
-
Added the React build target under the current scheme for my project. (Sidenote: if you're using fastlane to deploy, keep your project's build target in first place, otherwise fastlane gets confused and thinks you're building a library, so it never builds an ipa).
-
Added React under [Target] > Build Phases > Target Dependencies, which made Xcode build React before building the rest of the project.
-
Under [Target] > Build Settings, added a new User-Defined setting, called
REACT_HEADERS_PATH
. For all configurations not named Debug or Release, I set that to$(BUILD_DIR)/Release-$(PLATFORM_NAME)/include
. -
Under [Target] > Build Settings > Header Search Paths I added
$(REACT_HEADERS_PATH)
as an entry. -
Repeat for all targets in your project.
When my project builds, React builds first, and since it doesn't know about configurations other than Release and Debug, it builds with the Release configuration. This places its headers under [build dir]/Products/Release-iphoneos/include
. Since this path is now in the Header Search Paths of the main project, it gets picked up and everything else builds fine.
Hope this helps.
Updated 4/13 to mention repeating these steps for all targets (thanks @Twinski) and to change to the much shorter and more reliable $(BUILD_DIR)
(thanks @hoolymama).
@tisho your solution worked for me. Cheers!
I had to use
$(BUILD_DIR)/Release-$(PLATFORM_NAME)/include
not
BUILD_PRODUCTS_DIR
Good catch. It was actually supposed to say BUILT_PRODUCTS_DIR, not BUILD_PRODUCTS_DIR. I edited the original post to correct that.
I can't quite make it work with
For me it resolves to build/Staging-iphoneos/Release-iphoneos/include
Its probably something with my configuration - I'll experiment a bit later, but for now BUILD_DIR is working okay. Cheers!
I built a package that should help with automatically setting all of the build configurations up in your libraries on each subsequent install:
https://www.npmjs.com/package/react-native-schemes-manager
Please give it a try and let me know how it works for you. We've got ~20 native libs now in most of our RN projects, so manually managing this would have been a nightmare.
@tisho solution worked for me too. I also had to follow the same steps to my app's Test target in addition to the main app target
@tisho you deserve a medal for this!
Guys, the easiest fix that I found - is to set "CONFIGURATION_BUILD_DIR" in buildSettings of your configuration like:
CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)";
Or if you want to set in XCode:
Your Project -> Build Settings -> Build Locations -> Per-configuration Build Products Path
for your new configuration: $(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)
I would like to second that this is a major headache. Even if I patch it to find React, it can't find any other native dependencies. Do I have to patch the header search paths for every single dependency I add to the project?
Note, that if you're using Cocoapods, you may have to change another configuration variable to point to Release, or it won't be able to find linked Pods:
What about the "Per-configuration Immediate Build Products Path"? It'd make sense for Staging to share the same path as Release too?
@tisho Fix seems to be working! Maybe it's also useful to say that you also should repeat the $(REACT_HEADERS_PATH) for the VigiTest Target!
If anyone is running into this issue when using xcode's workspaces, just make sure to check the settings of all your projects within the workspace.
How do I Added the React build target under the current scheme for my project
? It's not working for me so far. Seems like that's the only step I'm missing. Still getting this error:
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging'
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging-iphoneos/AFNetworking'
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging-iphoneos/Lock'
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging-iphoneos/Masonry'
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging-iphoneos/SimpleKeychain'
ld: warning: directory not found for option '-L/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging-iphoneos/TouchIDAuth'
ld: warning: directory not found for option '-F/Users/nathanhyland/Library/Developer/Xcode/DerivedData/bideasy_rn-ddevhacvgkjqoigndhxjmlrtyyog/Build/Products/Staging'
ld: library not found for -lAFNetworking
clang: error: linker command failed with exit code 1 (use -v to see invocation)
After @j2kun 's step, I had to add "$PODS_CONFIGURATION_BUILD_DIR"
as recursive to Framework Search path to pass the build with cocoapods.
I am getting this error on Buddybuild - I'm unsure how it can be fixed! I tried using @philipshurpik solution but got the same errors on buddybuild, but when I ran the same xcode build command that buddybuild uses locally, it fixed it π€
@natdm I have the same issue. Were you able to solve it?
Update
This solved my issue with the ld -L warnings: oblador/react-native-vector-icons#223 (comment)
@jamesone I think we are in the same boat. Are you by chance trying to integrate code-push? haha. For us we can build our staging config locally using @philipshurpik's solution but only after we have built the project for release (building with the release scheme). If you clean your build then run your staging scheme does it still work? For us @philipshurpik's solution works locally if we build for release first, but Buddy Build doesn't work like that so BB fails
@jamesone @blargity's I'm using react-native-scheme-manager (thanks @blargity!) and works great locally. Buddy Build is still failing though :(
@stantoncbradley I'm getting that exact same error. I've also tried using the scheme manager, but it doesn't work for buddybuild :\
Have you contacted buddybuild about this?
Okay so here is what I did to get a new build configuration working:
I followed this guide: https://www.buddybuild.com/blog/running-multiple-ios-apps (this is not specific to buddybuild, it shows you how to add a new scheme & build configuration)
NOTE that when you get to:
Finally, update the build configuration referenced from the scheme - so that we build with the Staging build configuration.
You must make sure that the Archive
(located here: https://s3-us-west-2.amazonaws.com/buddybuild-public/blog-assets/multi-versions-of-your-app/multiple-versions-of-your-app-8.jpg) build configuration is pointing to your new one
@tisho Thank!! It worked!! I spend almost a week solving this problem. You saved me! Thank you.
@stantoncbradley did you get buddybuild to work with Schema manager?
@D1no Thanks!!! Your solution works.
For anyone coming here, React-Native has inherent problems with adding build configurations because of the way the packenger references the react-native xcode project libraries from the node_modules folder. In hopes this will be solved natively, the best approach for now (React Native Version 0.45.1 and belowish) is this:
(just jottet down for dummies and colleagues who are not that familia with the magic world of xcode)
Use Schemes Manager by @blargity
- Roll back any changes you did to the xcode project-workspace regarding build configurations. All the header/library search path hacks, manual library inclusion etc. The safest bet is to run a test init project and try to get it working there. Make sure to add cocoa pods first so you are working with the
*.xcworkspace
and not the*.xcodeproj
of yourios/
folder. Than transfer the learnings to your real project. - Install Schema Manager from npm as dev dependency (https://www.npmjs.com/package/react-native-schemes-manager)
- Add build configurations by copying the original release or debug variant respectively.
- Rename those build configurations to your desired name. I.e. We have two additional Release variants called "angel" and "tester" that carry each a different bundle id, use different logos and connect to different backends. Just some guidance how this looks like (different bundle ids & app icons β under target):
- Add the new config to the package.json as an instruction for Schemes Manager to add those build configs to all the react-native xcode projects in the node modules folder.
- Add schemes manager to your post install scripts (as described in the documents). We did it like so:
- When you run
npm run fix-xcode
(with that example), you'll see the following. This should be done anytime after you run npm install, hence, the postinstall reference:
- Now add a scheme to xcode that references your new build configuration. In xcode world, it's like a short cut pre-set of configurations. Those can be shared (are committed to the repository) or personal. If you want CI Systems such as BuddyBuild to pick up those schemes, make sure you tick the "shared" checkbox.
- Also make sure, that the new schema references the right build configuration in run and archive. To do so alt + click on the play symbol, duplicate the original scheme and do the following.
- You should now be set to build those variants.
Tips & Bottle Necks
- We were not able to build an archive from a different build config. Run is no problem. Since we use BuddyBuild and only require our release version to be build for archive (to be able to upload to itunes), this did not bother us. However, this means we have two branches. A staging branch for ad'hock distribution and a master branch from where our release is build for archive.
- The reason for that are probably build references paths that are auto generated from the new build naming and do not correspond to the hard coded packager references. Such as
- If you encounter linking errors, it's worth to take a look at the header & library search paths and check how they might differ to the original release paths.
- Since we can not use multiple targets, all files are linked to the same xcode target. That can cause issues when including files that should (for simplicity) be of the same reference but vary between builds. Such an example is the
GoogleService-Info.plist
for google login (you could reference them in your AppDelegate file). However, we try to touch as little of the native code as possible to have little hassle in upgrading further rn-versions. The best way to solve such situations is to have an extra folder in yourios/
folder, which is not added to the xcode project. And have files, depending on their build config suffix be copied to the app at build time. I.e. we manage our firebase files like so:
Here our script (simple shell command):
cp ${SRCROOT}/firebase/GoogleService-Info-${CONFIGURATION}.plist ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleService-Info.plist
Note: I jotted this down because it was quite a hassle to get react-native into a common xcode workflow. So this is also for my colleagues and my memory. I plan for a while to turn this into a proper blog post. But until than, this here is my scratch pad to signal what mess is behind this issue . π
@tisho I followed your solution,but it didn't work.this is my screenshot:
I also add React in Build Phases --> Target Dependencies,but it didn't work too......
@tisho Thx! Did the trick for me.
Extra thing that was needed in my case due to link errors:
add "$(BUILD_DIR)/Release$(EFFECTIVE_PLATFORM_NAME)" to Library Search Paths (only for the custom configuration)
@easybird I had the same issue and setting library search paths indeed solves the problem, thanks!
In case anyone else runs into this issue and wants to test out the schemes-manager solution, I created an example project that incorporates @D1no 's guide as a github project you can pull and play around with. I spent some time hard-coding paths to header files and realized that this would not scale well once more developers ended up working on our projects, so decided to go the schemes-manager route, and everything works great so far.
What a mess!!!! I just spent several days trying to figure out what is going on with my XCode project. We rely on custom configs heavily - this completely broke our project. When is this going to be fixed proper????
Just want to add that this error occurs with a clean project boilerplate based on react-native init. The error mentioned and error icon are there from the start. However the error mentioned didn't cause the build to fail, the simulator was still able to load up.
Steps to reproduce:
- In Terminal, create the project:
react-native init <project-name>
- Open the project in Xcode and open "AppDelegate.m" file, you should see the red error icon next to the code:
#import <React/RCTBundleURLProvider.h>
Package/Software Versions installed as follows:
- "react": "16.0.0-alpha.12",
- "react-native": "0.46.4"
- NPM: 3.10.10
- XCode: 8.2.1
Tried @tisho solution but i got a new error. Not really sure what am i suppose to do next.
library not found for -lRealmReact
@tisho Your answer is very exciting, according to your guidance, I built a number of new target, and can build success. But the new target fails in archive:
I was able to create a staging environment following @philipshurpik and @j2kun suggestions. However, if I create a new scheme to create a staging archive, the build fails with the same error React/RCTBridgeModule.h file not found
. If I edit the default scheme to use the staging configuration, then the archive is created successfully. Is there any other trick to get new schemes to work as well using the new staging configuration. I want to avoid having to keep editing the scheme every time I create a staging or a release archive. I fear I may forget to change and create unwanted problems.
I created a staging configuration and I was able to create an IPA file using the staging configuration. But when I upload the IPA to iTunesConnect, I see that the IPA is missing the frameworks that I am using in the app. The frameworks are present when the IPA is created using the release configuration. Below are the screenshots for the staging and the release configuration. Observe that the frameworks are not listed.
Observe that the frameworks are not listed in the staging IPA when I try to upload it iTunesConnect. Due to this, I got an error from iTunesConnect
Invalid Bundle - One or more dynamic libraries that are referenced by your app are not present in the dylib search path.
Below is a screenshot of the framework search paths in the Xcode project. The value is same for both staging and release.
Please let me know how can I fix this problem.
@varungupta85 check out schema manager mentioned above. Its purpose is to add the libraries from node_modules to the new release targets.
@D1no Thanks for your reply. I looked at the react-native-schemes-manager when I was going to through the comments. I felt that it is doing a lot of magic in the background which always worries me because if things start to break in future, I am not sure where to look at. I tried the suggestions from @philipshurpik and @j2kun using which I was able to build the app using staging configuration. I feel that I should be able to get the frameworks to be also present in the IPA with some change in settings in Xcode.
I will use the react-native-schemes-manager if I don't find a solution to this problem soon.
Actually there is not much magic. Just automation of a very annoying Xcode manual task. Read more at the bottom of the package, itβs sources and what it does. If all react native packages would be cocoa pods, the problem would not exist. But as they all require the rn packanger which has just two build configurations, those need to be copied for all of them. Thinkmill and we use it in production, and probably many more, and it works fine with version react-native@latest with Xcode 9.
So, requiring xproject files from node_modules was never something Xcode was designed for. I mean, sometimes it feels likeXcode projects were not even designed for a code revision system, due to its cryptic uid file steucture.
Until all that changes, or the guys at the metro bundler tackle this problem in a very smart way, the work stays the same. And it is very hard to configure yourself out of that.
@D1no Thanks for the detailed reply. I feel more confident about using the scheme manager now and since I haven't been able to work around the problem I reported, I will start using it.
I just wanted to point out one small thing that after I updated the CONFIGURATION_BUILD_DIR
AND POD_CONFIGURATION_BUILD_DIR
, I was able to build the app. The missing frameworks in the IPA are all pods that I have installed in my app mainly Sentry
, KSCrash
, RSKImageCropper
and QBImagePicker`. I am not sure if it sheds any more light on the problem I am having since you said that the said issue doesn't occur with packages installed using cocoa pods and that the scheme manager is mainly to fix the projects installed using npm.
Thanks again for taking the time to post your comments.
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. If you think this issue should definitely remain open, please let us know why. Thank you for your contributions.
worked.
@varungupta85 even i am facing the issue of frameworks not being listed in staging scheme. Did you find a solution for this?
@shohey1226 i tried the same thing but its not working for me. Looks like the pod libraries are getting copied into Staging folder instead of release which leads to #11813 (comment)
/Users/harkirat/Library/Developer/Xcode/DerivedData/wlv1-grovuwlrhzpjbvenlreejvbtlwol/Build/Intermediates.noindex/ArchiveIntermediates/wlv1 Staging/BuildProductsPath
tests-MBP:BuildProductsPath harkirat$ ls
Release-iphoneos Staging-iphoneos
tests-MBP:BuildProductsPath harkirat$
tests-MBP:BuildProductsPath harkirat$ cd Staging-iphoneos/
tests-MBP:Staging-iphoneos harkirat$ ls
GTMOAuth2 Mixpanel QBImagePickerController
GTMSessionFetcher Pods_wlv1.framework RSKImageCropper
GoogleToolboxForMac Protobuf nanopb
tests-MBP:Staging-iphoneos harkirat$
tests-MBP:BuildProductsPath harkirat$ cd Release-iphoneos/
tests-MBP:Release-iphoneos harkirat$ ls
49D27CAF-3566-30BB-9FF1-63E20D4D5231.bcsymbolmap libRCTMaterialKit.a
57C7F55D-A2AE-30F3-A6EA-9F38A1651329.bcsymbolmap libRCTNetwork.a
5maFL9 libRCTSettings.a
B00A891C-B9FD-3621-85B1-D7ACEEB3888C.bcsymbolmap libRCTText.a
B881CB00-A637-3C8C-90B1-36E49E358AA1.bcsymbolmap libRCTVibration.a
GeneratedInfoPlistDotEnv.h libRCTWebSocket.a
Hhe8NH libRNDeviceInfo.a
QBImagePicker.framework libRNFIRMessaging.a
QBImagePicker.framework.dSYM libRNFS.a
RSKImageCropper.framework libRNFetchBlob.a
RSKImageCropper.framework.dSYM libRNIntercom.a
include libRNMixpanel.a
libBVLinearGradient.a libReact.a
libBugsnagReactNative.a libReactNativeConfig.a
libBugsnagStatic.a libcxxreact.a
libCodePush.a libdouble-conversion.a
libRCTActionSheet.a libimageCropPicker.a
libRCTAnimation.a libjschelpers.a
libRCTCamera.a libthird-party.a
libRCTFBSDK.a libyoga.a
libRCTGeolocation.a wlv1.app
libRCTImage.a wlv1.swiftmodule
libRCTLinking.a
I tried adding "$PODS_CONFIGURATION_BUILD_DIR"
as recursive to FRAMEWORK_PATH but still it creates 2 folders.
I just download CORS extension for chrome and it works for me
For anyone who comes across this, I managed to piece together a working XCode setup to get:
- custom build configs working for
Build
andArchive
in myreact-native init
apps (using Cocoapods); if you're usingfastlane
, this supports its deployment, as well - Microsoft's AppCenter and CodePush iOS SDKs working with said custom build configs (
Staging
,Angel
, etc.)
Made a post on an issue in Microsoft's code-push repo detailing my setup.
Shout out to @D1no! your solution worked for me! Been banging my head against the wall for the past few days. The solution worked for my CI system as well (buddybuild).
@D1no you should post that in a medium article !! nice !
When I jotted that down, I hoped a blog article would be obsolete by the time it goes online. Aka improvements of the metro bundler. Oh well - for better SEO Iβll add it to my todo list. Hopefully saving some devs the long path of desperate hacks until they find that comment. π