Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: testing/iossim/iossim.mm

Issue 10828070: Don't directly link to the private Xcode framework, instead find it at runtime (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « testing/iossim/iossim.gyp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #import <Foundation/Foundation.h> 5 #import <Foundation/Foundation.h>
6 #include <asl.h> 6 #include <asl.h>
7 #include <libgen.h> 7 #include <libgen.h>
8 #include <stdarg.h> 8 #include <stdarg.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 10
(...skipping 25 matching lines...) Expand all
36 didStart:(BOOL)started 36 didStart:(BOOL)started
37 withError:(NSError*)error; 37 withError:(NSError*)error;
38 @end 38 @end
39 39
40 #import "iPhoneSimulatorRemoteClient.h" 40 #import "iPhoneSimulatorRemoteClient.h"
41 41
42 // An undocumented system log key included in messages from launchd. The value 42 // An undocumented system log key included in messages from launchd. The value
43 // is the PID of the process the message is about (as opposed to launchd's PID). 43 // is the PID of the process the message is about (as opposed to launchd's PID).
44 #define ASL_KEY_REF_PID "RefPID" 44 #define ASL_KEY_REF_PID "RefPID"
45 45
46 // The path within the developer dir of the private Simulator frameworks.
47 #define kSimulatorFrameworkPathLeaf \
48 @"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/iPhon eSimulatorRemoteClient.framework"
49 #define kDevToolsFoundationPathLeaf \
50 @"../OtherFrameworks/DevToolsFoundation.framework"
51
46 namespace { 52 namespace {
47 53
48 // Name of environment variables that control the user's home directory in the 54 // Name of environment variables that control the user's home directory in the
49 // simulator. 55 // simulator.
50 const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME"; 56 const char* const kUserHomeEnvVariable = "CFFIXED_USER_HOME";
51 const char* const kHomeEnvVariable = "HOME"; 57 const char* const kHomeEnvVariable = "HOME";
52 58
53 // Device family codes for iPhone and iPad. 59 // Device family codes for iPhone and iPad.
54 const int kIPhoneFamily = 1; 60 const int kIPhoneFamily = 1;
55 const int kIPadFamily = 2; 61 const int kIPadFamily = 2;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
241 if (entryFound) { 247 if (entryFound) {
242 LogError(@"Simulated app crashed or exited with non-zero status"); 248 LogError(@"Simulated app crashed or exited with non-zero status");
243 exit(EXIT_FAILURE); 249 exit(EXIT_FAILURE);
244 } 250 }
245 exit(EXIT_SUCCESS); 251 exit(EXIT_SUCCESS);
246 } 252 }
247 @end 253 @end
248 254
249 namespace { 255 namespace {
250 256
257 // Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
258 // variable.
259 NSString* FindDeveloperDir() {
260 // Check the env first.
261 NSDictionary* env = [[NSProcessInfo processInfo] environment];
262 NSString* devDir = [env objectForKey:@"DEVELOPER_DIR"];
263 if ([devDir length] > 0) {
264 return devDir;
265 }
266
267 // Go look for it via xcode-select.
268 NSTask* task;
269 task = [[[NSTask alloc] init] autorelease];
270 [task setLaunchPath:@"/usr/bin/xcode-select"];
271 [task setArguments:[NSArray arrayWithObject:@"-print-path"]];
272
273 NSPipe* pipe = [NSPipe pipe];
274 [task setStandardOutput: pipe];
275 NSFileHandle* file = [pipe fileHandleForReading];
276
277 [task launch];
278 NSData* output = [file readDataToEndOfFile];
279 [task terminate];
280
281 NSString* outputStr =
282 [[[NSString alloc] initWithData:output
lliabraa 2012/07/30 17:18:51 indent by 4
TVL 2012/07/30 17:23:05 Done.
283 encoding:NSUTF8StringEncoding] autorelease];
284 NSCharacterSet* wsNLSet = [NSCharacterSet whitespaceAndNewlineCharacterSet];
285 outputStr = [outputStr stringByTrimmingCharactersInSet:wsNLSet];
286 if ([outputStr length] == 0) {
287 outputStr = nil;
288 }
289 return outputStr;
290 }
291
292 // Loads the Simulator framework from the given developer dir.
293 NSBundle* LoadSimulatorFramework(NSString* developerDir) {
294 // The Simulator framework depends on some of the other Xcode private
295 // frameworks, manually load them first so everything can be linked up.
296 NSString* devToolsFoundationPath =
lliabraa 2012/07/30 17:18:51 indent by 4
TVL 2012/07/30 17:23:05 Done.
297 [developerDir stringByAppendingPathComponent:kDevToolsFoundationPathLeaf];
298 NSBundle* devToolsFoundationBundle =
299 [NSBundle bundleWithPath:devToolsFoundationPath];
lliabraa 2012/07/30 17:18:51 indent by 4
TVL 2012/07/30 17:23:05 Done.
300 if (![devToolsFoundationBundle load])
301 return nil;
302 NSString* simBundlePath =
303 [developerDir stringByAppendingPathComponent:kSimulatorFrameworkPathLeaf];
lliabraa 2012/07/30 17:18:51 indent by 4
TVL 2012/07/30 17:23:05 Done.
304 NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
305 if (![simBundle load])
306 return nil;
307 return simBundle;
308 }
309
310 // Helper to find a class by name and die if it isn't found.
311 Class FindClassByName(NSString* clazzName) {
312 Class theClass = NSClassFromString(clazzName);
313 if (!theClass) {
314 LogError(@"Failed to find class %@ at runtime.", clazzName);
315 exit(EXIT_FAILURE);
316 }
317 return theClass;
318 }
319
251 // Converts the given app path to an application spec, which requires an 320 // Converts the given app path to an application spec, which requires an
252 // absolute path. 321 // absolute path.
253 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { 322 DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
323 Class applicationSpecifierClass =
324 FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
lliabraa 2012/07/30 17:18:51 indent by 4
TVL 2012/07/30 17:23:05 Done.
254 if (![appPath isAbsolutePath]) { 325 if (![appPath isAbsolutePath]) {
255 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath]; 326 NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
256 appPath = [cwd stringByAppendingPathComponent:appPath]; 327 appPath = [cwd stringByAppendingPathComponent:appPath];
257 } 328 }
258 appPath = [appPath stringByStandardizingPath]; 329 appPath = [appPath stringByStandardizingPath];
259 return [DTiPhoneSimulatorApplicationSpecifier 330 return [applicationSpecifierClass specifierWithApplicationPath:appPath];
260 specifierWithApplicationPath:appPath];
261 } 331 }
262 332
263 // Returns the system root for the given SDK version. If sdkVersion is nil, the 333 // Returns the system root for the given SDK version. If sdkVersion is nil, the
264 // default system root is returned. Will return nil if the sdkVersion is not 334 // default system root is returned. Will return nil if the sdkVersion is not
265 // valid. 335 // valid.
266 DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) { 336 DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) {
267 DTiPhoneSimulatorSystemRoot* systemRoot = 337 Class systemRootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
268 [DTiPhoneSimulatorSystemRoot defaultRoot]; 338 DTiPhoneSimulatorSystemRoot* systemRoot = [systemRootClass defaultRoot];
269 if (sdkVersion) 339 if (sdkVersion)
270 systemRoot = [DTiPhoneSimulatorSystemRoot rootWithSDKVersion:sdkVersion]; 340 systemRoot = [systemRootClass rootWithSDKVersion:sdkVersion];
271 341
272 return systemRoot; 342 return systemRoot;
273 } 343 }
274 344
275 // Builds a config object for starting the specified app. 345 // Builds a config object for starting the specified app.
276 DTiPhoneSimulatorSessionConfig* BuildSessionConfig( 346 DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
277 DTiPhoneSimulatorApplicationSpecifier* appSpec, 347 DTiPhoneSimulatorApplicationSpecifier* appSpec,
278 DTiPhoneSimulatorSystemRoot* systemRoot, 348 DTiPhoneSimulatorSystemRoot* systemRoot,
279 NSString* stdoutPath, 349 NSString* stdoutPath,
280 NSString* stderrPath, 350 NSString* stderrPath,
281 NSArray* appArgs, 351 NSArray* appArgs,
282 NSDictionary* appEnv, 352 NSDictionary* appEnv,
283 NSNumber* deviceFamily) { 353 NSNumber* deviceFamily) {
354 Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
284 DTiPhoneSimulatorSessionConfig* sessionConfig = 355 DTiPhoneSimulatorSessionConfig* sessionConfig =
285 [[[DTiPhoneSimulatorSessionConfig alloc] init] autorelease]; 356 [[[sessionConfigClass alloc] init] autorelease];
286 sessionConfig.applicationToSimulateOnStart = appSpec; 357 sessionConfig.applicationToSimulateOnStart = appSpec;
287 sessionConfig.simulatedSystemRoot = systemRoot; 358 sessionConfig.simulatedSystemRoot = systemRoot;
288 sessionConfig.localizedClientName = @"chromium"; 359 sessionConfig.localizedClientName = @"chromium";
289 sessionConfig.simulatedApplicationStdErrPath = stderrPath; 360 sessionConfig.simulatedApplicationStdErrPath = stderrPath;
290 sessionConfig.simulatedApplicationStdOutPath = stdoutPath; 361 sessionConfig.simulatedApplicationStdOutPath = stdoutPath;
291 sessionConfig.simulatedApplicationLaunchArgs = appArgs; 362 sessionConfig.simulatedApplicationLaunchArgs = appArgs;
292 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv; 363 sessionConfig.simulatedApplicationLaunchEnvironment = appEnv;
293 sessionConfig.simulatedDeviceFamily = deviceFamily; 364 sessionConfig.simulatedDeviceFamily = deviceFamily;
294 return sessionConfig; 365 return sessionConfig;
295 } 366 }
296 367
297 // Builds a simulator session that will use the given delegate. 368 // Builds a simulator session that will use the given delegate.
298 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) { 369 DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
370 Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
299 DTiPhoneSimulatorSession* session = 371 DTiPhoneSimulatorSession* session =
300 [[[DTiPhoneSimulatorSession alloc] init] autorelease]; 372 [[[sessionClass alloc] init] autorelease];
301 session.delegate = delegate; 373 session.delegate = delegate;
302 return session; 374 return session;
303 } 375 }
304 376
305 // Creates a temporary directory with a unique name based on the provided 377 // Creates a temporary directory with a unique name based on the provided
306 // template. The template should not contain any path separators and be suffixed 378 // template. The template should not contain any path separators and be suffixed
307 // with X's, which will be substituted with a unique alphanumeric string (see 379 // with X's, which will be substituted with a unique alphanumeric string (see
308 // 'man mkdtemp' for details). The directory will be created as a subdirectory 380 // 'man mkdtemp' for details). The directory will be created as a subdirectory
309 // of NSTemporaryDirectory(). For example, if dirNameTemplate is 'test-XXX', 381 // of NSTemporaryDirectory(). For example, if dirNameTemplate is 'test-XXX',
310 // this method would return something like '/path/to/tempdir/test-3n2'. 382 // this method would return something like '/path/to/tempdir/test-3n2'.
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 appName = [appPath lastPathComponent]; 521 appName = [appPath lastPathComponent];
450 while (++optind < argc) { 522 while (++optind < argc) {
451 [appArgs addObject:[NSString stringWithUTF8String:argv[optind]]]; 523 [appArgs addObject:[NSString stringWithUTF8String:argv[optind]]];
452 } 524 }
453 } else { 525 } else {
454 LogError(@"Unable to parse command line arguments."); 526 LogError(@"Unable to parse command line arguments.");
455 PrintUsage(); 527 PrintUsage();
456 exit(EXIT_FAILURE); 528 exit(EXIT_FAILURE);
457 } 529 }
458 530
531 // Figure out the developer dir.
532 NSString* developerDir = FindDeveloperDir();
533 if (!developerDir) {
534 LogError(@"Unable to find developer directory.");
535 exit(EXIT_FAILURE);
536 }
537
538 // Load the Simulator Client framework.
539 NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir);
540 if (!simulatorFramework) {
541 LogError(@"Failed to load the Simulator Framework.");
542 exit(EXIT_FAILURE);
543 }
544
459 // Make sure the app path provided is legit. 545 // Make sure the app path provided is legit.
460 DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath); 546 DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath);
461 if (!appSpec) { 547 if (!appSpec) {
462 LogError(@"Invalid app path: %@", appPath); 548 LogError(@"Invalid app path: %@", appPath);
463 exit(EXIT_FAILURE); 549 exit(EXIT_FAILURE);
464 } 550 }
465 551
466 // Make sure the SDK path provided is legit (or nil). 552 // Make sure the SDK path provided is legit (or nil).
467 DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion); 553 DTiPhoneSimulatorSystemRoot* systemRoot = BuildSystemRoot(sdkVersion);
468 if (!systemRoot) { 554 if (!systemRoot) {
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 592
507 // Create the config and simulator session. 593 // Create the config and simulator session.
508 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec, 594 DTiPhoneSimulatorSessionConfig* config = BuildSessionConfig(appSpec,
509 systemRoot, 595 systemRoot,
510 stdioPath, 596 stdioPath,
511 stdioPath, 597 stdioPath,
512 appArgs, 598 appArgs,
513 appEnv, 599 appEnv,
514 deviceFamily); 600 deviceFamily);
515 SimulatorDelegate* delegate = 601 SimulatorDelegate* delegate =
516 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath] autorelease]; 602 [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath] autorelease];
517 DTiPhoneSimulatorSession* session = BuildSession(delegate); 603 DTiPhoneSimulatorSession* session = BuildSession(delegate);
518 604
519 // Start the simulator session. 605 // Start the simulator session.
520 NSError* error; 606 NSError* error;
521 BOOL started = [session requestStartWithConfig:config 607 BOOL started = [session requestStartWithConfig:config
522 timeout:kSessionStartTimeoutSeconds 608 timeout:kSessionStartTimeoutSeconds
523 error:&error]; 609 error:&error];
524 610
525 // Spin the runtime indefinitely. When the delegate gets the message that the 611 // Spin the runtime indefinitely. When the delegate gets the message that the
526 // app has quit it will exit this program. 612 // app has quit it will exit this program.
527 if (started) 613 if (started)
528 [[NSRunLoop mainRunLoop] run]; 614 [[NSRunLoop mainRunLoop] run];
529 else 615 else
530 LogError(@"Simulator failed to start: %@", [error localizedDescription]); 616 LogError(@"Simulator failed to start: %@", [error localizedDescription]);
531 617
532 // Note that this code is only executed if the simulator fails to start 618 // Note that this code is only executed if the simulator fails to start
533 // because once the main run loop is started, only the delegate calling 619 // because once the main run loop is started, only the delegate calling
534 // exit() will end the program. 620 // exit() will end the program.
535 [pool drain]; 621 [pool drain];
536 return EXIT_FAILURE; 622 return EXIT_FAILURE;
537 } 623 }
OLDNEW
« no previous file with comments | « testing/iossim/iossim.gyp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698