// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; using System.IO; using System.Collections.Generic; public class UnrealEnginePython : ModuleRules { // leave this string as empty for triggering auto-discovery of python installations... private string PythonHome = ""; bool UseThirdPartyPython = true; //embedded //Or use the one included in third party folder protected string ThirdPartyPythonHome { get { return Path.GetFullPath(Path.Combine(ThirdPartyPath, PythonType)); } } // otherwise specify the path of your python installation //private string PythonHome = "C:/Program Files/Python36"; // this is an example for Homebrew on Mac //private string pythonHome = "/usr/local/Cellar/python3/3.6.0/Frameworks/Python.framework/Versions/3.6/"; // on Linux an include;libs syntax is expected: //private string pythonHome = "/usr/local/include/python3.6;/usr/local/lib/libpython3.6.so" //Swap python versions here private string PythonType = "Python36"; //private string PythonType = "python27"; private string ThirdPartyPath { get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../ThirdParty/")); } } private string BinariesPath { get { return Path.GetFullPath(Path.Combine(ModuleDirectory, "../../Binaries/")); } } private string[] windowsKnownPaths = { "C:/Program Files/Python36", "C:/Program Files/Python35", "C:/Python27", "C:/IntelPython35" }; private string[] macKnownPaths = { "/Library/Frameworks/Python.framework/Versions/3.6", "/Library/Frameworks/Python.framework/Versions/3.5", "/Library/Frameworks/Python.framework/Versions/2.7", "/System/Library/Frameworks/Python.framework/Versions/3.6", "/System/Library/Frameworks/Python.framework/Versions/3.5", "/System/Library/Frameworks/Python.framework/Versions/2.7" }; private string[] linuxKnownIncludesPaths = { "/usr/local/include/python3.6", "/usr/local/include/python3.6m", "/usr/local/include/python3.5", "/usr/local/include/python3.5m", "/usr/local/include/python2.7", "/usr/include/python3.6", "/usr/include/python3.6m", "/usr/include/python3.5", "/usr/include/python3.5m", "/usr/include/python2.7", }; private string[] linuxKnownLibsPaths = { "/usr/local/lib/libpython3.6.so", "/usr/local/lib/libpython3.6m.so", "/usr/local/lib/x86_64-linux-gnu/libpython3.6.so", "/usr/local/lib/x86_64-linux-gnu/libpython3.6m.so", "/usr/local/lib/libpython3.5.so", "/usr/local/lib/libpython3.5m.so", "/usr/local/lib/x86_64-linux-gnu/libpython3.5.so", "/usr/local/lib/x86_64-linux-gnu/libpython3.5m.so", "/usr/local/lib/libpython2.7.so", "/usr/local/lib/x86_64-linux-gnu/libpython2.7.so", "/usr/lib/libpython3.6.so", "/usr/lib/libpython3.6m.so", "/usr/lib/x86_64-linux-gnu/libpython3.6.so", "/usr/lib/x86_64-linux-gnu/libpython3.6m.so", "/usr/lib/libpython3.5.so", "/usr/lib/libpython3.5m.so", "/usr/lib/x86_64-linux-gnu/libpython3.5.so", "/usr/lib/x86_64-linux-gnu/libpython3.5m.so", "/usr/lib/libpython2.7.so", "/usr/lib/x86_64-linux-gnu/libpython2.7.so", }; #if WITH_FORWARDED_MODULE_RULES_CTOR public UnrealEnginePython(ReadOnlyTargetRules Target) : base(Target) #else public UnrealEnginePython(TargetInfo Target) #endif { PublicIncludePaths.AddRange( new string[] { "UnrealEnginePython/Public", // ... add public include paths required here ... } ); PrivateIncludePaths.AddRange( new string[] { "UnrealEnginePython/Private", PythonHome, // ... add other private include paths required here ... } ); PublicDependencyModuleNames.AddRange( new string[] { "Core", "Sockets", "Networking", "Projects" // ... add other public dependencies that you statically link with here ... } ); PrivateDependencyModuleNames.AddRange( new string[] { "CoreUObject", "Engine", "InputCore", "Slate", "SlateCore", "MovieScene", "LevelSequence", "HTTP", "UMG", "AppFramework", "RHI", "Voice", "RenderCore", "MovieSceneCapture", "Landscape" // ... add private dependencies that you statically link with here ... } ); DynamicallyLoadedModuleNames.AddRange( new string[] { // ... add any modules that your module loads dynamically here ... } ); if (UEBuildConfiguration.bBuildEditor) { PrivateDependencyModuleNames.AddRange(new string[]{ "UnrealEd", "LevelEditor", "BlueprintGraph", "Projects", "Sequencer", "SequencerWidgets", "AssetTools", "LevelSequenceEditor", "MovieSceneTools", "MovieSceneTracks", "CinematicCamera", "EditorStyle", "GraphEditor", "UMGEditor", "AIGraph", "RawMesh", "DesktopWidgets", "EditorWidgets", "FBX", "Persona", "PropertyEditor", "LandscapeEditor" }); } if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32)) { if (UseThirdPartyPython) { PythonHome = ThirdPartyPythonHome; System.Console.WriteLine("Using Embedded Python at: " + PythonHome); PublicIncludePaths.Add(PythonHome); string libPath = Path.Combine(PythonHome, "Lib", string.Format("{0}.lib", PythonType.ToLower())); System.Console.WriteLine("full lib path: " + libPath); PublicLibraryPaths.Add(Path.GetDirectoryName(libPath)); PublicAdditionalLibraries.Add(libPath); string dllPath = Path.Combine(BinariesPath, "Win64", string.Format("{0}.dll", PythonType.ToLower())); RuntimeDependencies.Add(new RuntimeDependency(dllPath)); } else if (PythonHome == "") { PythonHome = DiscoverPythonPath(windowsKnownPaths); if (PythonHome == "") { throw new System.Exception("Unable to find Python installation"); } System.Console.WriteLine("Using Python at: " + PythonHome); PublicIncludePaths.Add(PythonHome); string libPath = GetWindowsPythonLibFile(PythonHome); PublicLibraryPaths.Add(Path.GetDirectoryName(libPath)); PublicAdditionalLibraries.Add(libPath); } } //other platforms else { if (PythonHome == "") { PythonHome = DiscoverPythonPath(macKnownPaths); if (PythonHome == "") { throw new System.Exception("Unable to find Python installation"); } System.Console.WriteLine("Using Python at: " + PythonHome); PublicIncludePaths.Add(PythonHome); PublicAdditionalLibraries.Add(Path.Combine(PythonHome, "Lib", string.Format("{0}.lib", PythonType))); } else if (Target.Platform == UnrealTargetPlatform.Mac) { string includesPath = DiscoverLinuxPythonIncludesPath(); if (includesPath == null) { throw new System.Exception("Unable to find Python includes, please add a search path to linuxKnownIncludesPaths"); } string libsPath = DiscoverLinuxPythonLibsPath(); if (libsPath == null) { throw new System.Exception("Unable to find Python libs, please add a search path to linuxKnownLibsPaths"); } PublicIncludePaths.Add(includesPath); PublicAdditionalLibraries.Add(libsPath); } else if (Target.Platform == UnrealTargetPlatform.Linux) { string[] items = PythonHome.Split(';'); PublicIncludePaths.Add(items[0]); PublicAdditionalLibraries.Add(items[1]); } } /*string enableThreads = System.Environment.GetEnvironmentVariable("UEP_ENABLE_THREADS"); if (!string.IsNullOrEmpty(enableThreads)) { Definitions.Add("UEPY_THREADING"); System.Console.WriteLine("*** Enabled Python Threads support ***"); }*/ } private string DiscoverPythonPath(string[] knownPaths) { // insert the PYTHONHOME content as the first known path List paths = new List(knownPaths); string environmentPath = System.Environment.GetEnvironmentVariable("PYTHONHOME"); if (!string.IsNullOrEmpty(environmentPath)) paths.Insert(0, environmentPath); foreach (string path in paths) { string headerFile = Path.Combine(path, "include", "Python.h"); if (File.Exists(headerFile)) { return path; } // this is mainly useful for OSX headerFile = Path.Combine(path, "Headers", "Python.h"); if (File.Exists(headerFile)) { return path; } } return ""; } private string DiscoverLinuxPythonIncludesPath() { foreach (string path in linuxKnownIncludesPaths) { string headerFile = Path.Combine(path, "Python.h"); if (File.Exists(headerFile)) { return path; } } return null; } private string DiscoverLinuxPythonLibsPath() { foreach (string path in linuxKnownLibsPaths) { if (File.Exists(path)) { return path; } } return null; } private string GetMacPythonLibFile(string basePath) { // first try with python3 for (int i = 9; i >= 0; i--) { string fileName = string.Format("libpython3.{0}.dylib", i); string fullPath = Path.Combine(basePath, "lib", fileName); if (File.Exists(fullPath)) { return fullPath; } fileName = string.Format("libpython3.{0}m.dylib", i); fullPath = Path.Combine(basePath, "lib", fileName); if (File.Exists(fullPath)) { return fullPath; } } // then python2 for (int i = 9; i >= 0; i--) { string fileName = string.Format("libpython2.{0}.dylib", i); string fullPath = Path.Combine(basePath, "lib", fileName); if (File.Exists(fullPath)) { return fullPath; } fileName = string.Format("libpython2.{0}m.dylib", i); fullPath = Path.Combine(basePath, "lib", fileName); if (File.Exists(fullPath)) { return fullPath; } } throw new System.Exception("Invalid Python installation, missing .dylib files"); } private string GetWindowsPythonLibFile(string basePath) { // just for usability, report if the PythonHome is not in the system path string[] allPaths = System.Environment.GetEnvironmentVariable("PATH").Split(';'); // this will transform the slashes in backslashes... string checkedPath = Path.GetFullPath(basePath); if (checkedPath.EndsWith("\\")) { checkedPath = checkedPath.Remove(checkedPath.Length - 1); } bool found = false; foreach (string item in allPaths) { if (item == checkedPath || item == checkedPath + "\\") { found = true; break; } } if (!found) { System.Console.WriteLine("[WARNING] Your Python installation is not in the system PATH environment variable, very probably the plugin will fail to load"); } // first try with python3 for (int i = 9; i >= 0; i--) { string fileName = string.Format("python3{0}.lib", i); string fullPath = Path.Combine(basePath, "libs", fileName); if (File.Exists(fullPath)) { return fullPath; } } // then python2 for (int i = 9; i >= 0; i--) { string fileName = string.Format("python2{0}.lib", i); string fullPath = Path.Combine(basePath, "libs", fileName); if (File.Exists(fullPath)) { return fullPath; } } throw new System.Exception("Invalid Python installation, missing .lib files"); } }