@@ -2,6 +2,7 @@ import groovy.json.JsonSlurper
2
2
import org.gradle.initialization.DefaultSettings
3
3
import org.apache.tools.ant.taskdefs.condition.Os
4
4
5
+ def jsAppDir = buildscript. sourceFile. toString(). split(" node_modules/@react-native-community/cli-platform-android" )[0 ]
5
6
def generatedFileName = " PackageList.java"
6
7
def generatedFilePackage = " com.facebook.react"
7
8
def generatedFileContentsTemplate = """
@@ -71,12 +72,14 @@ public class PackageList {
71
72
class ReactNativeModules {
72
73
private Logger logger
73
74
private String packageName
75
+ private String jsAppDir
74
76
private ArrayList<HashMap<String , String > > reactNativeModules
75
77
76
78
private static String LOG_PREFIX = " :ReactNative:"
77
79
78
- ReactNativeModules (Logger logger ) {
80
+ ReactNativeModules (Logger logger , String jsAppDir ) {
79
81
this . logger = logger
82
+ this . jsAppDir = jsAppDir
80
83
81
84
def (nativeModules, packageName) = this . getReactNativeConfig()
82
85
this . reactNativeModules = nativeModules
@@ -142,45 +145,66 @@ class ReactNativeModules {
142
145
}
143
146
144
147
/**
145
- * Runs a process to call the React Native CLI Config command and parses the output
146
- *
147
- * @return ArrayList < HashMap < String , String > >
148
+ * Runs a specified command using Runtime exec() in a specified directory.
149
+ * Throws when the command result is empty.
148
150
*/
149
- ArrayList<HashMap<String , String > > getReactNativeConfig () {
150
- if (this . reactNativeModules != null ) return this . reactNativeModules
151
- ArrayList<HashMap<String , String > > reactNativeModules = new ArrayList<HashMap<String , String > > ()
152
-
153
- def cmdProcess
154
- def npx = Os . isFamily(Os . FAMILY_WINDOWS ) ? " npx.cmd" : " npx"
155
- def command = " ${ npx} --quiet react-native config"
156
- def reactNativeConfigOutput = " "
157
-
151
+ String getCommandOutput (String command , File directory = null ) {
158
152
try {
159
- cmdProcess = Runtime . getRuntime(). exec(command)
153
+ def output = " "
154
+ def cmdProcess = Runtime . getRuntime(). exec(command, null , directory)
160
155
def bufferedReader = new BufferedReader (new InputStreamReader (cmdProcess. getInputStream()))
161
156
def buff = " "
162
157
def readBuffer = new StringBuffer ()
163
- while ((buff = bufferedReader. readLine()) != null ){
164
- readBuffer. append(buff)
158
+ while ((buff = bufferedReader. readLine()) != null ) {
159
+ readBuffer. append(buff)
160
+ }
161
+ output = readBuffer. toString()
162
+ if (! output) {
163
+ this . logger. error(" ${ LOG_PREFIX} Unexpected empty result of running '${ command} ' command from '${ directory} ' directory." )
164
+ def bufferedErrorReader = new BufferedReader (new InputStreamReader (cmdProcess. getErrorStream()))
165
+ def errBuff = " "
166
+ def readErrorBuffer = new StringBuffer ()
167
+ while ((errBuff = bufferedErrorReader. readLine()) != null ) {
168
+ readErrorBuffer. append(errBuff)
169
+ }
170
+ throw new Exception (readErrorBuffer. toString())
165
171
}
166
- reactNativeConfigOutput = readBuffer . toString()
172
+ return output
167
173
} catch (Exception exception) {
168
- this . logger. warn(" ${ LOG_PREFIX}${ exception.message} " )
169
- this . logger. warn(" ${ LOG_PREFIX} Automatic import of native modules failed." )
174
+ this . logger. error(" ${ LOG_PREFIX} Running '${ command} ' command from '${ directory} ' directory failed." )
175
+ throw exception
176
+ }
177
+ }
170
178
171
- def bufferedErrorReader = new BufferedReader (new InputStreamReader (cmdProcess. getErrorStream()))
172
- def buff = " "
173
- def readBuffer = new StringBuffer ()
174
- while ((buff = bufferedErrorReader. readLine()) != null ){
175
- readBuffer. append(buff)
176
- }
177
- this . logger. warn(" ${ LOG_PREFIX}${ readBuffer.toString()} " )
179
+ /**
180
+ * Runs a process to call the React Native CLI Config command and parses the output
181
+ */
182
+ ArrayList<HashMap<String , String > > getReactNativeConfig () {
183
+ if (this . reactNativeModules != null ) return this . reactNativeModules
178
184
179
- return reactNativeModules
185
+ ArrayList<HashMap<String , String > > reactNativeModules = new ArrayList<HashMap<String , String > > ()
186
+ def npx = Os . isFamily(Os . FAMILY_WINDOWS ) ? " npx.cmd" : " npx"
187
+ def command = " ${ npx} --quiet --no-install react-native config"
188
+ /**
189
+ * Running npx from the directory of the JS app which holds this script in its node_modules.
190
+ * We do so, because Gradle may be ran with a different directory as CWD, that's outside of JS project
191
+ * (e.g. when running with -p flag), in which case npx wouldn't resolve correct `react-native` binary.
192
+ */
193
+ def dir = new File (this . jsAppDir)
194
+ def reactNativeConfigOutput = this . getCommandOutput(command, dir)
195
+ def json
196
+ try {
197
+ json = new JsonSlurper (). parseText(reactNativeConfigOutput)
198
+ } catch (Exception exception) {
199
+ this . logger. error(" ${ LOG_PREFIX} Failed to parse React Native CLI configuration: ${ exception.toString()} " )
200
+ throw new Exception (" Failed to parse React Native CLI configuration. Expected running '${ command} ' command from '${ dir} ' directory to output valid JSON, but it didn't. This may be caused by npx resolving to a legacy global react-native binary. Please make sure to uninstall any global 'react-native' binaries: 'npm uninstall -g react-native react-native-cli' and try again" )
180
201
}
181
-
182
- def json = new JsonSlurper (). parseText(reactNativeConfigOutput)
183
202
def dependencies = json[" dependencies" ]
203
+ def project = json[" project" ][" android" ]
204
+
205
+ if (project == null ) {
206
+ throw new Exception (" React Native CLI failed to determine Android project configuration. This is likely due to misconfiguration. Config output:\n ${ json.toMapString()} " )
207
+ }
184
208
185
209
dependencies. each { name , value ->
186
210
def platformsConfig = value[" platforms" ];
@@ -211,7 +235,7 @@ class ReactNativeModules {
211
235
* Exported Extensions
212
236
* ------------------------ */
213
237
214
- def autoModules = new ReactNativeModules (logger)
238
+ def autoModules = new ReactNativeModules (logger, jsAppDir )
215
239
216
240
ext. applyNativeModulesSettingsGradle = { DefaultSettings defaultSettings , String root = null ->
217
241
if (root != null ) {
0 commit comments