Mac impl progress

This commit is contained in:
2022-01-03 13:59:52 +01:00
parent 9b991bcfdf
commit ca62cd2661
16 changed files with 294 additions and 20 deletions
@@ -0,0 +1,93 @@
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
#if PLATFORM_TOOLS_MAC
#include "MacPlatformTools.h"
#include "Engine/Platform/FileSystem.h"
#include "Engine/Platform/Mac/MacPlatformSettings.h"
#include "Engine/Core/Config/GameSettings.h"
#include "Editor/Utilities/EditorUtilities.h"
#include "Engine/Content/Content.h"
#include "Engine/Content/JsonAsset.h"
IMPLEMENT_SETTINGS_GETTER(MacPlatformSettings, MacPlatform);
MacPlatformTools::MacPlatformTools(ArchitectureType arch)
: _arch(arch)
{
}
const Char* MacPlatformTools::GetDisplayName() const
{
return TEXT("Mac");
}
const Char* MacPlatformTools::GetName() const
{
return TEXT("Mac");
}
PlatformType MacPlatformTools::GetPlatform() const
{
return PlatformType::Mac;
}
ArchitectureType MacPlatformTools::GetArchitecture() const
{
return _arch;
}
bool MacPlatformTools::OnDeployBinaries(CookingData& data)
{
const auto gameSettings = GameSettings::Get();
const auto platformSettings = MacPlatformSettings::Get();
const auto outputPath = data.DataOutputPath;
// Copy binaries
{
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++)
{
if (FileSystem::CopyFile(outputPath / StringUtils::GetFileName(files[i]), files[i]))
{
data.Error(TEXT("Failed to setup output directory."));
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;
}
#endif
@@ -0,0 +1,29 @@
// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved.
#pragma once
#if PLATFORM_TOOLS_MAC
#include "../../PlatformTools.h"
/// <summary>
/// The Mac platform support tools.
/// </summary>
class MacPlatformTools : public PlatformTools
{
private:
ArchitectureType _arch;
public:
MacPlatformTools(ArchitectureType arch);
// [PlatformTools]
const Char* GetDisplayName() const override;
const Char* GetName() const override;
PlatformType GetPlatform() const override;
ArchitectureType GetArchitecture() const override;
bool OnDeployBinaries(CookingData& data) override;
};
#endif
+1 -1
View File
@@ -223,7 +223,7 @@ bool ScriptsBuilder::RunBuildTool(const StringView& args, const StringView& work
// Prepare build options
StringBuilder cmdLine(args.Length() + buildToolPath.Length() + 200);
#if PLATFORM_LINUX
#if PLATFORM_LINUX || PLATFORM_MAC
const String monoPath = Globals::MonoPath / TEXT("bin/mono");
if (!FileSystem::FileExists(monoPath))
{
@@ -586,6 +586,67 @@ bool MacPlatform::SetEnvironmentVariable(const String& name, const String& value
return setenv(StringAsANSI<>(*name).Get(), StringAsANSI<>(*value).Get(), true) != 0;
}
int32 MacProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String>& environment, bool waitForEnd, bool logOutput)
{
LOG(Info, "Command: {0}", cmdLine);
if (workingDir.Length() != 0)
LOG(Info, "Working directory: {0}", workingDir);
StringAsANSI<> cmdLineAnsi(*cmdLine, cmdLine.Length());
FILE* pipe = popen(cmdLineAnsi.Get(), "r");
if (!pipe)
{
LOG(Warning, "Failed to start process, errno={}", errno);
return -1;
}
// TODO: workingDir
// TODO: environment
int32 returnCode = 0;
if (waitForEnd)
{
int stat_loc;
if (logOutput)
{
char lineBuffer[1024];
while (fgets(lineBuffer, sizeof(lineBuffer), pipe) != NULL)
{
char *p = lineBuffer + strlen(lineBuffer) - 1;
if (*p == '\n') *p=0;
Log::Logger::Write(LogType::Info, String(lineBuffer));
}
}
else
{
while (!feof(pipe))
{
sleep(1);
}
}
}
return returnCode;
}
int32 MacPlatform::StartProcess(const StringView& filename, const StringView& args, const StringView& workingDir, bool hiddenWindow, bool waitForEnd)
{
// hiddenWindow has hardly any meaning on UNIX/Linux/OSX as the program that is called decides whether it has a GUI or not
String cmdLine(filename);
if (args.HasChars()) cmdLine = cmdLine + TEXT(" ") + args;
return MacProcess(cmdLine, workingDir, Dictionary<String, String>(), waitForEnd, false);
}
int32 MacPlatform::RunProcess(const StringView& cmdLine, const StringView& workingDir, bool hiddenWindow)
{
return MacProcess(cmdLine, workingDir, Dictionary<String, String>(), true, true);
}
int32 MacPlatform::RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String>& environment, bool hiddenWindow)
{
return MacProcess(cmdLine, workingDir, environment, true, true);
}
void* MacPlatform::LoadLibrary(const Char* filename)
{
const StringAsANSI<> filenameANSI(filename);
+3
View File
@@ -106,6 +106,9 @@ public:
static Window* CreateWindow(const CreateWindowSettings& settings);
static bool GetEnvironmentVariable(const String& name, String& value);
static bool SetEnvironmentVariable(const String& name, const String& value);
static int32 StartProcess(const StringView& filename, const StringView& args, const StringView& workingDir, bool hiddenWindow = false, bool waitForEnd = false);
static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, bool hiddenWindow = true);
static int32 RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary<String, String, HeapAllocation>& environment, bool hiddenWindow = true);
static void* LoadLibrary(const Char* filename);
static void FreeLibrary(void* handle);
static void* GetProcAddress(void* handle, const char* symbol);
@@ -492,6 +492,9 @@ bool MCore::LoadEngine()
ThisLibHandle = dlopen(nullptr, RTLD_LAZY);
mono_dl_fallback_register(OnMonoLinuxDlOpen, OnMonoLinuxDlSym, nullptr, nullptr);
#endif
#elif PLATFORM_MAC
// Adjust GC threads suspending mode on Mac
Platform::SetEnvironmentVariable(TEXT("MONO_THREADS_SUSPEND"), TEXT("preemptive"));
#endif
const char* configPath = nullptr;
#if PLATFORM_SWITCH
+1 -3
View File
@@ -14,9 +14,7 @@
#include "ManagedCLR/MClass.h"
#include "ManagedCLR/MUtils.h"
#include "ManagedCLR/MField.h"
#if PLATFORM_LINUX
#include "ManagedCLR/MCore.h"
#endif
#include "FlaxEngine.Gen.h"
#if USE_MONO
#include <ThirdParty/mono-2.0/mono/metadata/object.h>
@@ -324,7 +322,7 @@ bool ScriptingObject::CanCast(MClass* from, MClass* to)
return true;
CHECK_RETURN(from && to, false);
#if PLATFORM_LINUX
#if PLATFORM_LINUX || PLATFORM_MAC
// Cannot enter GC unsafe region if the thread is not attached
MCore::AttachThread();
#endif
Binary file not shown.
Binary file not shown.
Binary file not shown.
+3
View File
@@ -38,8 +38,11 @@ public class curl : DepsModule
options.OutputFiles.Add("crypt32.lib");
break;
case TargetPlatform.Linux:
options.OutputFiles.Add(Path.Combine(depsRoot, "libcurl.a"));
break;
case TargetPlatform.Mac:
options.OutputFiles.Add(Path.Combine(depsRoot, "libcurl.a"));
options.OutputFiles.Add("Security.framework");
break;
default: throw new InvalidPlatformException(options.Platform.Target);
}
@@ -71,10 +71,9 @@ namespace Flax.Build
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
break;
case TargetPlatform.Mac:
// TODO: use bundled mono for Mac with csc
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Linux", "Mono");
monoPath = null;
cscPath = "csc";
monoRoot = Path.Combine(Globals.EngineRoot, "Source", "Platforms", "Editor", "Mac", "Mono");
monoPath = Path.Combine(monoRoot, "bin", "mono");
cscPath = Path.Combine(monoRoot, "lib", "mono", "4.5", "csc.exe");
break;
default: throw new InvalidPlatformException(buildPlatform);
}
@@ -29,6 +29,11 @@ namespace Flax.Deps.Dependencies
{
TargetPlatform.Linux,
};
case TargetPlatform.Mac:
return new[]
{
TargetPlatform.Mac,
};
default: return new TargetPlatform[0];
}
}
@@ -100,9 +105,9 @@ namespace Flax.Deps.Dependencies
// Build for Win64
File.Delete(Path.Combine(root, "CMakeCache.txt"));
RunCmake(root, TargetPlatform.Windows, TargetArchitecture.x64);
RunCmake(root, platform, TargetArchitecture.x64);
Deploy.VCEnvironment.BuildSolution(solutionPath, configuration, "x64");
var depsFolder = GetThirdPartyFolder(options, TargetPlatform.Windows, TargetArchitecture.x64);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
foreach (var file in binariesWin)
{
Utilities.FileCopy(file, Path.Combine(depsFolder, Path.GetFileName(file)));
@@ -113,9 +118,19 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Linux:
{
// Build for Linux
RunCmake(root, TargetPlatform.Linux, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
RunCmake(root, platform, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None);
var depsFolder = GetThirdPartyFolder(options, TargetPlatform.Linux, TargetArchitecture.x64);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Utilities.FileCopy(Path.Combine(root, "lib", "libassimp.a"), Path.Combine(depsFolder, "libassimp.a"));
Utilities.FileCopy(Path.Combine(root, "lib", "libIrrXML.a"), Path.Combine(depsFolder, "libIrrXML.a"));
break;
}
case TargetPlatform.Mac:
{
// Build for Mac
RunCmake(root, platform, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Utilities.FileCopy(Path.Combine(root, "lib", "libassimp.a"), Path.Combine(depsFolder, "libassimp.a"));
Utilities.FileCopy(Path.Combine(root, "lib", "libIrrXML.a"), Path.Combine(depsFolder, "libIrrXML.a"));
break;
@@ -31,6 +31,11 @@ namespace Flax.Deps.Dependencies
{
TargetPlatform.Linux,
};
case TargetPlatform.Mac:
return new[]
{
TargetPlatform.Mac,
};
default: return new TargetPlatform[0];
}
}
@@ -54,10 +59,12 @@ namespace Flax.Deps.Dependencies
};
// Get the source
Downloader.DownloadFileFromUrlToPath("https://curl.haxx.se/download/curl-7.64.1.zip", packagePath);
if (!File.Exists(packagePath))
Downloader.DownloadFileFromUrlToPath("https://curl.haxx.se/download/curl-7.64.1.zip", packagePath);
using (ZipArchive archive = ZipFile.Open(packagePath, ZipArchiveMode.Read))
{
archive.ExtractToDirectory(root);
if (!Directory.Exists(root))
archive.ExtractToDirectory(root);
root = Path.Combine(root, archive.Entries.First().FullName);
}
@@ -78,7 +85,7 @@ namespace Flax.Deps.Dependencies
{
// Build for Win64
Deploy.VCEnvironment.BuildSolution(vsSolutionPath, configuration, "x64");
var depsFolder = GetThirdPartyFolder(options, TargetPlatform.Windows, TargetArchitecture.x64);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
foreach (var filename in binariesToCopyWin)
Utilities.FileCopy(Path.Combine(root, "build", "Win64", vcVersion, configuration, filename), Path.Combine(depsFolder, Path.GetFileName(filename)));
}
@@ -89,7 +96,7 @@ namespace Flax.Deps.Dependencies
// Build for Linux
var settings = new []
{
"-without-librtmp",
"--without-librtmp",
"--without-ssl",
"--with-gnutls",
"--disable-ipv6",
@@ -102,7 +109,7 @@ namespace Flax.Deps.Dependencies
var envVars = new Dictionary<string, string>
{
{ "CC", "clang-7" },
{ "CC_FOR_BUILD", "clang-7" }
{ "CC_FOR_BUILD", "clang-7" },
};
var buildDir = Path.Combine(root, "build");
SetupDirectory(buildDir, true);
@@ -110,7 +117,45 @@ namespace Flax.Deps.Dependencies
Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None);
Utilities.Run("make", "install", null, root, Utilities.RunOptions.None);
var depsFolder = GetThirdPartyFolder(options, TargetPlatform.Linux, TargetArchitecture.x64);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
var filename = "libcurl.a";
Utilities.FileCopy(Path.Combine(buildDir, "lib", filename), Path.Combine(depsFolder, filename));
break;
}
case TargetPlatform.Mac:
{
// Build for Mac
var settings = new []
{
"--with-secure-transport",
"--without-librtmp",
"--disable-ipv6",
"--disable-manual",
"--disable-verbose",
"--disable-shared",
"--enable-static",
"-disable-ldap --disable-sspi --disable-ftp --disable-file --disable-dict --disable-telnet --disable-tftp --disable-rtsp --disable-pop3 --disable-imap --disable-smtp --disable-gopher --disable-smb",
};
var arch = "x86_64";
var archName = arch + "-apple-darwin18";
var compilerFlags = string.Format("-mmacosx-version-min={0} -arch {1}", Configuration.MacOSXMinVer, arch);
var envVars = new Dictionary<string, string>
{
{ "CFLAGS", compilerFlags },
{ "CXXFLAGS", compilerFlags },
{ "CPPFLAGS", compilerFlags },
{ "ARCH", arch },
{ "SDK", "macosx" },
{ "DEPLOYMENT_TARGET", Configuration.MacOSXMinVer },
};
var buildDir = Path.Combine(root, "build");
SetupDirectory(buildDir, true);
Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.None);
Utilities.Run("chmod", "+x install-sh", null, root, Utilities.RunOptions.None);
Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --host=" + archName + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.None, envVars);
Utilities.Run("make", null, null, root, Utilities.RunOptions.None);
Utilities.Run("make", "install", null, root, Utilities.RunOptions.None);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
var filename = "libcurl.a";
Utilities.FileCopy(Path.Combine(buildDir, "lib", filename), Path.Combine(depsFolder, filename));
break;
@@ -570,6 +570,8 @@ namespace Flax.Deps.Dependencies
var editoBinOutput = Path.Combine(options.PlatformsFolder, "Editor", "Linux", "Mono", "bin");
Utilities.FileCopy(Path.Combine(buildDir, "bin", "mono-sgen"), Path.Combine(editoBinOutput, "mono"));
Utilities.Run("strip", "mono", null, editoBinOutput, Utilities.RunOptions.None);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "etc"), true, true);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Binaries", "Mono", "etc"), true, true);
var srcMonoLibs = Path.Combine(buildDir, "lib", "mono");
var dstMonoLibs = Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "lib", "mono");
var dstMonoEditorLibs = Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Mono", "lib", "mono");
@@ -770,6 +772,8 @@ namespace Flax.Deps.Dependencies
Directory.CreateDirectory(editoBinOutput);
Utilities.FileCopy(Path.Combine(buildDir, "bin", "mono-sgen"), Path.Combine(editoBinOutput, "mono"));
Utilities.Run("strip", "mono", null, editoBinOutput, Utilities.RunOptions.None);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "etc"), true, true);
Utilities.DirectoryCopy(Path.Combine(buildDir, "etc"), Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Binaries", "Mono", "etc"), true, true);
var srcMonoLibs = Path.Combine(buildDir, "lib", "mono");
var dstMonoLibs = Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "Mono", "lib", "mono");
var dstMonoEditorLibs = Path.Combine(options.PlatformsFolder, "Editor", platform.ToString(), "Mono", "lib", "mono");
@@ -306,7 +306,11 @@ namespace Flax.Build.Platforms
{
var dir = Path.GetDirectoryName(library);
var ext = Path.GetExtension(library);
if (string.IsNullOrEmpty(dir))
if (ext == ".framework")
{
args.Add(string.Format("-framework {0}", library.Substring(0, library.Length - ext.Length)));
}
else if (string.IsNullOrEmpty(dir))
{
args.Add(string.Format("\"-l{0}\"", library));
}
@@ -332,7 +336,15 @@ namespace Flax.Build.Platforms
task.PrerequisiteFiles.AddRange(linkEnvironment.InputFiles);
foreach (var file in linkEnvironment.InputFiles)
{
args.Add(string.Format("\"{0}\"", file.Replace('\\', '/')));
var ext = Path.GetExtension(file);
if (ext == ".framework")
{
args.Add(string.Format("-framework {0}", file.Substring(0, file.Length - ext.Length)));
}
else
{
args.Add(string.Format("\"{0}\"", file.Replace('\\', '/')));
}
}
// Additional lib paths