2018-12-14 13:44:01 -05:00
// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
2014-03-14 14:13:41 -04:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.IO ;
using AutomationTool ;
using UnrealBuildTool ;
2017-01-30 16:52:08 -05:00
using Microsoft.Win32 ;
using System.Diagnostics ;
2017-08-31 12:08:38 -04:00
using Tools.DotNETCommon ;
2014-03-14 14:13:41 -04:00
public abstract class BaseWinPlatform : Platform
{
public BaseWinPlatform ( UnrealTargetPlatform P )
: base ( P )
2014-08-18 13:29:39 -04:00
{
2014-03-14 14:13:41 -04:00
}
public override void GetFilesToDeployOrStage ( ProjectParams Params , DeploymentContext SC )
{
// Engine non-ufs (binaries)
2014-08-18 13:29:39 -04:00
if ( SC . bStageCrashReporter )
2014-07-23 13:36:06 -04:00
{
2017-06-15 12:43:54 -04:00
FileReference ReceiptFileName = TargetReceipt . GetDefaultPath ( CommandUtils . EngineDirectory , "CrashReportClient" , SC . StageTargetPlatform . PlatformType , UnrealTargetConfiguration . Shipping , null ) ;
if ( FileReference . Exists ( ReceiptFileName ) )
2016-03-31 15:18:30 -04:00
{
2019-01-14 12:15:37 -05:00
TargetReceipt Receipt = TargetReceipt . Read ( ReceiptFileName ) ;
2016-03-31 15:18:30 -04:00
SC . StageBuildProductsFromReceipt ( Receipt , true , false ) ;
}
2014-07-23 13:36:06 -04:00
}
2014-03-14 14:13:41 -04:00
2015-05-09 11:37:24 -04:00
// Stage all the build products
2015-08-19 13:35:56 -04:00
foreach ( StageTarget Target in SC . StageTargets )
2014-03-14 14:13:41 -04:00
{
2016-03-14 21:21:09 -04:00
SC . StageBuildProductsFromReceipt ( Target . Receipt , Target . RequireFilesExist , Params . bTreatNonShippingBinariesAsDebugFiles ) ;
2014-03-14 14:13:41 -04:00
}
2014-08-18 13:29:39 -04:00
// Copy the splash screen, windows specific
2017-07-21 12:42:36 -04:00
FileReference SplashImage = FileReference . Combine ( SC . ProjectRoot , "Content" , "Splash" , "Splash.bmp" ) ;
if ( FileReference . Exists ( SplashImage ) )
{
SC . StageFile ( StagedFileType . NonUFS , SplashImage ) ;
}
2014-03-14 14:13:41 -04:00
2015-04-09 10:13:10 -04:00
// Stage the bootstrap executable
if ( ! Params . NoBootstrapExe )
2015-02-18 09:18:51 -05:00
{
2015-08-19 13:35:56 -04:00
foreach ( StageTarget Target in SC . StageTargets )
2015-04-09 10:13:10 -04:00
{
2015-08-19 13:35:56 -04:00
BuildProduct Executable = Target . Receipt . BuildProducts . FirstOrDefault ( x = > x . Type = = BuildProductType . Executable ) ;
2015-04-09 10:13:10 -04:00
if ( Executable ! = null )
2014-09-23 15:45:22 -04:00
{
2015-04-21 14:25:42 -04:00
// only create bootstraps for executables
2017-07-21 12:42:36 -04:00
List < StagedFileReference > StagedFiles = SC . FilesToStage . NonUFSFiles . Where ( x = > x . Value = = Executable . Path ) . Select ( x = > x . Key ) . ToList ( ) ;
2017-06-15 12:43:54 -04:00
if ( StagedFiles . Count > 0 & & Executable . Path . HasExtension ( ".exe" ) )
2015-02-01 12:33:30 -05:00
{
2015-04-21 14:25:42 -04:00
string BootstrapArguments = "" ;
2017-04-10 11:00:33 -04:00
if ( ! ShouldStageCommandLine ( Params , SC ) )
2015-04-21 14:25:42 -04:00
{
2017-04-10 11:00:33 -04:00
if ( ! SC . IsCodeBasedProject )
{
BootstrapArguments = String . Format ( "..\\..\\..\\{0}\\{0}.uproject" , SC . ShortProjectName ) ;
}
else
{
BootstrapArguments = SC . ShortProjectName ;
}
2015-04-21 14:25:42 -04:00
}
2015-02-01 12:33:30 -05:00
2015-05-02 14:41:23 -04:00
string BootstrapExeName ;
if ( SC . StageTargetConfigurations . Count > 1 )
{
2017-06-15 12:43:54 -04:00
BootstrapExeName = Executable . Path . GetFileName ( ) ;
2015-05-02 14:41:23 -04:00
}
else if ( Params . IsCodeBasedProject )
{
2015-08-26 08:25:10 -04:00
BootstrapExeName = Target . Receipt . TargetName + ".exe" ;
2015-05-02 14:41:23 -04:00
}
else
{
BootstrapExeName = SC . ShortProjectName + ".exe" ;
}
2017-06-15 12:43:54 -04:00
foreach ( StagedFileReference StagePath in StagedFiles )
2015-09-08 12:48:02 -04:00
{
2017-06-15 12:43:54 -04:00
StageBootstrapExecutable ( SC , BootstrapExeName , Executable . Path , StagePath , BootstrapArguments ) ;
2015-09-08 12:48:02 -04:00
}
2015-04-21 14:25:42 -04:00
}
2014-09-23 15:45:22 -04:00
}
}
2014-08-18 13:29:39 -04:00
}
2014-09-23 13:55:06 -04:00
}
2016-04-22 11:21:10 -04:00
public override void ExtractPackage ( ProjectParams Params , string SourcePath , string DestinationPath )
{
}
2018-04-03 15:23:51 -04:00
public override void GetTargetFile ( string RemoteFilePath , string LocalFile , ProjectParams Params )
{
var SourceFile = FileReference . Combine ( new DirectoryReference ( Params . BaseStageDirectory ) , GetCookPlatform ( Params . HasServerCookedTargets , Params . HasClientTargetDetected ) , RemoteFilePath ) ;
CommandUtils . CopyFile ( SourceFile . FullName , LocalFile ) ;
}
2017-06-15 12:43:54 -04:00
void StageBootstrapExecutable ( DeploymentContext SC , string ExeName , FileReference TargetFile , StagedFileReference StagedRelativeTargetPath , string StagedArguments )
2014-09-23 13:55:06 -04:00
{
2017-06-15 12:43:54 -04:00
FileReference InputFile = FileReference . Combine ( SC . LocalRoot , "Engine" , "Binaries" , SC . PlatformDir , String . Format ( "BootstrapPackagedGame-{0}-Shipping.exe" , SC . PlatformDir ) ) ;
if ( FileReference . Exists ( InputFile ) )
2014-09-23 13:55:06 -04:00
{
// Create the new bootstrap program
2017-06-15 12:43:54 -04:00
DirectoryReference IntermediateDir = DirectoryReference . Combine ( SC . ProjectRoot , "Intermediate" , "Staging" ) ;
DirectoryReference . CreateDirectory ( IntermediateDir ) ;
2014-09-23 13:55:06 -04:00
2017-07-21 12:42:36 -04:00
FileReference IntermediateFile = FileReference . Combine ( IntermediateDir , ExeName ) ;
CommandUtils . CopyFile ( InputFile . FullName , IntermediateFile . FullName ) ;
CommandUtils . SetFileAttributes ( IntermediateFile . FullName , ReadOnly : false ) ;
2014-09-23 13:55:06 -04:00
2015-04-08 16:59:20 -04:00
// currently the icon updating doesn't run under mono
if ( UnrealBuildTool . BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Win64 | |
UnrealBuildTool . BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Win32 )
2014-09-23 13:55:06 -04:00
{
2015-04-08 16:59:20 -04:00
// Get the icon from the build directory if possible
GroupIconResource GroupIcon = null ;
2017-06-15 12:43:54 -04:00
if ( FileReference . Exists ( FileReference . Combine ( SC . ProjectRoot , "Build/Windows/Application.ico" ) ) )
2015-04-08 16:59:20 -04:00
{
2017-06-15 12:43:54 -04:00
GroupIcon = GroupIconResource . FromIco ( FileReference . Combine ( SC . ProjectRoot , "Build/Windows/Application.ico" ) . FullName ) ;
2015-04-08 16:59:20 -04:00
}
if ( GroupIcon = = null )
{
2017-06-15 12:43:54 -04:00
GroupIcon = GroupIconResource . FromExe ( TargetFile . FullName ) ;
2015-04-08 16:59:20 -04:00
}
2014-09-23 13:55:06 -04:00
2015-04-08 16:59:20 -04:00
// Update the resources in the new file
2017-11-06 18:22:01 -05:00
using ( ModuleResourceUpdate Update = new ModuleResourceUpdate ( IntermediateFile . FullName , false ) )
2015-04-08 16:59:20 -04:00
{
const int IconResourceId = 101 ;
if ( GroupIcon ! = null ) Update . SetIcons ( IconResourceId , GroupIcon ) ;
2014-09-23 13:55:06 -04:00
2015-04-08 16:59:20 -04:00
const int ExecFileResourceId = 201 ;
Update . SetData ( ExecFileResourceId , ResourceType . RawData , Encoding . Unicode . GetBytes ( StagedRelativeTargetPath + "\0" ) ) ;
2014-09-23 13:55:06 -04:00
2015-04-08 16:59:20 -04:00
const int ExecArgsResourceId = 202 ;
Update . SetData ( ExecArgsResourceId , ResourceType . RawData , Encoding . Unicode . GetBytes ( StagedArguments + "\0" ) ) ;
}
2014-09-23 13:55:06 -04:00
}
// Copy it to the staging directory
2017-07-21 12:42:36 -04:00
SC . StageFile ( StagedFileType . SystemNonUFS , IntermediateFile , new StagedFileReference ( ExeName ) ) ;
2014-09-23 13:55:06 -04:00
}
2014-03-14 14:13:41 -04:00
}
2016-07-19 19:13:01 -04:00
public override string GetCookPlatform ( bool bDedicatedServer , bool bIsClientOnly )
2014-03-14 14:13:41 -04:00
{
const string NoEditorCookPlatform = "WindowsNoEditor" ;
const string ServerCookPlatform = "WindowsServer" ;
const string ClientCookPlatform = "WindowsClient" ;
2014-08-18 13:29:39 -04:00
if ( bDedicatedServer )
2014-03-14 14:13:41 -04:00
{
return ServerCookPlatform ;
}
2014-08-18 13:29:39 -04:00
else if ( bIsClientOnly )
2014-03-14 14:13:41 -04:00
{
return ClientCookPlatform ;
}
else
{
return NoEditorCookPlatform ;
}
}
2014-08-18 13:29:39 -04:00
public override string GetEditorCookPlatform ( )
{
return "Windows" ;
}
2019-01-29 04:41:32 -05:00
public override string GetPlatformPakCommandLine ( ProjectParams Params , DeploymentContext SC )
{
string PakParams = " -patchpaddingalign=2048" ;
2019-02-19 14:30:16 -05:00
if ( ! SC . DedicatedServer )
2019-01-29 04:41:32 -05:00
{
2019-02-19 14:30:16 -05:00
string OodleDllPath = DirectoryReference . Combine ( SC . ProjectRoot , "Binaries/ThirdParty/Oodle/Win64/UnrealPakPlugin.dll" ) . FullName ;
if ( File . Exists ( OodleDllPath ) )
{
PakParams + = String . Format ( " -customcompressor=\"{0}\"" , OodleDllPath ) ;
}
2019-01-29 04:41:32 -05:00
}
return PakParams ;
}
2016-04-22 11:21:10 -04:00
2014-03-14 14:13:41 -04:00
public override void Package ( ProjectParams Params , DeploymentContext SC , int WorkingCL )
{
2018-10-29 10:01:28 -04:00
// If this is a content-only project and there's a custom icon, update the executable
if ( ! Params . HasDLCName & & ! Params . IsCodeBasedProject )
2018-04-26 14:11:04 -04:00
{
2018-10-29 10:01:28 -04:00
FileReference IconFile = FileReference . Combine ( Params . RawProjectPath . Directory , "Build" , "Windows" , "Application.ico" ) ;
if ( FileReference . Exists ( IconFile ) )
{
CommandUtils . LogInformation ( "Updating executable with custom icon from {0}" , IconFile ) ;
GroupIconResource GroupIcon = GroupIconResource . FromIco ( IconFile . FullName ) ;
List < FileReference > ExecutablePaths = GetExecutableNames ( SC ) ;
foreach ( FileReference ExecutablePath in ExecutablePaths )
{
using ( ModuleResourceUpdate Update = new ModuleResourceUpdate ( ExecutablePath . FullName , false ) )
{
const int IconResourceId = 123 ; // As defined in Engine\Source\Runtime\Launch\Resources\Windows\resource.h
if ( GroupIcon ! = null )
{
Update . SetIcons ( IconResourceId , GroupIcon ) ;
}
}
}
}
2018-04-26 14:11:04 -04:00
}
2017-02-07 23:55:24 -05:00
2014-03-14 14:13:41 -04:00
PrintRunTime ( ) ;
}
2018-03-21 11:09:41 -04:00
public override bool UseAbsLog
{
get { return BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Win64 | | BuildHostPlatform . Current . Platform = = UnrealTargetPlatform . Win32 ; }
}
2014-08-18 13:29:39 -04:00
public override bool CanHostPlatform ( UnrealTargetPlatform Platform )
{
if ( Platform = = UnrealTargetPlatform . Mac )
{
return false ;
}
return true ;
}
2014-03-14 14:13:41 -04:00
2016-04-22 11:21:10 -04:00
public override bool ShouldStageCommandLine ( ProjectParams Params , DeploymentContext SC )
2015-04-04 15:11:53 -04:00
{
2015-06-03 18:25:44 -04:00
return false ; // !String.IsNullOrEmpty(Params.StageCommandline) || !String.IsNullOrEmpty(Params.RunCommandline) || (!Params.IsCodeBasedProject && Params.NoBootstrapExe);
2015-04-04 15:11:53 -04:00
}
2018-02-27 17:30:35 -05:00
public override List < string > GetDebugFileExtensions ( )
2014-08-18 13:29:39 -04:00
{
return new List < string > { ".pdb" , ".map" } ;
}
2015-07-10 14:06:52 -04:00
public override bool SignExecutables ( DeploymentContext SC , ProjectParams Params )
{
// Sign everything we built
2017-06-15 12:43:54 -04:00
List < FileReference > FilesToSign = GetExecutableNames ( SC ) ;
2015-07-10 14:06:52 -04:00
CodeSign . SignMultipleFilesIfEXEOrDLL ( FilesToSign ) ;
return true ;
}
2016-07-12 15:06:08 -04:00
public void StageAppLocalDependencies ( ProjectParams Params , DeploymentContext SC , string PlatformDir )
{
2017-03-26 15:18:02 -04:00
Dictionary < string , string > PathVariables = new Dictionary < string , string > ( ) ;
2017-06-15 12:43:54 -04:00
PathVariables [ "EngineDir" ] = SC . EngineRoot . FullName ;
PathVariables [ "ProjectDir" ] = SC . ProjectRoot . FullName ;
2017-03-26 15:18:02 -04:00
2017-08-03 14:06:31 -04:00
// support multiple comma-separated paths
string [ ] AppLocalDirectories = Params . AppLocalDirectory . Split ( ';' ) ;
foreach ( string AppLocalDirectory in AppLocalDirectories )
2016-07-12 15:06:08 -04:00
{
2017-08-03 14:06:31 -04:00
string ExpandedAppLocalDir = Utils . ExpandVariables ( AppLocalDirectory , PathVariables ) ;
2016-07-29 17:10:25 -04:00
2017-08-03 14:06:31 -04:00
DirectoryReference BaseAppLocalDependenciesPath = Path . IsPathRooted ( ExpandedAppLocalDir ) ? new DirectoryReference ( CombinePaths ( ExpandedAppLocalDir , PlatformDir ) ) : DirectoryReference . Combine ( SC . ProjectRoot , ExpandedAppLocalDir , PlatformDir ) ;
if ( DirectoryReference . Exists ( BaseAppLocalDependenciesPath ) )
2017-07-21 12:42:36 -04:00
{
2018-02-27 17:30:35 -05:00
StageAppLocalDependenciesToDir ( SC , BaseAppLocalDependenciesPath , StagedDirectoryReference . Combine ( "Engine" , "Binaries" , PlatformDir ) ) ;
StageAppLocalDependenciesToDir ( SC , BaseAppLocalDependenciesPath , StagedDirectoryReference . Combine ( SC . RelativeProjectRootForStage , "Binaries" , PlatformDir ) ) ;
2017-08-03 14:06:31 -04:00
}
else
{
LogWarning ( "Unable to deploy AppLocalDirectory dependencies. No such path: {0}" , BaseAppLocalDependenciesPath ) ;
2016-07-12 15:06:08 -04:00
}
2016-07-29 17:10:25 -04:00
}
2016-07-12 15:06:08 -04:00
}
2017-01-30 16:52:08 -05:00
2018-02-27 17:30:35 -05:00
static void StageAppLocalDependenciesToDir ( DeploymentContext SC , DirectoryReference BaseAppLocalDependenciesPath , StagedDirectoryReference StagedBinariesDir )
{
// Check if there are any executables being staged in this directory. Usually we only need to stage runtime dependencies next to the executable, but we may be staging
// other engine executables too (eg. CEF)
2018-09-04 14:32:41 -04:00
List < StagedFileReference > FilesInTargetDir = SC . FilesToStage . NonUFSFiles . Keys . Where ( x = > x . IsUnderDirectory ( StagedBinariesDir ) & & ( x . HasExtension ( ".exe" ) | | x . HasExtension ( ".dll" ) ) ) . ToList ( ) ;
2018-02-27 17:30:35 -05:00
if ( FilesInTargetDir . Count > 0 )
{
2018-09-04 14:32:41 -04:00
LogInformation ( "Copying AppLocal dependencies from {0} to {1}" , BaseAppLocalDependenciesPath , StagedBinariesDir ) ;
2018-02-27 17:30:35 -05:00
// Stage files in subdirs
foreach ( DirectoryReference DependencyDirectory in DirectoryReference . EnumerateDirectories ( BaseAppLocalDependenciesPath ) )
{
2018-06-07 22:39:07 -04:00
SC . StageFiles ( StagedFileType . NonUFS , DependencyDirectory , StageFilesSearch . AllDirectories , StagedBinariesDir ) ;
2018-02-27 17:30:35 -05:00
}
}
}
2017-01-30 16:52:08 -05:00
/// <summary>
/// Try to get the SYMSTORE.EXE path from the given Windows SDK version
/// </summary>
/// <param name="SdkVersion">The SDK version string</param>
/// <param name="SymStoreExe">Receives the path to symstore.exe if found</param>
/// <returns>True if found, false otherwise</returns>
private static bool TryGetSymStoreExe ( string SdkVersion , out FileReference SymStoreExe )
{
// Try to get the SDK installation directory
string SdkFolder = Registry . GetValue ( @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Microsoft SDKs\Windows\" + SdkVersion , "InstallationFolder" , null ) as String ;
if ( SdkFolder = = null )
{
SdkFolder = Registry . GetValue ( @"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\" + SdkVersion , "InstallationFolder" , null ) as String ;
if ( SdkFolder = = null )
{
SdkFolder = Registry . GetValue ( @"HKEY_CURRENT_USER\SOFTWARE\Wow6432Node\Microsoft\Microsoft SDKs\Windows\" + SdkVersion , "InstallationFolder" , null ) as String ;
if ( SdkFolder = = null )
{
SymStoreExe = null ;
return false ;
}
}
}
// Check for the 64-bit toolchain first, then the 32-bit toolchain
FileReference CheckSymStoreExe = FileReference . Combine ( new DirectoryReference ( SdkFolder ) , "Debuggers" , "x64" , "SymStore.exe" ) ;
if ( ! FileReference . Exists ( CheckSymStoreExe ) )
{
CheckSymStoreExe = FileReference . Combine ( new DirectoryReference ( SdkFolder ) , "Debuggers" , "x86" , "SymStore.exe" ) ;
if ( ! FileReference . Exists ( CheckSymStoreExe ) )
{
SymStoreExe = null ;
return false ;
}
}
SymStoreExe = CheckSymStoreExe ;
return true ;
}
2018-04-26 14:11:04 -04:00
public static bool TryGetPdbCopyLocation ( out FileReference OutLocation )
{
// Try to find an installation of the Windows 10 SDK
string SdkInstallFolder =
( Microsoft . Win32 . Registry . GetValue ( "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows Kits\\Installed Roots" , "KitsRoot10" , null ) as string ) ? ?
( Microsoft . Win32 . Registry . GetValue ( "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows Kits\\Installed Roots" , "KitsRoot10" , null ) as string ) ? ?
( Microsoft . Win32 . Registry . GetValue ( "HKEY_CURRENT_USER\\Software\\Wow6432Node\\Microsoft\\Windows Kits\\Installed Roots" , "KitsRoot10" , null ) as string ) ? ?
( Microsoft . Win32 . Registry . GetValue ( "HKEY_LOCAL_MACHINE\\Software\\Wow6432Node\\Microsoft\\Windows Kits\\Installed Roots" , "KitsRoot10" , null ) as string ) ;
if ( ! String . IsNullOrEmpty ( SdkInstallFolder ) )
{
FileReference Location = FileReference . Combine ( new DirectoryReference ( SdkInstallFolder ) , "Debuggers" , "x64" , "PDBCopy.exe" ) ;
if ( FileReference . Exists ( Location ) )
{
OutLocation = Location ;
return true ;
}
}
// Look for an installation of the MSBuild 14
FileReference LocationMsBuild14 = FileReference . Combine ( DirectoryReference . GetSpecialFolder ( Environment . SpecialFolder . ProgramFilesX86 ) , "MSBuild" , "Microsoft" , "VisualStudio" , "v14.0" , "AppxPackage" , "PDBCopy.exe" ) ;
if ( FileReference . Exists ( LocationMsBuild14 ) )
{
OutLocation = LocationMsBuild14 ;
return true ;
}
// Look for an installation of the MSBuild 12
FileReference LocationMsBuild12 = FileReference . Combine ( DirectoryReference . GetSpecialFolder ( Environment . SpecialFolder . ProgramFilesX86 ) , "MSBuild" , "Microsoft" , "VisualStudio" , "v12.0" , "AppxPackage" , "PDBCopy.exe" ) ;
if ( FileReference . Exists ( LocationMsBuild12 ) )
{
OutLocation = LocationMsBuild12 ;
return true ;
}
// Otherwise fail
OutLocation = null ;
return false ;
}
2017-02-21 15:51:42 -05:00
public override void StripSymbols ( FileReference SourceFile , FileReference TargetFile )
2017-01-30 16:52:08 -05:00
{
2017-02-21 15:51:42 -05:00
bool bStripInPlace = false ;
if ( SourceFile = = TargetFile )
{
// PDBCopy only supports creation of a brand new stripped file so we have to create a temporary filename
TargetFile = new FileReference ( Path . Combine ( TargetFile . Directory . FullName , Guid . NewGuid ( ) . ToString ( ) + TargetFile . GetExtension ( ) ) ) ;
bStripInPlace = true ;
}
2018-04-26 14:11:04 -04:00
FileReference PdbCopyLocation ;
if ( ! TryGetPdbCopyLocation ( out PdbCopyLocation ) )
2017-01-30 16:52:08 -05:00
{
2018-04-26 14:11:04 -04:00
throw new AutomationException ( "Unable to find installation of PDBCOPY.EXE, which is required to strip symbols. This tool is included as part of the 'Windows Debugging Tools' component of the Windows 10 SDK (https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)." ) ;
2017-01-30 16:52:08 -05:00
}
2018-04-26 14:11:04 -04:00
ProcessStartInfo StartInfo = new ProcessStartInfo ( ) ;
StartInfo . FileName = PdbCopyLocation . FullName ;
2017-02-21 15:51:42 -05:00
StartInfo . Arguments = String . Format ( "\"{0}\" \"{1}\" -p" , SourceFile . FullName , TargetFile . FullName ) ;
2017-01-30 16:52:08 -05:00
StartInfo . UseShellExecute = false ;
StartInfo . CreateNoWindow = true ;
Utils . RunLocalProcessAndLogOutput ( StartInfo ) ;
2017-02-21 15:51:42 -05:00
if ( bStripInPlace )
{
// Copy stripped file to original location and delete the temporary file
File . Copy ( TargetFile . FullName , SourceFile . FullName , true ) ;
FileReference . Delete ( TargetFile ) ;
}
2017-01-30 16:52:08 -05:00
}
2019-01-11 02:57:03 -05:00
public override bool PublishSymbols ( DirectoryReference SymbolStoreDirectory , List < FileReference > Files , string Product , string BuildVersion = null )
2017-01-30 16:52:08 -05:00
{
// Get the SYMSTORE.EXE path, using the latest SDK version we can find.
FileReference SymStoreExe ;
if ( ! TryGetSymStoreExe ( "v10.0" , out SymStoreExe ) & & ! TryGetSymStoreExe ( "v8.1" , out SymStoreExe ) & & ! TryGetSymStoreExe ( "v8.0" , out SymStoreExe ) )
{
CommandUtils . LogError ( "Couldn't find SYMSTORE.EXE in any Windows SDK installation" ) ;
return false ;
}
2018-06-07 22:39:07 -04:00
List < FileReference > FilesToAdd = Files . Where ( x = > x . HasExtension ( ".pdb" ) | | x . HasExtension ( ".exe" ) | | x . HasExtension ( ".dll" ) ) . ToList ( ) ;
if ( FilesToAdd . Count > 0 )
{
2018-11-16 14:01:06 -05:00
DateTime Start = DateTime . Now ;
DirectoryReference TempSymStoreDir = DirectoryReference . Combine ( RootDirectory , "Saved" , "SymStore" ) ;
2018-06-07 22:39:07 -04:00
string TempFileName = Path . GetTempFileName ( ) ;
try
{
File . WriteAllLines ( TempFileName , FilesToAdd . Select ( x = > x . FullName ) , Encoding . ASCII ) ;
2019-01-11 02:57:03 -05:00
// Copy everything to the temp symstore
2018-06-07 22:39:07 -04:00
ProcessStartInfo StartInfo = new ProcessStartInfo ( ) ;
StartInfo . FileName = SymStoreExe . FullName ;
2018-11-16 14:01:06 -05:00
StartInfo . Arguments = string . Format ( "add /f \"@{0}\" /s \"{1}\" /t \"{2}\" /compress" , TempFileName , TempSymStoreDir , Product ) ;
2018-06-07 22:39:07 -04:00
StartInfo . UseShellExecute = false ;
StartInfo . CreateNoWindow = true ;
if ( Utils . RunLocalProcessAndLogOutput ( StartInfo ) ! = 0 )
{
return false ;
}
}
finally
{
File . Delete ( TempFileName ) ;
}
2018-11-16 14:01:06 -05:00
DateTime CompressDone = DateTime . Now ;
LogInformation ( "Took {0}s to compress the symbol files" , ( CompressDone - Start ) . TotalSeconds ) ;
2019-01-11 02:57:03 -05:00
2018-11-16 14:01:06 -05:00
// Take each new compressed file made and try and copy it to the real symstore. Exclude any symstore admin files
2019-01-11 02:57:03 -05:00
foreach ( FileReference File in DirectoryReference . EnumerateFiles ( TempSymStoreDir , "*.*" , SearchOption . AllDirectories ) . Where ( File = > File . HasExtension ( ".dl_" ) | | File . HasExtension ( ".ex_" ) | | File . HasExtension ( ".pd_" ) ) )
2018-11-16 14:01:06 -05:00
{
string RelativePath = File . MakeRelativeTo ( DirectoryReference . Combine ( TempSymStoreDir ) ) ;
FileReference ActualDestinationFile = FileReference . Combine ( SymbolStoreDirectory , RelativePath ) ;
2017-01-30 16:52:08 -05:00
2019-01-11 02:57:03 -05:00
// Try and add a version file. Do this before checking to see if the symbol is there already in the case of exact matches (multiple builds could use the same pdb, for example)
if ( ! string . IsNullOrWhiteSpace ( BuildVersion ) )
2018-11-16 14:01:06 -05:00
{
2019-01-11 02:57:03 -05:00
FileReference BuildVersionFile = FileReference . Combine ( ActualDestinationFile . Directory , string . Format ( "{0}.version" , BuildVersion ) ) ;
// Attempt to create the file. Just continue if it fails.
try
{
DirectoryReference . CreateDirectory ( BuildVersionFile . Directory ) ;
FileReference . WriteAllText ( BuildVersionFile , string . Empty ) ;
}
catch ( Exception Ex )
{
LogWarning ( "Failed to write the version file, reason {0}" , Ex . ToString ( ) ) ;
}
2018-11-16 14:01:06 -05:00
}
2019-01-11 02:57:03 -05:00
// Don't bother copying the temp file if the destination file is there already.
if ( FileReference . Exists ( ActualDestinationFile ) )
{
LogInformation ( "Destination file {0} already exists, skipping" , ActualDestinationFile . FullName ) ;
continue ;
}
FileReference TempDestinationFile = new FileReference ( ActualDestinationFile . FullName + Guid . NewGuid ( ) . ToString ( ) ) ;
try
{
CommandUtils . CopyFile ( File . FullName , TempDestinationFile . FullName ) ;
}
catch ( Exception Ex )
{
throw new AutomationException ( "Couldn't copy the symbol file to the temp store! Reason: {0}" , Ex . ToString ( ) ) ;
}
// Move the file in the temp store over.
2018-11-16 14:01:06 -05:00
try
{
FileReference . Move ( TempDestinationFile , ActualDestinationFile ) ;
}
2019-01-11 02:57:03 -05:00
catch ( Exception Ex )
2018-11-16 14:01:06 -05:00
{
2019-01-11 02:57:03 -05:00
// If the file is there already, it was likely either copied elsewhere (and this is an ioexception) or it had a file handle open already.
// Either way, it's fine to just continue on.
2018-11-16 14:01:06 -05:00
if ( FileReference . Exists ( ActualDestinationFile ) )
{
LogInformation ( "Destination file {0} already exists or was in use, skipping." , ActualDestinationFile . FullName ) ;
2019-01-11 02:57:03 -05:00
continue ;
2018-11-16 14:01:06 -05:00
}
2019-01-11 02:57:03 -05:00
// If it doesn't exist, we actually failed to copy it entirely.
2018-11-16 14:01:06 -05:00
else
{
LogWarning ( "Couldn't move temp file {0} to the symbol store at location {1}! Reason: {2}" , TempDestinationFile . FullName , ActualDestinationFile . FullName , Ex . ToString ( ) ) ;
}
}
2019-01-11 02:57:03 -05:00
// Delete the temp one no matter what, don't want them hanging around in the symstore
2018-11-16 14:01:06 -05:00
finally
{
FileReference . Delete ( TempDestinationFile ) ;
}
2019-01-11 02:57:03 -05:00
}
2018-11-16 14:01:06 -05:00
LogInformation ( "Took {0}s to copy the symbol files to the store" , ( DateTime . Now - CompressDone ) . TotalSeconds ) ;
}
2018-06-07 22:39:07 -04:00
return true ;
2017-01-30 16:52:08 -05:00
}
public override string [ ] SymbolServerDirectoryStructure
{
get
{
return new string [ ]
{
"{0}*.pdb;{0}*.exe;{0}*.dll" , // Binary File Directory (e.g. QAGameClient-Win64-Test.exe --- .pdb, .dll and .exe are allowed extensions)
"*" , // Hash Directory (e.g. A92F5744D99F416EB0CCFD58CCE719CD1)
} ;
}
}
2018-11-16 14:01:06 -05:00
// Lock file no longer needed since files are moved over the top from the temp symstore
public override bool SymbolServerRequiresLock
{
get
{
return false ;
}
}
2014-03-14 14:13:41 -04:00
}
public class Win64Platform : BaseWinPlatform
{
public Win64Platform ( )
: base ( UnrealTargetPlatform . Win64 )
{
}
public override bool IsSupported { get { return true ; } }
2014-09-26 11:29:46 -04:00
public override void GetFilesToDeployOrStage ( ProjectParams Params , DeploymentContext SC )
{
base . GetFilesToDeployOrStage ( Params , SC ) ;
if ( Params . Prereqs )
{
2017-07-21 12:42:36 -04:00
SC . StageFile ( StagedFileType . NonUFS , FileReference . Combine ( SC . EngineRoot , "Extras" , "Redist" , "en-us" , "UE4PrereqSetup_x64.exe" ) ) ;
2016-07-29 17:10:25 -04:00
}
2016-07-12 15:06:08 -04:00
2016-07-29 17:10:25 -04:00
if ( ! string . IsNullOrWhiteSpace ( Params . AppLocalDirectory ) )
{
StageAppLocalDependencies ( Params , SC , "Win64" ) ;
2014-09-26 11:29:46 -04:00
}
}
2014-03-14 14:13:41 -04:00
}
public class Win32Platform : BaseWinPlatform
{
public Win32Platform ( )
: base ( UnrealTargetPlatform . Win32 )
{
}
public override bool IsSupported { get { return true ; } }
2014-09-26 11:29:46 -04:00
public override void GetFilesToDeployOrStage ( ProjectParams Params , DeploymentContext SC )
{
base . GetFilesToDeployOrStage ( Params , SC ) ;
2016-07-29 17:10:25 -04:00
if ( Params . Prereqs )
2014-09-26 11:29:46 -04:00
{
2017-07-21 12:42:36 -04:00
SC . StageFile ( StagedFileType . NonUFS , FileReference . Combine ( SC . EngineRoot , "Extras" , "Redist" , "en-us" , "UE4PrereqSetup_x86.exe" ) ) ;
2016-07-29 17:10:25 -04:00
}
2016-07-12 15:06:08 -04:00
2016-07-29 17:10:25 -04:00
if ( ! string . IsNullOrWhiteSpace ( Params . AppLocalDirectory ) )
{
StageAppLocalDependencies ( Params , SC , "Win32" ) ;
2014-09-26 11:29:46 -04:00
}
}
2014-09-23 13:55:06 -04:00
}