Progress on packaging for macOS
This commit is contained in:
@@ -9,6 +9,8 @@
|
||||
#include "Editor/Utilities/EditorUtilities.h"
|
||||
#include "Engine/Content/Content.h"
|
||||
#include "Engine/Content/JsonAsset.h"
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
|
||||
IMPLEMENT_SETTINGS_GETTER(MacPlatformSettings, MacPlatform);
|
||||
|
||||
@@ -37,56 +39,59 @@ ArchitectureType MacPlatformTools::GetArchitecture() const
|
||||
return _arch;
|
||||
}
|
||||
|
||||
bool MacPlatformTools::OnDeployBinaries(CookingData& data)
|
||||
void MacPlatformTools::OnBuildStarted(CookingData& data)
|
||||
{
|
||||
// Adjust the cooking output folders for packaging app
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
String productName = gameSettings->ProductName;
|
||||
productName.Replace(TEXT(" "), TEXT(""));
|
||||
productName.Replace(TEXT("."), TEXT(""));
|
||||
productName.Replace(TEXT("-"), TEXT(""));
|
||||
String contents = productName + TEXT(".app/Contents/");
|
||||
data.DataOutputPath /= contents;
|
||||
data.NativeCodeOutputPath /= contents;
|
||||
data.ManagedCodeOutputPath /= contents;
|
||||
|
||||
PlatformTools::OnBuildStarted(data);
|
||||
}
|
||||
|
||||
bool MacPlatformTools::OnPostProcess(CookingData& data)
|
||||
{
|
||||
const auto gameSettings = GameSettings::Get();
|
||||
const auto platformSettings = MacPlatformSettings::Get();
|
||||
const auto outputPath = data.DataOutputPath;
|
||||
const auto platformDataPath = data.GetPlatformBinariesRoot();
|
||||
const auto projectVersion = Editor::Project->Version.ToString();
|
||||
|
||||
// Copy binaries
|
||||
// Setup package name (eg. com.company.project)
|
||||
String appIdentifier = platformSettings->AppIdentifier;
|
||||
{
|
||||
if (!FileSystem::DirectoryExists(outputPath))
|
||||
FileSystem::CreateDirectory(outputPath);
|
||||
const auto binPath = data.GetGameBinariesPath();
|
||||
|
||||
// Gather files to deploy
|
||||
Array<String> files;
|
||||
files.Add(binPath / TEXT("FlaxGame"));
|
||||
FileSystem::DirectoryGetFiles(files, binPath, TEXT("*.a"), DirectorySearchOption::TopDirectoryOnly);
|
||||
|
||||
// Copy data
|
||||
for (int32 i = 0; i < files.Count(); i++)
|
||||
String productName = gameSettings->ProductName;
|
||||
productName.Replace(TEXT(" "), TEXT(""));
|
||||
productName.Replace(TEXT("."), TEXT(""));
|
||||
productName.Replace(TEXT("-"), TEXT(""));
|
||||
String companyName = gameSettings->CompanyName;
|
||||
companyName.Replace(TEXT(" "), TEXT(""));
|
||||
companyName.Replace(TEXT("."), TEXT(""));
|
||||
companyName.Replace(TEXT("-"), TEXT(""));
|
||||
appIdentifier.Replace(TEXT("${PROJECT_NAME}"), *productName, StringSearchCase::IgnoreCase);
|
||||
appIdentifier.Replace(TEXT("${COMPANY_NAME}"), *companyName, StringSearchCase::IgnoreCase);
|
||||
appIdentifier = appIdentifier.ToLower();
|
||||
for (int32 i = 0; i < appIdentifier.Length(); i++)
|
||||
{
|
||||
if (FileSystem::CopyFile(outputPath / StringUtils::GetFileName(files[i]), files[i]))
|
||||
const auto c = appIdentifier[i];
|
||||
if (c != '_' && c != '.' && !StringUtils::IsAlnum(c))
|
||||
{
|
||||
data.Error(TEXT("Failed to setup output directory."));
|
||||
LOG(Error, "Apple app identifier \'{0}\' contains invalid character. Only letters, numbers, dots and underscore characters are allowed.", appIdentifier);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (appIdentifier.IsEmpty())
|
||||
{
|
||||
LOG(Error, "Apple app identifier is empty.", appIdentifier);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply game executable file name
|
||||
#if !BUILD_DEBUG
|
||||
const String outputExePath = outputPath / TEXT("FlaxGame");
|
||||
const String gameExePath = outputPath / gameSettings->ProductName;
|
||||
if (FileSystem::FileExists(outputExePath) && gameExePath.Compare(outputExePath, StringSearchCase::IgnoreCase) != 0)
|
||||
{
|
||||
if (FileSystem::MoveFile(gameExePath, outputExePath, true))
|
||||
{
|
||||
data.Error(TEXT("Failed to rename output executable file."));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Don't change application name on a DEBUG build (for build game debugging)
|
||||
const String gameExePath = outputPath / TEXT("FlaxGame");
|
||||
#endif
|
||||
|
||||
// Ensure the output binary can be executed
|
||||
#if PLATFORM_MAC
|
||||
system(*StringAnsi(String::Format(TEXT("chmod +x \"{0}\""), gameExePath)));
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
const Char* GetName() const override;
|
||||
PlatformType GetPlatform() const override;
|
||||
ArchitectureType GetArchitecture() const override;
|
||||
bool OnDeployBinaries(CookingData& data) override;
|
||||
void OnBuildStarted(CookingData& data) override;
|
||||
bool OnPostProcess(CookingData& data) override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include "Editor/Editor.h"
|
||||
#include "Editor/ProjectInfo.h"
|
||||
#include "Engine/Engine/Globals.h"
|
||||
#if PLATFORM_MAC
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, const String& projectFolderPath)
|
||||
{
|
||||
@@ -122,11 +125,22 @@ bool CompileScriptsStep::DeployBinaries(CookingData& data, const String& path, c
|
||||
{
|
||||
const String& dstPath = data.Tools->IsNativeCodeFile(data, file) ? data.NativeCodeOutputPath : data.ManagedCodeOutputPath;
|
||||
const String dst = dstPath / StringUtils::GetFileName(file);
|
||||
if (dst != file && FileSystem::CopyFile(dst, file))
|
||||
if (dst == file)
|
||||
continue;
|
||||
if (FileSystem::CopyFile(dst, file))
|
||||
{
|
||||
data.Error(TEXT("Failed to copy file from {0} to {1}."), file, dst);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if PLATFORM_MAC
|
||||
// Ensure to keep valid file permissions for executable files
|
||||
const StringAsANSI<> fileANSI(*file, file.Length());
|
||||
const StringAsANSI<> dstANSI(*dst, dst.Length());
|
||||
struct stat st;
|
||||
stat(fileANSI.Get(), &st);
|
||||
chmod(dstANSI.Get(), st.st_mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -209,6 +223,7 @@ bool CompileScriptsStep::Perform(CookingData& data)
|
||||
_extensionsToSkip.Add(TEXT(".lib"));
|
||||
_extensionsToSkip.Add(TEXT(".a"));
|
||||
_extensionsToSkip.Add(TEXT(".Build.json"));
|
||||
_extensionsToSkip.Add(TEXT(".DS_Store"));
|
||||
if (data.Configuration == BuildConfiguration::Release)
|
||||
{
|
||||
_extensionsToSkip.Add(TEXT(".xml"));
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#if PLATFORM_MAC || USE_EDITOR
|
||||
|
||||
#include "Engine/Core/Config/PlatformSettingsBase.h"
|
||||
#include "Engine/Core/Types/String.h"
|
||||
|
||||
/// <summary>
|
||||
/// Mac platform settings.
|
||||
@@ -13,6 +14,13 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
{
|
||||
DECLARE_SCRIPTING_TYPE_MINIMAL(MacPlatformSettings);
|
||||
|
||||
/// <summary>
|
||||
/// The app identifier (reversed DNS, eg. com.company.product). Custom tokens: ${PROJECT_NAME}, ${COMPANY_NAME}.
|
||||
/// </summary>
|
||||
API_FIELD(Attributes="EditorOrder(0), EditorDisplay(\"General\")")
|
||||
String AppIdentifier = TEXT("com.${COMPANY_NAME}.${PROJECT_NAME}");
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||
/// </summary>
|
||||
@@ -21,6 +29,7 @@ API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings") class FLAXENGINE_API
|
||||
// [SettingsBase]
|
||||
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override
|
||||
{
|
||||
DESERIALIZE(AppIdentifier);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user