diff --git a/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.cpp b/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.cpp new file mode 100644 index 000000000..803336f4a --- /dev/null +++ b/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.cpp @@ -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 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 diff --git a/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.h b/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.h new file mode 100644 index 000000000..20e2cff0e --- /dev/null +++ b/Source/Editor/Cooker/Platform/Mac/MacPlatformTools.h @@ -0,0 +1,29 @@ +// Copyright (c) 2012-2019 Wojciech Figat. All rights reserved. + +#pragma once + +#if PLATFORM_TOOLS_MAC + +#include "../../PlatformTools.h" + +/// +/// The Mac platform support tools. +/// +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 diff --git a/Source/Editor/Scripting/ScriptsBuilder.cpp b/Source/Editor/Scripting/ScriptsBuilder.cpp index 5becec64c..1cfd838cd 100644 --- a/Source/Editor/Scripting/ScriptsBuilder.cpp +++ b/Source/Editor/Scripting/ScriptsBuilder.cpp @@ -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)) { diff --git a/Source/Engine/Platform/Mac/MacPlatform.cpp b/Source/Engine/Platform/Mac/MacPlatform.cpp index be5e2fe24..76c846d57 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.cpp +++ b/Source/Engine/Platform/Mac/MacPlatform.cpp @@ -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& 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(), waitForEnd, false); +} + +int32 MacPlatform::RunProcess(const StringView& cmdLine, const StringView& workingDir, bool hiddenWindow) +{ + return MacProcess(cmdLine, workingDir, Dictionary(), true, true); +} + +int32 MacPlatform::RunProcess(const StringView& cmdLine, const StringView& workingDir, const Dictionary& environment, bool hiddenWindow) +{ + return MacProcess(cmdLine, workingDir, environment, true, true); +} + void* MacPlatform::LoadLibrary(const Char* filename) { const StringAsANSI<> filenameANSI(filename); diff --git a/Source/Engine/Platform/Mac/MacPlatform.h b/Source/Engine/Platform/Mac/MacPlatform.h index b0315fb71..c701092f2 100644 --- a/Source/Engine/Platform/Mac/MacPlatform.h +++ b/Source/Engine/Platform/Mac/MacPlatform.h @@ -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& environment, bool hiddenWindow = true); static void* LoadLibrary(const Char* filename); static void FreeLibrary(void* handle); static void* GetProcAddress(void* handle, const char* symbol); diff --git a/Source/Engine/Scripting/ManagedCLR/MCore.cpp b/Source/Engine/Scripting/ManagedCLR/MCore.cpp index d58bcbd95..2e4ecf7ee 100644 --- a/Source/Engine/Scripting/ManagedCLR/MCore.cpp +++ b/Source/Engine/Scripting/ManagedCLR/MCore.cpp @@ -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 diff --git a/Source/Engine/Scripting/ScriptingObject.cpp b/Source/Engine/Scripting/ScriptingObject.cpp index c5c6b9dab..5d4c16825 100644 --- a/Source/Engine/Scripting/ScriptingObject.cpp +++ b/Source/Engine/Scripting/ScriptingObject.cpp @@ -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 @@ -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 diff --git a/Source/Platforms/Mac/Binaries/ThirdParty/x64/libIrrXML.a b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libIrrXML.a new file mode 100644 index 000000000..792b3daf5 --- /dev/null +++ b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libIrrXML.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b67f00759cb59c91e5fe3fcf8bc107c6ac5f54c1929cea246892298ec40f6ec +size 543624 diff --git a/Source/Platforms/Mac/Binaries/ThirdParty/x64/libassimp.a b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libassimp.a new file mode 100644 index 000000000..d0b42ce75 --- /dev/null +++ b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libassimp.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2f84848d7cd072db46c89ce45d469eea744bf1ebbbea245a1a0be7d4d431e14b +size 67715584 diff --git a/Source/Platforms/Mac/Binaries/ThirdParty/x64/libcurl.a b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libcurl.a new file mode 100644 index 000000000..af7cb482f --- /dev/null +++ b/Source/Platforms/Mac/Binaries/ThirdParty/x64/libcurl.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0b026aecb9d59e59252e80d6f9b84caafd0189293f3a1bcadba8121451a522f7 +size 486072 diff --git a/Source/ThirdParty/curl/curl.Build.cs b/Source/ThirdParty/curl/curl.Build.cs index ce4c9d380..0d5472a59 100644 --- a/Source/ThirdParty/curl/curl.Build.cs +++ b/Source/ThirdParty/curl/curl.Build.cs @@ -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); } diff --git a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs index 589ab72bb..1026b3a64 100644 --- a/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs +++ b/Source/Tools/Flax.Build/Build/DotNet/Builder.DotNet.cs @@ -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); } diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs index 1c671f4b4..6ff98135c 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs @@ -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; diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs index 6461706df..959b584db 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs @@ -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 { { "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 + { + { "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; diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/mono.cs b/Source/Tools/Flax.Build/Deps/Dependencies/mono.cs index 73ecbbb35..1576399b7 100644 --- a/Source/Tools/Flax.Build/Deps/Dependencies/mono.cs +++ b/Source/Tools/Flax.Build/Deps/Dependencies/mono.cs @@ -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"); diff --git a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs index 04b98c36c..da87519ed 100644 --- a/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs +++ b/Source/Tools/Flax.Build/Platforms/Mac/MacToolchain.cs @@ -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