Back in November, after 6 months of working on other projects, I picked up development for the EV-Point Mobile App again. The app is built using React Native and is available on both iOS and Android.
As Xcode got a new major release (from Xcode 9 to Xcode 10) since my last time working on the project I figured I’d trigger a new build on Bitrise, then see which errors would came at me, and continue from thereon. What I didn’t know however is that it would eventually take me 3 days, 17 failed builds, lots of Google Fu, and some guesswork to get everything working again. Here’s an overview of the biggest hurdles that I had to take, along with their solutions. I hope they might help you too.
There’s always a green light at the end of the build-pipeline tunnel …
My initial plan was to first get the current version of the app – still running React Native 0.53.3 – to build again in Xcode 10, and only then upgrade the React Native version to the latest one (0.57.4 at the time of writing). During the course of my journey I eventually flipped that around, as React Native 0.57.x already contained some fixes that I was in need of.
👋 I’m using Bitrise for automatically building all my apps. If you sign up through this referral link, we both get extra build-time: https://app.bitrise.io/users/sign_up?referrer=09c28434a5e3e18d
~
Problem #1: iOS: React Native project won’t build on Xcode 10
Of course my first Bitrise trigger using Xcode 10 would fail (but one can always try, right?). What I didn’t expect is that quite a lot of things were going wrong (REF):
- Xcode Signing Issues
- Failures indicating that
libfishook.a
could not be linked - Third party things such as
glog
that were not installed - etc.
As I stumbled from one build error into the other (locally, of course) and tried fixing these one by one, I eventually found that the most easy solution would be to upgrade to the latest RN version (0.57.4 at the time of writing) as it already contained most of the fixes.
Solution #1 (part1): Upgrading to the latest RN version
To upgrade to the latest RN version I used react-native-git-upgrade
. I didn’t immediately jump from RN 0.53 to RN 0.57 though, but gradually went through all intermediate releases.
# install react-native-git-upgrade
yarn global add react-native-git-upgrade
# Go to project folder
cd ~/repos/evpoint/mobileapp/
# Upgrade to RN 0.54.4
react-native-git-upgrade 0.54.4
# Upgrade to RN 0.55.4
react-native-git-upgrade 0.55.4
# Upgrade to RN 0.56.1
react-native-git-upgrade 0.56.1
# Upgrade to RN 0.57.4
react-native-git-upgrade 0.57.4
Using react-native-git-upgrade
to upgrade RN versions works like a charm, but it might will require you to resolve a few merge conflicts …
Upgrading from one React Native version to the other …
Once I performed all upgrades I tried building my app locally and … yes, great succes!
💁♂️ Note that when upgrading from RN 0.53 to 0.57, the Android build system will have migrated from Gradle 3 to Gradle 4. As we’re now focussing on getting iOS to build, we’ll skip this for now and tackle it later (see Problem #4 below)
Solution #1 (part2): Manually installing the third party scripts
UPDATE: This is fixed with the release of React Native 0.57.5 (#277c19c
). You can skip this step if you’re running 0.57.5 or newer.
After successfully building locally I pushed my changes online in order for Bitrise to kick into action. Bitrise however failed. Hmmz …
- Build input file cannot be found: `./node_modules/react-native/Libraries/WebSocket/libfishook.a`
- `configure: error: in `(..._/node_modules/react-native/third-party/glog-0.3.4'`
- `✗ Build input file cannot be found: 'node_modules/react-native/third-party/double-conversion-1.1.6/src/strtod.cc'`
- `No member named '__rip' in '__darwin_arm_thread_state64'`
Turns out that there was an issue with third party scripts not getting installed correctly. Locally they were, however.
FYI: Locally it worked fine because – as it turns out – a second build would correctly struggle through it. As Bitrise always starts from scratch (e.g. with a non-existing node_modules
folder) it couldn’t make it through.
To fix this I added an extra step in the build-pipeline to Manually install Third Party Scripts + Configure Glog, (REF)
:
#!/usr/bin/env bash -e
if [ ! -d "node_modules/react-native/third-party" ]; then
cd node_modules/react-native ; ./scripts/ios-install-third-party.sh ; cd ../../
cd node_modules/react-native/third-party/glog-0.3.5/ ; ./../../scripts/ios-configure-glog.sh ; cd ../../../../
fi
I’ve added this step right before Bitrise’s Certificate and Profile Installer step.
💡You’ll also need to execute this step locally, especially when starting from scratch. You can safely add this script to your local build-script as it contains a built-in check to not double install the Third Party Scripts in case they are already present.
~
Problem #2: Android: Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider
On Android I was still getting build errors though. My first one was something like this:
Error:Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider
java.lang.NoClassDefFoundError: Failed resolution of: android/support/v4/animation/AnimatorCompatHelper;
java.lang.NoSuchFieldError: No field notification_template_lines of type
Solution #2: Fixate the SDK version for com.android.support
to a specific version
Thankfully someone else had already stumbled onto this problem and provided a fix: fixate the SDK version for com.android.support
to version 24.2.1
. You can do this by adjusting your app/android/build.gradle
file:
android {
…
// Fix for "Program type already present: android.support.v4.app.ActionBarDrawerToggle$DelegateProvider"
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.android.support') {
if (!requested.name.startsWith("multidex")
&& !requested.name.startsWith("exifinterface")) {
details.useVersion '24.2.1'
}
}
}
}
}
~
Problem #3: Android: Unable to find a matching configuration in project
When running ./gradlew assembleDebug
I could successfully build for Android. Running ./gradlew assembleRelease
however, yielded this error:
Unable to find a matching configuration of project :react-native-devsettings-android:
- Configuration 'debugApiElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
- Found com.android.build.api.attributes.VariantAttr 'debug' but wasn't required.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
- Configuration 'debugRuntimeElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'debug'.
- Found com.android.build.api.attributes.VariantAttr 'debug' but wasn't required.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Required org.gradle.usage 'java-api' and found incompatible value 'java-runtime'.
- Configuration 'releaseApiElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
- Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Required org.gradle.usage 'java-api' and found compatible value 'java-api'.
- Configuration 'releaseRuntimeElements':
- Required com.android.build.api.attributes.BuildTypeAttr 'preview' and found incompatible value 'release'.
- Found com.android.build.api.attributes.VariantAttr 'release' but wasn't required.
- Required com.android.build.gradle.internal.dependency.AndroidTypeAttr 'Aar' and found compatible value 'Aar'.
- Required org.gradle.usage 'java-api' and found incompatible value 'java-runtime'.
at org.gradle.internal.component.model.AbstractDependencyMetadata.selectConfigurationUsingAttributeMatching(AbstractDependencyMetadata.java:46)
at org.gradle.internal.component.model.LocalComponentDependencyMetadata.selectConfigurations(LocalComponentDependencyMetadata.java:90)
at org.gradle.internal.component.local.model.DslOriginDependencyMetadataWrapper.selectConfigurations(DslOriginDependencyMetadataWrapper.java:60)
at org.gradle.api.internal.artifacts.ivyservice.resolveengine.graph.builder.EdgeState.calculateTargetConfigurations(EdgeState.java:143)
... 89 more
Solution #3: Use matchingFallbacks
The fix was to adjust the defined buildType
of debug
so that it falls back to the release
‘s buildType
values in case one is missing. This can be done by using the matchingFallbacks
instruction inside your app/android/build.gradle
file (REF, REF):
android {
…
buildTypes {
release {
…
}
preview {
…
matchingFallbacks = ['release', 'debug']
}
}
}
~
Problem #4 Android: Execution failed for task ':react-native-config:verifyReleaseResources'
The final Android problem I encountered was that dependencies would not properly compile anymore with the change to Gradle 4. Packaged like react-native-config
and react-native-devsettings-android
would fail on their verifyReleaseResources
step.
Solution #4: Upgrade packages and/or force subprojects to use same compileSdk
/BuildTools
as main project
Thankfully packages like react-native-config
have already landed fixes for this issue. Merely upgrading your affected dependencies using yarn
will fix it.
If you’re using packages do not yet have fixes – like react-native-devsettings-android
(ISSUE) – you can thankfully force them to use the correct compileSdk
/BuildTools
version from within your own android/build.gradle
file (REF, REF):
subprojects {
…
// Force subprojects to use same compileSdk/BuildTools as main project
afterEvaluate {project ->
if (project.hasProperty("android")) {
android {
compileSdkVersion rootProject.ext.compileSdkVersion
buildToolsVersion rootProject.ext.buildToolsVersion
}
}
}
}
~
Furthermore I have a few classic issues – such as signing certificates that were expired – which I had to tackle. Supposedly the release of RN 0.58 – which I’m looking forward to – should no longer require the adjustment mentioned above.
Thank me with a coffee.
I don\'t do this for profit but a small one-time donation would surely put a smile on my face. Thanks!
To stay in the loop you can follow @bramus or follow @bramusblog on Twitter.
What program do you use for the builds (the first image)?
I’m using Bitrise for this. If you sign up through this referral link, we both get extra build-time: https://app.bitrise.io/users/sign_up?referrer=09c28434a5e3e18d