-
Notifications
You must be signed in to change notification settings - Fork 24.8k
Description
Is this a bug report?
Yes
Have you read the Bugs section of the Contributing to React Native Guide?
Yes
Environment
react-native -v
: react-native-cli: 2.0.1, react-native: 0.46.1node -v
: v6.10.2npm -v
: 3.10.10yarn --version
(if you use Yarn): 0.24.6
Then, specify:
- Target Platform (e.g. iOS, Android): iOS
- Development Operating System (e.g. macOS Sierra, Windows 10): Mac OS X El Capitan
- Build tools (Xcode or Android Studio version, iOS or Android SDK version, if relevant): Xcode
Steps to Reproduce
- Create new application (
react-native init rnclifail
) - Open
rnclifail.xcodeproj
in Xcode - Go to Product > Manage Schemes
- Select
rnclifail
from list and click the setings icon - Click
duplicate
- Name it rnclifail2
- Click on
rnclifail
project in left side panel - Right click on first Target (
rnclifail
) and click Duplicate - Select Duplicate Only
- Click on the newly added Target, hit enter and change it's name from
rnclifail copy
tornclifail2
, and the change the bundle identifier postfix so it'srnclifail2
instead ofrnclifail-copy
. - Add a provisioning team as required
- Go to Product > Manage Schemes again
- Click on
rnclifail2
and enable Shared so it's similar to the originalrnclifail
- Click
Edit
- Change the Executable to
rnclifail2.app
- Change Build Configuration to
Release
- Go to the Terminal in the project folder and bundle the application for Release:
react-native bundle --platform ios --dev false --bundle-output iOS/main.jsbundle --entry-file index.ios.js
. - Drag and drop the generated
main.jsbundle
andmain.jsbundle.meta
into thernclifail
group folder in XCode. SelectCopy items if needed
, selectCreate groups
and select bothrnclifail
andrnclifail2
in Add to targets. - Now run the application using:
react-native run-ios --scheme rnclifail --configuration Debug
. It should pass and installrnclifail.app
which is expected behaviour. See output below. - Now run the application using:
react-native run-ios --scheme rnclifail2 --configuration Release
. It should pass too but it installedrnclifail.app
instead ofrnclifail2.app
. See output below.
Output from Step 19
Installing build/Build/Products/Debug-iphonesimulator/rnclifail.app
Launching org.reactjs.native.example.rnclifail
org.reactjs.native.example.rnclifail: 1063
Output from Step 20
Installing build/Build/Products/Release-iphonesimulator/rnclifail.app
Launching org.reactjs.native.example.rnclifail
org.reactjs.native.example.rnclifail: 99028
Expected Behavior
The rncliapp2.app
would get deployed.
Actual Behavior
The rncliapp.app
got built and deployed.
Reproducible Demo
- Clone the repo at https://github.com/zephinzer/rnclifail
- Do a
yarn install
- Perform steps 19/20 from above Steps to Reproduce
Fix
Have analysed the build output and logs and found that the block starting at 158 in /local-cli/runIOS/runIOS.js
(https://github.com/facebook/react-native/blob/master/local-cli/runIOS/runIOS.js#L158) contains the error:
The following is the current code:
buildProcess.on('close', function(code) {
let productNameMatch = /export FULL_PRODUCT_NAME="?(.+).app"?$/m.exec(buildOutput);
if (productNameMatch && productNameMatch.length && productNameMatch.length > 1) {
return resolve(productNameMatch[1]);//0 is the full match, 1 is the app name
}
return buildProcess.error? reject(error) : resolve();
});
Problem 1
This assumes a build output where a line exists such that:
export FULL_PRODUCT_NAME="appName.app"
exists, which does not happen to be true. The actual build output (gotten by console.log(buildOutput)
shows that the line we expect is actually without the apostrophes:
export FULL_PRODUCT_NAME=appName.app
What happens is that there is no matched productNameMatch
and resolve()
is called which results in appName
being null
on line 97 (https://github.com/facebook/react-native/blob/master/local-cli/runIOS/runIOS.js#L97), and the CLI defaults to using the inferredSchemeName
which is wrong.
Problem 2
The current code assumes that only one instance of export FULL_PRODUCT_NAME=<APP_NAME>.app
will appear in the build output, which may not be true in a custom build scheme, however according to Xcode behaviour, we can expect the final product of each Build Scheme to be the last listed. We can fix this by not assuming any length and instead taking the last index of the matches.
Solution
The fix would be to change the block of code to the following block, which would retrieve all instances of export FULL_PRODUCT_NAME=<APP_NAME>.app
and use the last one:
buildProcess.on('close', function(code) {
const fullProductNamePattern = /export FULL_PRODUCT_NAME=?(.+).app/mg;
const productNameMatch = [];
let match;
while((match = fullProductNamePattern.exec(buildOutput)) !== null) {
productNameMatch.push(match[1]);
}
if (productNameMatch && productNameMatch.length && productNameMatch.length > 0) {
const lastProductName = productNameMatch[productNameMatch.length - 1];
return resolve(lastProductName);//0 is the full match, 1 is the app name
}
});
Have already fixed this in my local repo so that I can get the correct files built, and will submit a PR when I can.