NVidia Shield (Tegra), Android with OpenGL ES 3.1 and UE4

Hi all,

I have spent a fair amount of time trying to build UE4 on Mac, Windows and Linux. My aim was to play some photo-realistic demos on an NVidia Shield tablet (with the Tegra K1 processor). The tablet I’m using is Google’s Project Tango, but a Nexus 9 would be similar for what I’m trying to do at the moment.

Pre-requisites to compile UE4 projects for Android:

  • Unreal Engine 4 needs to be built from source
  • Install NVidia’s Tegra Android Development Pack (TADP). I personally installed the latest version called AndroidWorks.

Given that I had a few problems and that I managed to fix a few things, I thought I’d share my findings.
All the changes that I mention below can be found on the project I forked, on the 4.7 branch: https://github.com/ofrebourg/UnrealEngine/tree/4.7
(So if you do clone my repository, you won’t need to apply all the changes detailed below.)
On this repository, I also added Engine/Extras/Android/AndroidWorks-1R1-windows.exe, which is the latest AndroidWorks version at the moment.

Building UE4 on Mac was the first one and simplest one I managed to build.
What Mac did I use? a MacBook Pro (late 2013 model), 15’’, with OS X Yosemite


git clone -b 4.7 https://github.com/EpicGames/UnrealEngine UnrealEngine4.7     // clone the 4.7 branch of UE4
cd UnrealEngine4.7
./Setup.sh
./GenerateProjectFiles.sh  *// not entirely sure this step is necessary as we're not building using Xcode. But it's not very long so you might as well do it*
vi Engine/Config/BaseEngine.ini                                        *// -> set bBuildForES2=false & bBuildForES31=true*
./Engine/Build/BatchFiles/Mac/Build.sh UE4Editor Mac Development       *// build the editor*
./Engine/Build/BatchFiles/Mac/Build.sh UE4Game Android Development     *// this is required for building/launching a project onto an Android device*
./Engine/Build/BatchFiles/Mac/Build.sh UE4Client Android Development   *// this is required for building/launching a project onto an Android device*
 
*And if you want to run a game/project on Mac:*
./Engine/Build/BatchFiles/Mac/Build.sh UE4Game Mac Development         *// this is required for launching a project on Mac*

Building UE4 on Linux
What Linux did I use? Ubuntu 15.04, 64bit

Before building the editor, I had to run the following commands:


sudo apt-get update
sudo apt-get install default-jdk
 
*Plus (if you're using a 64-bit installation) a couple of 32-bit libraries required for TADP's 32-bit aapt binary to run:*
sudo apt-get install lib32stdc++6
sudo apt-get install lib32z1

I had a few issues building the editor. I can’t remember if I actually managed to fix my problems with UE4Game and UE4Client for Android on Linux.
Anyway, here are the fixes I needed:



git clone -b 4.7 https://github.com/EpicGames/UnrealEngine UnrealEngine4.7     *// clone the 4.7 branch of UE4*
cd UnrealEngine4.7
./Setup.sh
./GenerateProjectFiles.sh
vi Engine/Config/BaseEngine.ini *// set bBuildForES2=false & bBuildForES31=true*
 
make UE4Editor UE4Game CrashReportClient ShaderCompileWorker UnrealLightmass

*in Engine/Source/Programs/UnrealBuildTool/Android/AndroidToolChain.cs
at line 226 after*
string ArchitecturePathMac = @"prebuilt/darwin-x86_64";
*add:*
string ArchitecturePathLinux = @"prebuilt/linux-x86_64";

*then a little further down find*
else if (Directory.Exists(Path.Combine(NDKPath, ArchitecturePathMac)))
{
    Log.TraceVerbose("        Found Mac versions of toolchain");
    ArchitecturePath = ArchitecturePathMac;
    ExeExtension = "";
}
*and add*
else if (Directory.Exists(Path.Combine(NDKPath, ArchitecturePathLinux)))
{
    Log.TraceVerbose("        Found Linux versions of toolchain");
    ArchitecturePath = ArchitecturePathLinux;
    ExeExtension = "";
}
*directly after. This remedies being unable to find the android toolchain.
 
As linux is case sensitive, we need to edit 2 more files.
open *Engine/Source/Runtime/Core/Private/Android/AndroidFile.cpp
 *
and fix the 2 includes at the top.
they should be lower case like so...*
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>
*next open Engine/Source/Runtime/Launch/Private/Android/AndroidJNI.cpp
and fix those as well:*
#include <android/asset_manager.h>
#include <android/asset_manager_jni.h>

*Then we need to fix the vorbis library by fixing the paths in:*
Engine/Source/ThirdParty/Vorbis/Vorbis.Build.cs
Engine/Source/ThirdParty/Vorbis/VorbisFile.Build.cs
*in which "Lib" should be replaced by "lib" as follows:*
else if (Target.Platform == UnrealTargetPlatform.Android)
{
    // toolchain will filter
    PublicLibraryPaths.Add(VorbisPath + "lib/Android/ARMv7");
    PublicLibraryPaths.Add(VorbisPath + "lib/Android/ARM64");
    PublicLibraryPaths.Add(VorbisPath + "lib/Android/x86");
    PublicLibraryPaths.Add(VorbisPath + "lib/Android/x64");
 
    PublicAdditionalLibraries.Add("vorbis");
}
 
*Then we can build:*
./Engine/Build/BatchFiles/Linux/Build.sh UE4Game Android Development
./Engine/Build/BatchFiles/Linux/Build.sh UE4Client Android Development

Building UE4 on Windows
What Windows did I use? Windows 7 Professional with SP1, 64bit

This YouTube video explains well the steps to do it: Setting Up Nvidia Shield Tablet with Unreal Engine 4

Following these instructions, I didn’t have any problem building the editor.
However I personally had problems building the Android stuff. I kept having the following error:


[2015.07.13-11.40.46:031][244]LogPlayLevel: ====13/07/2015 12:40:45====PREPARING NATIVE CODE=================================================================
[2015.07.13-11.40.46:384][246]LogPlayLevel: UEDeployAndroid.RunCommandLineProgramAndThrowOnError: Preparing native code for debugging...
[2015.07.13-11.40.46:384][246]LogPlayLevel: BuildCommand.Execute: ERROR: BUILD FAILED
[2015.07.13-11.40.46:384][246]LogPlayLevel: Program.Main: ERROR: AutomationTool terminated with exception:
[2015.07.13-11.40.46:384][246]LogPlayLevel: Program.Main: ERROR: Exception in UnrealBuildTool: ERROR: C:\NVPACK\android-ndk-r10e/ndk-build.cmd failed with args APP_ABI="armeabi-v7a " NDK_DEBUG=1
[2015.07.13-11.40.46:384][246]LogPlayLevel: Stacktrace:    at UnrealBuildTool.Android.UEDeployAndroid.RunCommandLineProgramAndThrowOnError(String WorkingDirectory, String Command, String Params, String OverrideDesc, Boolean bUseShellExecute) in c:\UnrealEngine4.7\Engine\Source\Programs\UnrealBuildTool\Android\UEDeployAndroid.cs:line 355
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at UnrealBuildTool.Android.UEDeployAndroid.MakeApk(String ProjectName, String ProjectDirectory, String OutputPath, String EngineDirectory, Boolean bForDistribution, String CookFlavor, Boolean bMakeSeparateApks, Boolean bIncrementalPackage, Boolean bDisallowPackagingDataInApk) in c:\UnrealEngine4.7\Engine\Source\Programs\UnrealBuildTool\Android\UEDeployAndroid.cs:line 965
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at UnrealBuildTool.Android.UEDeployAndroid.PrepForUATPackageOrDeploy(String ProjectName, String ProjectDirectory, String ExecutablePath, String EngineDirectory, Boolean bForDistribution, String CookFlavor, Boolean bIsDataDeploy) in c:\UnrealEngine4.7\Engine\Source\Programs\UnrealBuildTool\Android\UEDeployAndroid.cs:line 1087
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AndroidPlatform.Deploy(ProjectParams Params, DeploymentContext SC)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at Project.Deploy(ProjectParams Params)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at BuildCookRun.DoBuildCookRun(ProjectParams Params)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at BuildCommand.Execute()
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AutomationTool.Automation.Execute(List`1 CommandsToExecute, CaselessDictionary`1 Commands)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AutomationTool.Automation.Process(String] CommandLine)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AutomationTool.Program.MainProc(Object Param)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AutomationTool.InternalUtils.RunSingleInstance(MainProc Main, Object Param)
[2015.07.13-11.40.46:384][246]LogPlayLevel:    at AutomationTool.Program.Main()
[2015.07.13-11.40.46:384][246]LogPlayLevel: Program.Main: ERROR: ERROR: **C:\NVPACK\android-ndk-r10e/ndk-build.cmd failed with args APP_ABI="armeabi-v7a " NDK_DEBUG=1**

So I looked into what the problem was, added some debug and eventually found that in some scripts (used by UnrealBuildTool) NDK_PROJECT_PATH was undefined, and set to the wrong directory. If you’re interested in details, here they are:

  • UnrealBuildTool uses ndk-build.cmd from the TADP installation.
  • ndk-build.cmd launches the following command:

"%NDK_ROOT%prebuilt/%NDK_WIN_HOST%/bin/make.exe" -f "%NDK_ROOT%build/core/build-local.mk" SHELL=cmd %*

  • And build-local.mk was were NDK_PROJECT_PATH wasn’t set.

So I made the following changes to Engine/Source/Programs/UnrealBuildTool/Android/UEDeployAndroid.cs:
First I added some debug to RunCommandLineProgramAndThrowOnError to know where the script was being called from:


private static void RunCommandLineProgramAndThrowOnError(string WorkingDirectory, string Command, string Params, string OverrideDesc=null, bool bUseShellExecute=false)
{
	if (OverrideDesc == null)
	{
		Log.TraceInformation("
Running: " + Command + " " + Params + " from directory " + WorkingDirectory);
	}
	else if (OverrideDesc != "")
	{
		Log.TraceInformation(OverrideDesc);
		Log.TraceVerbose("
Running: " + Command + " " + Params + " from directory " + WorkingDirectory + " - OverrideDesc: " + OverrideDesc);
	}

	ProcessStartInfo StartInfo = new ProcessStartInfo();
	StartInfo.WorkingDirectory = WorkingDirectory;
	StartInfo.FileName = Command;
	StartInfo.Arguments = Params;
	StartInfo.UseShellExecute = bUseShellExecute;
	StartInfo.WindowStyle = ProcessWindowStyle.Minimized;

	Process Proc = new Process();
	Proc.StartInfo = StartInfo;
	Proc.Start();
	Proc.WaitForExit();

	// android bat failure
	if (Proc.ExitCode != 0)
	{
		Log.TraceError("
Error running: " + Command + " " + Params + " from directory " + WorkingDirectory);
		throw new BuildException("{0} failed with args {1}", Command, Params);
	}
}

Then I made the following change to MakeApk() - roughly around line 960:


// if we need to run ndk-build, do it now (if making a shared .apk, we need to wait until all .libs exist)
if (!string.IsNullOrEmpty(FinalNdkBuildABICommand))
{
	string CommandLine = "APP_ABI=\"" + FinalNdkBuildABICommand + "\"";
	if (!bForDistribution)
	{
		CommandLine += " NDK_DEBUG=1";
		CommandLine += " NDK_LOG=1";
		CommandLine += " NDK_PROJECT_PATH=" + UE4BuildPath;
	}
	RunCommandLineProgramAndThrowOnError(UE4BuildPath, NDKBuildPath, CommandLine, "Preparing native code for debugging...", true);

	// next loop we don't want to redo these ABIs
	FinalNdkBuildABICommand = "";
}

I hope this will help others!

I will try to build UE4 version 4.8 as well at some point, and make sure that I can build projects for Android. I haven’t done it yet.