GitHub Viewer
// 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 = "";
// 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";
private string[] windowsKnownPaths =
{
//"C:/Program Files/Python37",
"C:/Program Files/Python36",
"C:/Program Files/Python35",
"C:/Python27",
"C:/IntelPython35"
};
private string[] macKnownPaths =
{
"/Library/Frameworks/Python.framework/Versions/3.7",
"/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.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.8",
"/usr/local/include/python3.8m",
"/usr/local/include/python3.7",
"/usr/local/include/python3.7m",
"/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.8",
"/usr/include/python3.8m",
"/usr/include/python3.7",
"/usr/include/python3.7m",
"/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.8.so",
"/usr/local/lib/libpython3.8m.so",
"/usr/local/lib/x86_64-linux-gnu/libpython3.8.so",
"/usr/local/lib/x86_64-linux-gnu/libpython3.8m.so",
"/usr/local/lib/libpython3.7.so",
"/usr/local/lib/libpython3.7m.so",
"/usr/local/lib/x86_64-linux-gnu/libpython3.7.so",
"/usr/local/lib/x86_64-linux-gnu/libpython3.7m.so",
"/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.8.so",
"/usr/lib/libpython3.8m.so",
"/usr/lib/x86_64-linux-gnu/libpython3.8.so",
"/usr/lib/x86_64-linux-gnu/libpython3.8m.so",
"/usr/lib/libpython3.7.so",
"/usr/lib/libpython3.7m.so",
"/usr/lib/x86_64-linux-gnu/libpython3.7.so",
"/usr/lib/x86_64-linux-gnu/libpython3.7m.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
{
PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs;
PublicDefinitions.Add("WITH_UNREALENGINEPYTHON=1"); // fixed
string enableUnityBuild = System.Environment.GetEnvironmentVariable("UEP_ENABLE_UNITY_BUILD");
bUseUnity = string.IsNullOrEmpty(enableUnityBuild);
PublicIncludePaths.AddRange(
new string[] {
// ... add public include paths required here ...
}
);
PrivateIncludePaths.AddRange(
new string[] {
// ... add other private include paths required here ...
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Core",
"Sockets",
"Networking",
// ... 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",
"Foliage",
"AIModule"
// ... add private dependencies that you statically link with here ...
}
);
#if WITH_FORWARDED_MODULE_RULES_CTOR
BuildVersion Version;
if (BuildVersion.TryRead(BuildVersion.GetDefaultFileName(), out Version))
{
if (Version.MinorVersion >= 18)
{
PrivateDependencyModuleNames.Add("ApplicationCore");
}
}
#endif
DynamicallyLoadedModuleNames.AddRange(
new string[]
{
// ... add any modules that your module loads dynamically here ...
}
);
#if WITH_FORWARDED_MODULE_RULES_CTOR
if (Target.bBuildEditor)
#else
if (UEBuildConfiguration.bBuildEditor)
#endif
{
PublicIncludePaths.AddRange(
new string[] {
"Editor/Sequencer/Private",
}
);
PublicDependencyModuleNames.AddRange(
new string[]
{
"Sequencer",
}
);
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",
"MaterialEditor"
});
if (Version.MinorVersion > 21)
{
PrivateDependencyModuleNames.Add("MeshDescription");
PrivateDependencyModuleNames.Add("StaticMeshDescription");
}
}
if ((Target.Platform == UnrealTargetPlatform.Win64) || (Target.Platform == UnrealTargetPlatform.Win32))
{
if (pythonHome == "")
{
pythonHome = DiscoverPythonPath(windowsKnownPaths, "Win64");
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);
PublicSystemLibraryPaths.Add(Path.GetDirectoryName(libPath));
PublicAdditionalLibraries.Add(libPath);
}
else if (Target.Platform == UnrealTargetPlatform.Mac)
{
if (pythonHome == "")
{
pythonHome = DiscoverPythonPath(macKnownPaths, "Mac");
if (pythonHome == "")
{
throw new System.Exception("Unable to find Python installation");
}
}
System.Console.WriteLine("Using Python at: " + pythonHome);
PublicIncludePaths.Add(pythonHome);
string libPath = GetMacPythonLibFile(pythonHome);
PublicAdditionalLibraries.Add(Path.GetDirectoryName(libPath));
PublicDelayLoadDLLs.Add(libPath);
}
else if (Target.Platform == UnrealTargetPlatform.Linux)
{
if (pythonHome == "")
{
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(Path.Combine(ModuleDirectory,"Include"));
PublicIncludePaths.Add(includesPath);
PublicAdditionalLibraries.Add(libsPath);
System.Console.WriteLine("Using Python lib at: " + libsPath);
System.Console.WriteLine("Using Python lib at: " + string.Join(", ",PublicAdditionalLibraries));
//PublicAdditionalLibraries.Add("python3.8");
}
else
{
string[] items = pythonHome.Split(';');
PublicIncludePaths.Add(items[0]);
PublicAdditionalLibraries.Add(items[1]);
}
}
#if WITH_FORWARDED_MODULE_RULES_CTOR
else if (Target.Platform == UnrealTargetPlatform.Android)
{
PublicIncludePaths.Add(System.IO.Path.Combine(ModuleDirectory, "../../android/python35/include"));
PublicAdditionalLibraries.Add(System.IO.Path.Combine(ModuleDirectory, "../../android/armeabi-v7a"));
PublicAdditionalLibraries.Add("python3.5m");
string APLName = "UnrealEnginePython_APL.xml";
string RelAPLPath = Utils.MakePathRelativeTo(ModuleDirectory, Target.RelativeEnginePath);
AdditionalPropertiesForReceipt.Add("AndroidPlugin", Path.Combine(RelAPLPath, APLName));
}
#endif
}
private bool IsPathRelative(string Path)
{
bool IsRooted = Path.StartsWith("\\", System.StringComparison.Ordinal) || // Root of the current directory on Windows. Also covers "\\" for UNC or "network" paths.
Path.StartsWith("/", System.StringComparison.Ordinal) || // Root of the current directory on Windows, root on UNIX-likes.
// Also covers "\\", considering normalization replaces "\\" with "//".
(Path.Length >= 2 && char.IsLetter(Path[0]) && Path[1] == ':'); // Starts with ":"
return !IsRooted;
}
private string DiscoverPythonPath(string[] knownPaths, string binaryPath)
{
// insert the PYTHONHOME content as the first known path
List paths = new List(knownPaths);
paths.Insert(0, Path.Combine(ModuleDirectory, "../../Binaries", binaryPath));
string environmentPath = System.Environment.GetEnvironmentVariable("PYTHONHOME");
if (!string.IsNullOrEmpty(environmentPath))
paths.Insert(0, environmentPath);
// look in an alternate custom location
environmentPath = System.Environment.GetEnvironmentVariable("UNREALENGINEPYTHONHOME");
if (!string.IsNullOrEmpty(environmentPath))
paths.Insert(0, environmentPath);
foreach (string path in paths)
{
string actualPath = path;
if (IsPathRelative(actualPath))
{
actualPath = Path.GetFullPath(Path.Combine(ModuleDirectory, actualPath));
}
string headerFile = Path.Combine(actualPath, "include", "Python.h");
if (File.Exists(headerFile))
{
return actualPath;
}
// this is mainly useful for OSX
headerFile = Path.Combine(actualPath, "Headers", "Python.h");
if (File.Exists(headerFile))
{
return actualPath;
}
}
return "";
}
private string DiscoverLinuxPythonIncludesPath()
{
List paths = new List(linuxKnownIncludesPaths);
paths.Insert(0, Path.Combine(ModuleDirectory, "../../Binaries", "Linux", "include"));
foreach (string path in paths)
{
string headerFile = Path.Combine(path, "Python.h");
if (File.Exists(headerFile))
{
return path;
}
}
return null;
}
private string DiscoverLinuxPythonLibsPath()
{
List paths = new List(linuxKnownLibsPaths);
paths.Insert(0, Path.Combine(ModuleDirectory, "../../Binaries", "Linux", "lib"));
paths.Insert(0, Path.Combine(ModuleDirectory, "../../Binaries", "Linux", "lib64"));
foreach (string path in paths)
{
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.");
System.Console.WriteLine("[WARNING] Ensure your python paths are set in GlobalConfig (DefaultEngine.ini) so the path can be corrected at runtime.");
}
// 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");
}
}