// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. using System; using System.Collections.Generic; using System.IO; using Flax.Build; using Flax.Build.Platforms; namespace Flax.Deps { /// /// Represents a single dependency package required by the engine to be pre-build. /// abstract class Dependency { /// /// The options. /// public class BuildOptions { /// /// The intermediate folder for the deps to be build inside it. /// public string IntermediateFolder; /// /// The output folder for the platform dependencies. /// public string PlatformsFolder; /// /// The ThirdParty header files folder for the deps. /// public string ThirdPartyFolder; /// /// The target platforms to build dependency for (contains only platforms supported by the dependency itself). /// public TargetPlatform[] Platforms; } /// /// Gets the build platform. /// protected static TargetPlatform BuildPlatform => Platform.BuildPlatform.Target; /// /// Gets the platforms list supported by this dependency to build on the current build platform (based on ). /// public abstract TargetPlatform[] Platforms { get; } /// /// Builds the dependency package using the specified options. /// /// The options. public abstract void Build(BuildOptions options); /// /// Gets the dependency third-party packages binaries folder. /// /// The options. /// The target platform. /// The target architecture. /// The absolute path to the deps folder for the given platform and architecture configuration. public static string GetThirdPartyFolder(BuildOptions options, TargetPlatform platform, TargetArchitecture architecture) { return Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries", "ThirdParty", architecture.ToString()); } /// /// Gets the dependency packages binaries folder. /// /// The options. /// The target platform. /// The absolute path to the deps folder for the given platform and architecture configuration. public static string GetBinariesFolder(BuildOptions options, TargetPlatform platform) { return Path.Combine(options.PlatformsFolder, platform.ToString(), "Binaries"); } /// /// Setups the directory. /// /// The path. /// If set to true the directory will be cleared if not empty. public static void SetupDirectory(string path, bool forceEmpty) { if (Directory.Exists(path)) { if (forceEmpty) { Utilities.DirectoryDelete(path); Directory.CreateDirectory(path); } } else { Directory.CreateDirectory(path); } } /// /// Clones the git repository from the remote url (full repository). /// /// The local path for close. /// The remote url. /// The commit to checkout. /// The custom arguments to add to the clone command. public static void CloneGitRepo(string path, string url, string commit = null, string args = null) { if (!Directory.Exists(Path.Combine(path, Path.GetFileNameWithoutExtension(url), ".git"))) { string cmdLine = string.Format("clone \"{0}\" \"{1}\"", url, path); if (args != null) cmdLine += " " + args; Utilities.Run("git", cmdLine, null, null, Utilities.RunOptions.None); } if (commit != null) { Utilities.Run("git", string.Format("reset --hard {0}", commit), null, null, Utilities.RunOptions.None); } } /// /// Clones the git repository from the remote url. /// /// The local path for close. /// The remote url. /// The custom arguments to add to the clone command. public static void CloneGitRepoFast(string path, string url, string args = null) { if (!Directory.Exists(Path.Combine(path, Path.GetFileNameWithoutExtension(url), ".git"))) { string cmdLine = string.Format("clone \"{0}\" \"{1}\" --depth 1", url, path); if (args != null) cmdLine += " " + args; Utilities.Run("git", cmdLine, null, null, Utilities.RunOptions.None); } } /// /// Clones the git repository from the remote url (clones a single branch). /// /// The local path for close. /// The remote url. /// The name of the branch to checkout. /// The commit to checkout. /// The custom arguments to add to the clone command. public static void CloneGitRepoSingleBranch(string path, string url, string branch, string commit = null, string args = null) { if (!Directory.Exists(Path.Combine(path, Path.GetFileNameWithoutExtension(url), ".git"))) { string cmdLine = string.Format("clone --single-branch --branch {2} \"{0}\" \"{1}\"", url, path, branch); if (commit == null) cmdLine += " --depth 1"; if (args != null) cmdLine += " " + args; Utilities.Run("git", cmdLine, null, null, Utilities.RunOptions.None); } if (commit != null) { Utilities.Run("git", string.Format("reset --hard {0}", commit), null, path, Utilities.RunOptions.None); } } /// /// Changes the current branch to the given branch in the git repository (resets all the local changes). Does not perform pull command to update branch with remote repo. /// /// The local path that contains git repository. /// The name of the branch to checkout. /// The commit to checkout. /// The custom arguments to add to the clone command. public static void GitCheckout(string path, string branch, string commit = null, string args = null) { string cmdLine = string.Format("checkout -B {0} origin/{0}", branch); if (args != null) cmdLine += " " + args; Utilities.Run("git", cmdLine, null, path, Utilities.RunOptions.None); if (commit != null) { Utilities.Run("git", string.Format("reset --hard {0}", commit), null, path, Utilities.RunOptions.None); } } /// /// Resets all the local changes. /// /// The local path that contains git repository. public static void GitResetLocalChanges(string path) { Utilities.Run("git", "reset --hard", null, path, Utilities.RunOptions.None); } /// /// Runs the cmake tool. /// /// The path. /// The output platform. /// The output architecture. /// The custom arguments for the CMake. /// Custom environment variables to pass to the child process. public static void RunCmake(string path, TargetPlatform platform, TargetArchitecture architecture, string customArgs = null, Dictionary envVars = null) { string cmdLine; switch (platform) { case TargetPlatform.Windows: case TargetPlatform.XboxOne: case TargetPlatform.XboxScarlett: case TargetPlatform.UWP: { string arch; switch (architecture) { case TargetArchitecture.x86: arch = string.Empty; break; case TargetArchitecture.x64: arch = " Win64"; break; case TargetArchitecture.ARM: arch = " ARM"; break; case TargetArchitecture.ARM64: arch = " ARM64"; break; default: throw new InvalidArchitectureException(architecture); } cmdLine = string.Format("CMakeLists.txt -G \"Visual Studio 14 2015{0}\"", arch); break; } case TargetPlatform.Linux: case TargetPlatform.PS4: case TargetPlatform.PS5: { cmdLine = "CMakeLists.txt"; break; } case TargetPlatform.Switch: { cmdLine = string.Format("-DCMAKE_TOOLCHAIN_FILE=\"{1}\\Source\\Platforms\\Switch\\Data\\Switch.cmake\" -G \"NMake Makefiles\" -DCMAKE_MAKE_PROGRAM=\"{0}..\\..\\VC\\bin\\nmake.exe\"", Environment.GetEnvironmentVariable("VS140COMNTOOLS"), Globals.EngineRoot); break; } case TargetPlatform.Android: { var ndk = AndroidNdk.Instance.RootPath; var abi = AndroidToolchain.GetAbiName(architecture); var hostName = AndroidSdk.GetHostName(); cmdLine = string.Format("-DCMAKE_TOOLCHAIN_FILE=\"{0}/build/cmake/android.toolchain.cmake\" -DANDROID_NDK=\"{0}\" -DANDROID_STL=c++_shared -DANDROID_ABI={1} -DANDROID_PLATFORM=android-{2} -G \"MinGW Makefiles\" -DCMAKE_MAKE_PROGRAM=\"{0}/prebuilt/{3}/bin/make.exe\"", ndk, abi, Configuration.AndroidPlatformApi, hostName); break; } case TargetPlatform.Mac: { cmdLine = string.Format("CMakeLists.txt -DCMAKE_OSX_DEPLOYMENT_TARGET=\"{0}\"", Configuration.MacOSXMinVer); break; } default: throw new InvalidPlatformException(platform); } if (customArgs != null) cmdLine += " " + customArgs; Utilities.Run("cmake", cmdLine, null, path, Utilities.RunOptions.None, envVars); } /// /// Runs the bash script via Cygwin tool (native bash on platforms other than Windows). /// /// The path. /// The workspace folder. /// Custom environment variables to pass to the child process. public static void RunCygwin(string path, string workspace = null, Dictionary envVars = null) { string app; switch (BuildPlatform) { case TargetPlatform.Windows: { var cygwinFolder = Environment.GetEnvironmentVariable("CYGWIN"); if (string.IsNullOrEmpty(cygwinFolder) || !Directory.Exists(cygwinFolder)) { cygwinFolder = "C:\\cygwin"; if (!Directory.Exists(cygwinFolder)) throw new Exception("Missing Cygwin. Install Cygwin64 to C:\\cygwin or set CYGWIN env variable to install location folder."); } app = Path.Combine(cygwinFolder, "bin\\bash.exe"); break; } case TargetPlatform.Linux: app = "bash"; break; default: throw new InvalidPlatformException(BuildPlatform); } Utilities.Run(app, path, null, workspace, Utilities.RunOptions.None, envVars); } } }