/// <summary> /// Runs the cmake tool. /// </summary> /// <param name="path">The path.</param> /// <param name="platform">The output platform.</param> /// <param name="architecture">The output architecture.</param> /// <param name="customArgs">The custom arguments for the CMake.</param> /// <param name="envVars">Custom environment variables to pass to the child process.</param> public static void RunCmake(string path, TargetPlatform platform, TargetArchitecture architecture, string customArgs = null, Dictionary <string, string> 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: { 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; } default: throw new InvalidPlatformException(platform); } if (customArgs != null) { cmdLine += " " + customArgs; } Utilities.Run("cmake", cmdLine, null, path, Utilities.RunOptions.None, envVars); }
private void Build(BuildOptions options, string preset, TargetPlatform targetPlatform, TargetArchitecture architecture) { // Load preset configuration var presetPath = Path.Combine(projectGenDir, "buildtools", "presets", "public", preset + ".xml"); if (!File.Exists(presetPath)) { throw new Exception(string.Format("Missing PhysX preset {0} (file: {1})", preset, presetPath)); } var presetXml = new XmlDocument(); presetXml.Load(presetPath); // Configure preset var cmakeSwitches = presetXml["preset"]["CMakeSwitches"]; ConfigureCmakeSwitch(cmakeSwitches, "PX_BUILDSNIPPETS", "False"); ConfigureCmakeSwitch(cmakeSwitches, "PX_BUILDSAMPLES", "False"); ConfigureCmakeSwitch(cmakeSwitches, "PX_BUILDPUBLICSAMPLES", "False"); ConfigureCmakeSwitch(cmakeSwitches, "PX_GENERATE_STATIC_LIBRARIES", "True"); ConfigureCmakeSwitch(cmakeSwitches, "NV_USE_STATIC_WINCRT", "False"); ConfigureCmakeSwitch(cmakeSwitches, "NV_USE_DEBUG_WINCRT", "False"); ConfigureCmakeSwitch(cmakeSwitches, "PX_FLOAT_POINT_PRECISE_MATH", "False"); var cmakeParams = presetXml["preset"]["CMakeParams"]; switch (targetPlatform) { case TargetPlatform.Android: ConfigureCmakeSwitch(cmakeParams, "CMAKE_INSTALL_PREFIX", $"install/android-{Configuration.AndroidPlatformApi}/PhysX"); ConfigureCmakeSwitch(cmakeParams, "ANDROID_NATIVE_API_LEVEL", $"android-{Configuration.AndroidPlatformApi}"); ConfigureCmakeSwitch(cmakeParams, "ANDROID_ABI", AndroidToolchain.GetAbiName(architecture)); break; } // Save preset presetXml.Save(presetPath); // Peek options var platform = Platform.GetPlatform(targetPlatform); var configuration = "release"; string bits; string arch; string binariesSubDir; string buildPlatform; bool suppressBitsPostfix = false; string binariesPrefix = string.Empty; switch (architecture) { case TargetArchitecture.x86: arch = "x86"; bits = "32"; break; case TargetArchitecture.x64: arch = "x86"; bits = "64"; break; case TargetArchitecture.ARM: arch = "arm"; bits = "32"; break; case TargetArchitecture.ARM64: arch = "arm"; bits = "64"; break; default: throw new InvalidArchitectureException(architecture); } switch (architecture) { case TargetArchitecture.x86: buildPlatform = "Win32"; break; default: buildPlatform = architecture.ToString(); break; } switch (targetPlatform) { case TargetPlatform.Windows: binariesSubDir = string.Format("win.{0}_{1}.vc140.md", arch, bits); break; case TargetPlatform.UWP: binariesSubDir = string.Format("uwp.{0}_{1}.vc141", arch, bits); break; case TargetPlatform.Linux: binariesSubDir = "linux.clang"; binariesPrefix = "lib"; break; case TargetPlatform.PS4: binariesSubDir = "ps4"; buildPlatform = "ORBIS"; suppressBitsPostfix = true; binariesPrefix = "lib"; break; case TargetPlatform.XboxOne: case TargetPlatform.XboxScarlett: binariesSubDir = "win.x86_64.vc142.md"; break; case TargetPlatform.Android: switch (architecture) { case TargetArchitecture.ARM64: binariesSubDir = "android.arm64-v8a.fp-soft"; break; default: throw new InvalidArchitectureException(architecture); } binariesPrefix = "lib"; suppressBitsPostfix = true; break; case TargetPlatform.Switch: binariesSubDir = "switch64"; buildPlatform = "NX64"; suppressBitsPostfix = true; binariesPrefix = "lib"; break; default: throw new InvalidPlatformException(targetPlatform); } // Setup build environment variables for PhysX build system var envVars = new Dictionary <string, string>(); switch (BuildPlatform) { case TargetPlatform.Windows: { var msBuild = VCEnvironment.MSBuildPath; if (File.Exists(msBuild)) { envVars.Add("PATH", Path.GetDirectoryName(msBuild)); } break; } case TargetPlatform.Linux: { envVars.Add("CC", "clang-7"); envVars.Add("CC_FOR_BUILD", "clang-7"); break; } default: throw new InvalidPlatformException(BuildPlatform); } if (AndroidNdk.Instance.IsValid) { envVars.Add("PM_ANDROIDNDK_PATH", AndroidNdk.Instance.RootPath); } // Print the PhysX version Log.Info("Building PhysX version " + File.ReadAllText(Path.Combine(root, "physx", "version.txt")) + " to " + binariesSubDir); // Generate project files Utilities.Run(projectGenPath, preset, null, projectGenDir, Utilities.RunOptions.Default, envVars); switch (targetPlatform) { case TargetPlatform.PS4: // Hack: PS4 uses .o extension for compiler output files but CMake uses .obj even if CMAKE_CXX_OUTPUT_EXTENSION/CMAKE_C_OUTPUT_EXTENSION are specified Utilities.ReplaceInFiles(Path.Combine(root, "physx\\compiler\\ps4"), "*.vcxproj", SearchOption.AllDirectories, ".obj", ".o"); break; case TargetPlatform.XboxOne: case TargetPlatform.XboxScarlett: // Hack: force to use proper Win10 SDK Utilities.ReplaceInFiles(Path.Combine(root, "physx\\compiler\\vc16win64"), "*.vcxproj", SearchOption.AllDirectories, "10.0.18362.0", "10.0.19041.0"); // Hack: fix STL include Utilities.ReplaceInFile(Path.Combine(root, "physx\\source\\foundation\\include\\PsAllocator.h"), "#include <typeinfo.h>", "#include <typeinfo>"); break; case TargetPlatform.Android: // Hack: fix compilation errors if (!File.ReadAllText(Path.Combine(root, "physx\\source\\foundation\\include\\PsUtilities.h")).Contains("#if PX_GCC_FAMILY && !PX_EMSCRIPTEN && !PX_LINUX && !PX_ANDROID")) { Utilities.ReplaceInFile(Path.Combine(root, "physx\\source\\foundation\\include\\PsUtilities.h"), "#if PX_GCC_FAMILY && !PX_EMSCRIPTEN && !PX_LINUX", "#if PX_GCC_FAMILY && !PX_EMSCRIPTEN && !PX_LINUX && !PX_ANDROID"); } Utilities.ReplaceInFile(Path.Combine(root, "physx\\source\\compiler\\cmake\\android\\CMakeLists.txt"), "-Wno-maybe-uninitialized", "-Wno-unused-local-typedef -Wno-unused-private-field"); // PhysX build system for Android is old and doesn't support new NDK with clang so invoke cmake manually if (!Directory.Exists(Path.Combine(root, "physx\\compiler\\android"))) { Directory.CreateDirectory(Path.Combine(root, "physx\\compiler\\android")); } envVars.Add("PHYSX_ROOT_DIR", Path.Combine(root, "physx")); envVars.Add("PM_CMAKEMODULES_PATH", Path.Combine(root, "externals/CMakeModules")); envVars.Add("PM_PXSHARED_PATH", Path.Combine(root, "pxshared")); envVars.Add("PM_TARGA_PATH", Path.Combine(root, "externals/targa")); envVars.Add("PM_PATHS", Path.Combine(root, "externals/CMakeModules") + ';' + Path.Combine(root, "externals/targa")); RunCmake(Path.Combine(root, "physx\\compiler\\android"), targetPlatform, architecture, string.Format("\"{0}/physx/compiler/public\" -Wno-dev -DANDROID_NATIVE_API_LEVEL=android-{1} -DTARGET_BUILD_PLATFORM=android --no-warn-unused-cli -DCMAKE_BUILD_TYPE={2} -DCMAKE_PREFIX_PATH=\"{0}/externals/CMakeModules;{0}/externals/targa\" -DPHYSX_ROOT_DIR=\"{0}/physx\" -DPX_OUTPUT_LIB_DIR=\"{0}/physx\" -DPX_OUTPUT_BIN_DIR=\"{0}/physx\" -DPX_BUILDSNIPPETS=FALSE -DPX_GENERATE_STATIC_LIBRARIES=TRUE -DCMAKE_INSTALL_PREFIX=\"{0}/physx/install/android-{1}/PhysX\"", root, Configuration.AndroidPlatformApi, configuration), envVars); break; } // Run building based on the platform var defaultPhysXLibs = new[] { "PhysX", "PhysXCharacterKinematic", "PhysXCommon", "PhysXCooking", "PhysXExtensions", "PhysXFoundation", "PhysXPvdSDK", "PhysXVehicle", }; var dstBinaries = GetThirdPartyFolder(options, targetPlatform, architecture); var srcBinaries = Path.Combine(root, "physx", "bin", binariesSubDir, configuration); switch (BuildPlatform) { case TargetPlatform.Windows: switch (targetPlatform) { case TargetPlatform.Android: Utilities.Run("cmake", "--build .", null, Path.Combine(root, "physx\\compiler\\android"), Utilities.RunOptions.None, envVars); break; default: VCEnvironment.BuildSolution(Path.Combine(solutionFilesRoot, preset, "PhysXSDK.sln"), configuration, buildPlatform); break; } break; case TargetPlatform.Linux: Utilities.Run("make", null, null, Path.Combine(projectGenDir, "compiler", "linux-" + configuration), Utilities.RunOptions.None); break; default: throw new InvalidPlatformException(BuildPlatform); } // Deploy binaries var binariesExtension = platform.StaticLibraryFileExtension; Log.Verbose("Copy PhysX binaries from " + srcBinaries); foreach (var physXLib in defaultPhysXLibs) { var filename = suppressBitsPostfix ? string.Format("{0}{1}_static", binariesPrefix, physXLib) : string.Format("{0}{1}_static_{2}", binariesPrefix, physXLib, bits); filename += binariesExtension; Utilities.FileCopy(Path.Combine(srcBinaries, filename), Path.Combine(dstBinaries, filename)); var filenamePdb = Path.ChangeExtension(filename, "pdb"); if (File.Exists(Path.Combine(srcBinaries, filenamePdb))) { Utilities.FileCopy(Path.Combine(srcBinaries, filenamePdb), Path.Combine(dstBinaries, filenamePdb)); } } srcBinaries = Path.Combine(root, "physx", "compiler", preset, "sdk_source_bin", configuration); var additionalPhysXLibs = new[] { "FastXml", "LowLevel", "LowLevelAABB", "LowLevelDynamics", "PhysXTask", "SceneQuery", "SimulationController", }; foreach (var additionalPhysXLib in additionalPhysXLibs) { var filenamePdb = suppressBitsPostfix ? string.Format("{0}{1}", binariesPrefix, additionalPhysXLib) : string.Format("{0}{1}_{2}", binariesPrefix, additionalPhysXLib, bits); filenamePdb += ".pdb"; if (File.Exists(Path.Combine(srcBinaries, filenamePdb))) { Utilities.FileCopy(Path.Combine(srcBinaries, filenamePdb), Path.Combine(dstBinaries, filenamePdb)); } } }