I recently switched to the fish shell instead of bash as my default shell on OS X. Once I switched Terminal.app’s preferences from Default Login Shell to /usr/local/bin/fish
, my ability to right-click on a .uproject file and select “Generate Xcode Project…” stopped working. When I select it, a terminal window pops open, but the command doesn’t actually fire.
Currently, generateXcodeProjectService
in UE4EditorServicesAppDelegate.cpp is using AppleEvents to launch the terminal app via AppleEvents so that it can execute a shell script. A more straightforward approach to this would be to take Terminal.app out of the equation and simply run the shell script using NSTask
.
Developers are among the most likely people to have changed to a different shell and, frankly, Apple Events are kinda clunky, old, and fragile.
A more robust alternative might be something like this:
- (void)generateXcodeProjectService:(NSPasteboard *)PBoard userData:(NSString *)UserData error:(NSString **)Error
{
NSString* UnrealError = NULL;
if ([[PBoard types] containsObject:NSFilenamesPboardType])
{
NSURL* FileURL = [NSURL fileURLWithPath: [[PBoard propertyListForType:NSFilenamesPboardType] objectAtIndex:0]];
NSString* EnginePath = [self findEngineForUProjectFile:FileURL];
if (EnginePath)
{
NSString* ScriptPath = [EnginePath stringByAppendingPathComponent:@"Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh"];
if (![[NSFileManager defaultManager] fileExistsAtPath:ScriptPath])
{
ScriptPath = [EnginePath stringByAppendingPathComponent:@"Engine/Build/BatchFiles/Mac/RocketGenerateProjectFiles.sh"];
}
if ([[NSFileManager defaultManager] fileExistsAtPath:ScriptPath])
{
NSError *ScriptLoadError = nil;
NSString *ScriptContents = [NSString stringWithContentsOfFile:ScriptPath encoding:NSUTF8StringEncoding error:&ScriptLoadError];
if (!ScriptLoadError)
{
NSString* FullFolderPath = [[ScriptPath stringByDeletingLastPathComponent] stringByResolvingSymlinksInPath];
NSString* FullScriptPath = [ScriptPath stringByResolvingSymlinksInPath];
NSString* Command = [NSString stringWithFormat:@"cd \"%@\" \n sh \"%@\" -project=\"%@\" -game\n logout\n", FullFolderPath, FullScriptPath, [FileURL path]];
NSString* FullCommand = [Command stringByAppendingString:ScriptContents];
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/bash"];
[task setArguments:@[ @"-c", FullCommand ]];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput:pipe];
[task launch];
NSFileHandle *file = pipe.fileHandleForReading;
NSData *data = [file readDataToEndOfFile];
[file closeFile];
NSString *output = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
// Parse output for errors / success
}
else
{
UnrealError = @"Could generate project files.";
}
}
else
{
UnrealError = @"No application to generate project files available.";
}
}
}
else
{
UnrealError = @"No valid project file selected.";
}
if (UnrealError && Error)
{
*Error = UnrealError;
}
}