private static void BuildTargetLibForPlatform(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations, List<WindowsCompiler> TargetWindowsCompilers)
	{
		if (DoesPlatformUseMSBuild(TargetData))
		{
			switch (TargetData.Platform)
			{
				case UnrealTargetPlatform.Win32:
				case UnrealTargetPlatform.Win64:
					// for windows platforms we support building against multiple compilers
					foreach (WindowsCompiler TargetWindowsCompiler in TargetWindowsCompilers)
					{
						BuildMSBuildTarget(TargetLib, TargetData, TargetConfigurations, TargetWindowsCompiler);
					}
					break;
				case UnrealTargetPlatform.XboxOne:
					BuildXboxTarget(TargetLib, TargetData, TargetConfigurations);
					break;
				default:
					BuildMSBuildTarget(TargetLib, TargetData, TargetConfigurations);
					break;
			}
		}
		else if (DoesPlatformUseXcode(TargetData))
		{
			BuildXcodeTarget(TargetLib, TargetData, TargetConfigurations);
		}
		else if (DoesPlatformUseMakefiles(TargetData))
		{
			BuildMakefileTarget(TargetLib, TargetData, TargetConfigurations);
		}
		else
		{
			throw new AutomationException(String.Format("Unsupported target platform '{0}' passed to BuildTargetLibForPlatform", TargetData));
		}
	}
	private static void BuildMakefileTarget(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations)
	{
		// FIXME: use absolute path
		string MakeCommand = "make";

		// FIXME: "j -16" should be tweakable
		string MakeOptions = "-j 16";

        // Bundled GNU make does not pass job number to subprocesses on Windows, work around that...
        if (BuildHostPlatform.Current.Platform == UnrealTargetPlatform.Win64)
        {
            // Redefining the MAKE variable will cause the -j flag to be passed to child make instances.
            MakeOptions = string.Format("{1} \"MAKE={0} {1}\"", MakeCommand, MakeOptions);
        }

		// this will be replaced for HTML5 - see SetupBuildForTargetLibAndPlatform() for details
		Dictionary<string, string> BuildMap = new Dictionary<string, string>()
		{
			{"debug", "debug"},
			{"checked", "checked"},
			{"profile", "profile"},
			{"release", "release"}
		};

		switch (TargetData.Platform)
		{
			case UnrealTargetPlatform.Android:
				{
					// Use make from Android toolchain
					string NDKDirectory = Environment.GetEnvironmentVariable("NDKROOT");
		
					// don't register if we don't have an NDKROOT specified
					if (String.IsNullOrEmpty(NDKDirectory))
					{
						throw new BuildException("NDKROOT is not specified; cannot build Android.");
					}
		
					NDKDirectory = NDKDirectory.Replace("\"", "");
		
					MakeCommand = NDKDirectory + "\\prebuilt\\windows-x86_64\\bin\\make.exe";
				}
				break;
			case UnrealTargetPlatform.HTML5:
				{
					// Use emscripten toolchain
					MakeCommand = "python";
					MakeOptions = HTML5SDKInfo.EMSCRIPTEN_ROOT + "\\emmake make";
					BuildMap = new Dictionary<string, string>()
					{
						{"debug", "Build-O0"},
						{"checked", "Build-O2"},
						{"profile", "Build-Oz"},
						{"release", "Build-O3"}
					};
				}
				break;
			default:
				break;
		}

		// makefile build has "projects" for every configuration. However, we abstract away from that by assuming GetProjectDirectory points to the "meta-project"
		foreach (string BuildConfig in TargetConfigurations)
		{
			UnrealBuildTool.DirectoryReference MetaProjectDirectory = GetProjectDirectory(TargetLib, TargetData);
			UnrealBuildTool.DirectoryReference ConfigDirectory = UnrealBuildTool.DirectoryReference.Combine(MetaProjectDirectory, BuildMap[BuildConfig]);
			string Makefile = UnrealBuildTool.FileReference.Combine(ConfigDirectory, "Makefile").ToString();
			if (!FileExists(Makefile))
			{
				throw new AutomationException(String.Format("Unabled to build {0} - file not found.", Makefile));
			}

			ProcessStartInfo StartInfo = new ProcessStartInfo();
			StartInfo.FileName = MakeCommand;
			StartInfo.WorkingDirectory = ConfigDirectory.ToString();
			StartInfo.Arguments = MakeOptions;

			Log("Working in: {0}", StartInfo.WorkingDirectory);
			Log("{0} {1}", StartInfo.FileName, StartInfo.Arguments);

			if (RunLocalProcessAndLogOutput(StartInfo) != 0)
			{
				throw new AutomationException(String.Format("Unabled to build {0}. Build process failed.", Makefile));
			}
		}
	}
	private static void BuildXcodeTarget(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations)
	{
		UnrealBuildTool.DirectoryReference Directory = GetProjectDirectory(TargetLib, TargetData);
		string ProjectFile = UnrealBuildTool.FileReference.Combine(Directory, (TargetLib == PhysXTargetLib.PhysX ? "PhysX" : "APEX") + ".xcodeproj").ToString();

		if (!DirectoryExists(ProjectFile))
		{
			throw new AutomationException(String.Format("Unabled to build project {0}. Project file not found.", ProjectFile));
		}

		foreach (string BuildConfig in TargetConfigurations)
		{
			string CmdLine = String.Format("-project \"{0}\" -target=\"ALL_BUILD\" -configuration {1}", ProjectFile, BuildConfig);
			RunAndLog(BuildCommand.CmdEnv, "/usr/bin/xcodebuild", CmdLine);
		}
	}
	private static void BuildMSBuildTarget(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations, WindowsCompiler TargetWindowsCompiler = WindowsCompiler.VisualStudio2015)
	{
		string SolutionFile = GetTargetLibSolutionFileName(TargetLib, TargetData, TargetWindowsCompiler).ToString();
		string MSDevExe = GetMsDevExe(TargetData);

		if (!FileExists(SolutionFile))
		{
			throw new AutomationException(String.Format("Unabled to build Solution {0}. Solution file not found.", SolutionFile));
		}
		if (String.IsNullOrEmpty(MSDevExe))
		{
			throw new AutomationException(String.Format("Unabled to build Solution {0}. devenv.com not found.", SolutionFile));
		}

		foreach (string BuildConfig in TargetConfigurations)
		{
			string CmdLine = String.Format("\"{0}\" /build \"{1}\"", SolutionFile, BuildConfig);
			RunAndLog(BuildCommand.CmdEnv, MSDevExe, CmdLine);
		}
	}
	private static void BuildXboxTarget(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations, WindowsCompiler TargetWindowsCompiler = WindowsCompiler.VisualStudio2015)
	{
		if (TargetData.Platform != UnrealTargetPlatform.XboxOne)
		{
			return;
		}

		string SolutionFile = GetTargetLibSolutionFileName(TargetLib, TargetData, TargetWindowsCompiler).ToString();
		string MSBuildExe = GetMsBuildExe(TargetData);

		if (!FileExists(SolutionFile))
		{
			throw new AutomationException(String.Format("Unabled to build Solution {0}. Solution file not found.", SolutionFile));
		}
		if (String.IsNullOrEmpty(MSBuildExe))
		{
			throw new AutomationException(String.Format("Unabled to build Solution {0}. msbuild.exe not found.", SolutionFile));
		}

		string AdditionalProperties = "";
		string AutoSDKPropsPath = Environment.GetEnvironmentVariable("XboxOneAutoSDKProp");
		if (AutoSDKPropsPath != null && AutoSDKPropsPath.Length > 0)
		{
			AdditionalProperties += String.Format(";CustomBeforeMicrosoftCommonProps={0}", AutoSDKPropsPath);
		}
		string XboxCMakeModulesPath = Path.Combine(PhysXSourceRootDirectory.FullName, "Externals", "CMakeModules", "XboxOne", "Microsoft.Cpp.Durango.user.props");
		if (File.Exists(XboxCMakeModulesPath))
		{
			AdditionalProperties += String.Format(";ForceImportBeforeCppTargets={0}", XboxCMakeModulesPath);
		}

		foreach (string BuildConfig in TargetConfigurations)
		{
			string CmdLine = String.Format("\"{0}\" /t:build /p:Configuration={1};Platform=Durango{2}", SolutionFile, BuildConfig, AdditionalProperties);
			RunAndLog(BuildCommand.CmdEnv, MSBuildExe, CmdLine);
		}
	}
	private static DirectoryReference GetTargetLibRootDirectory(PhysXTargetLib TargetLib)
	{
		switch (TargetLib)
		{
			case PhysXTargetLib.PhysX:
				return PhysX34SourceRootDirectory;
			case PhysXTargetLib.APEX:
				return APEX14SourceRootDirectory;
			default:
				throw new AutomationException(String.Format("Unknown target lib '{0}' specified to GetTargetLibRootDirectory", TargetLib));
		}
	}
	private static void SetupBuildForTargetLibAndPlatform(PhysXTargetLib TargetLib, TargetPlatformData TargetData, List<string> TargetConfigurations, List<WindowsCompiler> TargetWindowsCompilers, bool bCleanOnly)
	{
		// make sure we set up the environment variable specifying where the root of the PhysX SDK is
		Environment.SetEnvironmentVariable("GW_DEPS_ROOT", PhysXSourceRootDirectory.ToString());
		Log("set {0}={1}", "GW_DEPS_ROOT", Environment.GetEnvironmentVariable("GW_DEPS_ROOT"));
		Environment.SetEnvironmentVariable("CMAKE_MODULE_PATH", DirectoryReference.Combine(PhysXSourceRootDirectory, "Externals", "CMakeModules").ToString());
		Log("set {0}={1}", "CMAKE_MODULE_PATH", Environment.GetEnvironmentVariable("CMAKE_MODULE_PATH"));

		string CMakeName = GetCMakeNameAndSetupEnv(TargetData);

        switch (TargetData.Platform)
		{
			case UnrealTargetPlatform.Win32:
			case UnrealTargetPlatform.Win64:
				// for windows platforms we support building against multiple compilers
				foreach(WindowsCompiler TargetWindowsCompiler in TargetWindowsCompilers)
				{
					UnrealBuildTool.DirectoryReference CMakeTargetDirectory = GetProjectDirectory(TargetLib, TargetData, TargetWindowsCompiler);
					MakeFreshDirectoryIfRequired(CMakeTargetDirectory);

					if(!bCleanOnly)
					{
						Log("Generating projects for lib " + TargetLib.ToString() + ", " + TargetData.ToString());

						ProcessStartInfo StartInfo = new ProcessStartInfo();
                        StartInfo.FileName = CMakeName;
                        StartInfo.WorkingDirectory = CMakeTargetDirectory.ToString();
						StartInfo.Arguments = GetCMakeArguments(TargetLib, TargetData, "", TargetWindowsCompiler);

						RunLocalProcessAndLogOutput(StartInfo);
					}
				}
				break;
            case UnrealTargetPlatform.PS4:
			case UnrealTargetPlatform.Android:
			case UnrealTargetPlatform.Linux:
				foreach(string BuildConfig in TargetConfigurations)
				{
					UnrealBuildTool.DirectoryReference CMakeTargetDirectory = GetProjectDirectory(TargetLib, TargetData);
					CMakeTargetDirectory = UnrealBuildTool.DirectoryReference.Combine(CMakeTargetDirectory, BuildConfig);
					MakeFreshDirectoryIfRequired(CMakeTargetDirectory);

					if (!bCleanOnly)
					{
						Log("Generating projects for lib " + TargetLib.ToString() + ", " + TargetData.ToString());

						ProcessStartInfo StartInfo = new ProcessStartInfo();
                        StartInfo.FileName = CMakeName;
                        StartInfo.WorkingDirectory = CMakeTargetDirectory.ToString();
						StartInfo.Arguments = GetCMakeArguments(TargetLib, TargetData, BuildConfig);

						System.Console.WriteLine("Working in '{0}'", StartInfo.WorkingDirectory);
						Log("Working in '{0}'", StartInfo.WorkingDirectory);

						System.Console.WriteLine("{0} {1}", StartInfo.FileName, StartInfo.Arguments);
						Log("{0} {1}", StartInfo.FileName, StartInfo.Arguments);
						
						if (RunLocalProcessAndLogOutput(StartInfo) != 0)
						{
							throw new AutomationException(String.Format("Unable to generate projects for {0}.", TargetLib.ToString() + ", " + TargetData.ToString()));
						}
					}
				}
				break;
			case UnrealTargetPlatform.Mac:
			case UnrealTargetPlatform.IOS:
			case UnrealTargetPlatform.TVOS:
				{
					UnrealBuildTool.DirectoryReference CMakeTargetDirectory = GetProjectDirectory(TargetLib, TargetData);
					MakeFreshDirectoryIfRequired(CMakeTargetDirectory);

					if (!bCleanOnly)
					{
						Log("Generating projects for lib " + TargetLib.ToString() + ", " + TargetData.ToString());

						ProcessStartInfo StartInfo = new ProcessStartInfo();
						StartInfo.FileName = CMakeName;
                        StartInfo.WorkingDirectory = CMakeTargetDirectory.ToString();
						StartInfo.Arguments = GetCMakeArguments(TargetLib, TargetData);

						RunLocalProcessAndLogOutput(StartInfo);
					}
				}
				break;
			case UnrealTargetPlatform.HTML5:
				// NOTE: HTML5 does not do "debug" - the full text blows out memory
				//       instead, HTML5 builds have 4 levels of optimizations
				// so, MAP BuildConfig to HTML5 optimization levels
				Dictionary<string, string> BuildMap = new Dictionary<string, string>()
				{
					{"debug", "-O0"},
					{"checked", "-O2"},
					{"profile", "-Oz"},
					{"release", "-O3"}
				};
				Dictionary<string, string> BuildSuffix = new Dictionary<string, string>()
				{
					{"debug", ""},
					{"checked", "_O2"},
					{"profile", "_Oz"},
					{"release", "_O3"}
				};
				UnrealBuildTool.DirectoryReference HTML5CMakeModules = DirectoryReference.Combine(PhysXSourceRootDirectory, "Externals", "CMakeModules", "HTML5");
				string CmakeToolchainFile = FileReference.Combine(HTML5CMakeModules, "Emscripten.cmake").ToString();

				foreach(string BuildConfig in TargetConfigurations)
				{
					UnrealBuildTool.DirectoryReference CMakeTargetDirectory = GetProjectDirectory(TargetLib, TargetData);
					CMakeTargetDirectory = UnrealBuildTool.DirectoryReference.Combine(CMakeTargetDirectory, "BUILD" + BuildMap[BuildConfig]);
					MakeFreshDirectoryIfRequired(CMakeTargetDirectory);

					if (!bCleanOnly)
					{
						Log("Generating projects for lib " + TargetLib.ToString() + ", " + TargetData.ToString());

						// CMAKE_TOOLCHAIN_FILE
						MakeFreshDirectoryIfRequired(HTML5CMakeModules);
						Environment.SetEnvironmentVariable("LIB_SUFFIX", BuildSuffix[BuildConfig]);

						string orig = File.ReadAllText(HTML5SDKInfo.EmscriptenCMakeToolChainFile);
						string txt = Regex.Replace(orig, "(EPIC_BUILD_FLAGS}) .*-O2" , "$1 " + BuildMap["release"] );
						File.WriteAllText(CmakeToolchainFile, txt);

						// ----------------------------------------

						// CMAKE
						ProcessStartInfo StartInfo = new ProcessStartInfo();
						StartInfo.FileName = "cmake";
						StartInfo.WorkingDirectory = CMakeTargetDirectory.ToString();
						StartInfo.Arguments = GetCMakeArguments(TargetLib, TargetData, BuildConfig);

						Log("Working in: {0}", StartInfo.WorkingDirectory);
						Log("{0} {1}", StartInfo.FileName, StartInfo.Arguments);
						
						if (RunLocalProcessAndLogOutput(StartInfo) != 0)
						{
							throw new AutomationException(String.Format("Unabled to generate projects for {0}.", TargetLib.ToString() + ", " + TargetData.ToString()));
						}
					}
				}
				break;
			default:
				{
					UnrealBuildTool.DirectoryReference CMakeTargetDirectory = GetProjectDirectory(TargetLib, TargetData);
					MakeFreshDirectoryIfRequired(CMakeTargetDirectory);

					if (!bCleanOnly)
					{
						Log("Generating projects for lib " + TargetLib.ToString() + ", " + TargetData.ToString());

						ProcessStartInfo StartInfo = new ProcessStartInfo();
						StartInfo.FileName = CMakeName;
                        StartInfo.WorkingDirectory = CMakeTargetDirectory.ToString();
						StartInfo.Arguments = GetCMakeArguments(TargetLib, TargetData);

						RunLocalProcessAndLogOutput(StartInfo);
					}
				}
				break;
		}
	}
	private static string GetTargetLibSolutionName(PhysXTargetLib TargetLib)
	{
		switch (TargetLib)
		{
			case PhysXTargetLib.PhysX:
				return "PhysX.sln";
			case PhysXTargetLib.APEX:
				return "APEX.sln";
			default:
				throw new AutomationException(String.Format("Unknown target lib '{0}' specified to GetTargetLibSolutionName", TargetLib));
		}
	}
	private static UnrealBuildTool.FileReference GetTargetLibSolutionFileName(PhysXTargetLib TargetLib, TargetPlatformData TargetData, WindowsCompiler TargetWindowsCompiler)
	{
		UnrealBuildTool.DirectoryReference Directory = GetProjectDirectory(TargetLib, TargetData, TargetWindowsCompiler);
		return UnrealBuildTool.FileReference.Combine(Directory, GetTargetLibSolutionName(TargetLib));
	}
	private static string GetCMakeArguments(PhysXTargetLib TargetLib, TargetPlatformData TargetData, string BuildConfig = "", WindowsCompiler TargetWindowsCompiler = WindowsCompiler.VisualStudio2015)
	{
		string VisualStudioName;
		switch(TargetWindowsCompiler)
		{
			case WindowsCompiler.VisualStudio2013:
				VisualStudioName = "Visual Studio 12 2013";
				break;
			case WindowsCompiler.VisualStudio2015:
				VisualStudioName = "Visual Studio 14 2015";
				break;
			default:
				throw new AutomationException(String.Format("Non-CMake or unsupported platform '{0}' supplied to GetCMakeArguments", TargetData.ToString()));
		}

		string OutputFlags = " -DPX_OUTPUT_LIB_DIR=" + GetPlatformLibDirectory(TargetData, TargetWindowsCompiler);
		if(PlatformHasBinaries(TargetData))
		{
			OutputFlags += " -DPX_OUTPUT_DLL_DIR=" + GetPlatformBinaryDirectory(TargetData, TargetWindowsCompiler) + " -DPX_OUTPUT_EXE_DIR=" + GetPlatformBinaryDirectory(TargetData, TargetWindowsCompiler);
		}

        // Enable response files for platforms that require them.
        // Response files are used for include paths etc, to fix max command line length issues.
        switch (TargetData.Platform)
        {
            case UnrealTargetPlatform.PS4:
            case UnrealTargetPlatform.Linux:
                OutputFlags += " -DUSE_RESPONSE_FILES=1";
                break;
        }

		string CustomFlags = " -DAPEX_ENABLE_UE4=1";
		switch (TargetLib)
		{
			case PhysXTargetLib.PhysX:
				DirectoryReference PhysXCMakeFiles = DirectoryReference.Combine(PhysX34SourceRootDirectory, "Source", "compiler", "cmake");
				switch (TargetData.Platform)
				{
					case UnrealTargetPlatform.Win32:
						return DirectoryReference.Combine(PhysXCMakeFiles, "Windows").ToString() + " -G \"" + VisualStudioName + "\" -AWin32 -DTARGET_BUILD_PLATFORM=Windows" + OutputFlags;
					case UnrealTargetPlatform.Win64:
						return DirectoryReference.Combine(PhysXCMakeFiles, "Windows").ToString() + " -G \"" + VisualStudioName + "\" -Ax64 -DTARGET_BUILD_PLATFORM=Windows" + OutputFlags;
					 case UnrealTargetPlatform.PS4:
                        return DirectoryReference.Combine(PhysXCMakeFiles, "PS4").ToString() + " -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=PS4 -DCMAKE_BUILD_TYPE=" + BuildConfig + " -DCMAKE_TOOLCHAIN_FILE=\"" + PhysXSourceRootDirectory + "\\Externals\\CMakeModules\\PS4\\PS4Toolchain.txt\"" + OutputFlags;
                    case UnrealTargetPlatform.XboxOne:
						return DirectoryReference.Combine(PhysXCMakeFiles, "XboxOne").ToString() + " -G \"Visual Studio 14 2015\" -DTARGET_BUILD_PLATFORM=XboxOne -DCMAKE_TOOLCHAIN_FILE=\"" + PhysXSourceRootDirectory + "\\Externals\\CMakeModules\\XboxOne\\XboxOneToolchain.txt\" -DCMAKE_GENERATOR_PLATFORM=DURANGO" + OutputFlags;
					case UnrealTargetPlatform.Android:
						string NDKDirectory = Environment.GetEnvironmentVariable("NDKROOT");

						// don't register if we don't have an NDKROOT specified
						if (String.IsNullOrEmpty(NDKDirectory))
						{
							throw new BuildException("NDKROOT is not specified; cannot build Android.");
						}

						NDKDirectory = NDKDirectory.Replace("\"", "");

						string AndroidAPILevel = "android-19";
						string AndroidABI = "armeabi-v7a";
						switch (TargetData.Architecture)
						{
							case "armv7": AndroidAPILevel = "android-19"; AndroidABI = "armeabi-v7a"; break;
							case "arm64": AndroidAPILevel = "android-21"; AndroidABI = "arm64-v8a"; break;
							case "x86":   AndroidAPILevel = "android-19"; AndroidABI = "x86"; break;
							case "x64":   AndroidAPILevel = "android-21"; AndroidABI = "x86_64"; break;
						}
						return DirectoryReference.Combine(PhysXCMakeFiles, "Android").ToString() + " -G \"MinGW Makefiles\" -DTARGET_BUILD_PLATFORM=Android -DCMAKE_BUILD_TYPE=" + BuildConfig + " -DCMAKE_TOOLCHAIN_FILE=\"" + PhysXSourceRootDirectory + "\\Externals\\CMakeModules\\Android\\android.toolchain.cmake\" -DANDROID_NDK=\"" + NDKDirectory + "\" -DCMAKE_MAKE_PROGRAM=\"" + NDKDirectory + "\\prebuilt\\windows-x86_64\\bin\\make.exe\" -DANDROID_NATIVE_API_LEVEL=\"" + AndroidAPILevel + "\" -DANDROID_ABI=\"" + AndroidABI + "\" -DANDROID_STL=gnustl_shared" + OutputFlags;
					case UnrealTargetPlatform.Linux:
						return DirectoryReference.Combine(PhysXCMakeFiles, "Linux").ToString() + " -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=Linux -DCMAKE_BUILD_TYPE=" + BuildConfig + GetLinuxToolchainSettings(TargetData) + OutputFlags;
					case UnrealTargetPlatform.Mac:
						return DirectoryReference.Combine(PhysXCMakeFiles, "Mac").ToString() + " -G \"Xcode\" -DTARGET_BUILD_PLATFORM=Mac" + OutputFlags;
					case UnrealTargetPlatform.IOS:
						return DirectoryReference.Combine(PhysXCMakeFiles, "IOS").ToString() + " -G \"Xcode\" -DTARGET_BUILD_PLATFORM=IOS" + OutputFlags;
					case UnrealTargetPlatform.TVOS:
						return DirectoryReference.Combine(PhysXCMakeFiles, "TVOS").ToString() + " -G \"Xcode\" -DTARGET_BUILD_PLATFORM=TVOS" + OutputFlags;
					case UnrealTargetPlatform.HTML5:
						string CmakeToolchainFile = FileReference.Combine(PhysXSourceRootDirectory, "Externals", "CMakeModules", "HTML5", "Emscripten.cmake").ToString();
						return DirectoryReference.Combine(PhysXCMakeFiles, "HTML5").ToString() +
							" -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=HTML5" +
							" -DPXSHARED_ROOT_DIR=\"" + SharedSourceRootDirectory.ToString() + "\"" +
							" -DNVSIMD_INCLUDE_DIR=\"" + SharedSourceRootDirectory.ToString() + "/src/NvSimd\"" +
							" -DNVTOOLSEXT_INCLUDE_DIRS=\"" + PhysX34SourceRootDirectory + "/externals/nvToolsExt/include\"" +
							" -DCMAKE_BUILD_TYPE=\"Release\" -DCMAKE_TOOLCHAIN_FILE=\"" + CmakeToolchainFile + "\"" +
							OutputFlags;
					default:
						throw new AutomationException(String.Format("Non-CMake or unsupported platform '{0}' supplied to GetCMakeArguments", TargetData.ToString()));
				}
			case PhysXTargetLib.APEX:
				DirectoryReference ApexCMakeFiles = DirectoryReference.Combine(APEX14SourceRootDirectory, "compiler", "cmake");
				switch (TargetData.Platform)
				{
					case UnrealTargetPlatform.Win32:
						return DirectoryReference.Combine(ApexCMakeFiles, "Windows").ToString() + " -G \"" + VisualStudioName + "\" -AWin32 -DTARGET_BUILD_PLATFORM=Windows" + OutputFlags + CustomFlags;
					case UnrealTargetPlatform.Win64:
						return DirectoryReference.Combine(ApexCMakeFiles, "Windows").ToString() + " -G \"" + VisualStudioName + "\" -Ax64 -DTARGET_BUILD_PLATFORM=Windows" + OutputFlags + CustomFlags;
					case UnrealTargetPlatform.PS4:
                        return DirectoryReference.Combine(ApexCMakeFiles, "PS4").ToString() + " -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=PS4 -DCMAKE_BUILD_TYPE=" + BuildConfig + " -DCMAKE_TOOLCHAIN_FILE=\"" + PhysXSourceRootDirectory + "\\Externals\\CMakeModules\\PS4\\PS4Toolchain.txt\"" + OutputFlags + CustomFlags;
                    case UnrealTargetPlatform.XboxOne:
						return DirectoryReference.Combine(ApexCMakeFiles, "XboxOne").ToString() + " -G \"Visual Studio 14 2015\" -DTARGET_BUILD_PLATFORM=XboxOne -DCMAKE_TOOLCHAIN_FILE=\"" + PhysXSourceRootDirectory + "\\Externals\\CMakeModules\\XboxOne\\XboxOneToolchain.txt\" -DCMAKE_GENERATOR_PLATFORM=DURANGO" + OutputFlags + CustomFlags;
					case UnrealTargetPlatform.Linux:
						return DirectoryReference.Combine(ApexCMakeFiles, "Linux").ToString() + " -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=Linux -DCMAKE_BUILD_TYPE=" + BuildConfig + GetLinuxToolchainSettings(TargetData) + OutputFlags + CustomFlags;
					case UnrealTargetPlatform.Mac:
						return DirectoryReference.Combine(ApexCMakeFiles, "Mac").ToString() + " -G \"Xcode\" -DTARGET_BUILD_PLATFORM=Mac" + OutputFlags + CustomFlags;
					case UnrealTargetPlatform.HTML5:
						string CmakeToolchainFile = FileReference.Combine(PhysXSourceRootDirectory, "Externals", "CMakeModules", "HTML5", "Emscripten.cmake").ToString();
						return DirectoryReference.Combine(ApexCMakeFiles, "HTML5").ToString() +
							" -G \"Unix Makefiles\" -DTARGET_BUILD_PLATFORM=HTML5" +
							" -DPHYSX_ROOT_DIR=\"" + PhysX34SourceRootDirectory.ToString() + "\"" +
							" -DPXSHARED_ROOT_DIR=\"" + SharedSourceRootDirectory.ToString() + "\"" +
							" -DNVSIMD_INCLUDE_DIR=\"" + SharedSourceRootDirectory.ToString() + "/src/NvSimd\"" +
							" -DNVTOOLSEXT_INCLUDE_DIRS=\"" + PhysX34SourceRootDirectory + "/externals/nvToolsExt/include\"" +
							" -DCMAKE_BUILD_TYPE=\"Release\" -DCMAKE_TOOLCHAIN_FILE=\"" + CmakeToolchainFile + "\"" +
							OutputFlags + CustomFlags;
					 default:
						throw new AutomationException(String.Format("Non-CMake or unsupported platform '{0}' supplied to GetCMakeArguments", TargetData.ToString()));
				}
			default:
				throw new AutomationException(String.Format("Non-CMake or unsupported lib '{0}' supplied to GetCMakeArguments", TargetLib));
		}
	}
	private static UnrealBuildTool.DirectoryReference GetProjectDirectory(PhysXTargetLib TargetLib, TargetPlatformData TargetData, WindowsCompiler TargetWindowsCompiler = WindowsCompiler.VisualStudio2015)
	{
		UnrealBuildTool.DirectoryReference Directory = new UnrealBuildTool.DirectoryReference(GetTargetLibRootDirectory(TargetLib).ToString());

		switch(TargetLib)
		{
			case PhysXTargetLib.PhysX:
				Directory = UnrealBuildTool.DirectoryReference.Combine(Directory, "Source");
				break;
			case PhysXTargetLib.APEX:
				// APEX has its 'compiler' directory in a different location off the root of APEX
				break;
		}

		return UnrealBuildTool.DirectoryReference.Combine(Directory, "compiler", GetCMakeTargetDirectoryName(TargetData, TargetWindowsCompiler));
	}
    private static bool PlatformSupportsTargetLib(PhysXTargetLib TargetLib, TargetPlatformData TargetData)
    {
        if(TargetLib == PhysXTargetLib.APEX)
        {
            switch (TargetData.Platform)
            {
                case UnrealTargetPlatform.Win32:
                case UnrealTargetPlatform.Win64:
                case UnrealTargetPlatform.PS4:
                case UnrealTargetPlatform.XboxOne:
                case UnrealTargetPlatform.Mac:
                case UnrealTargetPlatform.HTML5:
                    return true;
				case UnrealTargetPlatform.Linux:
					// only x86_64 Linux supports it.
					return TargetData.Architecture.StartsWith("x86_64");
				default:
                    return false;
            }
        }

        return true;
    }
    private static void FindOutputFiles(HashSet<FileReference> OutputFiles, PhysXTargetLib TargetLib, TargetPlatformData TargetData, string TargetConfiguration, WindowsCompiler TargetWindowsCompiler = WindowsCompiler.VisualStudio2015)
	{
        string SearchPrefix = "*" + GetConfigurationSuffix(TargetConfiguration).ToUpper() + "*.";
        string DebugExtension = PlatformUsesDebugDatabase(TargetData) ? GetPlatformDebugDatabaseExtension(TargetData) : "";

        if (PlatformHasBinaries(TargetData))
		{
			DirectoryReference BinaryDir = GetPlatformBinaryDirectory(TargetData, TargetWindowsCompiler);
            FindOutputFilesHelper(OutputFiles, BinaryDir, SearchPrefix + GetPlatformBinaryExtension(TargetData), TargetLib);

			if (PlatformUsesDebugDatabase(TargetData))
			{
                FindOutputFilesHelper(OutputFiles, BinaryDir, SearchPrefix + DebugExtension, TargetLib);
			}
		}

		DirectoryReference LibDir = GetPlatformLibDirectory(TargetData, TargetWindowsCompiler);
        FindOutputFilesHelper(OutputFiles, LibDir, SearchPrefix + GetPlatformLibExtension(TargetData), TargetLib);

		if (PlatformUsesDebugDatabase(TargetData))
		{
            FindOutputFilesHelper(OutputFiles, LibDir, SearchPrefix + DebugExtension, TargetLib);
		}
	}
    private static void FindOutputFilesHelper(HashSet<FileReference> OutputFiles, DirectoryReference BaseDir, string SearchPrefix, PhysXTargetLib TargetLib)
    {
        if(!BaseDir.Exists())
        {
            return;
        }

        foreach (FileReference FoundFile in BaseDir.EnumerateFileReferences(SearchPrefix))
        {
            string FileNameUpper = FoundFile.GetFileName().ToString().ToUpper();
            
            bool bIncludeFile = false;
            if(TargetLib == PhysXTargetLib.APEX)
            {
                bIncludeFile = FileGeneratedByAPEX(FileNameUpper);
            }
            else
            {
                bIncludeFile = !FileGeneratedByAPEX(FileNameUpper);
            }

            if(bIncludeFile)
	        {
                OutputFiles.Add(FoundFile);
            }
        }
    }