Add support for separate data and code output directories in Game Cooker
This commit is contained in:
@@ -152,9 +152,14 @@ struct FLAXENGINE_API CookingData
|
|||||||
String OriginalOutputPath;
|
String OriginalOutputPath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The output path.
|
/// The output path for data files (Content, Mono, etc.).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
String OutputPath;
|
String DataOutputPath;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output path for binaries (executable and code libraries).
|
||||||
|
/// </summary>
|
||||||
|
String CodeOutputPath;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The platform tools.
|
/// The platform tools.
|
||||||
|
|||||||
@@ -333,9 +333,10 @@ void GameCooker::Build(BuildPlatform platform, BuildConfiguration configuration,
|
|||||||
data.Configuration = configuration;
|
data.Configuration = configuration;
|
||||||
data.Options = options;
|
data.Options = options;
|
||||||
data.CustomDefines = customDefines;
|
data.CustomDefines = customDefines;
|
||||||
data.OutputPath = outputPath;
|
data.OriginalOutputPath = outputPath;
|
||||||
FileSystem::NormalizePath(data.OutputPath);
|
FileSystem::NormalizePath(data.OriginalOutputPath);
|
||||||
data.OutputPath = data.OriginalOutputPath = FileSystem::ConvertRelativePathToAbsolute(Globals::ProjectFolder, data.OutputPath);
|
data.OriginalOutputPath = FileSystem::ConvertRelativePathToAbsolute(Globals::ProjectFolder, data.OriginalOutputPath);
|
||||||
|
data.CodeOutputPath = data.DataOutputPath = data.OriginalOutputPath;
|
||||||
data.CacheDirectory = Globals::ProjectCacheFolder / TEXT("Cooker") / tools->GetName();
|
data.CacheDirectory = Globals::ProjectCacheFolder / TEXT("Cooker") / tools->GetName();
|
||||||
if (!FileSystem::DirectoryExists(data.CacheDirectory))
|
if (!FileSystem::DirectoryExists(data.CacheDirectory))
|
||||||
{
|
{
|
||||||
@@ -418,7 +419,7 @@ bool GameCookerImpl::Build()
|
|||||||
CookingData& data = Data;
|
CookingData& data = Data;
|
||||||
LOG(Info, "Starting Game Cooker...");
|
LOG(Info, "Starting Game Cooker...");
|
||||||
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
|
LOG(Info, "Platform: {0}, Configuration: {2}, Options: {1}", ::ToString(data.Platform), (int32)data.Options, ::ToString(data.Configuration));
|
||||||
LOG(Info, "Output Path: {0}", data.OutputPath);
|
LOG(Info, "Output Path: {0}", data.OriginalOutputPath);
|
||||||
|
|
||||||
// Late init feature
|
// Late init feature
|
||||||
if (Steps.IsEmpty())
|
if (Steps.IsEmpty())
|
||||||
|
|||||||
@@ -104,7 +104,8 @@ PixelFormat AndroidPlatformTools::GetTextureFormat(CookingData& data, TextureBas
|
|||||||
void AndroidPlatformTools::OnBuildStarted(CookingData& data)
|
void AndroidPlatformTools::OnBuildStarted(CookingData& data)
|
||||||
{
|
{
|
||||||
// Adjust the cooking output folder to be located inside the Gradle assets directory
|
// Adjust the cooking output folder to be located inside the Gradle assets directory
|
||||||
data.OutputPath /= TEXT("app/assets");
|
data.DataOutputPath /= TEXT("app/assets");
|
||||||
|
data.CodeOutputPath /= TEXT("app/assets");
|
||||||
|
|
||||||
PlatformTools::OnBuildStarted(data);
|
PlatformTools::OnBuildStarted(data);
|
||||||
}
|
}
|
||||||
@@ -114,7 +115,7 @@ bool AndroidPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
const auto gameSettings = GameSettings::Get();
|
const auto gameSettings = GameSettings::Get();
|
||||||
const auto platformSettings = AndroidPlatformSettings::Get();
|
const auto platformSettings = AndroidPlatformSettings::Get();
|
||||||
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
||||||
const auto assetsPath = data.OutputPath;
|
const auto assetsPath = data.DataOutputPath;
|
||||||
const auto jniLibsPath = data.OriginalOutputPath / TEXT("app/jniLibs");
|
const auto jniLibsPath = data.OriginalOutputPath / TEXT("app/jniLibs");
|
||||||
const auto projectVersion = Editor::Project->Version.ToString();
|
const auto projectVersion = Editor::Project->Version.ToString();
|
||||||
const Char* abi;
|
const Char* abi;
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ bool LinuxPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
{
|
{
|
||||||
const auto gameSettings = GameSettings::Get();
|
const auto gameSettings = GameSettings::Get();
|
||||||
const auto platformSettings = LinuxPlatformSettings::Get();
|
const auto platformSettings = LinuxPlatformSettings::Get();
|
||||||
const auto outputPath = data.OutputPath;
|
const auto outputPath = data.DataOutputPath;
|
||||||
|
|
||||||
// Copy binaries
|
// Copy binaries
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ bool UWPPlatformTools::OnScriptsStepDone(CookingData& data)
|
|||||||
{
|
{
|
||||||
// Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation)
|
// Override Newtonsoft.Json.dll for some platforms (that don't support runtime code generation)
|
||||||
const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll");
|
const String customBinPath = data.GetPlatformBinariesRoot() / TEXT("Newtonsoft.Json.dll");
|
||||||
const String assembliesPath = data.OutputPath;
|
const String assembliesPath = data.CodeOutputPath;
|
||||||
if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath))
|
if (FileSystem::CopyFile(assembliesPath / TEXT("Newtonsoft.Json.dll"), customBinPath))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to copy deploy custom assembly."));
|
data.Error(TEXT("Failed to copy deploy custom assembly."));
|
||||||
@@ -64,7 +64,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FileSystem::CopyFile(data.OutputPath / StringUtils::GetFileName(files[i]), files[i]))
|
if (FileSystem::CopyFile(data.DataOutputPath / StringUtils::GetFileName(files[i]), files[i]))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to setup output directory."));
|
data.Error(TEXT("Failed to setup output directory."));
|
||||||
return true;
|
return true;
|
||||||
@@ -92,7 +92,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
|
|
||||||
// Prepare certificate
|
// Prepare certificate
|
||||||
const auto srcCertificatePath = Globals::ProjectFolder / platformSettings->CertificateLocation;
|
const auto srcCertificatePath = Globals::ProjectFolder / platformSettings->CertificateLocation;
|
||||||
const auto dstCertificatePath = data.OutputPath / TEXT("WSACertificate.pfx");
|
const auto dstCertificatePath = data.DataOutputPath / TEXT("WSACertificate.pfx");
|
||||||
if (platformSettings->CertificateLocation.HasChars() && FileSystem::FileExists(srcCertificatePath))
|
if (platformSettings->CertificateLocation.HasChars() && FileSystem::FileExists(srcCertificatePath))
|
||||||
{
|
{
|
||||||
// Use cert from settings
|
// Use cert from settings
|
||||||
@@ -115,7 +115,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copy assets
|
// Copy assets
|
||||||
const auto dstAssetsPath = data.OutputPath / TEXT("Assets");
|
const auto dstAssetsPath = data.DataOutputPath / TEXT("Assets");
|
||||||
const auto srcAssetsPath = uwpDataPath / TEXT("Assets");
|
const auto srcAssetsPath = uwpDataPath / TEXT("Assets");
|
||||||
if (!FileSystem::DirectoryExists(dstAssetsPath))
|
if (!FileSystem::DirectoryExists(dstAssetsPath))
|
||||||
{
|
{
|
||||||
@@ -125,7 +125,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto dstPropertiesPath = data.OutputPath / TEXT("Properties");
|
const auto dstPropertiesPath = data.DataOutputPath / TEXT("Properties");
|
||||||
if (!FileSystem::DirectoryExists(dstPropertiesPath))
|
if (!FileSystem::DirectoryExists(dstPropertiesPath))
|
||||||
{
|
{
|
||||||
if (FileSystem::CreateDirectory(dstPropertiesPath))
|
if (FileSystem::CreateDirectory(dstPropertiesPath))
|
||||||
@@ -177,7 +177,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto dstAppPath = data.OutputPath / TEXT("App.cs");
|
const auto dstAppPath = data.DataOutputPath / TEXT("App.cs");
|
||||||
const auto srcAppPath = uwpDataPath / TEXT("App.cs");
|
const auto srcAppPath = uwpDataPath / TEXT("App.cs");
|
||||||
if (!FileSystem::FileExists(dstAppPath))
|
if (!FileSystem::FileExists(dstAppPath))
|
||||||
{
|
{
|
||||||
@@ -207,7 +207,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const auto dstFlaxGeneratedPath = data.OutputPath / TEXT("FlaxGenerated.cs");
|
const auto dstFlaxGeneratedPath = data.DataOutputPath / TEXT("FlaxGenerated.cs");
|
||||||
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
|
const auto srcFlaxGeneratedPath = uwpDataPath / TEXT("FlaxGenerated.cs");
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
@@ -267,7 +267,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create solution
|
// Create solution
|
||||||
const auto dstSolutionPath = data.OutputPath / projectName + TEXT(".sln");
|
const auto dstSolutionPath = data.DataOutputPath / projectName + TEXT(".sln");
|
||||||
const auto srcSolutionPath = uwpDataPath / TEXT("Solution.sln");
|
const auto srcSolutionPath = uwpDataPath / TEXT("Solution.sln");
|
||||||
if (!FileSystem::FileExists(dstSolutionPath))
|
if (!FileSystem::FileExists(dstSolutionPath))
|
||||||
{
|
{
|
||||||
@@ -301,7 +301,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create project
|
// Create project
|
||||||
const auto dstProjectPath = data.OutputPath / projectName + TEXT(".csproj");
|
const auto dstProjectPath = data.DataOutputPath / projectName + TEXT(".csproj");
|
||||||
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
|
const auto srcProjectPath = uwpDataPath / TEXT("Project.csproj");
|
||||||
{
|
{
|
||||||
// Get template
|
// Get template
|
||||||
@@ -352,7 +352,7 @@ bool UWPPlatformTools::OnDeployBinaries(CookingData& data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create manifest
|
// Create manifest
|
||||||
const auto dstManifestPath = data.OutputPath / TEXT("Package.appxmanifest");
|
const auto dstManifestPath = data.DataOutputPath / TEXT("Package.appxmanifest");
|
||||||
const auto srcManifestPath = uwpDataPath / TEXT("Package.appxmanifest");
|
const auto srcManifestPath = uwpDataPath / TEXT("Package.appxmanifest");
|
||||||
if (!FileSystem::FileExists(dstManifestPath))
|
if (!FileSystem::FileExists(dstManifestPath))
|
||||||
{
|
{
|
||||||
@@ -490,8 +490,8 @@ bool UWPPlatformTools::OnPostProcess(CookingData& data)
|
|||||||
// Special case for UWP
|
// Special case for UWP
|
||||||
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
|
// FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll)
|
||||||
// Use special directory for it (generated UWP project handles this case and copies lib to the output)
|
// Use special directory for it (generated UWP project handles this case and copies lib to the output)
|
||||||
const String assembliesPath = data.OutputPath;
|
const String assembliesPath = data.DataOutputPath;
|
||||||
const auto dstPath1 = data.OutputPath / TEXT("DataSecondary");
|
const auto dstPath1 = data.DataOutputPath / TEXT("DataSecondary");
|
||||||
if (!FileSystem::DirectoryExists(dstPath1))
|
if (!FileSystem::DirectoryExists(dstPath1))
|
||||||
{
|
{
|
||||||
if (FileSystem::CreateDirectory(dstPath1))
|
if (FileSystem::CreateDirectory(dstPath1))
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ ArchitectureType WindowsPlatformTools::GetArchitecture() const
|
|||||||
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
|
bool WindowsPlatformTools::OnDeployBinaries(CookingData& data)
|
||||||
{
|
{
|
||||||
const auto platformSettings = WindowsPlatformSettings::Get();
|
const auto platformSettings = WindowsPlatformSettings::Get();
|
||||||
const auto& outputPath = data.OutputPath;
|
const auto& outputPath = data.CodeOutputPath;
|
||||||
|
|
||||||
// Apply executable icon
|
// Apply executable icon
|
||||||
Array<String> files;
|
Array<String> files;
|
||||||
|
|||||||
@@ -144,8 +144,8 @@ public:
|
|||||||
AotConfig(CookingData& data)
|
AotConfig(CookingData& data)
|
||||||
{
|
{
|
||||||
Platform::GetEnvironmentVariables(EnvVars);
|
Platform::GetEnvironmentVariables(EnvVars);
|
||||||
EnvVars[TEXT("MONO_PATH")] = data.OutputPath / TEXT("Mono/lib/mono/4.5");
|
EnvVars[TEXT("MONO_PATH")] = data.DataOutputPath / TEXT("Mono/lib/mono/4.5");
|
||||||
AssembliesSearchDirs.Add(data.OutputPath / TEXT("Mono/lib/mono/4.5"));
|
AssembliesSearchDirs.Add(data.DataOutputPath / TEXT("Mono/lib/mono/4.5"));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
|||||||
}
|
}
|
||||||
for (auto& file : files)
|
for (auto& file : files)
|
||||||
{
|
{
|
||||||
const String dst = data.OutputPath / StringUtils::GetFileName(file);
|
const String dst = data.CodeOutputPath / StringUtils::GetFileName(file);
|
||||||
if (dst != file && FileSystem::CopyFile(dst, file))
|
if (dst != file && FileSystem::CopyFile(dst, file))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to copy file from {0} to {1}."), file, dst);
|
data.Error(TEXT("Failed to copy file from {0} to {1}."), file, dst);
|
||||||
@@ -294,7 +294,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
writer.EndObject();
|
writer.EndObject();
|
||||||
|
|
||||||
const String outputBuildInfo = data.OutputPath / TEXT("Game.Build.json");
|
const String outputBuildInfo = data.CodeOutputPath / TEXT("Game.Build.json");
|
||||||
if (File::WriteAllBytes(outputBuildInfo, (byte*)buffer.GetString(), (int32)buffer.GetSize()))
|
if (File::WriteAllBytes(outputBuildInfo, (byte*)buffer.GetString(), (int32)buffer.GetSize()))
|
||||||
{
|
{
|
||||||
LOG(Error, "Failed to save binary modules info file {0}.", outputBuildInfo);
|
LOG(Error, "Failed to save binary modules info file {0}.", outputBuildInfo);
|
||||||
|
|||||||
@@ -869,7 +869,7 @@ public:
|
|||||||
// Create package
|
// Create package
|
||||||
// Note: FlaxStorage::Create overrides chunks locations in file so don't use files anymore (only readonly)
|
// Note: FlaxStorage::Create overrides chunks locations in file so don't use files anymore (only readonly)
|
||||||
const String localPath = String::Format(TEXT("Content/Data_{0}.{1}"), _packageIndex, PACKAGE_FILES_EXTENSION);
|
const String localPath = String::Format(TEXT("Content/Data_{0}.{1}"), _packageIndex, PACKAGE_FILES_EXTENSION);
|
||||||
const String path = data.OutputPath / localPath;
|
const String path = data.DataOutputPath / localPath;
|
||||||
if (FlaxStorage::Create(path, assetsData, false, &CustomData))
|
if (FlaxStorage::Create(path, assetsData, false, &CustomData))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to create assets package."));
|
data.Error(TEXT("Failed to create assets package."));
|
||||||
@@ -1035,7 +1035,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
gameFlags |= GameHeaderFlags::ShowSplashScreen;
|
gameFlags |= GameHeaderFlags::ShowSplashScreen;
|
||||||
|
|
||||||
// Open file
|
// Open file
|
||||||
auto stream = FileWriteStream::Open(data.OutputPath / TEXT("Content/head"));
|
auto stream = FileWriteStream::Open(data.DataOutputPath / TEXT("Content/head"));
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to create game data file."));
|
data.Error(TEXT("Failed to create game data file."));
|
||||||
@@ -1129,7 +1129,7 @@ bool CookAssetsStep::Perform(CookingData& data)
|
|||||||
BUILD_STEP_CANCEL_CHECK;
|
BUILD_STEP_CANCEL_CHECK;
|
||||||
|
|
||||||
// Save assets cache
|
// Save assets cache
|
||||||
if (AssetsCache::Save(data.OutputPath / TEXT("Content/AssetsCache.dat"), AssetsRegistry, AssetPathsMapping, AssetsCacheFlags::RelativePaths))
|
if (AssetsCache::Save(data.DataOutputPath / TEXT("Content/AssetsCache.dat"), AssetsRegistry, AssetPathsMapping, AssetsCacheFlags::RelativePaths))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to create assets registry."));
|
data.Error(TEXT("Failed to create assets registry."));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
const auto gameSettings = GameSettings::Get();
|
const auto gameSettings = GameSettings::Get();
|
||||||
|
|
||||||
// Setup output folders and copy required data
|
// Setup output folders and copy required data
|
||||||
const auto contentDir = data.OutputPath / TEXT("Content");
|
const auto contentDir = data.DataOutputPath / TEXT("Content");
|
||||||
if (FileSystem::DirectoryExists(contentDir))
|
if (FileSystem::DirectoryExists(contentDir))
|
||||||
{
|
{
|
||||||
// Remove old content files
|
// Remove old content files
|
||||||
@@ -26,7 +26,7 @@ bool DeployDataStep::Perform(CookingData& data)
|
|||||||
}
|
}
|
||||||
FileSystem::CreateDirectory(contentDir);
|
FileSystem::CreateDirectory(contentDir);
|
||||||
const auto srcMono = depsRoot / TEXT("Mono");
|
const auto srcMono = depsRoot / TEXT("Mono");
|
||||||
const auto dstMono = data.OutputPath / TEXT("Mono");
|
const auto dstMono = data.DataOutputPath / TEXT("Mono");
|
||||||
if (!FileSystem::DirectoryExists(dstMono))
|
if (!FileSystem::DirectoryExists(dstMono))
|
||||||
{
|
{
|
||||||
if (!FileSystem::DirectoryExists(srcMono))
|
if (!FileSystem::DirectoryExists(srcMono))
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
|
|||||||
data.Tools->OnConfigureAOT(data, config);
|
data.Tools->OnConfigureAOT(data, config);
|
||||||
|
|
||||||
// Prepare output directory
|
// Prepare output directory
|
||||||
config.AotCachePath = data.OutputPath / TEXT("Mono/lib/mono/aot-cache");
|
config.AotCachePath = data.DataOutputPath / TEXT("Mono/lib/mono/aot-cache");
|
||||||
switch (data.Tools->GetArchitecture())
|
switch (data.Tools->GetArchitecture())
|
||||||
{
|
{
|
||||||
case ArchitectureType::x86:
|
case ArchitectureType::x86:
|
||||||
@@ -52,9 +52,9 @@ bool PrecompileAssembliesStep::Perform(CookingData& data)
|
|||||||
FileSystem::DirectoryGetFiles(config.Assemblies, dir, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
|
FileSystem::DirectoryGetFiles(config.Assemblies, dir, TEXT("*.dll"), DirectorySearchOption::TopDirectoryOnly);
|
||||||
for (auto& binaryModule : data.BinaryModules)
|
for (auto& binaryModule : data.BinaryModules)
|
||||||
if (binaryModule.ManagedPath.HasChars())
|
if (binaryModule.ManagedPath.HasChars())
|
||||||
config.Assemblies.Add(data.OutputPath / binaryModule.ManagedPath);
|
config.Assemblies.Add(data.CodeOutputPath / binaryModule.ManagedPath);
|
||||||
// TODO: move AOT to Flax.Build and perform it on all C# assemblies used in target build
|
// TODO: move AOT to Flax.Build and perform it on all C# assemblies used in target build
|
||||||
config.Assemblies.Add(data.OutputPath / TEXT("Newtonsoft.Json.dll"));
|
config.Assemblies.Add(data.CodeOutputPath / TEXT("Newtonsoft.Json.dll"));
|
||||||
|
|
||||||
// Perform AOT for the assemblies
|
// Perform AOT for the assemblies
|
||||||
for (int32 i = 0; i < config.Assemblies.Count(); i++)
|
for (int32 i = 0; i < config.Assemblies.Count(); i++)
|
||||||
|
|||||||
@@ -11,9 +11,17 @@ bool ValidateStep::Perform(CookingData& data)
|
|||||||
data.StepProgress(TEXT("Performing validation"), 0);
|
data.StepProgress(TEXT("Performing validation"), 0);
|
||||||
|
|
||||||
// Ensure output and cache directories exist
|
// Ensure output and cache directories exist
|
||||||
if (!FileSystem::DirectoryExists(data.OutputPath))
|
if (!FileSystem::DirectoryExists(data.CodeOutputPath))
|
||||||
{
|
{
|
||||||
if (FileSystem::CreateDirectory(data.OutputPath))
|
if (FileSystem::CreateDirectory(data.CodeOutputPath))
|
||||||
|
{
|
||||||
|
data.Error(TEXT("Failed to create build output directory."));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!FileSystem::DirectoryExists(data.DataOutputPath))
|
||||||
|
{
|
||||||
|
if (FileSystem::CreateDirectory(data.DataOutputPath))
|
||||||
{
|
{
|
||||||
data.Error(TEXT("Failed to create build output directory."));
|
data.Error(TEXT("Failed to create build output directory."));
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user