Generate Xcode Project fails if default shell changed in OS X

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;
	}
}

Hey -

It seems you’ve already entered a pull request regarding this issue. (https://github.com/EpicGames/UnrealEngine/pull/1434) We will continue to follow up on the pull request since that would be the best means to incorporate the suggested change.

Cheers