2014-03-14 14:13:41 -04:00
// Copyright 1998-2014 Epic Games, Inc. All Rights Reserved.
using System ;
using System.Collections ;
using System.Collections.Generic ;
2014-04-28 19:56:45 -04:00
using System.Linq ;
2014-03-14 14:13:41 -04:00
using System.IO ;
using System.Diagnostics ;
using System.Security.AccessControl ;
using System.Xml ;
using System.Text ;
2014-04-23 19:28:13 -04:00
using Ionic.Zip ;
using Ionic.Zlib ;
2014-03-14 14:13:41 -04:00
namespace UnrealBuildTool
{
2014-06-05 12:12:32 -04:00
[XmlConfig(true)]
2014-03-14 14:13:41 -04:00
class IOSToolChain : RemoteToolChain
{
public override void RegisterToolChain ( )
{
RegisterRemoteToolChain ( UnrealTargetPlatform . Mac , CPPTargetPlatform . IOS ) ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* NOTE :
* Do NOT change the defaults to set your values , instead you should set the environment variables
* properly in your system , as other tools make use of them to work properly !
* The defaults are there simply for examples so you know what to put in your env vars . . .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
// If you are looking for where to change the remote compile server name, look in RemoteToolChain.cs
/** If this is set, then we don't do any post-compile steps except moving the executable into the proper spot on the Mac */
2014-04-23 18:00:27 -04:00
public static bool bUseDangerouslyFastMode = false ;
2014-03-14 14:13:41 -04:00
/** Which version of the iOS SDK to target at build time */
2014-04-23 18:00:27 -04:00
public static string IOSSDKVersion = "latest" ;
2014-03-14 14:13:41 -04:00
/** The architecture(s) to compile */
2014-04-23 18:00:27 -04:00
public static string NonShippingArchitectures = "armv7" ;
public static string ShippingArchitectures = "armv7" ;
2014-03-14 14:13:41 -04:00
// In case the SDK checking fails for some reason, use this version
private static string BackupVersion = "6.0" ;
/** Which version of the iOS to allow at run time */
2014-04-23 18:00:27 -04:00
public static string IOSVersion = "6.0" ;
2014-03-14 14:13:41 -04:00
/** Which developer directory to root from */
2014-04-23 18:00:27 -04:00
public static string XcodeDeveloperDir = "/Applications/Xcode.app/Contents/Developer/" ;
2014-03-14 14:13:41 -04:00
/** Location of the SDKs */
2014-04-23 18:00:27 -04:00
private static string BaseSDKDir ;
private static string BaseSDKDirSim ;
2014-03-14 14:13:41 -04:00
/** Which compiler frontend to use */
private static string IOSCompiler = "clang++" ;
/** Which linker frontend to use */
private static string IOSLinker = "clang++" ;
/** Which library archiver to use */
private static string IOSArchiver = "libtool" ;
2014-04-28 19:56:45 -04:00
public List < string > BuiltBinaries = new List < string > ( ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
/** Additional frameworks stored locally so we have access without LinkEnvironment */
public List < UEBuildFramework > RememberedAdditionalFrameworks = new List < UEBuildFramework > ( ) ;
2014-04-30 14:09:06 -04:00
2014-04-23 18:00:27 -04:00
/// <summary>
2014-06-05 12:12:32 -04:00
/// Function to call to after reset default data.
2014-04-23 18:00:27 -04:00
/// </summary>
2014-06-05 12:12:32 -04:00
public static void PostReset ( )
2014-04-23 18:00:27 -04:00
{
/** Location of the SDKs */
BaseSDKDir = XcodeDeveloperDir + "Platforms/iPhoneOS.platform/Developer/SDKs" ;
BaseSDKDirSim = XcodeDeveloperDir + "Platforms/iPhoneSimulator.platform/Developer/SDKs" ;
}
2014-03-14 14:13:41 -04:00
/** Hunt down the latest IOS sdk if desired */
public override void SetUpGlobalEnvironment ( )
{
base . SetUpGlobalEnvironment ( ) ;
if ( IOSSDKVersion = = "latest" )
{
try
{
string [ ] SubDirs = null ;
if ( Utils . IsRunningOnMono )
{
// on the Mac, we can just get the directory name
SubDirs = System . IO . Directory . GetDirectories ( BaseSDKDir ) ;
Log . TraceInformation ( String . Format ( "Directories : {0} {1}" , SubDirs , SubDirs [ 0 ] ) ) ;
}
else
{
Hashtable Results = RPCUtilHelper . Command ( "/" , "ls" , BaseSDKDir , null ) ;
if ( Results ! = null )
{
string Result = ( string ) Results [ "CommandOutput" ] ;
SubDirs = Result . Split ( "\r\n" . ToCharArray ( ) , StringSplitOptions . RemoveEmptyEntries ) ;
}
}
// loop over the subdirs and parse out the version
float MaxSDKVersion = 0.0f ;
string MaxSDKVersionString = null ;
foreach ( string SubDir in SubDirs )
{
string SubDirName = Path . GetFileNameWithoutExtension ( SubDir ) ;
if ( SubDirName . StartsWith ( "iPhoneOS" ) )
{
// get the SDK version from the directory name
string SDKString = SubDirName . Replace ( "iPhoneOS" , "" ) ;
2014-05-06 14:14:12 -04:00
float SDKVersion = 0.0f ;
try
{
SDKVersion = float . Parse ( SDKString , System . Globalization . CultureInfo . InvariantCulture ) ;
}
catch ( Exception )
{
// weirdly formatted SDKs
continue ;
}
2014-03-14 14:13:41 -04:00
// update largest SDK version number
if ( SDKVersion > MaxSDKVersion )
{
MaxSDKVersion = SDKVersion ;
MaxSDKVersionString = SDKString ;
}
}
}
// convert back to a string with the exact format
if ( MaxSDKVersionString ! = null )
{
IOSSDKVersion = MaxSDKVersionString ;
}
}
catch ( Exception )
{
// on any exception, just use the backup version
IOSSDKVersion = BackupVersion ;
}
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
Log . TraceInformation ( "Compiling with IOS SDK {0} on Mac {1}" , IOSSDKVersion , RemoteServerName ) ;
}
else
{
Log . TraceInformation ( "Compiling with IOS SDK {0}" , IOSSDKVersion ) ;
}
}
}
2014-04-23 18:33:14 -04:00
static public void AddStubToManifest ( ref FileManifest Manifest , UEBuildBinary Binary )
{
2014-04-23 19:28:13 -04:00
if ( BuildConfiguration . bCreateStubIPA )
{
string StubFile = Path . Combine ( Path . GetDirectoryName ( Binary . Config . OutputFilePath ) , Path . GetFileNameWithoutExtension ( Binary . Config . OutputFilePath ) + ".stub" ) ;
Manifest . AddFileName ( StubFile ) ;
}
2014-04-23 18:33:14 -04:00
}
2014-03-14 14:13:41 -04:00
static bool bHasPrinted = false ;
static string GetArchitectureArgument ( CPPTargetConfiguration Configuration , string UBTArchitecture )
{
// get the list of architectures to compile
string Archs =
UBTArchitecture = = "-simulator" ? "i386" :
( Configuration = = CPPTargetConfiguration . Shipping ) ? ShippingArchitectures : NonShippingArchitectures ;
if ( ! bHasPrinted )
{
bHasPrinted = true ;
Console . WriteLine ( "Compiling with these architectures: " + Archs ) ;
}
// parse the string
string [ ] Tokens = Archs . Split ( "," . ToCharArray ( ) ) ;
string Result = "" ;
foreach ( string Token in Tokens )
{
Result + = " -arch " + Token ;
}
return Result ;
}
static string GetCompileArguments_Global ( CPPEnvironment CompileEnvironment )
{
string Result = "" ;
Result + = " -fmessage-length=0" ;
Result + = " -pipe" ;
Result + = " -fpascal-strings" ;
Result + = " -fno-exceptions" ;
Result + = " -fno-rtti" ;
Result + = " -fvisibility=hidden" ; // hides the linker warnings with PhysX
Result + = " -Wall -Werror" ;
Result + = " -Wno-unused-variable" ;
Result + = " -Wno-unused-value" ;
// this will hide the warnings about static functions in headers that aren't used in every single .cpp file
Result + = " -Wno-unused-function" ;
// this hides the "enumeration value 'XXXXX' not handled in switch [-Wswitch]" warnings - we should maybe remove this at some point and add UE_LOG(, Fatal, ) to default cases
Result + = " -Wno-switch" ;
// this hides the "warning : comparison of unsigned expression < 0 is always false" type warnings due to constant comparisons, which are possible with template arguments
Result + = " -Wno-tautological-compare" ;
//This will prevent the issue of warnings for unused private variables.
Result + = " -Wno-unused-private-field" ;
Result + = " -Wno-invalid-offsetof" ; // needed to suppress warnings about using offsetof on non-POD types.
Result + = " -c" ;
// What architecture(s) to build for
Result + = GetArchitectureArgument ( CompileEnvironment . Config . TargetConfiguration , CompileEnvironment . Config . TargetArchitecture ) ;
if ( CompileEnvironment . Config . TargetArchitecture = = "-simulator" )
{
Result + = " -isysroot " + BaseSDKDirSim + "/iPhoneSimulator" + IOSSDKVersion + ".sdk" ;
}
else
{
Result + = " -isysroot " + BaseSDKDir + "/iPhoneOS" + IOSSDKVersion + ".sdk" ;
}
Result + = " -miphoneos-version-min=" + IOSVersion ;
// Optimize non- debug builds.
if ( CompileEnvironment . Config . TargetConfiguration ! = CPPTargetConfiguration . Debug )
{
Result + = " -O3" ;
}
else
{
Result + = " -O0" ;
}
// Create DWARF format debug info if wanted,
if ( CompileEnvironment . Config . bCreateDebugInfo )
{
Result + = " -gdwarf-2" ;
}
return Result ;
}
static string GetCompileArguments_CPP ( )
{
string Result = "" ;
Result + = " -x objective-c++" ;
Result + = " -fno-rtti" ;
Result + = " -fobjc-abi-version=2" ;
Result + = " -fobjc-legacy-dispatch" ;
Result + = " -std=c++0x" ;
return Result ;
}
static string GetCompileArguments_MM ( )
{
string Result = "" ;
Result + = " -x objective-c++" ;
Result + = " -fobjc-abi-version=2" ;
Result + = " -fobjc-legacy-dispatch" ;
Result + = " -fno-rtti" ;
Result + = " -std=c++0x" ;
return Result ;
}
static string GetCompileArguments_M ( )
{
string Result = "" ;
Result + = " -x objective-c" ;
Result + = " -fobjc-abi-version=2" ;
Result + = " -fobjc-legacy-dispatch" ;
Result + = " -std=c++0x" ;
return Result ;
}
static string GetCompileArguments_C ( )
{
string Result = "" ;
Result + = " -x c" ;
return Result ;
}
static string GetCompileArguments_PCH ( )
{
string Result = "" ;
Result + = " -x objective-c++-header" ;
Result + = " -fno-rtti" ;
Result + = " -std=c++0x" ;
return Result ;
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
string GetLocalFrameworkZipPath ( UEBuildFramework Framework )
{
2014-05-12 18:51:03 -04:00
if ( Framework . OwningModule = = null )
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
{
2014-05-12 18:51:03 -04:00
throw new BuildException ( "GetLocalFrameworkZipPath: No owning module for framework {0}" , Framework . FrameworkName ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
}
2014-05-12 18:51:03 -04:00
return Path . GetFullPath ( Framework . OwningModule . ModuleDirectory + "/" + Framework . FrameworkZipPath ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
}
string GetRemoteFrameworkZipPath ( UEBuildFramework Framework )
{
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
return ConvertPath ( GetLocalFrameworkZipPath ( Framework ) ) ;
}
return GetLocalFrameworkZipPath ( Framework ) ;
}
2014-05-12 18:51:03 -04:00
string GetRemoteIntermediateFrameworkZipPath ( UEBuildFramework Framework )
{
if ( Framework . OwningModule = = null )
{
throw new BuildException ( "GetRemoteIntermediateFrameworkZipPath: No owning module for framework {0}" , Framework . FrameworkName ) ;
}
string IntermediatePath = Framework . OwningModule . Target . ProjectDirectory + "/Intermediate/UnzippedFrameworks/" + Framework . OwningModule . Name ;
IntermediatePath = Path . GetFullPath ( ( IntermediatePath + Framework . FrameworkZipPath ) . Replace ( ".zip" , "" ) ) ;
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
return ConvertPath ( IntermediatePath ) ;
}
return IntermediatePath ;
}
void CleanIntermediateDirectory ( string Path )
{
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
// Delete the intermediate directory on the mac
RPCUtilHelper . Command ( "/" , String . Format ( "rm -rf {0}" , Path ) , "" , null ) ;
// Create a fresh intermediate after we delete it
RPCUtilHelper . Command ( "/" , String . Format ( "mkdir -p {0}" , Path ) , "" , null ) ;
}
else
{
// Delete the local dest directory if it exists
if ( Directory . Exists ( Path ) )
{
Directory . Delete ( Path , true ) ;
}
// Create the intermediate local directory
string ResultsText ;
RunExecutableAndWait ( "mkdir" , String . Format ( "-p {0}" , Path ) , out ResultsText ) ;
}
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
string GetLinkArguments_Global ( LinkEnvironment LinkEnvironment )
2014-03-14 14:13:41 -04:00
{
string Result = "" ;
if ( LinkEnvironment . Config . TargetArchitecture = = "-simulator" )
{
Result + = " -arch i386" ;
2014-04-23 18:00:27 -04:00
Result + = " -isysroot " + XcodeDeveloperDir + "Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator" + IOSSDKVersion + ".sdk" ;
2014-03-14 14:13:41 -04:00
}
else
{
Result + = Result + = GetArchitectureArgument ( LinkEnvironment . Config . TargetConfiguration , LinkEnvironment . Config . TargetArchitecture ) ;
2014-04-23 18:00:27 -04:00
Result + = " -isysroot " + XcodeDeveloperDir + "Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS" + IOSSDKVersion + ".sdk" ;
2014-03-14 14:13:41 -04:00
}
Result + = " -dead_strip" ;
Result + = " -miphoneos-version-min=" + IOSVersion ;
Result + = " -Wl,-no_pie" ;
// Result += " -v";
// link in the frameworks
foreach ( string Framework in LinkEnvironment . Config . Frameworks )
{
Result + = " -framework " + Framework ;
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
foreach ( UEBuildFramework Framework in LinkEnvironment . Config . AdditionalFrameworks )
2014-03-14 14:13:41 -04:00
{
2014-05-12 18:51:03 -04:00
if ( Framework . OwningModule ! = null & & Framework . FrameworkZipPath ! = null & & Framework . FrameworkZipPath ! = "" )
2014-04-30 14:09:06 -04:00
{
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
// If this framework has a zip specified, we'll need to setup the path as well
2014-05-12 18:51:03 -04:00
Result + = " -F " + GetRemoteIntermediateFrameworkZipPath ( Framework ) ;
2014-04-30 14:09:06 -04:00
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
Result + = " -framework " + Framework . FrameworkName ;
2014-03-14 14:13:41 -04:00
}
foreach ( string Framework in LinkEnvironment . Config . WeakFrameworks )
{
Result + = " -weak_framework " + Framework ;
}
return Result ;
}
static string GetArchiveArguments_Global ( LinkEnvironment LinkEnvironment )
{
string Result = "" ;
Result + = " -static" ;
return Result ;
}
public override CPPOutput CompileCPPFiles ( CPPEnvironment CompileEnvironment , List < FileItem > SourceFiles , string ModuleName )
{
string Arguments = GetCompileArguments_Global ( CompileEnvironment ) ;
string PCHArguments = "" ;
if ( CompileEnvironment . Config . PrecompiledHeaderAction = = PrecompiledHeaderAction . Include )
{
// Add the precompiled header file's path to the include path so GCC can find it.
// This needs to be before the other include paths to ensure GCC uses it instead of the source header file.
2014-06-05 12:11:58 -04:00
var PrecompiledFileExtension = UEBuildPlatform . BuildPlatformDictionary [ UnrealTargetPlatform . IOS ] . GetBinaryExtension ( UEBuildBinaryType . PrecompiledHeader ) ;
PCHArguments + = string . Format ( " -include \"{0}\"" , ConvertPath ( CompileEnvironment . PrecompiledHeaderFile . AbsolutePath . Replace ( PrecompiledFileExtension , "" ) ) ) ;
2014-03-14 14:13:41 -04:00
}
// Add include paths to the argument list.
List < string > AllIncludes = CompileEnvironment . Config . IncludePaths ;
AllIncludes . AddRange ( CompileEnvironment . Config . SystemIncludePaths ) ;
foreach ( string IncludePath in AllIncludes )
{
Arguments + = string . Format ( " -I\"{0}\"" , ConvertPath ( Path . GetFullPath ( IncludePath ) ) ) ;
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
// sync any third party headers we may need
if ( IncludePath . Contains ( "ThirdParty" ) )
{
string [ ] FileList = Directory . GetFiles ( IncludePath , "*.h" , SearchOption . AllDirectories ) ;
foreach ( string File in FileList )
{
FileItem ExternalDependency = FileItem . GetItemByPath ( File ) ;
LocalToRemoteFileItem ( ExternalDependency , true ) ;
}
FileList = Directory . GetFiles ( IncludePath , "*.cpp" , SearchOption . AllDirectories ) ;
foreach ( string File in FileList )
{
FileItem ExternalDependency = FileItem . GetItemByPath ( File ) ;
LocalToRemoteFileItem ( ExternalDependency , true ) ;
}
}
}
}
foreach ( string Definition in CompileEnvironment . Config . Definitions )
{
Arguments + = string . Format ( " -D\"{0}\"" , Definition ) ;
}
CPPOutput Result = new CPPOutput ( ) ;
// Create a compile action for each source file.
foreach ( FileItem SourceFile in SourceFiles )
{
Action CompileAction = new Action ( ActionType . Compile ) ;
string FileArguments = "" ;
string Extension = Path . GetExtension ( SourceFile . AbsolutePath ) . ToUpperInvariant ( ) ;
if ( CompileEnvironment . Config . PrecompiledHeaderAction = = PrecompiledHeaderAction . Create )
{
// Compile the file as a C++ PCH.
FileArguments + = GetCompileArguments_PCH ( ) ;
}
else if ( Extension = = ".C" )
{
// Compile the file as C code.
FileArguments + = GetCompileArguments_C ( ) ;
}
else if ( Extension = = ".CC" )
{
// Compile the file as C++ code.
FileArguments + = GetCompileArguments_CPP ( ) ;
}
else if ( Extension = = ".MM" )
{
// Compile the file as Objective-C++ code.
FileArguments + = GetCompileArguments_MM ( ) ;
}
else if ( Extension = = ".M" )
{
// Compile the file as Objective-C++ code.
FileArguments + = GetCompileArguments_M ( ) ;
}
else
{
// Compile the file as C++ code.
FileArguments + = GetCompileArguments_CPP ( ) ;
// only use PCH for .cpp files
FileArguments + = PCHArguments ;
}
// Add the C++ source file and its included files to the prerequisite item list.
CompileAction . PrerequisiteItems . Add ( SourceFile ) ;
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
QueueFileForBatchUpload ( SourceFile ) ;
}
foreach ( FileItem IncludedFile in CompileEnvironment . GetIncludeDependencies ( SourceFile ) )
{
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
QueueFileForBatchUpload ( IncludedFile ) ;
}
CompileAction . PrerequisiteItems . Add ( IncludedFile ) ;
}
if ( CompileEnvironment . Config . PrecompiledHeaderAction = = PrecompiledHeaderAction . Create )
{
2014-06-05 12:11:58 -04:00
var PrecompiledFileExtension = UEBuildPlatform . BuildPlatformDictionary [ UnrealTargetPlatform . IOS ] . GetBinaryExtension ( UEBuildBinaryType . PrecompiledHeader ) ;
2014-03-14 14:13:41 -04:00
// Add the precompiled header file to the produced item list.
FileItem PrecompiledHeaderFile = FileItem . GetItemByPath (
Path . Combine (
CompileEnvironment . Config . OutputDirectory ,
2014-06-05 12:11:58 -04:00
Path . GetFileName ( SourceFile . AbsolutePath ) + PrecompiledFileExtension
2014-03-14 14:13:41 -04:00
)
) ;
FileItem RemotePrecompiledHeaderFile = LocalToRemoteFileItem ( PrecompiledHeaderFile , false ) ;
CompileAction . ProducedItems . Add ( RemotePrecompiledHeaderFile ) ;
Result . PrecompiledHeaderFile = RemotePrecompiledHeaderFile ;
// Add the parameters needed to compile the precompiled header file to the command-line.
FileArguments + = string . Format ( " -o \"{0}\"" , RemotePrecompiledHeaderFile . AbsolutePath , false ) ;
}
else
{
if ( CompileEnvironment . Config . PrecompiledHeaderAction = = PrecompiledHeaderAction . Include )
{
CompileAction . bIsUsingPCH = true ;
CompileAction . PrerequisiteItems . Add ( CompileEnvironment . PrecompiledHeaderFile ) ;
}
2014-06-05 12:11:58 -04:00
var ObjectFileExtension = UEBuildPlatform . BuildPlatformDictionary [ UnrealTargetPlatform . IOS ] . GetBinaryExtension ( UEBuildBinaryType . Object ) ;
2014-03-14 14:13:41 -04:00
// Add the object file to the produced item list.
FileItem ObjectFile = FileItem . GetItemByPath (
Path . Combine (
CompileEnvironment . Config . OutputDirectory ,
2014-06-05 12:11:58 -04:00
Path . GetFileName ( SourceFile . AbsolutePath ) + ObjectFileExtension
2014-03-14 14:13:41 -04:00
)
) ;
FileItem RemoteObjectFile = LocalToRemoteFileItem ( ObjectFile , false ) ;
CompileAction . ProducedItems . Add ( RemoteObjectFile ) ;
Result . ObjectFiles . Add ( RemoteObjectFile ) ;
FileArguments + = string . Format ( " -o \"{0}\"" , RemoteObjectFile . AbsolutePath , false ) ;
}
// Add the source file path to the command-line.
FileArguments + = string . Format ( " \"{0}\"" , ConvertPath ( SourceFile . AbsolutePath ) , false ) ;
2014-04-23 18:00:27 -04:00
string CompilerPath = XcodeDeveloperDir + "Toolchains/XcodeDefault.xctoolchain/usr/bin/" + IOSCompiler ;
2014-03-14 14:13:41 -04:00
if ( ! Utils . IsRunningOnMono & & ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
CompileAction . ActionHandler = new Action . BlockingActionHandler ( RPCUtilHelper . RPCActionHandler ) ;
}
// RPC utility parameters are in terms of the Mac side
CompileAction . WorkingDirectory = GetMacDevSrcRoot ( ) ;
CompileAction . CommandPath = CompilerPath ;
CompileAction . CommandArguments = Arguments + FileArguments + CompileEnvironment . Config . AdditionalArguments ;
CompileAction . StatusDescription = string . Format ( "{0}" , Path . GetFileName ( SourceFile . AbsolutePath ) ) ;
CompileAction . StatusDetailedDescription = SourceFile . Description ;
CompileAction . bIsGCCCompiler = true ;
// We're already distributing the command by execution on Mac.
CompileAction . bCanExecuteRemotely = false ;
CompileAction . OutputEventHandler = new DataReceivedEventHandler ( RemoteOutputReceivedEventHandler ) ;
}
return Result ;
}
public override FileItem LinkFiles ( LinkEnvironment LinkEnvironment , bool bBuildImportLibraryOnly )
{
2014-04-23 18:00:27 -04:00
string LinkerPath = XcodeDeveloperDir + "Toolchains/XcodeDefault.xctoolchain/usr/bin/" +
2014-03-14 14:13:41 -04:00
( LinkEnvironment . Config . bIsBuildingLibrary ? IOSArchiver : IOSLinker ) ;
// Create an action that invokes the linker.
Action LinkAction = new Action ( ActionType . Link ) ;
if ( ! Utils . IsRunningOnMono & & ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
LinkAction . ActionHandler = new Action . BlockingActionHandler ( RPCUtilHelper . RPCActionHandler ) ;
}
// RPC utility parameters are in terms of the Mac side
LinkAction . WorkingDirectory = GetMacDevSrcRoot ( ) ;
LinkAction . CommandPath = LinkerPath ;
// build this up over the rest of the function
LinkAction . CommandArguments = LinkEnvironment . Config . bIsBuildingLibrary ? GetArchiveArguments_Global ( LinkEnvironment ) : GetLinkArguments_Global ( LinkEnvironment ) ;
if ( ! LinkEnvironment . Config . bIsBuildingLibrary )
{
// Add the library paths to the argument list.
foreach ( string LibraryPath in LinkEnvironment . Config . LibraryPaths )
{
LinkAction . CommandArguments + = string . Format ( " -L\"{0}\"" , LibraryPath ) ;
}
// Add the additional libraries to the argument list.
foreach ( string AdditionalLibrary in LinkEnvironment . Config . AdditionalLibraries )
{
// for absolute library paths, convert to remote filename
if ( ! String . IsNullOrEmpty ( Path . GetDirectoryName ( AdditionalLibrary ) ) )
{
// add it to the prerequisites to make sure it's built first (this should be the case of non-system libraries)
FileItem LibFile = FileItem . GetItemByPath ( Path . GetFullPath ( AdditionalLibrary ) ) ;
FileItem RemoteLibFile = LocalToRemoteFileItem ( LibFile , false ) ;
LinkAction . PrerequisiteItems . Add ( RemoteLibFile ) ;
// and add to the commandline
2014-04-28 19:56:45 -04:00
LinkAction . CommandArguments + = string . Format ( " \"{0}\"" , ConvertPath ( Path . GetFullPath ( AdditionalLibrary ) ) ) ;
2014-03-14 14:13:41 -04:00
}
else
{
LinkAction . CommandArguments + = string . Format ( " -l\"{0}\"" , AdditionalLibrary ) ;
}
}
}
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
// Add any additional files that we'll need in order to link the app
foreach ( string AdditionalShadowFile in LinkEnvironment . Config . AdditionalShadowFiles )
{
FileItem ShadowFile = FileItem . GetExistingItemByPath ( AdditionalShadowFile ) ;
if ( ShadowFile ! = null )
{
QueueFileForBatchUpload ( ShadowFile ) ;
LinkAction . PrerequisiteItems . Add ( ShadowFile ) ;
}
else
{
throw new BuildException ( "Couldn't find required additional file to shadow: {0}" , AdditionalShadowFile ) ;
}
}
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
// Handle additional framework assets that might need to be shadowed
foreach ( UEBuildFramework Framework in LinkEnvironment . Config . AdditionalFrameworks )
{
if ( Framework . OwningModule = = null | | Framework . FrameworkZipPath = = null | | Framework . FrameworkZipPath = = "" )
{
continue ; // Only care about frameworks that have a zip specified
}
// If we've already remembered this framework, skip
if ( RememberedAdditionalFrameworks . Contains ( Framework ) )
{
continue ;
}
// Remember any files we need to unzip
RememberedAdditionalFrameworks . Add ( Framework ) ;
// Copy them to remote mac if needed
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
FileItem ShadowFile = FileItem . GetExistingItemByPath ( GetLocalFrameworkZipPath ( Framework ) ) ;
if ( ShadowFile ! = null )
{
QueueFileForBatchUpload ( ShadowFile ) ;
LinkAction . PrerequisiteItems . Add ( ShadowFile ) ;
}
else
{
throw new BuildException ( "Couldn't find required additional file to shadow: {0}" , Framework . FrameworkZipPath ) ;
}
}
}
2014-03-14 14:13:41 -04:00
// Add the output file as a production of the link action.
FileItem OutputFile = FileItem . GetItemByPath ( Path . GetFullPath ( LinkEnvironment . Config . OutputFilePath ) ) ;
FileItem RemoteOutputFile = LocalToRemoteFileItem ( OutputFile , false ) ;
LinkAction . ProducedItems . Add ( RemoteOutputFile ) ;
// Add the input files to a response file, and pass the response file on the command-line.
List < string > InputFileNames = new List < string > ( ) ;
foreach ( FileItem InputFile in LinkEnvironment . InputFiles )
{
InputFileNames . Add ( string . Format ( "\"{0}\"" , InputFile . AbsolutePath ) ) ;
LinkAction . PrerequisiteItems . Add ( InputFile ) ;
}
// Write the list of input files to a response file, with a tempfilename, on remote machine
if ( LinkEnvironment . Config . bIsBuildingLibrary )
{
foreach ( string Filename in InputFileNames )
{
LinkAction . CommandArguments + = " " + Filename ;
}
// @todo rocket lib: the -filelist command should take a response file (see else condition), except that it just says it can't
// find the file that's in there. Rocket.lib may overflow the commandline by putting all files on the commandline, so this
// may be needed:
// LinkAction.CommandArguments += string.Format(" -filelist \"{0}\"", ConvertPath(ResponsePath));
}
else
{
string ResponsePath = Path . GetFullPath ( "..\\Intermediate\\IOS\\LinkFileList_" + Path . GetFileNameWithoutExtension ( LinkEnvironment . Config . OutputFilePath ) + ".tmp" ) ;
if ( ! Utils . IsRunningOnMono & & ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
ResponseFile . Create ( ResponsePath , InputFileNames ) ;
RPCUtilHelper . CopyFile ( ResponsePath , ConvertPath ( ResponsePath ) , true ) ;
}
else
{
ResponseFile . Create ( ConvertPath ( ResponsePath ) , InputFileNames ) ;
}
LinkAction . CommandArguments + = string . Format ( " @\"{0}\"" , ConvertPath ( ResponsePath ) ) ;
}
// Add the output file to the command-line.
LinkAction . CommandArguments + = string . Format ( " -o \"{0}\"" , RemoteOutputFile . AbsolutePath ) ;
// Add the additional arguments specified by the environment.
LinkAction . CommandArguments + = LinkEnvironment . Config . AdditionalArguments ;
// Only execute linking on the local PC.
LinkAction . bCanExecuteRemotely = false ;
LinkAction . StatusDescription = string . Format ( "{0}" , OutputFile . AbsolutePath ) ;
LinkAction . OutputEventHandler = new DataReceivedEventHandler ( RemoteOutputReceivedEventHandler ) ;
// For iPhone, generate the dSYM file if the config file is set to do so
if ( BuildConfiguration . bGeneratedSYMFile = = true )
{
Log . TraceInformation ( "Generating the dSYM file - this will add some time to your build..." ) ;
RemoteOutputFile = GenerateDebugInfo ( RemoteOutputFile ) ;
}
return RemoteOutputFile ;
}
/ * *
* Generates debug info for a given executable
*
* @param Executable FileItem describing the executable to generate debug info for
* /
static public FileItem GenerateDebugInfo ( FileItem Executable )
{
// Make a file item for the source and destination files
string FullDestPathRoot = Executable . AbsolutePath + ".app.dSYM" ;
string FullDestPath = FullDestPathRoot ;
FileItem DestFile = FileItem . GetRemoteItemByPath ( FullDestPath , UnrealTargetPlatform . IOS ) ;
// Make the compile action
Action GenDebugAction = new Action ( ActionType . GenerateDebugInfo ) ;
if ( ! Utils . IsRunningOnMono )
{
GenDebugAction . ActionHandler = new Action . BlockingActionHandler ( RPCUtilHelper . RPCActionHandler ) ;
}
GenDebugAction . WorkingDirectory = GetMacDevSrcRoot ( ) ;
GenDebugAction . CommandPath = "sh" ;
// note that the source and dest are switched from a copy command
GenDebugAction . CommandArguments = string . Format ( "-c '{0}/usr/bin/dsymutil {1} -o {2}; cd {2}/..; zip -r -y -1 {3}.app.dSYM.zip {3}.app.dSYM'" ,
2014-04-23 18:00:27 -04:00
XcodeDeveloperDir ,
2014-03-14 14:13:41 -04:00
Executable . AbsolutePath ,
FullDestPathRoot ,
Path . GetFileName ( Executable . AbsolutePath ) ) ;
GenDebugAction . PrerequisiteItems . Add ( Executable ) ;
GenDebugAction . ProducedItems . Add ( DestFile ) ;
GenDebugAction . StatusDescription = GenDebugAction . CommandArguments ; // string.Format("Generating debug info for {0}", Path.GetFileName(Executable.AbsolutePath));
GenDebugAction . bCanExecuteRemotely = false ;
return DestFile ;
}
2014-04-23 19:28:13 -04:00
private void PackageStub ( string BinaryPath , string GameName , string ExeName )
{
// create the ipa
string IPAName = BinaryPath + "/" + ExeName + ".stub" ;
// delete the old one
if ( File . Exists ( IPAName ) )
{
File . Delete ( IPAName ) ;
}
// make the subdirectory if needed
string DestSubdir = Path . GetDirectoryName ( IPAName ) ;
if ( ! Directory . Exists ( DestSubdir ) )
{
Directory . CreateDirectory ( DestSubdir ) ;
}
// set up the directories
string ZipWorkingDir = String . Format ( "Payload/{0}.app/" , GameName ) ;
string ZipSourceDir = string . Format ( "{0}/Payload/{1}.app" , BinaryPath , GameName ) ;
// create the file
using ( ZipFile Zip = new ZipFile ( ) )
{
// add the entire directory
Zip . AddDirectory ( ZipSourceDir , ZipWorkingDir ) ;
// Update permissions to be UNIX-style
// Modify the file attributes of any added file to unix format
foreach ( ZipEntry E in Zip . Entries )
{
const byte FileAttributePlatform_NTFS = 0x0A ;
const byte FileAttributePlatform_UNIX = 0x03 ;
const byte FileAttributePlatform_FAT = 0x00 ;
const int UNIX_FILETYPE_NORMAL_FILE = 0x8000 ;
//const int UNIX_FILETYPE_SOCKET = 0xC000;
//const int UNIX_FILETYPE_SYMLINK = 0xA000;
//const int UNIX_FILETYPE_BLOCKSPECIAL = 0x6000;
const int UNIX_FILETYPE_DIRECTORY = 0x4000 ;
//const int UNIX_FILETYPE_CHARSPECIAL = 0x2000;
//const int UNIX_FILETYPE_FIFO = 0x1000;
const int UNIX_EXEC = 1 ;
const int UNIX_WRITE = 2 ;
const int UNIX_READ = 4 ;
int MyPermissions = UNIX_READ | UNIX_WRITE ;
int OtherPermissions = UNIX_READ ;
int PlatformEncodedBy = ( E . VersionMadeBy > > 8 ) & 0xFF ;
int LowerBits = 0 ;
// Try to preserve read-only if it was set
bool bIsDirectory = E . IsDirectory ;
// Check to see if this
bool bIsExecutable = false ;
if ( Path . GetFileNameWithoutExtension ( E . FileName ) . Equals ( GameName , StringComparison . InvariantCultureIgnoreCase ) )
{
bIsExecutable = true ;
}
if ( bIsExecutable )
{
// The executable will be encrypted in the final distribution IPA and will compress very poorly, so keeping it
// uncompressed gives a better indicator of IPA size for our distro builds
E . CompressionLevel = CompressionLevel . None ;
}
if ( ( PlatformEncodedBy = = FileAttributePlatform_NTFS ) | | ( PlatformEncodedBy = = FileAttributePlatform_FAT ) )
{
FileAttributes OldAttributes = E . Attributes ;
//LowerBits = ((int)E.Attributes) & 0xFFFF;
if ( ( OldAttributes & FileAttributes . Directory ) ! = 0 )
{
bIsDirectory = true ;
}
// Permissions
if ( ( OldAttributes & FileAttributes . ReadOnly ) ! = 0 )
{
MyPermissions & = ~ UNIX_WRITE ;
OtherPermissions & = ~ UNIX_WRITE ;
}
}
if ( bIsDirectory | | bIsExecutable )
{
MyPermissions | = UNIX_EXEC ;
OtherPermissions | = UNIX_EXEC ;
}
// Re-jigger the external file attributes to UNIX style if they're not already that way
if ( PlatformEncodedBy ! = FileAttributePlatform_UNIX )
{
int NewAttributes = bIsDirectory ? UNIX_FILETYPE_DIRECTORY : UNIX_FILETYPE_NORMAL_FILE ;
NewAttributes | = ( MyPermissions < < 6 ) ;
NewAttributes | = ( OtherPermissions < < 3 ) ;
NewAttributes | = ( OtherPermissions < < 0 ) ;
// Now modify the properties
E . AdjustExternalFileAttributes ( FileAttributePlatform_UNIX , ( NewAttributes < < 16 ) | LowerBits ) ;
}
}
// Save it out
Zip . Save ( IPAName ) ;
}
}
2014-04-28 19:56:45 -04:00
public override void PreBuildSync ( )
{
if ( ExternalExecution . GetRuntimePlatform ( ) ! = UnrealTargetPlatform . Mac )
{
BuiltBinaries = new List < string > ( ) ;
}
base . PreBuildSync ( ) ;
2014-04-30 14:09:06 -04:00
// Unzip any third party frameworks that are stored as zips
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
foreach ( UEBuildFramework Framework in RememberedAdditionalFrameworks )
2014-04-30 14:09:06 -04:00
{
2014-05-12 18:51:03 -04:00
string ZipSrcPath = GetRemoteFrameworkZipPath ( Framework ) ;
string ZipDstPath = GetRemoteIntermediateFrameworkZipPath ( Framework ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
2014-05-12 18:51:03 -04:00
Log . TraceInformation ( "Unzipping: {0} -> {1}" , ZipSrcPath , ZipDstPath ) ;
2014-04-30 14:09:06 -04:00
2014-05-12 18:51:03 -04:00
CleanIntermediateDirectory ( ZipDstPath ) ;
// Assume that there is another directory inside the zip with the same name as the zip
ZipDstPath = ZipDstPath . Substring ( 0 , ZipDstPath . LastIndexOf ( '/' ) ) ;
2014-04-30 14:09:06 -04:00
if ( ExternalExecution . GetRuntimePlatform ( ) = = UnrealTargetPlatform . Mac )
{
// If we're on the mac, just unzip using the shell
string ResultsText ;
2014-05-12 18:51:03 -04:00
RunExecutableAndWait ( "unzip" , String . Format ( "-o {0} -d {1}" , ZipSrcPath , ZipDstPath ) , out ResultsText ) ;
2014-04-30 14:09:06 -04:00
continue ;
}
2014-05-12 18:51:03 -04:00
// Use RPC utility if the zip is on remote mac
Hashtable Result = RPCUtilHelper . Command ( "/" , String . Format ( "unzip -o {0} -d {1}" , ZipSrcPath , ZipDstPath ) , "" , null ) ;
2014-04-30 14:09:06 -04:00
foreach ( DictionaryEntry Entry in Result )
{
Log . TraceInformation ( "{0}" , Entry . Value ) ;
}
}
2014-04-28 19:56:45 -04:00
}
2014-03-14 14:13:41 -04:00
public override void PostBuildSync ( UEBuildTarget Target )
{
base . PostBuildSync ( Target ) ;
string AppName = Target . Rules . Type = = TargetRules . TargetType . Game ? Target . GameName : Target . AppName ;
if ( ExternalExecution . GetRuntimePlatform ( ) = = UnrealTargetPlatform . Mac )
{
string RemoteShadowDirectoryMac = Path . GetDirectoryName ( Target . OutputPath ) ;
string FinalRemoteExecutablePath = String . Format ( "{0}/Payload/{1}.app/{1}" , RemoteShadowDirectoryMac , Target . GameName ) ;
2014-04-02 18:09:23 -04:00
// strip the debug info from the executable if needed
if ( BuildConfiguration . bStripSymbolsOnIOS | | ( Target . Configuration = = UnrealTargetConfiguration . Shipping ) )
{
Process StripProcess = new Process ( ) ;
StripProcess . StartInfo . WorkingDirectory = RemoteShadowDirectoryMac ;
StripProcess . StartInfo . FileName = "/usr/bin/xcrun" ;
StripProcess . StartInfo . Arguments = "strip \"" + Target . OutputPath + "\"" ;
StripProcess . OutputDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
StripProcess . ErrorDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
OutputReceivedDataEventHandlerEncounteredError = false ;
OutputReceivedDataEventHandlerEncounteredErrorMessage = "" ;
Utils . RunLocalProcess ( StripProcess ) ;
if ( OutputReceivedDataEventHandlerEncounteredError )
{
throw new Exception ( OutputReceivedDataEventHandlerEncounteredErrorMessage ) ;
}
}
// copy the executable
2014-03-14 14:13:41 -04:00
if ( ! File . Exists ( FinalRemoteExecutablePath ) )
{
Directory . CreateDirectory ( String . Format ( "{0}/Payload/{1}.app" , RemoteShadowDirectoryMac , Target . GameName ) ) ;
}
File . Copy ( Target . OutputPath , FinalRemoteExecutablePath , true ) ;
2014-04-23 19:28:13 -04:00
if ( BuildConfiguration . bCreateStubIPA )
{
string Project = Target . ProjectDirectory + "/" + Target . GameName + ".uproject" ;
// generate the dummy project so signing works
if ( Target . GameName = = "UE4Game" | | Target . GameName = = "UE4Client" | | Utils . IsFileUnderDirectory ( Target . ProjectDirectory + "/" + Target . GameName + ".uproject" , Path . GetFullPath ( "../.." ) ) )
{
2014-04-25 13:10:14 -04:00
UnrealBuildTool . GenerateProjectFiles ( new XcodeProjectFileGenerator ( ) , new string [ ] { "-platforms=IOS" , "-NoIntellIsense" , "-iosdeployonly" , "-ignorejunk" } ) ;
2014-04-23 19:28:13 -04:00
Project = Path . GetFullPath ( "../.." ) + "/UE4_IOS.xcodeproj" ;
}
else
{
Project = Target . ProjectDirectory + "/" + Target . GameName + ".xcodeproj" ;
}
if ( Directory . Exists ( Project ) )
{
2014-04-27 21:21:43 -04:00
// ensure the plist, entitlements, and provision files are properly copied
2014-05-21 06:09:37 -04:00
var DeployHandler = UEBuildDeploy . GetBuildDeploy ( Target . Platform ) ;
2014-04-27 21:21:43 -04:00
if ( DeployHandler ! = null )
{
DeployHandler . PrepTargetForDeployment ( Target ) ;
}
2014-04-23 19:28:13 -04:00
// code sign the project
string CmdLine = XcodeDeveloperDir + "usr/bin/xcodebuild" +
" -project \"" + Project + "\"" +
" -configuration " + Target . Configuration +
" -scheme '" + Target . GameName + " - iOS'" +
" -sdk iphoneos" +
" CODE_SIGN_IDENTITY=\"iPhone Developer\"" ;
2014-05-02 00:36:54 -04:00
Console . WriteLine ( "Code signing with command line: " + CmdLine ) ;
2014-04-23 19:28:13 -04:00
Process SignProcess = new Process ( ) ;
SignProcess . StartInfo . WorkingDirectory = RemoteShadowDirectoryMac ;
SignProcess . StartInfo . FileName = "/usr/bin/xcrun" ;
SignProcess . StartInfo . Arguments = CmdLine ;
SignProcess . OutputDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
SignProcess . ErrorDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
OutputReceivedDataEventHandlerEncounteredError = false ;
OutputReceivedDataEventHandlerEncounteredErrorMessage = "" ;
Utils . RunLocalProcess ( SignProcess ) ;
// delete the temp project
if ( Project . Contains ( "_IOS.xcodeproj" ) )
{
2014-05-02 09:43:59 -04:00
Directory . Delete ( Project , true ) ;
2014-04-23 19:28:13 -04:00
}
if ( OutputReceivedDataEventHandlerEncounteredError )
{
throw new Exception ( OutputReceivedDataEventHandlerEncounteredErrorMessage ) ;
}
// Package the stub
PackageStub ( RemoteShadowDirectoryMac , Target . GameName , Path . GetFileNameWithoutExtension ( Target . OutputPath ) ) ;
}
}
2014-05-09 17:38:40 -04:00
{
// Copy bundled assets from additional frameworks to the intermediate assets directory (so they can get picked up during staging)
String LocalFrameworkAssets = Path . GetFullPath ( Target . ProjectDirectory + "/Intermediate/IOS/FrameworkAssets" ) ;
2014-05-12 18:51:03 -04:00
// Clean the local dest directory if it exists
CleanIntermediateDirectory ( LocalFrameworkAssets ) ;
2014-05-09 17:38:40 -04:00
foreach ( UEBuildFramework Framework in RememberedAdditionalFrameworks )
{
if ( Framework . OwningModule = = null | | Framework . CopyBundledAssets = = null | | Framework . CopyBundledAssets = = "" )
{
continue ; // Only care if we need to copy bundle assets
}
2014-05-12 18:51:03 -04:00
if ( Framework . OwningModule . Target ! = Target )
{
continue ; // This framework item doesn't belong to this target, skip it
}
2014-05-09 17:38:40 -04:00
string LocalZipPath = GetLocalFrameworkZipPath ( Framework ) ;
LocalZipPath = LocalZipPath . Replace ( ".zip" , "" ) ;
// For now, this is hard coded, but we need to loop over all modules, and copy bundled assets that need it
string LocalSource = LocalZipPath + "/" + Framework . CopyBundledAssets ;
string BundleName = Framework . CopyBundledAssets . Substring ( Framework . CopyBundledAssets . LastIndexOf ( '/' ) + 1 ) ;
string LocalDest = LocalFrameworkAssets + "/" + BundleName ;
Log . TraceInformation ( "Copying bundled asset... LocalSource: {0}, LocalDest: {1}" , LocalSource , LocalDest ) ;
2014-05-12 18:51:03 -04:00
string ResultsText ;
2014-05-09 17:38:40 -04:00
RunExecutableAndWait ( "cp" , String . Format ( "-R -L {0} {1}" , LocalSource , LocalDest ) , out ResultsText ) ;
}
}
2014-03-14 14:13:41 -04:00
}
else
{
2014-04-28 19:56:45 -04:00
// store off the binaries
foreach ( UEBuildBinary Binary in Target . AppBinaries )
{
BuiltBinaries . Add ( Path . GetFullPath ( Binary . ToString ( ) ) ) ;
}
// Generate static libraries for monolithic games in Rocket
if ( ( UnrealBuildTool . BuildingRocket ( ) | | UnrealBuildTool . RunningRocket ( ) ) & & TargetRules . IsAGame ( Target . Rules . Type ) )
{
List < UEBuildModule > Modules = Target . AppBinaries [ 0 ] . GetAllDependencyModules ( true , false ) ;
foreach ( UEBuildModuleCPP Module in Modules . OfType < UEBuildModuleCPP > ( ) )
{
if ( Utils . IsFileUnderDirectory ( Module . ModuleDirectory , BuildConfiguration . RelativeEnginePath ) & & Module . Binary = = Target . AppBinaries [ 0 ] )
{
if ( Module . bBuildingRedistStaticLibrary )
{
BuiltBinaries . Add ( Path . GetFullPath ( Module . RedistStaticLibraryPath ) ) ;
}
}
}
}
2014-03-14 14:13:41 -04:00
// check to see if the DangerouslyFast mode is valid (in other words, a build has gone through since a Rebuild/Clean operation)
string DangerouslyFastValidFile = Path . Combine ( Target . GlobalLinkEnvironment . Config . IntermediateDirectory , "DangerouslyFastIsNotDangerous" ) ;
bool bUseDangerouslyFastModeWasRequested = bUseDangerouslyFastMode ;
if ( bUseDangerouslyFastMode )
{
if ( ! File . Exists ( DangerouslyFastValidFile ) )
{
Log . TraceInformation ( "Dangeroulsy Fast mode was requested, but a slow mode hasn't completed. Performing slow now..." ) ;
bUseDangerouslyFastMode = false ;
}
}
string RemoteExecutablePath = ConvertPath ( Target . OutputPath ) ;
// when going super fast, just copy the executable to the final resting spot
if ( bUseDangerouslyFastMode )
{
Log . TraceInformation ( "==============================================================================" ) ;
Log . TraceInformation ( "USING DANGEROUSLY FAST MODE! IF YOU HAVE ANY PROBLEMS, TRY A REBUILD/CLEAN!!!!" ) ;
Log . TraceInformation ( "==============================================================================" ) ;
// copy the executable
string RemoteShadowDirectoryMac = ConvertPath ( Path . GetDirectoryName ( Target . OutputPath ) ) ;
string FinalRemoteExecutablePath = String . Format ( "{0}/Payload/{1}.app/{1}" , RemoteShadowDirectoryMac , Target . GameName ) ;
RPCUtilHelper . Command ( "/" , String . Format ( "cp -f {0} {1}" , RemoteExecutablePath , FinalRemoteExecutablePath ) , "" , null ) ;
}
else
{
RPCUtilHelper . CopyFile ( RemoteExecutablePath , Target . OutputPath , false ) ;
if ( BuildConfiguration . bGeneratedSYMFile = = true )
{
string DSYMExt = ".app.dSYM.zip" ;
RPCUtilHelper . CopyFile ( RemoteExecutablePath + DSYMExt , Target . OutputPath + DSYMExt , false ) ;
}
}
// Generate the stub
if ( BuildConfiguration . bCreateStubIPA | | bUseDangerouslyFastMode )
{
if ( ! bUseDangerouslyFastMode )
{
// generate the dummy project so signing works
2014-05-06 16:04:39 -04:00
UnrealBuildTool . GenerateProjectFiles ( new XcodeProjectFileGenerator ( ) , new string [ ] { "-NoIntellisense" , "-iosdeployonly" } ) ;
2014-03-14 14:13:41 -04:00
}
Process StubGenerateProcess = new Process ( ) ;
StubGenerateProcess . StartInfo . WorkingDirectory = Path . GetFullPath ( "..\\Binaries\\DotNET\\IOS" ) ;
StubGenerateProcess . StartInfo . FileName = Path . Combine ( StubGenerateProcess . StartInfo . WorkingDirectory , "iPhonePackager.exe" ) ;
string PathToApp = RulesCompiler . GetTargetFilename ( AppName ) ;
// right now, no programs have a Source subdirectory, so assume the PathToApp is directly in the root
if ( Path . GetDirectoryName ( PathToApp ) . Contains ( @"\Engine\Source\Programs" ) )
{
PathToApp = Path . GetDirectoryName ( PathToApp ) ;
}
else
{
Int32 SourceIndex = PathToApp . LastIndexOf ( @"\Source" ) ;
if ( SourceIndex ! = - 1 )
{
PathToApp = PathToApp . Substring ( 0 , SourceIndex ) ;
}
else
{
throw new BuildException ( "The target was not in a /Source subdirectory" ) ;
}
}
if ( bUseDangerouslyFastMode )
{
// the quickness!
StubGenerateProcess . StartInfo . Arguments = "DangerouslyFast " + PathToApp ;
}
else
{
StubGenerateProcess . StartInfo . Arguments = "PackageIPA " + PathToApp + " -createstub" ;
// if we are making the dsym, then we can strip the debug info from the executable
if ( BuildConfiguration . bStripSymbolsOnIOS | | ( Target . Configuration = = UnrealTargetConfiguration . Shipping ) )
{
StubGenerateProcess . StartInfo . Arguments + = " -strip" ;
}
}
StubGenerateProcess . StartInfo . Arguments + = " -config " + Target . Configuration + " -mac " + RemoteServerName ;
2014-05-21 06:09:37 -04:00
var BuildPlatform = UEBuildPlatform . GetBuildPlatform ( Target . Platform ) ;
2014-03-14 14:13:41 -04:00
string Architecture = BuildPlatform . GetActiveArchitecture ( ) ;
if ( Architecture ! = "" )
{
// pass along the architecture if we need, skipping the initial -, so we have "-architecture simulator"
StubGenerateProcess . StartInfo . Arguments + = " -architecture " + Architecture . Substring ( 1 ) ;
}
// programmers that use Xcode packaging mode should use the following commandline instead, as it will package for Xcode on each compile
// StubGenerateProcess.StartInfo.Arguments = "PackageApp " + GameName + " " + Configuration;
StubGenerateProcess . OutputDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
StubGenerateProcess . ErrorDataReceived + = new DataReceivedEventHandler ( OutputReceivedDataEventHandler ) ;
OutputReceivedDataEventHandlerEncounteredError = false ;
OutputReceivedDataEventHandlerEncounteredErrorMessage = "" ;
Utils . RunLocalProcess ( StubGenerateProcess ) ;
if ( OutputReceivedDataEventHandlerEncounteredError )
{
throw new Exception ( OutputReceivedDataEventHandlerEncounteredErrorMessage ) ;
}
// now that a slow mode sync has finished, we can now do DangerouslyFast mode again (if requested)
if ( bUseDangerouslyFastModeWasRequested )
{
File . Create ( DangerouslyFastValidFile ) ;
}
else
{
// if we didn't want dangerously fast, then delete the file so that setting/unsetting the flag will do the right thing without a Rebuild
File . Delete ( DangerouslyFastValidFile ) ;
}
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
{
2014-05-09 17:38:40 -04:00
// Copy bundled assets from additional frameworks to the intermediate assets directory (so they can get picked up during staging)
String LocalFrameworkAssets = Path . GetFullPath ( Target . ProjectDirectory + "/Intermediate/IOS/FrameworkAssets" ) ;
String RemoteFrameworkAssets = ConvertPath ( LocalFrameworkAssets ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
2014-05-12 18:51:03 -04:00
CleanIntermediateDirectory ( RemoteFrameworkAssets ) ;
2014-05-09 17:38:40 -04:00
// Delete the local dest directory if it exists
if ( Directory . Exists ( LocalFrameworkAssets ) )
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
{
2014-05-09 17:38:40 -04:00
Directory . Delete ( LocalFrameworkAssets , true ) ;
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
}
2014-05-09 17:38:40 -04:00
foreach ( UEBuildFramework Framework in RememberedAdditionalFrameworks )
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
{
2014-05-09 17:38:40 -04:00
if ( Framework . OwningModule = = null | | Framework . CopyBundledAssets = = null | | Framework . CopyBundledAssets = = "" )
{
continue ; // Only care if we need to copy bundle assets
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
2014-05-12 18:51:03 -04:00
if ( Framework . OwningModule . Target ! = Target )
{
continue ; // This framework item doesn't belong to this target, skip it
}
2014-05-09 17:38:40 -04:00
string RemoteZipPath = GetRemoteFrameworkZipPath ( Framework ) ;
RemoteZipPath = RemoteZipPath . Replace ( ".zip" , "" ) ;
// For now, this is hard coded, but we need to loop over all modules, and copy bundled assets that need it
string RemoteSource = RemoteZipPath + "/" + Framework . CopyBundledAssets ;
string BundleName = Framework . CopyBundledAssets . Substring ( Framework . CopyBundledAssets . LastIndexOf ( '/' ) + 1 ) ;
String RemoteDest = RemoteFrameworkAssets + "/" + BundleName ;
String LocalDest = LocalFrameworkAssets + "\\" + BundleName ;
Log . TraceInformation ( "Copying bundled asset... RemoteSource: {0}, RemoteDest: {1}, LocalDest: {2}" , RemoteSource , RemoteDest , LocalDest ) ;
Hashtable Results = RPCUtilHelper . Command ( "/" , String . Format ( "cp -R -L {0} {1}" , RemoteSource , RemoteDest ) , "" , null ) ;
foreach ( DictionaryEntry Entry in Results )
{
Log . TraceInformation ( "{0}" , Entry . Value ) ;
}
// Copy the bundled resource from the remote mac to the local dest
RPCUtilHelper . CopyDirectory ( RemoteDest , LocalDest , RPCUtilHelper . ECopyOptions . None ) ;
}
Support for third party iOS framework bundled assets
* Work in progress, works with RPC utility, local mac support incoming
* Changed AdditionalPublicFrameworks from storing just string, to storing the frame work name, zip name, and bundled asset name that needs to be copied
* We also now store the module that added this framework, so we can derive the module project path, etc when we need it for when we create intermediate directories
#Codereview Josh.Adams, Peter.Sauerbrei, Michael.Noland, Gil.Gribb, Robert.Manuszewski
[CL 2068603 by John Pollard in Main branch]
2014-05-09 16:38:26 -04:00
}
2014-03-14 14:13:41 -04:00
}
}
2014-04-30 14:09:06 -04:00
public static int RunExecutableAndWait ( string ExeName , string ArgumentList , out string StdOutResults )
{
// Create the process
ProcessStartInfo PSI = new ProcessStartInfo ( ExeName , ArgumentList ) ;
PSI . RedirectStandardOutput = true ;
PSI . UseShellExecute = false ;
PSI . CreateNoWindow = true ;
Process NewProcess = Process . Start ( PSI ) ;
// Wait for the process to exit and grab it's output
StdOutResults = NewProcess . StandardOutput . ReadToEnd ( ) ;
NewProcess . WaitForExit ( ) ;
return NewProcess . ExitCode ;
}
2014-03-14 14:13:41 -04:00
} ;
}