Commit aaba7448 authored by thomasvl@chromium.org's avatar thomasvl@chromium.org

- Don't directly link to the private Xcode framework, instead find it at runtime

  and lookup the classes by name. This allows the binary to work with multiple
  versions of Xcode and doesn't tile the binary to an Xcode install location.
- Fix problem where the tool could log the wrong thing since basename()
  returns an internal buffer.

Review URL: https://chromiumcodereview.appspot.com/10828070

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149067 0039d316-1c4b-4281-b951-d872f2087c98
parent f1d37b14
...@@ -23,17 +23,7 @@ ...@@ -23,17 +23,7 @@
], ],
'libraries': [ 'libraries': [
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework', '$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
'<(iphone_sim_path)/iPhoneSimulatorRemoteClient.framework',
], ],
'mac_framework_dirs': [
'<(iphone_sim_path)',
],
'xcode_settings': {
'LD_RUNPATH_SEARCH_PATHS': [
'<(iphone_sim_path)',
'<(other_frameworks_path)',
]
},
'actions': [ 'actions': [
{ {
'action_name': 'generate_iphone_sim_header', 'action_name': 'generate_iphone_sim_header',
......
...@@ -70,6 +70,13 @@ const NSTimeInterval kSessionStartTimeoutSeconds = 30; ...@@ -70,6 +70,13 @@ const NSTimeInterval kSessionStartTimeoutSeconds = 30;
// polling interval. // polling interval.
const NSTimeInterval kOutputPollIntervalSeconds = 0.1; const NSTimeInterval kOutputPollIntervalSeconds = 0.1;
// The path within the developer dir of the private Simulator frameworks.
NSString* const kSimulatorFrameworkRelativePath =
@"Platforms/iPhoneSimulator.platform/Developer/Library/PrivateFrameworks/"
@"iPhoneSimulatorRemoteClient.framework";
NSString* const kDevToolsFoundationRelativePath =
@"../OtherFrameworks/DevToolsFoundation.framework";
const char* gToolName = "iossim"; const char* gToolName = "iossim";
void LogError(NSString* format, ...) { void LogError(NSString* format, ...) {
...@@ -248,26 +255,87 @@ void LogWarning(NSString* format, ...) { ...@@ -248,26 +255,87 @@ void LogWarning(NSString* format, ...) {
namespace { namespace {
// Finds the developer dir via xcode-select or the DEVELOPER_DIR environment
// variable.
NSString* FindDeveloperDir() {
// Check the env first.
NSDictionary* env = [[NSProcessInfo processInfo] environment];
NSString* developerDir = [env objectForKey:@"DEVELOPER_DIR"];
if ([developerDir length] > 0)
return developerDir;
// Go look for it via xcode-select.
NSTask* xcodeSelectTask = [[[NSTask alloc] init] autorelease];
[xcodeSelectTask setLaunchPath:@"/usr/bin/xcode-select"];
[xcodeSelectTask setArguments:[NSArray arrayWithObject:@"-print-path"]];
NSPipe* outputPipe = [NSPipe pipe];
[xcodeSelectTask setStandardOutput:outputPipe];
NSFileHandle* outputFile = [outputPipe fileHandleForReading];
[xcodeSelectTask launch];
NSData* outputData = [outputFile readDataToEndOfFile];
[xcodeSelectTask terminate];
NSString* output =
[[[NSString alloc] initWithData:outputData
encoding:NSUTF8StringEncoding] autorelease];
output = [output stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
if ([output length] == 0)
output = nil;
return output;
}
// Loads the Simulator framework from the given developer dir.
NSBundle* LoadSimulatorFramework(NSString* developerDir) {
// The Simulator framework depends on some of the other Xcode private
// frameworks; manually load them first so everything can be linked up.
NSString* devToolsFoundationPath = [developerDir
stringByAppendingPathComponent:kDevToolsFoundationRelativePath];
NSBundle* devToolsFoundationBundle =
[NSBundle bundleWithPath:devToolsFoundationPath];
if (![devToolsFoundationBundle load])
return nil;
NSString* simBundlePath = [developerDir
stringByAppendingPathComponent:kSimulatorFrameworkRelativePath];
NSBundle* simBundle = [NSBundle bundleWithPath:simBundlePath];
if (![simBundle load])
return nil;
return simBundle;
}
// Helper to find a class by name and die if it isn't found.
Class FindClassByName(NSString* nameOfClass) {
Class theClass = NSClassFromString(nameOfClass);
if (!theClass) {
LogError(@"Failed to find class %@ at runtime.", nameOfClass);
exit(EXIT_FAILURE);
}
return theClass;
}
// Converts the given app path to an application spec, which requires an // Converts the given app path to an application spec, which requires an
// absolute path. // absolute path.
DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) { DTiPhoneSimulatorApplicationSpecifier* BuildAppSpec(NSString* appPath) {
Class applicationSpecifierClass =
FindClassByName(@"DTiPhoneSimulatorApplicationSpecifier");
if (![appPath isAbsolutePath]) { if (![appPath isAbsolutePath]) {
NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath]; NSString* cwd = [[NSFileManager defaultManager] currentDirectoryPath];
appPath = [cwd stringByAppendingPathComponent:appPath]; appPath = [cwd stringByAppendingPathComponent:appPath];
} }
appPath = [appPath stringByStandardizingPath]; appPath = [appPath stringByStandardizingPath];
return [DTiPhoneSimulatorApplicationSpecifier return [applicationSpecifierClass specifierWithApplicationPath:appPath];
specifierWithApplicationPath:appPath];
} }
// Returns the system root for the given SDK version. If sdkVersion is nil, the // Returns the system root for the given SDK version. If sdkVersion is nil, the
// default system root is returned. Will return nil if the sdkVersion is not // default system root is returned. Will return nil if the sdkVersion is not
// valid. // valid.
DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) { DTiPhoneSimulatorSystemRoot* BuildSystemRoot(NSString* sdkVersion) {
DTiPhoneSimulatorSystemRoot* systemRoot = Class systemRootClass = FindClassByName(@"DTiPhoneSimulatorSystemRoot");
[DTiPhoneSimulatorSystemRoot defaultRoot]; DTiPhoneSimulatorSystemRoot* systemRoot = [systemRootClass defaultRoot];
if (sdkVersion) if (sdkVersion)
systemRoot = [DTiPhoneSimulatorSystemRoot rootWithSDKVersion:sdkVersion]; systemRoot = [systemRootClass rootWithSDKVersion:sdkVersion];
return systemRoot; return systemRoot;
} }
...@@ -281,8 +349,9 @@ DTiPhoneSimulatorSessionConfig* BuildSessionConfig( ...@@ -281,8 +349,9 @@ DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
NSArray* appArgs, NSArray* appArgs,
NSDictionary* appEnv, NSDictionary* appEnv,
NSNumber* deviceFamily) { NSNumber* deviceFamily) {
Class sessionConfigClass = FindClassByName(@"DTiPhoneSimulatorSessionConfig");
DTiPhoneSimulatorSessionConfig* sessionConfig = DTiPhoneSimulatorSessionConfig* sessionConfig =
[[[DTiPhoneSimulatorSessionConfig alloc] init] autorelease]; [[[sessionConfigClass alloc] init] autorelease];
sessionConfig.applicationToSimulateOnStart = appSpec; sessionConfig.applicationToSimulateOnStart = appSpec;
sessionConfig.simulatedSystemRoot = systemRoot; sessionConfig.simulatedSystemRoot = systemRoot;
sessionConfig.localizedClientName = @"chromium"; sessionConfig.localizedClientName = @"chromium";
...@@ -296,8 +365,9 @@ DTiPhoneSimulatorSessionConfig* BuildSessionConfig( ...@@ -296,8 +365,9 @@ DTiPhoneSimulatorSessionConfig* BuildSessionConfig(
// Builds a simulator session that will use the given delegate. // Builds a simulator session that will use the given delegate.
DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) { DTiPhoneSimulatorSession* BuildSession(SimulatorDelegate* delegate) {
Class sessionClass = FindClassByName(@"DTiPhoneSimulatorSession");
DTiPhoneSimulatorSession* session = DTiPhoneSimulatorSession* session =
[[[DTiPhoneSimulatorSession alloc] init] autorelease]; [[[sessionClass alloc] init] autorelease];
session.delegate = delegate; session.delegate = delegate;
return session; return session;
} }
...@@ -392,9 +462,17 @@ void PrintUsage() { ...@@ -392,9 +462,17 @@ void PrintUsage() {
int main(int argc, char* const argv[]) { int main(int argc, char* const argv[]) {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
char* toolName = basename(argv[0]); // basename() may modify the passed in string and it returns a pointer to an
if (toolName != NULL) // internal buffer. Give it a copy to modify, and copy what it returns.
gToolName = toolName; char* worker = strdup(argv[0]);
char* toolName = basename(worker);
if (toolName != NULL) {
toolName = strdup(toolName);
if (toolName != NULL)
gToolName = toolName;
}
if (worker != NULL)
free(worker);
NSString* appPath = nil; NSString* appPath = nil;
NSString* appName = nil; NSString* appName = nil;
...@@ -456,6 +534,18 @@ int main(int argc, char* const argv[]) { ...@@ -456,6 +534,18 @@ int main(int argc, char* const argv[]) {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
NSString* developerDir = FindDeveloperDir();
if (!developerDir) {
LogError(@"Unable to find developer directory.");
exit(EXIT_FAILURE);
}
NSBundle* simulatorFramework = LoadSimulatorFramework(developerDir);
if (!simulatorFramework) {
LogError(@"Failed to load the Simulator Framework.");
exit(EXIT_FAILURE);
}
// Make sure the app path provided is legit. // Make sure the app path provided is legit.
DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath); DTiPhoneSimulatorApplicationSpecifier* appSpec = BuildAppSpec(appPath);
if (!appSpec) { if (!appSpec) {
...@@ -513,7 +603,7 @@ int main(int argc, char* const argv[]) { ...@@ -513,7 +603,7 @@ int main(int argc, char* const argv[]) {
appEnv, appEnv,
deviceFamily); deviceFamily);
SimulatorDelegate* delegate = SimulatorDelegate* delegate =
[[[SimulatorDelegate alloc] initWithStdioPath:stdioPath] autorelease]; [[[SimulatorDelegate alloc] initWithStdioPath:stdioPath] autorelease];
DTiPhoneSimulatorSession* session = BuildSession(delegate); DTiPhoneSimulatorSession* session = BuildSession(delegate);
// Start the simulator session. // Start the simulator session.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment