@@ -292,28 +292,109 @@ function writeBuildscriptHook(enable) {
292
292
console . log ( "Install Crashlytics buildscript hook." ) ;
293
293
try {
294
294
var scriptContent =
295
- `var fs = require('fs-extra');
296
- var path = require('path');
297
- var xcode = require('xcode');
295
+ `const fs = require('fs-extra');
296
+ const path = require('path');
297
+ const xcode = require('xcode');
298
+
299
+ const pattern1 = /\\n\\s*\\/\\/Crashlytics 1 BEGIN[\\s\\w]*\\/\\/Crashlytics 1 END.*\\n/m;
300
+ const pattern2 = /\\n\\s*\\/\\/Crashlytics 2 BEGIN[\\s\\w]*\\/\\/Crashlytics 2 END.*\\n/m;
301
+ const pattern3 = /\\n\\s*\\/\\/Crashlytics 3 BEGIN[\\s\\w]*\\/\\/Crashlytics 3 END.*\\n/m;
302
+
303
+ const string1 = \`
304
+ //Crashlytics 1 BEGIN
305
+ #else
306
+ #import <Crashlytics/CLSLogging.h>
307
+ #endif
308
+ //Crashlytics 1 END
309
+ \`;
310
+
311
+ const string2 = \`
312
+ #if DEBUG
313
+ #else
314
+ //Crashlytics 2 BEGIN
315
+ static int redirect_cls(const char *prefix, const char *buffer, int size) {
316
+ CLSLog(@"%s: %.*s", prefix, size, buffer);
317
+ return size;
318
+ }
319
+
320
+ static int stderr_redirect(void *inFD, const char *buffer, int size) {
321
+ return redirect_cls("stderr", buffer, size);
322
+ }
298
323
324
+ static int stdout_redirect(void *inFD, const char *buffer, int size) {
325
+ return redirect_cls("stdout", buffer, size);
326
+ }
327
+ //Crashlytics 2 END
328
+ #endif
329
+ \`;
330
+
331
+ const string3 = \`
332
+ //Crashlytics 3 BEGIN
333
+ #if DEBUG
334
+ #else
335
+ // Per https://docs.fabric.io/apple/crashlytics/enhanced-reports.html#custom-logs :
336
+ // Crashlytics ensures that all log entries are recorded, even if the very next line of code crashes.
337
+ // This means that logging must incur some IO. Be careful when logging in performance-critical areas.
338
+
339
+ // As per the note above, enabling this can affect performance if too much logging is present.
340
+ // stdout->_write = stdout_redirect;
341
+
342
+ // stderr usually only occurs during critical failures;
343
+ // so it is usually essential to identifying crashes, especially in JS
344
+ stderr->_write = stderr_redirect;
345
+ //Crashlytics 3 END
346
+ #endif
347
+ \`;
299
348
300
349
module.exports = function($logger, $projectData, hookArgs) {
301
- var platform = hookArgs.platform.toLowerCase();
350
+ const platform = hookArgs.platform.toLowerCase();
302
351
return new Promise(function(resolve, reject) {
303
- var isNativeProjectPrepared = !hookArgs.nativePrepare || !hookArgs.nativePrepare.skipNativePrepare;
352
+ const isNativeProjectPrepared = !hookArgs.nativePrepare || !hookArgs.nativePrepare.skipNativePrepare;
304
353
if (isNativeProjectPrepared) {
305
354
try {
306
355
if (platform === 'ios') {
307
- var appName = path.basename($projectData.projectDir);
308
- var sanitizedName = appName.split('').filter(function(c) { return /[a-zA-Z0-9]/.test(c); }).join('');
309
- var projectPath = path.join($projectData.platformsDir, 'ios', sanitizedName + '.xcodeproj', 'project.pbxproj');
310
- $logger.trace('Using Xcode project', projectPath);
311
- var xcodeProject = xcode.project(projectPath);
312
- xcodeProject.parseSync();
313
- var options = { shellPath: '/bin/sh', shellScript: '\${PODS_ROOT}/Fabric/run' };
314
- var buildPhase = xcodeProject.addBuildPhase([], 'PBXShellScriptBuildPhase', 'Configure Crashlytics', xcodeProject.getFirstTarget().uuid, options).buildPhase;
315
- fs.writeFileSync(projectPath, xcodeProject.writeSync());
316
- $logger.trace('Xcode project written');
356
+ const sanitizedAppName = path.basename($projectData.projectDir).split('').filter((c) => /[a-zA-Z0-9]/.test(c)).join('');
357
+
358
+ // write buildscript for dSYM upload
359
+ const xcodeProjectPath = path.join($projectData.platformsDir, 'ios', sanitizedAppName + '.xcodeproj', 'project.pbxproj');
360
+ $logger.trace('Using Xcode project', xcodeProjectPath);
361
+ if (fs.existsSync(xcodeProjectPath)) {
362
+ var xcodeProject = xcode.project(xcodeProjectPath);
363
+ xcodeProject.parseSync();
364
+ var options = { shellPath: '/bin/sh', shellScript: '\${PODS_ROOT}/Fabric/run' };
365
+ xcodeProject.addBuildPhase(
366
+ [], 'PBXShellScriptBuildPhase', 'Configure Crashlytics', xcodeProject.getFirstTarget().uuid, options
367
+ ).buildPhase;
368
+ fs.writeFileSync(xcodeProjectPath, xcodeProject.writeSync());
369
+ $logger.trace('Xcode project written');
370
+ } else {
371
+ $logger.error(xcodeProjectPath + ' is missing.');
372
+ reject()
373
+ }
374
+
375
+ // Logging from stdout/stderr
376
+ $logger.out('Add iOS crash logging');
377
+ const mainmPath = path.join($projectData.platformsDir, 'ios', 'internal', 'main.m');
378
+ if (fs.existsSync(mainmPath)) {
379
+ let mainmContent = fs.readFileSync(mainmPath).toString();
380
+ // string1
381
+ mainmContent = pattern1.test(mainmPath)
382
+ ? mainmContent.replace(pattern1, string1)
383
+ : mainmContent.replace(/(\\n#endif\\n)/, string1);
384
+ // string2
385
+ mainmContent = pattern2.test(mainmPath)
386
+ ? mainmContent.replace(pattern2, string2)
387
+ : mainmContent.replace(/(\\nint main.*)/, string2 + '$1');
388
+ // string3
389
+ mainmContent = pattern3.test(mainmPath)
390
+ ? mainmContent.replace(pattern3, string3)
391
+ : mainmContent.replace(/(int main.*\\n)/, '$1' + string3 + '\\n');
392
+ fs.writeFileSync(mainmPath, mainmContent);
393
+ } else {
394
+ $logger.error(mainmPath + ' is missing.');
395
+ reject()
396
+ }
397
+
317
398
resolve();
318
399
} else {
319
400
resolve();
@@ -515,7 +596,7 @@ module.exports = function($logger, $projectData) {
515
596
});
516
597
};
517
598
` ;
518
- console . log ( "Writing 'firebase-build-gradle.js' to " + appRoot + "/ hooks/after-prepare" ) ;
599
+ console . log ( "Writing 'firebase-build-gradle.js' to " + appRoot + "hooks/after-prepare" ) ;
519
600
var scriptPath = path . join ( appRoot , "hooks" , "after-prepare" , "firebase-build-gradle.js" ) ;
520
601
fs . writeFileSync ( scriptPath , scriptContent ) ;
521
602
} catch ( e ) {
0 commit comments