2022-07-19 13:24:38 -04:00
// Copyright Epic Games, Inc. All Rights Reserved.
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Text ;
using EpicGames.Core ;
using Microsoft.Extensions.Logging ;
2023-05-30 18:38:07 -04:00
using UnrealBuildBase ;
2022-08-23 15:40:10 -04:00
using UnrealBuildTool.XcodeProjectXcconfig ;
2022-07-19 13:24:38 -04:00
namespace UnrealBuildTool.XcodeProjectLegacy
{
/// <summary>
/// Represents a group of files shown in Xcode's project navigator as a folder
/// </summary>
class XcodeFileGroup
{
public XcodeFileGroup ( string InName , string InPath , bool InIsReference )
{
GroupName = InName ;
GroupPath = InPath ;
GroupGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
bIsReference = InIsReference ;
}
public string GroupGuid ;
public string GroupName ;
public string GroupPath ;
public Dictionary < string , XcodeFileGroup > Children = new Dictionary < string , XcodeFileGroup > ( ) ;
public List < XcodeSourceFile > Files = new List < XcodeSourceFile > ( ) ;
public bool bIsReference ;
}
class XcodeBuildConfig
{
public XcodeBuildConfig ( string InDisplayName , string InBuildTarget , FileReference ? InMacExecutablePath , FileReference ? InIOSExecutablePath , FileReference ? InTVOSExecutablePath ,
ProjectTarget ? InProjectTarget , UnrealTargetConfiguration InBuildConfig )
{
DisplayName = InDisplayName ;
MacExecutablePath = InMacExecutablePath ;
IOSExecutablePath = InIOSExecutablePath ;
TVOSExecutablePath = InTVOSExecutablePath ;
BuildTarget = InBuildTarget ;
ProjectTarget = InProjectTarget ;
BuildConfig = InBuildConfig ;
}
public string DisplayName ;
public FileReference ? MacExecutablePath ;
public FileReference ? IOSExecutablePath ;
public FileReference ? TVOSExecutablePath ;
public string BuildTarget ;
public ProjectTarget ? ProjectTarget ;
public UnrealTargetConfiguration BuildConfig ;
} ;
class XcodeExtensionInfo
{
public XcodeExtensionInfo ( string InName )
{
Name = InName ;
TargetDependencyGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
TargetProxyGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
TargetGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
ProductGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
ResourceBuildPhaseGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
ConfigListGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
AllConfigs = new Dictionary < string , XcodeBuildConfig > ( ) ;
}
public string Name ;
public string TargetDependencyGuid ;
public string TargetProxyGuid ;
public string TargetGuid ;
public string ProductGuid ;
public string ResourceBuildPhaseGuid ;
public string ConfigListGuid ;
public Dictionary < string , XcodeBuildConfig > AllConfigs ;
public string? ConfigurationContents ;
}
class XcodeProjectFile : ProjectFile
{
Dictionary < string , XcodeFileGroup > Groups = new Dictionary < string , XcodeFileGroup > ( ) ;
/// <summary>
/// Constructs a new project file object
/// </summary>
/// <param name="InitFilePath">The path to the project file on disk</param>
/// <param name="BaseDir">The base directory for files within this project</param>
/// <param name="IsForDistribution">True for distribution builds</param>
/// <param name="BundleID">Override option for bundle identifier</param>
/// <param name="InAppName"></param>
2023-02-17 12:53:28 -05:00
/// <param name="bMakeProjectPerTarget"></param>
public XcodeProjectFile ( FileReference InitFilePath , DirectoryReference BaseDir , bool IsForDistribution , string BundleID , string InAppName , bool bMakeProjectPerTarget )
2022-07-19 13:24:38 -04:00
: base ( InitFilePath , BaseDir )
{
bForDistribution = IsForDistribution ;
BundleIdentifier = BundleID ;
AppName = InAppName ;
2023-02-17 12:53:28 -05:00
this . bMakeProjectPerTarget = bMakeProjectPerTarget ;
2022-07-19 13:24:38 -04:00
}
public override string ToString ( )
{
return ProjectFilePath . GetFileNameWithoutExtension ( ) ;
}
2023-02-17 12:53:28 -05:00
/// <summary>
/// Temporary for developing this feature
/// </summary>
bool bMakeProjectPerTarget ;
2022-07-19 13:24:38 -04:00
/// <summary>
/// Used to mark the project for distribution (some platforms require this)
/// </summary>
bool bForDistribution = false ;
/// <summary>
/// Override for bundle identifier
/// </summary>
string BundleIdentifier = "" ;
/// <summary>
/// Override AppName
/// </summary>
string AppName = "" ;
/// <summary>
/// Architectures supported for iOS
/// </summary>
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
UnrealArch [ ] SupportedIOSArchitectures = { UnrealArch . Arm64 } ;
2022-07-19 13:24:38 -04:00
/// <summary>
/// Gets Xcode file category based on its extension
/// </summary>
private string GetFileCategory ( string Extension )
{
// @todo Mac: Handle more categories
switch ( Extension )
{
case ".framework" :
return "Frameworks" ;
default :
return "Sources" ;
}
}
/// <summary>
/// Gets Xcode file type based on its extension
/// </summary>
private string GetFileType ( string Extension )
{
// @todo Mac: Handle more file types
switch ( Extension )
{
case ".c" :
case ".m" :
return "sourcecode.c.objc" ;
case ".cc" :
case ".cpp" :
case ".mm" :
return "sourcecode.cpp.objcpp" ;
case ".h" :
case ".inl" :
case ".pch" :
return "sourcecode.c.h" ;
case ".framework" :
return "wrapper.framework" ;
case ".plist" :
return "text.plist.xml" ;
case ".png" :
return "image.png" ;
case ".icns" :
return "image.icns" ;
default :
return "file.text" ;
}
}
/// <summary>
/// Returns true if Extension is a known extension for files containing source code
/// </summary>
private bool IsSourceCode ( string Extension )
{
return Extension = = ".c" | | Extension = = ".cc" | | Extension = = ".cpp" | | Extension = = ".m" | | Extension = = ".mm" ;
}
private bool ShouldIncludeFileInBuildPhaseSection ( XcodeSourceFile SourceFile )
{
string FileExtension = SourceFile . Reference . GetExtension ( ) ;
if ( IsSourceCode ( FileExtension ) )
{
foreach ( string PlatformName in UnrealTargetPlatform . GetValidPlatformNames ( ) )
{
string AltName = PlatformName = = "Win64" ? "windows" : PlatformName . ToLower ( ) ;
if ( ( SourceFile . Reference . FullName . ToLower ( ) . Contains ( "/" + PlatformName . ToLower ( ) + "/" ) | | SourceFile . Reference . FullName . ToLower ( ) . Contains ( "/" + AltName + "/" ) )
& & PlatformName ! = "Mac" & & PlatformName ! = "IOS" & & PlatformName ! = "TVOS" )
{
// Build phase is used for indexing only and indexing currently works only with files that can be compiled for Mac, so skip files for other platforms
return false ;
}
}
return true ;
}
return false ;
}
/// <summary>
/// Returns a project navigator group to which the file should belong based on its path.
/// Creates a group tree if it doesn't exist yet.
/// </summary>
public XcodeFileGroup ? FindGroupByAbsolutePath ( ref Dictionary < string , XcodeFileGroup > Groups , string AbsolutePath )
{
string [ ] Parts = AbsolutePath . Split ( Path . DirectorySeparatorChar ) ;
string CurrentPath = "/" ;
Dictionary < string , XcodeFileGroup > CurrentSubGroups = Groups ;
for ( int Index = 1 ; Index < Parts . Count ( ) ; + + Index )
{
string Part = Parts [ Index ] ;
if ( CurrentPath . Length > 1 )
{
CurrentPath + = Path . DirectorySeparatorChar ;
}
CurrentPath + = Part ;
XcodeFileGroup CurrentGroup ;
if ( ! CurrentSubGroups . ContainsKey ( CurrentPath ) )
{
CurrentGroup = new XcodeFileGroup ( Path . GetFileName ( CurrentPath ) , CurrentPath , CurrentPath . EndsWith ( ".xcassets" ) ) ;
CurrentSubGroups . Add ( CurrentPath , CurrentGroup ) ;
}
else
{
CurrentGroup = CurrentSubGroups [ CurrentPath ] ;
}
if ( CurrentPath = = AbsolutePath )
{
return CurrentGroup ;
}
CurrentSubGroups = CurrentGroup . Children ;
}
return null ;
}
/// <summary>
/// Convert all paths to Apple/Unix format (with forward slashes)
/// </summary>
/// <param name="InPath">The path to convert</param>
/// <returns>The normalized path</returns>
private static string ConvertPath ( string InPath )
{
return InPath . Replace ( "\\" , "/" ) ;
}
/// <summary>
/// Allocates a generator-specific source file object
/// </summary>
/// <param name="InitFilePath">Path to the source file on disk</param>
/// <param name="InitProjectSubFolder">Optional sub-folder to put the file in. If empty, this will be determined automatically from the file's path relative to the project file</param>
/// <returns>The newly allocated source file object</returns>
public override SourceFile ? AllocSourceFile ( FileReference InitFilePath , DirectoryReference ? InitProjectSubFolder )
{
if ( InitFilePath . GetFileName ( ) . StartsWith ( "." ) )
{
return null ;
}
return new XcodeSourceFile ( InitFilePath , InitProjectSubFolder ) ;
}
/// <summary>
/// Generates bodies of all sections that contain a list of source files plus a dictionary of project navigator groups.
/// </summary>
private void GenerateSectionsWithSourceFiles ( StringBuilder PBXBuildFileSection , StringBuilder PBXFileReferenceSection , StringBuilder PBXSourcesBuildPhaseSection , string TargetAppGuid , string TargetName , bool bIsAppBundle )
{
SourceFiles . Sort ( ( x , y ) = > { return x . Reference . FullName . CompareTo ( y . Reference . FullName ) ; } ) ;
foreach ( XcodeSourceFile SourceFile in SourceFiles . OfType < XcodeSourceFile > ( ) )
{
string FileName = SourceFile . Reference . GetFileName ( ) ;
string FileExtension = Path . GetExtension ( FileName ) ;
string FilePath = SourceFile . Reference . MakeRelativeTo ( ProjectFilePath . Directory ) ;
string FilePathMac = Utils . CleanDirectorySeparators ( FilePath , '/' ) ;
if ( IsGeneratedProject )
{
2023-05-30 18:59:32 -04:00
PBXBuildFileSection . Append ( String . Format ( "\t\t{0} /* {1} in {2} */ = {{isa = PBXBuildFile; fileRef = {3} /* {1} */; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
SourceFile . FileGuid ,
FileName ,
GetFileCategory ( FileExtension ) ,
SourceFile . FileRefGuid ) ) ;
}
2023-05-30 18:59:32 -04:00
PBXFileReferenceSection . Append ( String . Format ( "\t\t{0} /* {1} */ = {{isa = PBXFileReference; explicitFileType = {2}; name = \"{1}\"; path = \"{3}\"; sourceTree = SOURCE_ROOT; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
SourceFile . FileRefGuid ,
FileName ,
GetFileType ( FileExtension ) ,
FilePathMac ) ) ;
if ( ShouldIncludeFileInBuildPhaseSection ( SourceFile ) )
{
PBXSourcesBuildPhaseSection . Append ( "\t\t\t\t" + SourceFile . FileGuid + " /* " + FileName + " in Sources */," + ProjectFileGenerator . NewLine ) ;
}
XcodeFileGroup ? Group = FindGroupByAbsolutePath ( ref Groups , SourceFile . Reference . Directory . FullName ) ;
if ( Group ! = null )
{
Group . Files . Add ( SourceFile ) ;
}
}
2023-05-30 18:59:32 -04:00
PBXFileReferenceSection . Append ( String . Format ( "\t\t{0} /* {1} */ = {{isa = PBXFileReference; explicitFileType = {2}; path = {1}; sourceTree = BUILT_PRODUCTS_DIR; }};" + ProjectFileGenerator . NewLine , TargetAppGuid , TargetName , bIsAppBundle ? "wrapper.application" : "\"compiled.mach-o.executable\"" ) ) ;
2022-07-19 13:24:38 -04:00
}
private void GenerateSectionsWithExtensions ( StringBuilder PBXBuildFileSection , StringBuilder PBXFileReferenceSection , StringBuilder PBXCopyFilesBuildPhaseSection , StringBuilder PBXResourcesBuildPhaseSection ,
List < XcodeExtensionInfo > AllExtensions , FileReference ? UProjectPath , List < XcodeBuildConfig > BuildConfigs , ILogger Logger )
{
if ( UProjectPath ! = null )
{
string ProjectExtensionsDir = Path . Combine ( Path . GetDirectoryName ( UProjectPath . FullName ) ! , "Build/IOS/Extensions" ) ;
//string ProjectIntermediateDir = Path.Combine(Path.GetDirectoryName(UProjectPath.FullName), "Intermediate/IOS/Extensions");
if ( Directory . Exists ( ProjectExtensionsDir ) )
{
foreach ( DirectoryInfo DI in new System . IO . DirectoryInfo ( ProjectExtensionsDir ) . EnumerateDirectories ( ) )
{
Console . WriteLine ( " Project {0} has Extension {1}!" , UProjectPath , DI ) ;
// assume each Extension in here will create a resulting Extension.appex
string Extension = DI . Name + ".appex" ;
string ExtensionGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
// make an extension info object
XcodeExtensionInfo ExtensionInfo = new XcodeExtensionInfo ( DI . Name ) ;
AllExtensions . Add ( ExtensionInfo ) ;
2023-05-30 18:59:32 -04:00
PBXBuildFileSection . Append ( String . Format ( "\t\t{0} /* {1} in Embed App Extensions */ = {{isa = PBXBuildFile; fileRef = {2} /* {1} */; settings = {{ATTRIBUTES = (RemoveHeadersOnCopy, ); }}; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
ExtensionGuid ,
Extension ,
ExtensionInfo . ProductGuid ) ) ;
2023-05-30 18:59:32 -04:00
PBXFileReferenceSection . Append ( String . Format ( "\t\t{0} /* {1} */ = {{isa = PBXFileReference; explicitFileType = wrapper.app-extension; path = \"{1}\"; sourceTree = BUILT_PRODUCTS_DIR; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
ExtensionInfo . ProductGuid ,
Extension ) ) ;
2023-05-30 18:59:32 -04:00
PBXCopyFilesBuildPhaseSection . Append ( String . Format ( "\t\t\t\t{0} /* {1} in Embed App Extensions */," + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
ExtensionGuid ,
Extension ) ) ;
PBXResourcesBuildPhaseSection . Append ( "/* Begin PBXResourcesBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t" + ExtensionInfo . ResourceBuildPhaseGuid + " /* Resources */ = {" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t\tisa = PBXResourcesBuildPhase;" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t\tbuildActionMask = 2147483647;" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t\tfiles = (" + ProjectFileGenerator . NewLine ) ;
if ( Directory . Exists ( Path . Combine ( DI . FullName , "Resources" ) ) )
{
DirectoryInfo ResourceDir = new System . IO . DirectoryInfo ( Path . Combine ( DI . FullName , "Resources" ) ) ;
foreach ( FileSystemInfo FSI in ResourceDir . EnumerateFileSystemInfos ( ) )
{
if ( FSI . Name . StartsWith ( "." ) )
{
continue ;
}
// for each resource, put it into the File/FileRef section, and into the CopyResuorceBuildPhase
string ResourceGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ResourceRefGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
2023-05-30 18:59:32 -04:00
PBXBuildFileSection . Append ( String . Format ( "\t\t{0} /* {1} in Embed App Extensions */ = {{isa = PBXBuildFile; fileRef = {2} /* {1} */; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
ResourceGuid ,
FSI . Name ,
ResourceRefGuid ) ) ;
// lastKnownFileType = wrapper.app-extension;
2023-05-30 18:59:32 -04:00
PBXFileReferenceSection . Append ( String . Format ( "\t\t{0} /* {1} */ = {{isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = \"{2}\"; sourceTree = \"<absolute>\"; }};" + ProjectFileGenerator . NewLine ,
2022-07-19 13:24:38 -04:00
ResourceRefGuid ,
FSI . Name ,
// @todo: make this relative path!!
FSI . FullName ) ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t\t\t" + ResourceGuid + " /* " + FSI . Name + " in " + ResourceDir . Name + " */," + ProjectFileGenerator . NewLine ) ;
}
}
PBXResourcesBuildPhaseSection . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t\trunOnlyForDeploymentPostprocessing = 0;" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
PBXResourcesBuildPhaseSection . Append ( "/* End PBXResourcesBuildPhase section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
StringBuilder ConfigSection = new StringBuilder ( ) ;
// copy over the configs from the general project to the extension
foreach ( XcodeBuildConfig Configuration in BuildConfigs )
{
string ConfigGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ConfigName = Configuration . DisplayName ;
ConfigSection . Append ( "\t\t" + ConfigGuid + " /* " + ConfigName + " */ = {" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\tisa = XCBuildConfiguration;" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\tbuildSettings = {" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = \"iMessage App Icon\";" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\t\tINFOPLIST_FILE = \"" + Path . Combine ( DI . FullName , "Info.plist" ) + "\";" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\t\tSKIP_INSTALL = YES;" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";" + ProjectFileGenerator . NewLine ) ;
bool bSupportIOS = true ;
bool bSupportTVOS = true ;
if ( bSupportIOS & & InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . IOS , EProjectType . Code ) )
{
IOSPlatform IOSPlatform = ( ( IOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . IOS ) ) ;
IOSProjectSettings ProjectSettings = IOSPlatform . ReadProjectSettings ( UProjectPath ) ;
ConfigSection . Append ( "\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]\" = " + ProjectSettings . BundleIdentifier + "." + ExtensionInfo . Name + ";" + ProjectFileGenerator . NewLine ) ;
}
if ( bSupportTVOS & & InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . TVOS , EProjectType . Code ) )
{
TVOSPlatform TVOSPlatform = ( ( TVOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . TVOS ) ) ;
TVOSProjectSettings ProjectSettings = TVOSPlatform . ReadProjectSettings ( UProjectPath ) ;
ConfigSection . Append ( "\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=appletvos*]\" = " + ProjectSettings . BundleIdentifier + "." + ExtensionInfo . Name + ";" + ProjectFileGenerator . NewLine ) ;
}
string? IOSRuntimeVersion , TVOSRuntimeVersion ;
AppendPlatformConfiguration ( ConfigSection , Configuration , ExtensionInfo . Name , UProjectPath , false , bSupportIOS , bSupportTVOS , Logger , out IOSRuntimeVersion , out TVOSRuntimeVersion ) ;
ConfigSection . Append ( "\t\t\t};" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t\tname = \"" + ConfigName + "\";" + ProjectFileGenerator . NewLine ) ;
ConfigSection . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
XcodeBuildConfig Config = new XcodeBuildConfig ( ConfigName , ExtensionInfo . Name , null , null , null , null , Configuration . BuildConfig ) ;
ExtensionInfo . AllConfigs . Add ( ConfigGuid , Config ) ;
}
ExtensionInfo . ConfigurationContents = ConfigSection . ToString ( ) ;
}
}
}
}
private void AppendGroup ( XcodeFileGroup Group , StringBuilder Content )
{
if ( ! Group . bIsReference )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t{0} = {{{1}" , Group . GroupGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\tisa = PBXGroup;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tchildren = (" + ProjectFileGenerator . NewLine ) ;
foreach ( XcodeFileGroup ChildGroup in Group . Children . Values )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , ChildGroup . GroupGuid , ChildGroup . GroupName , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
}
foreach ( XcodeSourceFile File in Group . Files )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , File . FileRefGuid , File . Reference . GetFileName ( ) , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + Group . GroupName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tpath = \"" + Group . GroupPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tsourceTree = \"<absolute>\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
foreach ( XcodeFileGroup ChildGroup in Group . Children . Values )
{
AppendGroup ( ChildGroup , Content ) ;
}
}
}
private void AppendBuildFileSection ( StringBuilder Content , StringBuilder SectionContent )
{
Content . Append ( "/* Begin PBXBuildFile section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( SectionContent ) ;
Content . Append ( "/* End PBXBuildFile section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendFileReferenceSection ( StringBuilder Content , StringBuilder SectionContent )
{
Content . Append ( "/* Begin PBXFileReference section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( SectionContent ) ;
Content . Append ( "/* End PBXFileReference section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendSourcesBuildPhaseSection ( StringBuilder Content , StringBuilder SectionContent , string SourcesBuildPhaseGuid )
{
Content . Append ( "/* Begin PBXSourcesBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t{0} = {{{1}" , SourcesBuildPhaseGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\tisa = PBXSourcesBuildPhase;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildActionMask = 2147483647;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tfiles = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( SectionContent ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\trunOnlyForDeploymentPostprocessing = 0;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXSourcesBuildPhase section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private XcodeFileGroup ? FindRootFileGroup ( Dictionary < string , XcodeFileGroup > GroupsDict )
{
foreach ( XcodeFileGroup Group in GroupsDict . Values )
{
if ( Group . Children . Count > 1 | | Group . Files . Count > 0 )
{
return Group ;
}
else
{
XcodeFileGroup ? Found = FindRootFileGroup ( Group . Children ) ;
if ( Found ! = null )
{
return Found ;
}
}
}
return null ;
}
private void AppendCopyExtensionsBuildPhaseSection ( StringBuilder Content , StringBuilder SectionContent , string CopyFilesBuildPhaseGuid )
{
Content . Append ( "/* Begin PBXCopyFilesBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t{0} /* Embed App Extensions */ = {{{1}" , CopyFilesBuildPhaseGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\tisa = PBXCopyFilesBuildPhase;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\tbuildActionMask = 2147483647;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\tdstPath = \"\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\tdstSubfolderSpec = 13;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\tfiles = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( SectionContent ) ;
Content . Append ( "\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\tname = \"Embed App Extensions\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\trunOnlyForDeploymentPostprocessing = 0;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXCopyFilesBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
}
private void AppendGroupSection ( StringBuilder Content , string MainGroupGuid , string ProductRefGroupGuid , string TargetAppGuid , string TargetName , List < XcodeExtensionInfo > AllExtensions )
{
XcodeFileGroup ? RootGroup = FindRootFileGroup ( Groups ) ;
if ( RootGroup = = null )
{
return ;
}
Content . Append ( "/* Begin PBXGroup section */" + ProjectFileGenerator . NewLine ) ;
// Main group
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t{0} = {{{1}" , MainGroupGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\tisa = PBXGroup;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tchildren = (" + ProjectFileGenerator . NewLine ) ;
foreach ( XcodeFileGroup Group in RootGroup . Children . Values )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , Group . GroupGuid , Group . GroupName , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
}
foreach ( XcodeSourceFile File in RootGroup . Files )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , File . FileRefGuid , File . Reference . GetFileName ( ) , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* Products */,{1}" , ProductRefGroupGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tsourceTree = \"<group>\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
// Sources groups
foreach ( XcodeFileGroup Group in RootGroup . Children . Values )
{
AppendGroup ( Group , Content ) ;
}
// Products group
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t{0} /* Products */ = {{{1}" , ProductRefGroupGuid , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\tisa = PBXGroup;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tchildren = (" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , TargetAppGuid , TargetName , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\t\t{0} /* {1} */,{2}" , EI . ProductGuid , EI . Name , ProjectFileGenerator . NewLine ) ) ;
2022-07-19 13:24:38 -04:00
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = Products;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tsourceTree = \"<group>\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXGroup section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendLegacyTargetSection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetBuildConfigGuid , FileReference ? UProjectPath )
{
string UEDir = ConvertPath ( Path . GetFullPath ( Directory . GetCurrentDirectory ( ) + "../../.." ) ) ;
string BuildToolPath = UEDir + "/Engine/Build/BatchFiles/Mac/XcodeBuild.sh" ;
Content . Append ( "/* Begin PBXLegacyTarget section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + TargetGuid + " /* " + TargetName + " */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXLegacyTarget;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildArgumentsString = \"$(ACTION) $(UE_BUILD_TARGET_NAME) $(PLATFORM_NAME) $(UE_BUILD_TARGET_CONFIG)"
+ ( UProjectPath = = null ? "" : " \\\"" + UProjectPath . FullName + "\\\"" )
+ "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildConfigurationList = " + TargetBuildConfigGuid + " /* Build configuration list for PBXLegacyTarget \"" + TargetName + "\" */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildPhases = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildToolPath = \"" + BuildToolPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildWorkingDirectory = \"" + UEDir + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdependencies = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tpassBuildSettingsInEnvironment = 1;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductName = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXLegacyTarget section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendRunTargetSection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetBuildConfigGuid , string TargetDependencyGuid ,
string TargetAppGuid , string CopyExtensionsBuildPhaseGuid , string ShellScriptSectionGuid , List < XcodeExtensionInfo > AllExtensions , bool bIsAppBundle )
{
List < string > DependencyGuids = new List < string > ( ) ;
// depends on the Run target if we want one
2022-09-22 11:42:27 -04:00
if ( ! XcodeProjectFileGenerator . bGenerateRunOnlyProject )
2022-07-19 13:24:38 -04:00
{
DependencyGuids . Add ( TargetDependencyGuid ) ;
}
// make sure extensions get built
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
DependencyGuids . Add ( EI . TargetDependencyGuid ) ;
}
Dictionary < string , string > BuildPhases = new Dictionary < string , string > ( ) ;
// add optional build phases
2023-05-30 18:59:32 -04:00
if ( ! String . IsNullOrEmpty ( CopyExtensionsBuildPhaseGuid ) )
2022-07-19 13:24:38 -04:00
{
BuildPhases . Add ( CopyExtensionsBuildPhaseGuid , "Embed App Extensions" ) ;
}
2023-05-30 18:59:32 -04:00
if ( ! String . IsNullOrEmpty ( ShellScriptSectionGuid ) )
2022-07-19 13:24:38 -04:00
{
BuildPhases . Add ( ShellScriptSectionGuid , "Shell Script" ) ;
}
// use generica target section function for an application type
AppendGenericTargetSection ( Content , TargetName , TargetGuid , bIsAppBundle ? "com.apple.product-type.application" : "com.apple.product-type.tool" , TargetBuildConfigGuid , TargetAppGuid , DependencyGuids , BuildPhases ) ;
}
private void AppendGenericTargetSection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetType , string TargetBuildConfigGuid , string TargetAppGuid , IEnumerable < string > ? TargetDependencyGuids , Dictionary < string , string > BuildPhases )
{
Content . Append ( "/* Begin PBXNativeTarget section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + TargetGuid + " /* " + TargetName + " */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXNativeTarget;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildConfigurationList = " + TargetBuildConfigGuid + " /* Build configuration list for PBXNativeTarget \"" + TargetName + "\" */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildPhases = (" + ProjectFileGenerator . NewLine ) ;
if ( BuildPhases ! = null )
{
foreach ( KeyValuePair < string , string > BuildPhasePair in BuildPhases )
{
Content . Append ( "\t\t\t\t" + BuildPhasePair . Key + " /* " + BuildPhasePair . Value + " */, " + ProjectFileGenerator . NewLine ) ;
}
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdependencies = (" + ProjectFileGenerator . NewLine ) ;
if ( TargetDependencyGuids ! = null )
{
foreach ( string DependencyGuid in TargetDependencyGuids )
{
Content . Append ( "\t\t\t\t" + DependencyGuid + " /* PBXTargetDependency */," + ProjectFileGenerator . NewLine ) ;
}
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tpassBuildSettingsInEnvironment = 1;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductName = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductReference = \"" + TargetAppGuid + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductType = \"" + TargetType + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXNativeTarget section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendIndexTargetSection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetBuildConfigGuid , string SourcesBuildPhaseGuid )
{
Content . Append ( "/* Begin PBXNativeTarget section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + TargetGuid + " /* " + TargetName + " */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXNativeTarget;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildConfigurationList = " + TargetBuildConfigGuid + " /* Build configuration list for PBXNativeTarget \"" + TargetName + "\" */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildPhases = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t" + SourcesBuildPhaseGuid + " /* Sources */," + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdependencies = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tpassBuildSettingsInEnvironment = 1;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductName = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductType = \"com.apple.product-type.library.static\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXNativeTarget section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendShellScriptSection ( StringBuilder Content , string ShellScriptGuid , FileReference ? UProjectPath )
{
StringBuilder FrameworkScript = new StringBuilder ( ) ;
2022-12-12 17:46:48 -05:00
if ( UProjectPath ! = null )
2022-07-19 13:24:38 -04:00
{
2022-12-12 17:46:48 -05:00
// @todo: look also in Project/Build/Frameworks directory!
ProjectDescriptor Project = ProjectDescriptor . FromFile ( UProjectPath ) ;
List < PluginInfo > AvailablePlugins = Plugins . ReadAvailablePlugins ( Unreal . EngineDirectory , DirectoryReference . FromFile ( UProjectPath ) , Project . AdditionalPluginDirectories ) ;
2022-07-19 13:24:38 -04:00
2022-12-12 17:46:48 -05:00
// look in each plugin for frameworks
// @todo: Cache this kind of things since every target will re-do this work!
foreach ( PluginInfo PI in AvailablePlugins )
2022-07-19 13:24:38 -04:00
{
2022-12-12 17:46:48 -05:00
if ( ! Plugins . IsPluginEnabledForTarget ( PI , Project , UnrealTargetPlatform . IOS , UnrealTargetConfiguration . Development , TargetRules . TargetType . Game ) )
2022-07-19 13:24:38 -04:00
{
2022-12-12 17:46:48 -05:00
continue ;
}
2022-07-19 13:24:38 -04:00
2022-12-12 17:46:48 -05:00
// for now, we copy and code sign all *.framework.zip, even if the have no code (non-code frameworks are assumed to be *.embeddedframework.zip
DirectoryReference FrameworkDir = DirectoryReference . Combine ( PI . Directory , "Source/Frameworks" ) ;
if ( ! DirectoryReference . Exists ( FrameworkDir ) )
{
FrameworkDir = DirectoryReference . Combine ( PI . Directory , "Frameworks" ) ;
}
if ( DirectoryReference . Exists ( FrameworkDir ) )
{
// look at each zip
foreach ( FileInfo FI in new System . IO . DirectoryInfo ( FrameworkDir . FullName ) . EnumerateFiles ( "*.framework.zip" ) )
{
//string Guid = XcodeProjectFileGenerator.MakeXcodeGuid();
//string RefGuid = XcodeProjectFileGenerator.MakeXcodeGuid();
2022-07-19 13:24:38 -04:00
2022-12-12 17:46:48 -05:00
// for FI of foo.framework.zip, this will give us foo.framework
//string Framework = Path.GetFileNameWithoutExtension(FI.FullName);
// unzip the framework right into the .app
FrameworkScript . AppendFormat ( "\\techo Unzipping {0}...\\n" , FI . FullName ) ;
FrameworkScript . AppendFormat ( "\\tunzip -o -q {0} -d ${{FRAMEWORK_DIR}} -x \\\"__MACOSX/*\\\" \\\"*/.DS_Store\\\"\\n" , FI . FullName ) ;
}
2022-07-19 13:24:38 -04:00
}
}
}
string ShellScript = "set -e\\n\\nIFS=$'\\\\n'\\n\\n" +
"if [ $PLATFORM_NAME = iphoneos ] || [ $PLATFORM_NAME = tvos ]; then \\n" +
"\\tFRAMEWORK_DIR=$TARGET_BUILD_DIR/$EXECUTABLE_FOLDER_PATH/Frameworks\\n" +
FrameworkScript . ToString ( ) +
// and now code sign anything that has been unzipped above
"\\tfor FRAMEWORK in ${FRAMEWORK_DIR}/*.framework; do\\n" +
"\\t\\t[ -d \\\"${FRAMEWORK}\\\" ] || continue\\n" +
"\\t\\techo Codesigning ${FRAMEWORK}\\n" +
"\\t\\tcodesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --generate-entitlement-der --verbose --preserve-metadata=identifier,entitlements,flags --timestamp=none \\\"${FRAMEWORK}\\\"\\n" +
"\\tdone\\n" +
"fi\\n" ;
Content . Append ( "/* Begin PBXShellScriptBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t{0} /* Sign Frameworks */ = {{" + ProjectFileGenerator . NewLine , ShellScriptGuid ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\tisa = PBXShellScriptBuildPhase;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildActionMask = 2147483647;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tfiles = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tinputPaths = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\toutputPaths = (" + ProjectFileGenerator . NewLine ) ;
2023-03-01 16:02:32 -05:00
Content . Append ( "\t\t\t\t/dev/null" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"Sign Manual Frameworks\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\trunOnlyForDeploymentPostprocessing = 0;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tshellPath = /bin/sh;" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
Content . Append ( String . Format ( "\t\t\tshellScript = \"{0}\";" + ProjectFileGenerator . NewLine , ShellScript ) ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXShellScriptBuildPhase section */" + ProjectFileGenerator . NewLine ) ;
}
private void AppendExtensionTargetSections ( StringBuilder ProjectFileContent , List < XcodeExtensionInfo > AllExtensions )
{
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
Dictionary < string , string > BuildPhases = new Dictionary < string , string > ( ) ;
BuildPhases . Add ( EI . ResourceBuildPhaseGuid , "Resources" ) ;
AppendGenericTargetSection ( ProjectFileContent , EI . Name , EI . TargetGuid , "com.apple.product-type.app-extension.messages-sticker-pack" , EI . ConfigListGuid , EI . ProductGuid , null , BuildPhases ) ;
}
}
private void AppendProjectSection ( StringBuilder Content , string TargetName , string TargetGuid , string BuildTargetName , string BuildTargetGuid , string IndexTargetName , string IndexTargetGuid , string MainGroupGuid , string ProductRefGroupGuid , string ProjectGuid , string ProjectBuildConfigGuid , FileReference ? ProjectFile , List < XcodeExtensionInfo > AllExtensions )
{
Content . Append ( "/* Begin PBXProject section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + ProjectGuid + " /* Project object */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXProject;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tattributes = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tLastUpgradeCheck = 2000;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tORGANIZATIONNAME = \"Epic Games, Inc.\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tTargetAttributes = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\t" + TargetGuid + " = {" + ProjectFileGenerator . NewLine ) ;
bool bAutomaticSigning = false ;
if ( InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . IOS , EProjectType . Code ) )
{
IOSPlatform IOSPlatform = ( ( IOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . IOS ) ) ;
IOSProjectSettings ProjectSettings = IOSPlatform . ReadProjectSettings ( ProjectFile ) ;
bAutomaticSigning = ProjectSettings . bAutomaticSigning ;
}
if ( InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . TVOS , EProjectType . Code ) )
{
TVOSPlatform TVOSPlatform = ( ( TVOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . TVOS ) ) ;
TVOSProjectSettings ProjectSettings = TVOSPlatform . ReadProjectSettings ( ProjectFile ) ;
//TVOSProvisioningData ProvisioningData = TVOSPlatform.ReadProvisioningData(ProjectSettings, bForDistribution);
bAutomaticSigning = ProjectSettings . bAutomaticSigning ;
}
if ( bAutomaticSigning )
{
Content . Append ( "\t\t\t\t\t\tProvisioningStyle = Automatic;" + ProjectFileGenerator . NewLine ) ;
}
else
{
Content . Append ( "\t\t\t\t\t\tProvisioningStyle = Manual;" + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildConfigurationList = " + ProjectBuildConfigGuid + " /* Build configuration list for PBXProject \"" + TargetName + "\" */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tcompatibilityVersion = \"Xcode 8.0\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdevelopmentRegion = English;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\thasScannedForEncodings = 0;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tknownRegions = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\ten" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tmainGroup = " + MainGroupGuid + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproductRefGroup = " + ProductRefGroupGuid + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tprojectDirPath = \"\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tprojectRoot = \"\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\ttargets = (" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t" + TargetGuid + " /* " + TargetName + " */," + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t" + BuildTargetGuid + " /* " + BuildTargetName + " */," + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t" + IndexTargetGuid + " /* " + IndexTargetName + " */," + ProjectFileGenerator . NewLine ) ;
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
Content . Append ( "\t\t\t" + EI . TargetGuid + " /* " + EI . Name + " */," + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXProject section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendContainerItemProxySection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetProxyGuid , string ProjectGuid )
{
Content . Append ( "/* Begin PBXContainerItemProxy section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + TargetProxyGuid + " /* PBXContainerItemProxy */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXContainerItemProxy;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tcontainerPortal = " + ProjectGuid + " /* Project object */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tproxyType = 1;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tremoteGlobalIDString = " + TargetGuid + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tremoteInfo = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXContainerItemProxy section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendTargetDependencySection ( StringBuilder Content , string TargetName , string TargetGuid , string TargetDependencyGuid , string TargetProxyGuid )
{
Content . Append ( "/* Begin PBXTargetDependency section */" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t" + TargetDependencyGuid + " /* PBXTargetDependency */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = PBXTargetDependency;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\ttarget = " + TargetGuid + " /* " + TargetName + " */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\ttargetProxy = " + TargetProxyGuid + " /* PBXContainerItemProxy */;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "/* End PBXTargetDependency section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendProjectBuildConfiguration ( StringBuilder Content , string ConfigName , string ConfigGuid )
{
Content . Append ( "\t\t" + ConfigGuid + " /* \"" + ConfigName + "\" */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = XCBuildConfiguration;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildSettings = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (" + ProjectFileGenerator . NewLine ) ;
foreach ( string Definition in IntelliSensePreprocessorDefinitions )
{
Content . Append ( "\t\t\t\t\t\"" + Definition . Replace ( "\"" , "" ) . Replace ( "\\" , "" ) + "\"," + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\t\t\"__INTELLISENSE__\"," + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\t\"MONOLITHIC_BUILD=1\"," + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tHEADER_SEARCH_PATHS = (" + ProjectFileGenerator . NewLine ) ;
foreach ( string SearchPath in IntelliSenseSystemIncludeSearchPaths )
{
2023-05-31 13:37:21 -04:00
string Path = SearchPath . Contains ( ' ' ) ? "\\\"" + SearchPath + "\\\"" : SearchPath ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t\t\t\"" + Path + "\"," + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tUSER_HEADER_SEARCH_PATHS = (" + ProjectFileGenerator . NewLine ) ;
foreach ( string SearchPath in IntelliSenseIncludeSearchPaths )
{
2023-05-31 13:37:21 -04:00
string Path = SearchPath . Contains ( ' ' ) ? "\\\"" + SearchPath + "\\\"" : SearchPath ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t\t\t\"" + Path + "\"," + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tONLY_ACTIVE_ARCH = YES;" + ProjectFileGenerator . NewLine ) ;
if ( ConfigName = = "Debug" )
{
Content . Append ( "\t\t\t\tENABLE_TESTABILITY = YES;" + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"c++14\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tGCC_ENABLE_CPP_RTTI = NO;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tGCC_WARN_CHECK_SWITCH_STATEMENTS = NO;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tUSE_HEADERMAP = NO;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + ConfigName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
}
// cache for the below function
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
Dictionary < string , UnrealArchitectures > CachedMacProjectArcitectures = new ( ) ;
2022-07-19 13:24:38 -04:00
/// <summary>
/// Returns the Mac architectures that should be configured for the provided target. If the target has a project we'll adhere
/// to whether it's set as Intel/Universal/Apple unless the type is denied (pretty much just Editor)
///
/// If the target has no project we'll support allow-listed targets for installed builds and all non-editor architectures
/// for source builds. Not all programs are going to compile for Apple Silicon, but being able to build and fail is useful...
/// </summary>
/// <param name="Config">Build config for the target we're generating</param>
/// <param name="InProjectFile">Path to the project file, or null if the target has no project</param>
/// <returns></returns>
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
UnrealArchitectures GetSupportedMacArchitectures ( XcodeBuildConfig Config , FileReference ? InProjectFile )
2022-07-19 13:24:38 -04:00
{
// All architectures supported
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
UnrealArchitectures AllArchitectures = new ( new [ ] { UnrealArch . Arm64 , UnrealArch . X64 } ) ;
2022-07-19 13:24:38 -04:00
// Add a way on the command line of forcing a project file with all architectures (there isn't a good way to let this be
// set and checked where we can access it).
bool ForceAllArchitectures = Environment . GetCommandLineArgs ( ) . Contains ( "AllArchitectures" , StringComparer . OrdinalIgnoreCase ) ;
if ( ForceAllArchitectures )
{
return AllArchitectures ;
}
string TargetName = Config . BuildTarget ;
// First time seeing this target?
if ( ! CachedMacProjectArcitectures . ContainsKey ( TargetName ) )
{
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
CachedMacProjectArcitectures [ TargetName ] = UnrealArchitectureConfig . ForPlatform ( UnrealTargetPlatform . Mac ) . ProjectSupportedArchitectures ( InProjectFile , TargetName ) ;
2022-07-19 13:24:38 -04:00
}
return CachedMacProjectArcitectures [ TargetName ] ;
}
private void AppendPlatformConfiguration ( StringBuilder Content , XcodeBuildConfig Config , string TargetName , FileReference ? ProjectFile , bool bSupportMac , bool bSupportIOS , bool bSupportTVOS , ILogger Logger , out string? IOSRunTimeVersion , out string? TVOSRunTimeVersion , string BinariesSubDir = "/Payload" )
{
FileReference MacExecutablePath = Config . MacExecutablePath ! ;
string UEDir = ConvertPath ( Path . GetFullPath ( Directory . GetCurrentDirectory ( ) + "../../.." ) ) ;
string MacExecutableDir = bSupportMac ? ConvertPath ( MacExecutablePath . Directory . FullName ) : "" ;
string MacExecutableFileName = bSupportMac ? MacExecutablePath . GetFileName ( ) : "" ;
// Get Mac architectures supported by this project
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
UnrealArchitectures SupportedMacArchitectures = GetSupportedMacArchitectures ( Config , ProjectFile ) ;
2022-07-19 13:24:38 -04:00
IOSRunTimeVersion = null ;
TVOSRunTimeVersion = null ;
2023-05-30 18:38:07 -04:00
bool bIsUnrealGame = TargetName . Equals ( "UnrealGame" , StringComparison . InvariantCultureIgnoreCase ) ;
bool bIsUnrealClient = TargetName . Equals ( "UnrealClient" , StringComparison . InvariantCultureIgnoreCase ) ;
DirectoryReference ? GameDir = ProjectFile ? . Directory ;
string? GamePath = GameDir ! = null ? ConvertPath ( GameDir . FullName ) : null ;
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
string? IOSRunTimeDevices = null ;
string? TVOSRunTimeDevices = null ;
string SupportedPlatforms = bSupportMac ? "macosx" : "" ;
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
bool bAutomaticSigning = false ;
string? UUID_IOS = "" ;
string? UUID_TVOS = "" ;
string? TEAM_IOS = "" ;
string? TEAM_TVOS = "" ;
string? IOS_CERT = "iPhone Developer" ;
string? TVOS_CERT = "iPhone Developer" ;
string IOS_BUNDLE = "" ;
string TVOS_BUNDLE = "" ;
if ( bSupportIOS & & InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . IOS , EProjectType . Code ) )
{
IOSPlatform IOSPlatform = ( ( IOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . IOS ) ) ;
IOSProjectSettings ProjectSettings = IOSPlatform . ReadProjectSettings ( ProjectFile ) ;
IOSProvisioningData ProvisioningData = IOSPlatform . ReadProvisioningData ( ProjectSettings , bForDistribution ) ;
IOSRunTimeVersion = ProjectSettings . RuntimeVersion ;
IOSRunTimeDevices = ProjectSettings . RuntimeDevices ;
SupportedPlatforms + = " iphoneos" ;
bAutomaticSigning = ProjectSettings . bAutomaticSigning ;
if ( ! bAutomaticSigning )
2022-09-15 23:54:29 -04:00
{
2023-05-30 18:38:07 -04:00
UUID_IOS = ProvisioningData . MobileProvisionUUID ;
IOS_CERT = ProvisioningData . SigningCertificate ;
2022-09-15 23:54:29 -04:00
}
2023-05-30 18:38:07 -04:00
TEAM_IOS = ProvisioningData . TeamUUID ;
IOS_BUNDLE = ProjectSettings . BundleIdentifier ;
}
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
if ( bSupportTVOS & & InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . TVOS , EProjectType . Code ) )
{
TVOSPlatform TVOSPlatform = ( ( TVOSPlatform ) UEBuildPlatform . GetBuildPlatform ( UnrealTargetPlatform . TVOS ) ) ;
TVOSProjectSettings ProjectSettings = TVOSPlatform . ReadProjectSettings ( ProjectFile ) ;
TVOSProvisioningData ProvisioningData = TVOSPlatform . ReadProvisioningData ( ProjectSettings , bForDistribution ) ;
TVOSRunTimeVersion = ProjectSettings . RuntimeVersion ;
TVOSRunTimeDevices = ProjectSettings . RuntimeDevices ;
SupportedPlatforms + = " appletvos" ;
if ( ! bAutomaticSigning )
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
UUID_TVOS = ProvisioningData . MobileProvisionUUID ;
TVOS_CERT = ProvisioningData . SigningCertificate ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
TEAM_TVOS = ProvisioningData . TeamUUID ;
TVOS_BUNDLE = ProjectSettings . BundleIdentifier ;
}
2022-07-19 13:24:38 -04:00
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\tSUPPORTED_PLATFORMS = \"" + SupportedPlatforms . Trim ( ) + "\";" + ProjectFileGenerator . NewLine ) ;
if ( bAutomaticSigning )
{
Content . Append ( "\t\t\t\tCODE_SIGN_STYLE = Automatic;" + ProjectFileGenerator . NewLine ) ;
}
if ( IOSRunTimeVersion ! = null )
{
2023-05-30 18:59:32 -04:00
Content . Append ( "\t\t\t\t\"VALID_ARCHS[sdk=iphoneos*]\" = \"" + String . Join ( " " , SupportedIOSArchitectures ) + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = " + IOSRunTimeVersion + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\"PRODUCT_NAME[sdk=iphoneos*]\" = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ; // @todo: change to Path.GetFileName(Config.IOSExecutablePath) when we stop using payload
Content . Append ( "\t\t\t\t\"TARGETED_DEVICE_FAMILY[sdk=iphoneos*]\" = \"" + IOSRunTimeDevices + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
if ( ! String . IsNullOrEmpty ( TEAM_IOS ) )
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"DEVELOPMENT_TEAM[sdk=iphoneos*]\" = " + TEAM_IOS + ";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"" + IOS_CERT + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
if ( ! bAutomaticSigning & & ! String . IsNullOrEmpty ( UUID_IOS ) )
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]\" = \"" + UUID_IOS + "\";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
if ( ProjectFile ! = null )
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=iphoneos*]\" = " + IOS_BUNDLE + ";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
}
if ( TVOSRunTimeVersion ! = null )
{
2023-05-30 18:59:32 -04:00
Content . Append ( "\t\t\t\t\"VALID_ARCHS[sdk=appletvos*]\" = \"" + String . Join ( " " , SupportedIOSArchitectures ) + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\tTVOS_DEPLOYMENT_TARGET = " + TVOSRunTimeVersion + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\"PRODUCT_NAME[sdk=appletvos*]\" = \"" + TargetName + "\";" + ProjectFileGenerator . NewLine ) ; // @todo: change to Path.GetFileName(Config.TVOSExecutablePath) when we stop using payload
Content . Append ( "\t\t\t\t\"TARGETED_DEVICE_FAMILY[sdk=appletvos*]\" = \"" + TVOSRunTimeDevices + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
if ( ! String . IsNullOrEmpty ( TEAM_TVOS ) )
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"DEVELOPMENT_TEAM[sdk=appletvos*]\" = " + TEAM_TVOS + ";" + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=appletvos*]\" = \"" + TVOS_CERT + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
if ( ! bAutomaticSigning & & ! String . IsNullOrEmpty ( UUID_TVOS ) )
2023-05-30 18:38:07 -04:00
{
Content . Append ( "\t\t\t\t\"PROVISIONING_PROFILE_SPECIFIER[sdk=appletvos*]\" = \"" + UUID_TVOS + "\";" + ProjectFileGenerator . NewLine ) ;
}
if ( ProjectFile ! = null )
{
Content . Append ( "\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=appletvos*]\" = " + TVOS_BUNDLE + ";" + ProjectFileGenerator . NewLine ) ;
}
}
if ( bSupportMac )
{
2023-05-30 18:59:32 -04:00
Content . Append ( "\t\t\t\t\"VALID_ARCHS[sdk=macosx*]\" = \"" + String . Join ( " " , SupportedMacArchitectures . Architectures . Select ( x = > x . AppleName ) ) + "\";" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"PRODUCT_NAME[sdk=macosx*]\" = \"" + MacExecutableFileName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\"CONFIGURATION_BUILD_DIR[sdk=macosx*]\" = \"" + MacExecutableDir + "\";" + ProjectFileGenerator . NewLine ) ;
2022-09-22 11:42:27 -04:00
2023-05-30 18:38:07 -04:00
// MacToolchain uses the IOS bundle identifier
ConfigHierarchy IOSIni = ConfigCache . ReadHierarchy ( ConfigHierarchyType . Engine , ProjectFile ? . Directory , UnrealTargetPlatform . IOS ) ;
string IOSBundleIdentifier ;
IOSIni . GetString ( "/Script/IOSRuntimeSettings.IOSRuntimeSettings" , "BundleIdentifier" , out IOSBundleIdentifier ! ) ;
2022-09-22 11:42:27 -04:00
2023-05-30 18:38:07 -04:00
// we are going to load/sign the UnrealEditor.app when doing modular editor builds, so reuse the shared identifier
bool bBuildingEditor = Config . ProjectTarget ! . TargetRules ! . Type = = TargetType . Editor & & Config . ProjectTarget ! . TargetRules ! . LinkType = = TargetLinkType . Modular ;
string MacBundleIdentifier = bBuildingEditor ? ( "com.epicgames.UnrealEditor" ) : ( IOSBundleIdentifier . Replace ( "[PROJECT_NAME]" , TargetName ) . Replace ( "_" , "" ) ) ;
// Xcode 14 wants this to match what is in the final plist
Content . Append ( "\t\t\t\t\"PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*]\" = " + MacBundleIdentifier + ";" + ProjectFileGenerator . NewLine ) ;
}
2022-09-22 11:42:27 -04:00
2023-05-30 18:38:07 -04:00
if ( IOSRunTimeVersion ! = null )
{
Content . Append ( "\t\t\t\t\"CONFIGURATION_BUILD_DIR[sdk=iphoneos*]\" = \"" + Config . IOSExecutablePath ! . Directory ! . FullName + BinariesSubDir + "\";" + ProjectFileGenerator . NewLine ) ;
}
if ( TVOSRunTimeVersion ! = null )
{
Content . Append ( "\t\t\t\t\"CONFIGURATION_BUILD_DIR[sdk=appletvos*]\" = \"" + Config . TVOSExecutablePath ! . Directory ! . FullName + BinariesSubDir + "\";" + ProjectFileGenerator . NewLine ) ;
}
2022-07-19 13:24:38 -04:00
}
private void AppendNativeTargetBuildConfiguration ( StringBuilder Content , XcodeBuildConfig Config , string ConfigGuid , FileReference ? ProjectFile , ILogger Logger )
{
bool bMacOnly = true ;
2023-01-18 13:36:29 -05:00
if ( Config . ProjectTarget ! . TargetRules ! = null )
2022-07-19 13:24:38 -04:00
{
2023-01-18 13:36:29 -05:00
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . IOS ) & & Config . ProjectTarget . SupportedPlatforms . Contains ( UnrealTargetPlatform . IOS ) )
{
bMacOnly = false ;
}
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . TVOS ) & & Config . ProjectTarget . SupportedPlatforms . Contains ( UnrealTargetPlatform . TVOS ) )
2022-07-19 13:24:38 -04:00
{
bMacOnly = false ;
}
}
Content . Append ( "\t\t" + ConfigGuid + " /* \"" + Config . DisplayName + "\" */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = XCBuildConfiguration;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildSettings = {" + ProjectFileGenerator . NewLine ) ;
string UEDir = ConvertPath ( Path . GetFullPath ( Directory . GetCurrentDirectory ( ) + "../../.." ) ) ;
//string MacExecutableDir = ConvertPath(Config.MacExecutablePath.Directory.FullName);
string MacExecutableFileName = Config . MacExecutablePath ! . GetFileName ( ) ;
string? IOSRunTimeVersion , TVOSRunTimeVersion ;
AppendPlatformConfiguration ( Content , Config , Config . BuildTarget , ProjectFile , true , ! bMacOnly , ! bMacOnly , Logger , out IOSRunTimeVersion , out TVOSRunTimeVersion ) ;
2023-05-30 18:38:07 -04:00
bool bIsUnrealGame = Config . BuildTarget . Equals ( "UnrealGame" , StringComparison . InvariantCultureIgnoreCase ) ;
bool bIsUnrealClient = Config . BuildTarget . Equals ( "UnrealClient" , StringComparison . InvariantCultureIgnoreCase ) ;
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
DirectoryReference ? GameDir = ProjectFile ? . Directory ;
string? GamePath = GameDir ! = null ? ConvertPath ( GameDir . FullName ) : null ;
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
string IOSInfoPlistPath ;
string TVOSInfoPlistPath ;
string MacInfoPlistPath ;
string? IOSEntitlementPath = null ;
string? TVOSEntitlementPath = null ;
if ( bIsUnrealGame )
{
IOSInfoPlistPath = UEDir + "/Engine/Intermediate/IOS/" + Config . BuildTarget + "-Info.plist" ;
TVOSInfoPlistPath = UEDir + "/Engine/Intermediate/TVOS/" + Config . BuildTarget + "-Info.plist" ;
MacInfoPlistPath = UEDir + "/Engine/Intermediate/Mac/" + MacExecutableFileName + "-Info.plist" ;
IOSEntitlementPath = "" ;
TVOSEntitlementPath = "" ;
}
else if ( bIsUnrealClient )
{
IOSInfoPlistPath = UEDir + "/Engine/Intermediate/IOS/UnrealGame-Info.plist" ;
TVOSInfoPlistPath = UEDir + "/Engine/Intermediate/TVOS/UnrealGame-Info.plist" ;
MacInfoPlistPath = UEDir + "/Engine/Intermediate/Mac/" + MacExecutableFileName + "-Info.plist" ;
IOSEntitlementPath = "" ;
TVOSEntitlementPath = "" ;
}
else if ( ProjectFile ! = null )
{
IOSInfoPlistPath = GamePath + "/Intermediate/IOS/" + Config . BuildTarget + "-Info.plist" ;
TVOSInfoPlistPath = GamePath + "/Intermediate/TVOS/" + Config . BuildTarget + "-Info.plist" ;
MacInfoPlistPath = GamePath + "/Intermediate/Mac/" + MacExecutableFileName + "-Info.plist" ;
IOSEntitlementPath = GamePath + "/Intermediate/IOS/" + Config . BuildTarget + ".entitlements" ;
TVOSEntitlementPath = GamePath + "/Intermediate/TVOS/" + Config . BuildTarget + ".entitlements" ;
}
else
{
if ( GamePath = = null )
2022-07-19 13:24:38 -04:00
{
IOSInfoPlistPath = UEDir + "/Engine/Intermediate/IOS/" + Config . BuildTarget + "-Info.plist" ;
TVOSInfoPlistPath = UEDir + "/Engine/Intermediate/TVOS/" + Config . BuildTarget + "-Info.plist" ;
MacInfoPlistPath = UEDir + "/Engine/Intermediate/Mac/" + MacExecutableFileName + "-Info.plist" ;
}
2023-05-30 18:38:07 -04:00
else
2022-07-19 13:24:38 -04:00
{
IOSInfoPlistPath = GamePath + "/Intermediate/IOS/" + Config . BuildTarget + "-Info.plist" ;
TVOSInfoPlistPath = GamePath + "/Intermediate/TVOS/" + Config . BuildTarget + "-Info.plist" ;
MacInfoPlistPath = GamePath + "/Intermediate/Mac/" + MacExecutableFileName + "-Info.plist" ;
}
2023-05-30 18:38:07 -04:00
}
2022-09-22 11:42:27 -04:00
2023-05-30 18:38:07 -04:00
if ( XcodeProjectFileGenerator . bGenerateRunOnlyProject )
{
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . IOS ) )
2022-09-22 11:42:27 -04:00
{
Content . Append ( "\t\t\t\tINFOPLIST_FILE = \"" + IOSInfoPlistPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"" + IOSEntitlementPath + "\";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
else
2022-07-19 13:24:38 -04:00
{
2022-09-22 11:42:27 -04:00
Content . Append ( "\t\t\t\tINFOPLIST_FILE = \"" + TVOSInfoPlistPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tCODE_SIGN_ENTITLEMENTS = \"" + TVOSEntitlementPath + "\";" + ProjectFileGenerator . NewLine ) ;
}
2023-05-30 18:38:07 -04:00
}
else
{
Content . Append ( "\t\t\t\t\"INFOPLIST_FILE[sdk=macosx*]\" = \"" + MacInfoPlistPath + "\";" + ProjectFileGenerator . NewLine ) ;
if ( IOSRunTimeVersion ! = null )
2022-09-22 11:42:27 -04:00
{
2023-05-30 18:38:07 -04:00
Content . Append ( "\t\t\t\t\"INFOPLIST_FILE[sdk=iphoneos*]\" = \"" + IOSInfoPlistPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]\" = \"" + IOSEntitlementPath + "\";" + ProjectFileGenerator . NewLine ) ;
2022-09-22 11:42:27 -04:00
}
2023-05-30 18:38:07 -04:00
if ( TVOSRunTimeVersion ! = null )
{
Content . Append ( "\t\t\t\t\"INFOPLIST_FILE[sdk=appletvos*]\" = \"" + TVOSInfoPlistPath + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\t\"CODE_SIGN_ENTITLEMENTS[sdk=appletvos*]\" = \"" + TVOSEntitlementPath + "\";" + ProjectFileGenerator . NewLine ) ;
}
}
2022-09-15 23:54:29 -04:00
2023-05-30 18:38:07 -04:00
// Prepare a temp Info.plist file so Xcode has some basic info about the target immediately after opening the project.
// This is needed for the target to pass the settings validation before code signing. UBT will overwrite this plist file later, with proper contents.
if ( BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Mac )
{
bool bCreateMacInfoPlist = ! File . Exists ( MacInfoPlistPath ) ;
bool bCreateIOSInfoPlist = ! File . Exists ( IOSInfoPlistPath ) & & IOSRunTimeVersion ! = null ;
bool bCreateTVOSInfoPlist = ! File . Exists ( TVOSInfoPlistPath ) & & TVOSRunTimeVersion ! = null ;
if ( bCreateMacInfoPlist | | bCreateIOSInfoPlist | | bCreateTVOSInfoPlist )
2022-09-22 11:42:27 -04:00
{
2023-05-30 18:38:07 -04:00
DirectoryReference ? ProjectPath = GameDir ;
DirectoryReference EngineDir = DirectoryReference . Combine ( new DirectoryReference ( UEDir ) , "Engine" ) ;
string GameName = Config . BuildTarget ;
bool bIsClient = false ;
if ( ProjectPath = = null )
2022-09-15 23:54:29 -04:00
{
2023-05-30 18:38:07 -04:00
ProjectPath = EngineDir ;
}
if ( bIsUnrealGame )
{
ProjectPath = EngineDir ;
GameName = "UnrealGame" ;
bIsClient = ( AppName = = "UnrealClient" ) ;
}
if ( bCreateMacInfoPlist )
{
Directory . CreateDirectory ( Path . GetDirectoryName ( MacInfoPlistPath ) ! ) ;
2024-02-20 13:42:11 -05:00
UEDeployMac . GeneratePList ( ProjectPath . FullName , bIsUnrealGame , GameName , Config . BuildTarget , EngineDir . FullName , MacExecutableFileName , Config . ProjectTarget ! . TargetRules ! . Type ) ;
2023-05-30 18:38:07 -04:00
}
if ( bCreateIOSInfoPlist )
{
// get the receipt
FileReference ReceiptFilename ;
UnrealArchitectures Architectures = UnrealArchitectureConfig . ForPlatform ( UnrealTargetPlatform . IOS ) . ActiveArchitectures ( ProjectFile , GameName ) ;
2022-07-19 13:24:38 -04:00
if ( bIsUnrealGame )
{
2023-05-30 18:38:07 -04:00
ReceiptFilename = TargetReceipt . GetDefaultPath ( Unreal . EngineDirectory , "UnrealGame" , UnrealTargetPlatform . IOS , Config . BuildConfig , Architectures ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
else
2022-07-19 13:24:38 -04:00
{
2023-05-30 18:38:07 -04:00
ReceiptFilename = TargetReceipt . GetDefaultPath ( ProjectPath , GameName , UnrealTargetPlatform . IOS , Config . BuildConfig , Architectures ) ;
2022-07-19 13:24:38 -04:00
}
2023-05-30 18:38:07 -04:00
Directory . CreateDirectory ( Path . GetDirectoryName ( IOSInfoPlistPath ) ! ) ;
TargetReceipt ? Receipt ;
TargetReceipt . TryRead ( ReceiptFilename , out Receipt ) ;
bool bBuildAsFramework = UEDeployIOS . GetCompileAsDll ( Receipt ) ;
UEDeployIOS . GenerateIOSPList ( ProjectFile , Config . BuildConfig , ProjectPath . FullName , bIsUnrealGame , GameName , bIsClient , Config . BuildTarget , EngineDir . FullName , ProjectPath + "/Binaries/IOS/Payload" , null , BundleIdentifier , bBuildAsFramework , Logger ) ;
}
if ( bCreateTVOSInfoPlist )
{
Directory . CreateDirectory ( Path . GetDirectoryName ( TVOSInfoPlistPath ) ! ) ;
UEDeployTVOS . GenerateTVOSPList ( ProjectPath . FullName , bIsUnrealGame , GameName , bIsClient , Config . BuildTarget , EngineDir . FullName , ProjectPath + "/Binaries/TVOS/Payload" , null , BundleIdentifier , Logger ) ;
2022-07-19 13:24:38 -04:00
}
}
2023-05-30 18:38:07 -04:00
}
2022-07-19 13:24:38 -04:00
// #jira UE-143619: Pre Monterey macOS requires this option for a packaged app to run on iOS15 due to new code signature format. Could be removed once Monterey is minimum OS.
2022-10-06 20:10:51 -04:00
Content . Append ( "\t\t\t\tOTHER_CODE_SIGN_FLAGS = \"--generate-entitlement-der --deep\";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
2024-02-20 13:42:11 -05:00
Content . Append ( "\t\t\t\tMACOSX_DEPLOYMENT_TARGET = " + MacToolChain . Settings . MinMacDeploymentVersion ( Config . ProjectTarget ! . TargetRules ! . Type ) + ";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t\tINFOPLIST_OUTPUT_FORMAT = xml;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tCOMBINE_HIDPI_IMAGES = YES;" + ProjectFileGenerator . NewLine ) ;
//#jira UE-50382 Xcode Address Sanitizer feature does not work on iOS
// address sanitizer dylib loader depends on the SDKROOT parameter. For macosx or default (missing, translated as macosx), the path is incorrect for iphone/appletv
2022-09-22 11:42:27 -04:00
if ( XcodeProjectFileGenerator . bGenerateRunOnlyProject )
{
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . IOS ) )
2023-05-30 18:38:07 -04:00
{
Content . Append ( "\t\t\t\tSDKROOT = iphoneos;" + ProjectFileGenerator . NewLine ) ;
}
2022-09-22 11:42:27 -04:00
else
2023-05-30 18:38:07 -04:00
{
Content . Append ( "\t\t\t\tSDKROOT = appletvos;" + ProjectFileGenerator . NewLine ) ;
}
2022-09-22 11:42:27 -04:00
}
2022-07-19 13:24:38 -04:00
else
{
Content . Append ( "\t\t\t\tSDKROOT = macosx;" + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\tGCC_PRECOMPILE_PREFIX_HEADER = YES;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tGCC_PREFIX_HEADER = \"" + UEDir + "/Engine/Source/Editor/UnrealEd/Public/UnrealEd.h\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + Config . DisplayName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
}
private void AppendLegacyTargetBuildConfiguration ( StringBuilder Content , XcodeBuildConfig Config , string ConfigGuid , FileReference ? ProjectFile )
{
bool bMacOnly = true ;
2023-01-18 13:36:29 -05:00
if ( Config . ProjectTarget ! . TargetRules ! = null )
2022-07-19 13:24:38 -04:00
{
2023-01-18 13:36:29 -05:00
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . IOS ) & & Config . ProjectTarget . SupportedPlatforms . Contains ( UnrealTargetPlatform . IOS ) )
{
bMacOnly = false ;
}
if ( XcodeProjectFileGenerator . XcodePlatforms . Contains ( UnrealTargetPlatform . TVOS ) & & Config . ProjectTarget . SupportedPlatforms . Contains ( UnrealTargetPlatform . TVOS ) )
2022-07-19 13:24:38 -04:00
{
bMacOnly = false ;
}
}
// Get Mac architectures supported by this project
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
UnrealArchitectures SupportedMacArchitectures = GetSupportedMacArchitectures ( Config , ProjectFilePath ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t" + ConfigGuid + " /* \"" + Config . DisplayName + "\" */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = XCBuildConfiguration;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildSettings = {" + ProjectFileGenerator . NewLine ) ;
if ( bMacOnly )
{
2023-05-30 18:59:32 -04:00
Content . Append ( "\t\t\t\tVALID_ARCHS = \"" + String . Join ( " " , SupportedMacArchitectures . Architectures . Select ( x = > x . AppleName ) ) + "\";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t\tSUPPORTED_PLATFORMS = \"macosx\";" + ProjectFileGenerator . NewLine ) ;
}
else
{
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
IEnumerable < UnrealArch > ValidArchs = SupportedMacArchitectures . Architectures ;
2022-07-19 13:24:38 -04:00
string SupportedPlatforms = "macosx" ;
if ( InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . IOS , EProjectType . Code ) )
{
2023-05-30 18:59:32 -04:00
ValidArchs = ValidArchs . Union ( SupportedIOSArchitectures ) ;
2022-07-19 13:24:38 -04:00
SupportedPlatforms + = " iphoneos" ;
}
if ( InstalledPlatformInfo . IsValidPlatform ( UnrealTargetPlatform . TVOS , EProjectType . Code ) )
{
2023-05-30 18:59:32 -04:00
ValidArchs = ValidArchs . Union ( SupportedIOSArchitectures ) ;
2022-07-19 13:24:38 -04:00
SupportedPlatforms + = " appletvos" ;
}
2023-05-30 18:59:32 -04:00
Content . Append ( "\t\t\t\tVALID_ARCHS = \"" + String . Join ( " " , ValidArchs . Select ( x = > x . AppleName ) ) + "\";" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( "\t\t\t\tSUPPORTED_PLATFORMS = \"" + SupportedPlatforms + "\";" + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = ();" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tHEADER_SEARCH_PATHS = ();" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tUSER_HEADER_SEARCH_PATHS = ();" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tUE_BUILD_TARGET_NAME = \"" + Config . BuildTarget + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t\tUE_BUILD_TARGET_CONFIG = \"" + Config . BuildConfig + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t};" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tname = \"" + Config . DisplayName + "\";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
}
private void AppendXCBuildConfigurationSection ( StringBuilder Content , Dictionary < string , XcodeBuildConfig > ProjectBuildConfigs , Dictionary < string , XcodeBuildConfig > TargetBuildConfigs ,
Dictionary < string , XcodeBuildConfig > BuildTargetBuildConfigs , Dictionary < string , XcodeBuildConfig > IndexTargetBuildConfigs , FileReference ? GameProjectPath ,
List < XcodeExtensionInfo > AllExtensions , ILogger Logger )
{
Content . Append ( "/* Begin XCBuildConfiguration section */" + ProjectFileGenerator . NewLine ) ;
foreach ( KeyValuePair < string , XcodeBuildConfig > Config in ProjectBuildConfigs )
{
AppendProjectBuildConfiguration ( Content , Config . Value . DisplayName , Config . Key ) ;
}
foreach ( KeyValuePair < string , XcodeBuildConfig > Config in TargetBuildConfigs )
{
AppendNativeTargetBuildConfiguration ( Content , Config . Value , Config . Key , GameProjectPath , Logger ) ;
}
foreach ( KeyValuePair < string , XcodeBuildConfig > Config in BuildTargetBuildConfigs )
{
AppendLegacyTargetBuildConfiguration ( Content , Config . Value , Config . Key , GameProjectPath ) ;
}
foreach ( KeyValuePair < string , XcodeBuildConfig > Config in IndexTargetBuildConfigs )
{
AppendNativeTargetBuildConfiguration ( Content , Config . Value , Config . Key , GameProjectPath , Logger ) ;
}
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
Content . Append ( EI . ConfigurationContents ) ;
}
Content . Append ( "/* End XCBuildConfiguration section */" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
}
private void AppendXCConfigurationList ( StringBuilder Content , string TypeName , string TargetName , string ConfigListGuid , Dictionary < string , XcodeBuildConfig > BuildConfigs , string Default = "Development" )
{
Content . Append ( "\t\t" + ConfigListGuid + " /* Build configuration list for " + TypeName + " \"" + TargetName + "\" */ = {" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tisa = XCConfigurationList;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tbuildConfigurations = (" + ProjectFileGenerator . NewLine ) ;
foreach ( KeyValuePair < string , XcodeBuildConfig > Config in BuildConfigs )
{
Content . Append ( "\t\t\t\t" + Config . Key + " /* \"" + Config . Value . DisplayName + "\" */," + ProjectFileGenerator . NewLine ) ;
}
Content . Append ( "\t\t\t);" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdefaultConfigurationIsVisible = 0;" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\tdefaultConfigurationName = " + Default + ";" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t};" + ProjectFileGenerator . NewLine ) ;
}
private void AppendXCConfigurationListSection ( StringBuilder Content , string TargetName , string BuildTargetName , string IndexTargetName , string ProjectConfigListGuid ,
Dictionary < string , XcodeBuildConfig > ProjectBuildConfigs , string TargetConfigListGuid , Dictionary < string , XcodeBuildConfig > TargetBuildConfigs ,
string BuildTargetConfigListGuid , Dictionary < string , XcodeBuildConfig > BuildTargetBuildConfigs ,
string IndexTargetConfigListGuid , Dictionary < string , XcodeBuildConfig > IndexTargetBuildConfigs ,
List < XcodeExtensionInfo > AllExtensions )
{
Content . Append ( "/* Begin XCConfigurationList section */" + ProjectFileGenerator . NewLine ) ;
AppendXCConfigurationList ( Content , "PBXProject" , TargetName , ProjectConfigListGuid , ProjectBuildConfigs ) ;
AppendXCConfigurationList ( Content , "PBXLegacyTarget" , BuildTargetName , BuildTargetConfigListGuid , BuildTargetBuildConfigs ) ;
AppendXCConfigurationList ( Content , "PBXNativeTarget" , TargetName , TargetConfigListGuid , TargetBuildConfigs ) ;
AppendXCConfigurationList ( Content , "PBXNativeTarget" , IndexTargetName , IndexTargetConfigListGuid , IndexTargetBuildConfigs ) ;
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
AppendXCConfigurationList ( Content , "PBXNativeTarget" , EI . Name , EI . ConfigListGuid , EI . AllConfigs ) ;
}
Content . Append ( "/* End XCConfigurationList section */" + ProjectFileGenerator . NewLine ) ;
}
private List < XcodeBuildConfig > GetSupportedBuildConfigs ( List < UnrealTargetPlatform > Platforms , List < UnrealTargetConfiguration > Configurations , ILogger Logger )
{
List < XcodeBuildConfig > BuildConfigs = new List < XcodeBuildConfig > ( ) ;
//string ProjectName = ProjectFilePath.GetFileNameWithoutExtension();
foreach ( UnrealTargetConfiguration Configuration in Configurations )
{
if ( InstalledPlatformInfo . IsValidConfiguration ( Configuration , EProjectType . Code ) )
{
foreach ( UnrealTargetPlatform Platform in Platforms )
{
if ( InstalledPlatformInfo . IsValidPlatform ( Platform , EProjectType . Code ) & & ( Platform = = UnrealTargetPlatform . Mac | | Platform = = UnrealTargetPlatform . IOS | | Platform = = UnrealTargetPlatform . TVOS ) ) // @todo support other platforms
{
UEBuildPlatform ? BuildPlatform ;
if ( UEBuildPlatform . TryGetBuildPlatform ( Platform , out BuildPlatform ) & & ( BuildPlatform . HasRequiredSDKsInstalled ( ) = = SDKStatus . Valid ) )
{
// Check we have targets (Expected to be no Engine targets when generating for a single .uproject)
if ( ProjectTargets . Count = = 0 & & BaseDir ! = Unreal . EngineDirectory )
{
throw new BuildException ( "Expecting at least one ProjectTarget to be associated with project '{0}' in the TargetProjects list " , ProjectFilePath ) ;
}
// Now go through all of the target types for this project
foreach ( ProjectTarget ProjectTarget in ProjectTargets . OfType < ProjectTarget > ( ) )
{
if ( MSBuildProjectFile . IsValidProjectPlatformAndConfiguration ( ProjectTarget , Platform , Configuration , Logger ) )
{
// Figure out if this is a monolithic build
bool bShouldCompileMonolithic = BuildPlatform . ShouldCompileMonolithicBinary ( Platform ) ;
2023-05-17 16:22:48 -04:00
try
{
bShouldCompileMonolithic | = ( ProjectTarget . CreateRulesDelegate ( Platform , Configuration ) . LinkType = = TargetLinkType . Monolithic ) ;
}
catch ( BuildException )
{
}
2022-07-19 13:24:38 -04:00
string ConfigName = Configuration . ToString ( ) ;
2023-02-17 12:53:28 -05:00
if ( ! bMakeProjectPerTarget & & ProjectTarget . TargetRules ! . Type ! = TargetType . Game & & ProjectTarget . TargetRules . Type ! = TargetType . Program )
2022-07-19 13:24:38 -04:00
{
ConfigName + = " " + ProjectTarget . TargetRules . Type . ToString ( ) ;
}
if ( BuildConfigs . Where ( Config = > Config . DisplayName = = ConfigName ) . ToList ( ) . Count = = 0 )
{
string TargetName = ProjectTarget . TargetFilePath . GetFileNameWithoutAnyExtensions ( ) ;
2022-12-12 17:46:48 -05:00
// Get the .uproject directory
DirectoryReference ? UProjectDirectory = DirectoryReference . FromFile ( ProjectTarget . UnrealProjectFilePath ) ;
2022-07-19 13:24:38 -04:00
// Get the output directory
2022-12-12 17:46:48 -05:00
DirectoryReference RootDirectory ;
if ( UProjectDirectory ! = null & &
2023-02-17 12:53:28 -05:00
( bShouldCompileMonolithic | | ProjectTarget . TargetRules ! . BuildEnvironment = = TargetBuildEnvironment . Unique ) & &
ProjectTarget . TargetRules ! . File ! . IsUnderDirectory ( UProjectDirectory ) )
2022-07-19 13:24:38 -04:00
{
2022-12-12 17:46:48 -05:00
RootDirectory = UEBuildTarget . GetOutputDirectoryForExecutable ( UProjectDirectory , ProjectTarget . TargetRules . File ! ) ;
2022-07-19 13:24:38 -04:00
}
2022-12-12 17:46:48 -05:00
else
2022-07-19 13:24:38 -04:00
{
2023-02-17 12:53:28 -05:00
RootDirectory = UEBuildTarget . GetOutputDirectoryForExecutable ( Unreal . EngineDirectory , ProjectTarget . TargetRules ! . File ! ) ;
2022-07-19 13:24:38 -04:00
}
string ExeName = TargetName ;
if ( ! bShouldCompileMonolithic & & ProjectTarget . TargetRules . Type ! = TargetType . Program )
{
// Figure out what the compiled binary will be called so that we can point the IDE to the correct file
if ( ProjectTarget . TargetRules . Type ! = TargetType . Game )
{
// Only if shared - unique retains the Target Name
if ( ProjectTarget . TargetRules . BuildEnvironment = = TargetBuildEnvironment . Shared )
{
ExeName = "Unreal" + ProjectTarget . TargetRules . Type . ToString ( ) ;
}
}
}
2022-12-12 17:46:48 -05:00
// Get the output directory
DirectoryReference OutputDirectory = DirectoryReference . Combine ( RootDirectory , "Binaries" ) ;
DirectoryReference MacBinaryDir = DirectoryReference . Combine ( OutputDirectory , "Mac" ) ;
DirectoryReference IOSBinaryDir = DirectoryReference . Combine ( OutputDirectory , "IOS" ) ;
DirectoryReference TVOSBinaryDir = DirectoryReference . Combine ( OutputDirectory , "TVOS" ) ;
2023-05-30 18:59:32 -04:00
if ( ! String . IsNullOrEmpty ( ProjectTarget . TargetRules . ExeBinariesSubFolder ) )
2022-12-12 17:46:48 -05:00
{
MacBinaryDir = DirectoryReference . Combine ( MacBinaryDir , ProjectTarget . TargetRules . ExeBinariesSubFolder ) ;
IOSBinaryDir = DirectoryReference . Combine ( IOSBinaryDir , ProjectTarget . TargetRules . ExeBinariesSubFolder ) ;
TVOSBinaryDir = DirectoryReference . Combine ( TVOSBinaryDir , ProjectTarget . TargetRules . ExeBinariesSubFolder ) ;
}
2022-07-19 13:24:38 -04:00
if ( BuildPlatform . Platform = = UnrealTargetPlatform . Mac )
{
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
string MacExecutableName = MakeExecutableFileName ( ExeName , UnrealTargetPlatform . Mac , Configuration , ProjectTarget . TargetRules . Architectures , ProjectTarget . TargetRules . UndecoratedConfiguration ) ;
2022-07-19 13:24:38 -04:00
string IOSExecutableName = MacExecutableName . Replace ( "-Mac-" , "-IOS-" ) ;
string TVOSExecutableName = MacExecutableName . Replace ( "-Mac-" , "-TVOS-" ) ;
2022-12-12 17:46:48 -05:00
BuildConfigs . Add ( new XcodeBuildConfig ( ConfigName , TargetName , FileReference . Combine ( MacBinaryDir , MacExecutableName ) , FileReference . Combine ( IOSBinaryDir , IOSExecutableName ) , FileReference . Combine ( TVOSBinaryDir , TVOSExecutableName ) , ProjectTarget , Configuration ) ) ;
2022-07-19 13:24:38 -04:00
}
else if ( BuildPlatform . Platform = = UnrealTargetPlatform . IOS | | BuildPlatform . Platform = = UnrealTargetPlatform . TVOS )
{
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
string IOSExecutableName = MakeExecutableFileName ( ExeName , UnrealTargetPlatform . IOS , Configuration , ProjectTarget . TargetRules . Architectures , ProjectTarget . TargetRules . UndecoratedConfiguration ) ;
2022-07-19 13:24:38 -04:00
string TVOSExecutableName = IOSExecutableName . Replace ( "-IOS-" , "-TVOS-" ) ;
//string MacExecutableName = IOSExecutableName.Replace("-IOS-", "-Mac-");
2022-12-12 17:46:48 -05:00
BuildConfigs . Add ( new XcodeBuildConfig ( ConfigName , TargetName , FileReference . Combine ( MacBinaryDir , IOSExecutableName ) , FileReference . Combine ( IOSBinaryDir , IOSExecutableName ) , FileReference . Combine ( TVOSBinaryDir , TVOSExecutableName ) , ProjectTarget , Configuration ) ) ;
2022-07-19 13:24:38 -04:00
}
}
}
}
}
}
}
}
}
return BuildConfigs ;
}
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
private static string MakeExecutableFileName ( string BinaryName , UnrealTargetPlatform Platform , UnrealTargetConfiguration Configuration , UnrealArchitectures Architectures , UnrealTargetConfiguration UndecoratedConfiguration )
2022-07-19 13:24:38 -04:00
{
StringBuilder Result = new StringBuilder ( ) ;
Result . Append ( BinaryName ) ;
if ( Configuration ! = UndecoratedConfiguration )
{
Result . AppendFormat ( "-{0}-{1}" , Platform . ToString ( ) , Configuration . ToString ( ) ) ;
}
UEBuildPlatform BuildPlatform = UEBuildPlatform . GetBuildPlatform ( Platform ) ;
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
if ( UnrealArchitectureConfig . ForPlatform ( Platform ) . RequiresArchitectureFilenames ( Architectures ) )
2022-07-19 13:24:38 -04:00
{
UnrealArch/UnrealArchitectures changes
- Creates the UnrealArchitectures class, which wraps a list of UnrealArch objects
- UnrealArch is a single architecture, expandable enum-like struct
- There is no more concept of "no/default architecture", there is always a valid active architecture when building
- Most uses of "string Architecture" are replaced with one of the two above, depending if multiple architectures are supported or not
- UnrealArch has some platform-extensions for platform-specific naming (like Linux adds in LinuxName that turns, for instance, Arm64 -> aarch64-unknown-linux-gnueabi, which is used in folder names, etc)
- UnrealArch has bIsX64 which can be used determine intel instruction set (as opposed to arm)
- TargetRules class has an "Architecture" accessor that will return a single architecture if the active architectures is a single architecture, or throw an exception if multiple. This is useful in a majority of the cases where a paltform can only have a single architecture active in TargetRules (microsoft platforms, for instance, will create separate targets when compiling multiple architectures at once)
- Added UnrealArchitectureConfig class, which contains all the architecture information for a platform (what architectures are supported, what ones are currently active for given project, etc)
#preflight 63c81fb5b065224750a1759e
#rb mike.fricker,roman.dzieciol,joe.kirchoff,dmytro.vovk,brandon.schaefer [various parts]
#p4v-preflight-copy 23562471
[CL 23829977 by josh adams in ue5-main branch]
2023-01-24 09:30:28 -05:00
Result . Append ( Architectures . ToString ( ) ) ;
2022-07-19 13:24:38 -04:00
}
return Result . ToString ( ) ;
}
private FileReference GetUserSchemeManagementFilePath ( )
{
return new FileReference ( ProjectFilePath . FullName + "/xcuserdata/" + Environment . UserName + ".xcuserdatad/xcschemes/xcschememanagement.plist" ) ;
}
private DirectoryReference GetProjectSchemeDirectory ( )
{
return new DirectoryReference ( ProjectFilePath . FullName + "/xcshareddata/xcschemes" ) ;
}
private FileReference GetProjectSchemeFilePathForTarget ( string TargetName )
{
return FileReference . Combine ( GetProjectSchemeDirectory ( ) , TargetName + ".xcscheme" ) ;
}
private void WriteSchemeFile ( string TargetName , string TargetGuid , string BuildTargetGuid , string IndexTargetGuid , bool bHasEditorConfiguration , string GameProjectPath )
{
FileReference SchemeFilePath = GetProjectSchemeFilePathForTarget ( TargetName ) ;
DirectoryReference . CreateDirectory ( SchemeFilePath . Directory ) ;
string? OldCommandLineArguments = null ;
if ( FileReference . Exists ( SchemeFilePath ) )
{
string OldContents = File . ReadAllText ( SchemeFilePath . FullName ) ;
int OldCommandLineArgumentsStart = OldContents . IndexOf ( "<CommandLineArguments>" ) + "<CommandLineArguments>" . Length ;
int OldCommandLineArgumentsEnd = OldContents . IndexOf ( "</CommandLineArguments>" ) ;
if ( OldCommandLineArgumentsStart ! = - 1 & & OldCommandLineArgumentsEnd ! = - 1 )
{
OldCommandLineArguments = OldContents . Substring ( OldCommandLineArgumentsStart , OldCommandLineArgumentsEnd - OldCommandLineArgumentsStart ) ;
}
}
2023-02-17 15:55:46 -05:00
string DefaultConfiguration = bMakeProjectPerTarget & & bHasEditorConfiguration & & ! XcodeProjectFileGenerator . bGenerateRunOnlyProject ? "Development Editor" : "Development" ;
2022-07-19 13:24:38 -04:00
StringBuilder Content = new StringBuilder ( ) ;
Content . Append ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "<Scheme" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " LastUpgradeVersion = \"2000\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " version = \"1.3\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " parallelizeBuildables = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildImplicitDependencies = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildActionEntries>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildActionEntry" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildForTesting = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildForRunning = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildForProfiling = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildForArchiving = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildForAnalyzing = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildableReference" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableIdentifier = \"primary\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintIdentifier = \"" + TargetGuid + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableName = \"" + TargetName + ".app\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintName = \"" + TargetName + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " ReferencedContainer = \"container:" + TargetName + ".xcodeproj\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableReference>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildActionEntry>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildActionEntries>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <TestAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildConfiguration = \"" + DefaultConfiguration + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " shouldUseLaunchSchemeArgsEnv = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <Testables>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </Testables>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <MacroExpansion>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildableReference" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableIdentifier = \"primary\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintIdentifier = \"" + TargetGuid + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableName = \"" + TargetName + ".app\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintName = \"" + TargetName + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " ReferencedContainer = \"container:" + TargetName + ".xcodeproj\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableReference>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </MacroExpansion>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <AdditionalOptions>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </AdditionalOptions>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </TestAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <LaunchAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildConfiguration = \"" + DefaultConfiguration + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " launchStyle = \"0\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " useCustomWorkingDirectory = \"NO\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " ignoresPersistentStateOnLaunch = \"NO\"" + ProjectFileGenerator . NewLine ) ;
2022-09-16 10:30:38 -04:00
Content . Append ( " debugDocumentVersioning = \"NO\"" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( " debugServiceExtension = \"internal\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " allowLocationSimulation = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildableProductRunnable" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " runnableDebuggingMode = \"0\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildableReference" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableIdentifier = \"primary\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintIdentifier = \"" + TargetGuid + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableName = \"" + TargetName + ".app\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintName = \"" + TargetName + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " ReferencedContainer = \"container:" + TargetName + ".xcodeproj\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableReference>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableProductRunnable>" + ProjectFileGenerator . NewLine ) ;
2023-05-30 18:59:32 -04:00
if ( String . IsNullOrEmpty ( OldCommandLineArguments ) )
2022-07-19 13:24:38 -04:00
{
2023-05-31 13:37:21 -04:00
if ( bHasEditorConfiguration & & ! String . IsNullOrEmpty ( GameProjectPath ) )
2022-07-19 13:24:38 -04:00
{
Content . Append ( " <CommandLineArguments>" + ProjectFileGenerator . NewLine ) ;
if ( IsForeignProject )
{
Content . Append ( " <CommandLineArgument" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " argument = \""" + GameProjectPath + ""\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " isEnabled = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </CommandLineArgument>" + ProjectFileGenerator . NewLine ) ;
}
else
{
Content . Append ( " <CommandLineArgument" + ProjectFileGenerator . NewLine ) ;
2023-02-20 16:31:09 -05:00
Content . Append ( " argument = \"" + Path . GetFileNameWithoutExtension ( GameProjectPath ) + "\"" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( " isEnabled = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </CommandLineArgument>" + ProjectFileGenerator . NewLine ) ;
}
// Always add a configuration argument
Content . Append ( " <CommandLineArgument" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " argument = \"-RunConfig=$(Configuration)\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " isEnabled = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </CommandLineArgument>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </CommandLineArguments>" + ProjectFileGenerator . NewLine ) ;
}
}
else
{
Content . Append ( " <CommandLineArguments>" + OldCommandLineArguments + "</CommandLineArguments>" ) ;
}
Content . Append ( " <AdditionalOptions>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </AdditionalOptions>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </LaunchAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <ProfileAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildConfiguration = \"" + DefaultConfiguration + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " shouldUseLaunchSchemeArgsEnv = \"YES\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " savedToolIdentifier = \"\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " useCustomWorkingDirectory = \"NO\"" + ProjectFileGenerator . NewLine ) ;
2022-09-16 10:30:38 -04:00
Content . Append ( " debugDocumentVersioning = \"NO\">" + ProjectFileGenerator . NewLine ) ;
2022-07-19 13:24:38 -04:00
Content . Append ( " <BuildableProductRunnable" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " runnableDebuggingMode = \"0\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <BuildableReference" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableIdentifier = \"primary\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintIdentifier = \"" + TargetGuid + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BuildableName = \"" + TargetName + ".app\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " BlueprintName = \"" + TargetName + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " ReferencedContainer = \"container:" + TargetName + ".xcodeproj\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableReference>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </BuildableProductRunnable>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </ProfileAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <AnalyzeAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildConfiguration = \"" + DefaultConfiguration + "\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </AnalyzeAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " <ArchiveAction" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " buildConfiguration = \"" + DefaultConfiguration + "\"" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " revealArchiveInOrganizer = \"YES\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( " </ArchiveAction>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "</Scheme>" + ProjectFileGenerator . NewLine ) ;
File . WriteAllText ( SchemeFilePath . FullName , Content . ToString ( ) , new UTF8Encoding ( ) ) ;
Content . Clear ( ) ;
Content . Append ( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "<plist version=\"1.0\">" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t<key>SchemeUserState</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<key>" + TargetName + ".xcscheme_^#shared#^_</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<key>orderHint</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<integer>1</integer>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t<key>SuppressBuildableAutocreation</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<key>" + TargetGuid + "</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<key>primary</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<true/>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<key>" + BuildTargetGuid + "</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<key>primary</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<true/>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<key>" + IndexTargetGuid + "</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t<dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<key>primary</key>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t\t<true/>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "\t</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "</dict>" + ProjectFileGenerator . NewLine ) ;
Content . Append ( "</plist>" + ProjectFileGenerator . NewLine ) ;
FileReference ManagementFile = GetUserSchemeManagementFilePath ( ) ;
if ( ! DirectoryReference . Exists ( ManagementFile . Directory ) )
{
DirectoryReference . CreateDirectory ( ManagementFile . Directory ) ;
}
File . WriteAllText ( ManagementFile . FullName , Content . ToString ( ) , new UTF8Encoding ( ) ) ;
}
public static IEnumerable < UnrealTargetConfiguration > GetSupportedConfigurations ( )
{
return new UnrealTargetConfiguration [ ] {
UnrealTargetConfiguration . Debug ,
UnrealTargetConfiguration . DebugGame ,
UnrealTargetConfiguration . Development ,
UnrealTargetConfiguration . Test ,
UnrealTargetConfiguration . Shipping
} ;
}
public bool ShouldIncludeProjectInWorkspace ( ILogger Logger )
{
return CanBuildProjectLocally ( Logger ) ;
}
public bool CanBuildProjectLocally ( ILogger Logger )
{
foreach ( Project ProjectTarget in ProjectTargets )
{
2022-09-22 11:42:27 -04:00
foreach ( UnrealTargetPlatform Platform in XcodeProjectFileGenerator . XcodePlatforms )
2022-07-19 13:24:38 -04:00
{
foreach ( UnrealTargetConfiguration Config in GetSupportedConfigurations ( ) )
{
if ( MSBuildProjectFile . IsValidProjectPlatformAndConfiguration ( ProjectTarget , Platform , Config , Logger ) )
{
return true ;
}
}
}
}
return false ;
}
/// Implements Project interface
public override bool WriteProjectFile ( List < UnrealTargetPlatform > InPlatforms , List < UnrealTargetConfiguration > InConfigurations , PlatformProjectGeneratorCollection PlatformProjectGenerators , ILogger Logger )
{
bool bSuccess = true ;
string TargetName = ProjectFilePath . GetFileNameWithoutExtension ( ) ;
string TargetGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string TargetConfigListGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string TargetDependencyGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string TargetProxyGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string TargetAppGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string BuildTargetName = TargetName + "_Build" ;
string BuildTargetGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string BuildTargetConfigListGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string IndexTargetName = TargetName + "_Index" ;
string IndexTargetGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string IndexTargetConfigListGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ProjectGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ProjectConfigListGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string MainGroupGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ProductRefGroupGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string SourcesBuildPhaseGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string CopyExtensionsBuildPhaseGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
string ShellScriptSectionGuid = XcodeProjectFileGenerator . MakeXcodeGuid ( ) ;
// Figure out all the desired configurations
List < XcodeBuildConfig > BuildConfigs = GetSupportedBuildConfigs ( InPlatforms , InConfigurations , Logger ) ;
if ( BuildConfigs . Count = = 0 )
{
return true ;
}
2023-04-04 20:08:36 -04:00
// if a single project was specified then start with that, this will allow content-only projects to have
// their BundleID set in the stub xcode project when codesigning, which Xcode needs to have now)
// note that usually SingleGameProject is null
FileReference ? GameProjectPath = XcodeProjectFileGenerator . SingleGameProject ;
2022-07-19 13:24:38 -04:00
foreach ( Project Target in ProjectTargets )
{
if ( Target . UnrealProjectFilePath ! = null )
{
GameProjectPath = Target . UnrealProjectFilePath ;
break ;
}
}
bool bHasEditorConfiguration = false ;
bool bIsAppBundle = true ;
Dictionary < string , XcodeBuildConfig > ProjectBuildConfigs = new Dictionary < string , XcodeBuildConfig > ( ) ;
Dictionary < string , XcodeBuildConfig > TargetBuildConfigs = new Dictionary < string , XcodeBuildConfig > ( ) ;
Dictionary < string , XcodeBuildConfig > BuildTargetBuildConfigs = new Dictionary < string , XcodeBuildConfig > ( ) ;
Dictionary < string , XcodeBuildConfig > IndexTargetBuildConfigs = new Dictionary < string , XcodeBuildConfig > ( ) ;
foreach ( XcodeBuildConfig Config in BuildConfigs )
{
ProjectBuildConfigs [ XcodeProjectFileGenerator . MakeXcodeGuid ( ) ] = Config ;
TargetBuildConfigs [ XcodeProjectFileGenerator . MakeXcodeGuid ( ) ] = Config ;
BuildTargetBuildConfigs [ XcodeProjectFileGenerator . MakeXcodeGuid ( ) ] = Config ;
IndexTargetBuildConfigs [ XcodeProjectFileGenerator . MakeXcodeGuid ( ) ] = Config ;
if ( Config . ProjectTarget ! . TargetRules ! . Type = = TargetType . Editor )
{
bHasEditorConfiguration = true ;
}
else if ( Config . ProjectTarget . TargetRules . bIsBuildingConsoleApplication | | Config . ProjectTarget . TargetRules . bShouldCompileAsDLL )
{
bIsAppBundle = false ;
}
}
StringBuilder PBXBuildFileSection = new StringBuilder ( ) ;
StringBuilder PBXFileReferenceSection = new StringBuilder ( ) ;
StringBuilder PBXSourcesBuildPhaseSection = new StringBuilder ( ) ;
StringBuilder PBXCopyExtensionsBuildPhaseSection = new StringBuilder ( ) ;
StringBuilder PBXResourcesBuildPhaseSection = new StringBuilder ( ) ;
List < XcodeExtensionInfo > AllExtensions = new List < XcodeExtensionInfo > ( ) ;
GenerateSectionsWithSourceFiles ( PBXBuildFileSection , PBXFileReferenceSection , PBXSourcesBuildPhaseSection , TargetAppGuid , TargetName , bIsAppBundle ) ;
GenerateSectionsWithExtensions ( PBXBuildFileSection , PBXFileReferenceSection , PBXCopyExtensionsBuildPhaseSection , PBXResourcesBuildPhaseSection , AllExtensions , GameProjectPath , BuildConfigs , Logger ) ;
StringBuilder ProjectFileContent = new StringBuilder ( ) ;
ProjectFileContent . Append ( "// !$*UTF8*$!" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "{" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\tarchiveVersion = 1;" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\tclasses = {" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\t};" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\tobjectVersion = 46;" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\tobjects = {" + ProjectFileGenerator . NewLine + ProjectFileGenerator . NewLine ) ;
AppendBuildFileSection ( ProjectFileContent , PBXBuildFileSection ) ;
AppendFileReferenceSection ( ProjectFileContent , PBXFileReferenceSection ) ;
AppendSourcesBuildPhaseSection ( ProjectFileContent , PBXSourcesBuildPhaseSection , SourcesBuildPhaseGuid ) ;
AppendCopyExtensionsBuildPhaseSection ( ProjectFileContent , PBXCopyExtensionsBuildPhaseSection , CopyExtensionsBuildPhaseGuid ) ;
ProjectFileContent . Append ( PBXResourcesBuildPhaseSection ) ;
AppendContainerItemProxySection ( ProjectFileContent , BuildTargetName , BuildTargetGuid , TargetProxyGuid , ProjectGuid ) ;
2022-09-22 11:42:27 -04:00
if ( ! XcodeProjectFileGenerator . bGenerateRunOnlyProject )
2022-07-19 13:24:38 -04:00
{
AppendTargetDependencySection ( ProjectFileContent , BuildTargetName , BuildTargetGuid , TargetDependencyGuid , TargetProxyGuid ) ;
}
foreach ( XcodeExtensionInfo EI in AllExtensions )
{
AppendContainerItemProxySection ( ProjectFileContent , EI . Name , EI . TargetGuid , EI . TargetProxyGuid , ProjectGuid ) ;
AppendTargetDependencySection ( ProjectFileContent , EI . Name , EI . TargetGuid , EI . TargetDependencyGuid , EI . TargetProxyGuid ) ;
}
AppendGroupSection ( ProjectFileContent , MainGroupGuid , ProductRefGroupGuid , TargetAppGuid , TargetName , AllExtensions ) ;
AppendLegacyTargetSection ( ProjectFileContent , BuildTargetName , BuildTargetGuid , BuildTargetConfigListGuid , GameProjectPath ) ;
AppendRunTargetSection ( ProjectFileContent , TargetName , TargetGuid , TargetConfigListGuid , TargetDependencyGuid , TargetAppGuid , CopyExtensionsBuildPhaseGuid , ShellScriptSectionGuid , AllExtensions , bIsAppBundle ) ;
AppendIndexTargetSection ( ProjectFileContent , IndexTargetName , IndexTargetGuid , IndexTargetConfigListGuid , SourcesBuildPhaseGuid ) ;
AppendExtensionTargetSections ( ProjectFileContent , AllExtensions ) ;
AppendProjectSection ( ProjectFileContent , TargetName , TargetGuid , BuildTargetName , BuildTargetGuid , IndexTargetName , IndexTargetGuid , MainGroupGuid , ProductRefGroupGuid , ProjectGuid , ProjectConfigListGuid , GameProjectPath , AllExtensions ) ;
AppendXCBuildConfigurationSection ( ProjectFileContent , ProjectBuildConfigs , TargetBuildConfigs , BuildTargetBuildConfigs , IndexTargetBuildConfigs , GameProjectPath , AllExtensions , Logger ) ;
AppendXCConfigurationListSection ( ProjectFileContent , TargetName , BuildTargetName , IndexTargetName , ProjectConfigListGuid , ProjectBuildConfigs ,
TargetConfigListGuid , TargetBuildConfigs , BuildTargetConfigListGuid , BuildTargetBuildConfigs , IndexTargetConfigListGuid , IndexTargetBuildConfigs , AllExtensions ) ;
AppendShellScriptSection ( ProjectFileContent , ShellScriptSectionGuid , GameProjectPath ) ;
ProjectFileContent . Append ( "\t};" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "\trootObject = " + ProjectGuid + " /* Project object */;" + ProjectFileGenerator . NewLine ) ;
ProjectFileContent . Append ( "}" + ProjectFileGenerator . NewLine ) ;
if ( bSuccess )
{
FileReference PBXProjFilePath = ProjectFilePath + "/project.pbxproj" ;
bSuccess = ProjectFileGenerator . WriteFileIfChanged ( PBXProjFilePath . FullName , ProjectFileContent . ToString ( ) , Logger , new UTF8Encoding ( ) ) ;
}
bool bNeedScheme = CanBuildProjectLocally ( Logger ) ;
if ( bNeedScheme )
{
if ( bSuccess )
{
WriteSchemeFile ( TargetName , TargetGuid , BuildTargetGuid , IndexTargetGuid , bHasEditorConfiguration , GameProjectPath ! = null ? GameProjectPath . FullName : "" ) ;
}
}
else
{
// clean this up because we don't want it persisting if we narrow our project list
DirectoryReference SchemeDir = GetProjectSchemeDirectory ( ) ;
if ( DirectoryReference . Exists ( SchemeDir ) )
{
DirectoryReference . Delete ( SchemeDir , true ) ;
}
}
return bSuccess ;
}
}
}