build_package_image.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #!/usr/bin/env python3
  2. #
  3. # Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. #
  5. # SPDX-License-Identifier: Apache-2.0 OR MIT
  6. #
  7. #
  8. import argparse
  9. import functools
  10. import json
  11. import os
  12. import re
  13. import pathlib
  14. from pathlib import Path
  15. import shutil
  16. import subprocess
  17. from tempfile import TemporaryDirectory
  18. import sys
  19. sys.path.append(str(Path(__file__).parent.parent.parent / 'Scripts'))
  20. from builders.vcpkgbuilder import VcpkgBuilder
  21. import builders.monkeypatch_tempdir_cleanup
  22. class NvClothBuilder(object):
  23. def __init__(self, workingDir: pathlib.Path, basePackageSystemDir: pathlib.Path, targetPlatform: str):
  24. self._workingDir = workingDir
  25. self._packageSystemDir = basePackageSystemDir
  26. self._platform = targetPlatform
  27. self._env = dict(os.environ)
  28. self._env.update(
  29. GW_DEPS_ROOT=str(workingDir),
  30. )
  31. self.check_call = functools.partial(subprocess.check_call,
  32. cwd=self.workingDir,
  33. env=self.env
  34. )
  35. @property
  36. def workingDir(self):
  37. return self._workingDir
  38. @property
  39. def packageSystemDir(self):
  40. return self._packageSystemDir
  41. @property
  42. def platform(self):
  43. return self._platform
  44. @property
  45. def env(self):
  46. return self._env
  47. def clone(self, lockToCommit: str):
  48. if not (self.workingDir / '.git').exists():
  49. self.check_call(
  50. ['git', 'init',],
  51. )
  52. self.check_call(
  53. ['git', 'remote', 'add', 'origin', 'https://github.com/NVIDIAGameWorks/NvCloth.git',],
  54. )
  55. self.check_call(
  56. ['git', 'fetch', 'origin', '--depth=1', 'pull/58/head:pr-58',],
  57. )
  58. self.check_call(
  59. ['git', 'checkout', 'pr-58',],
  60. )
  61. # Remove /LTCG and /GL flags as it's causing compile warnings
  62. if self.platform == 'windows':
  63. windows_cmake_file = self.workingDir / 'NvCloth/compiler/cmake/windows/CMakeLists.txt'
  64. f = open(windows_cmake_file, 'r')
  65. content = f.read()
  66. f.close()
  67. content = re.sub('/LTCG', r'', content, flags = re.M)
  68. content = re.sub('/GL', r'', content, flags = re.M)
  69. f = open(windows_cmake_file, 'w')
  70. f.write(content)
  71. f.close()
  72. # Remove warnings as errors for iOS
  73. if self.platform == 'ios':
  74. ios_cmake_file = self.workingDir / 'NvCloth/compiler/cmake/ios/CMakeLists.txt'
  75. f = open(ios_cmake_file, 'r')
  76. content = f.read()
  77. f.close()
  78. content = re.sub('-Werror', r'', content, flags = re.M)
  79. f = open(ios_cmake_file, 'w')
  80. f.write(content)
  81. f.close()
  82. def build(self):
  83. cmake_scripts_path = os.path.abspath(os.path.join(self.packageSystemDir, '../Scripts/cmake'))
  84. nvcloth_dir = self.workingDir / 'NvCloth'
  85. ly_3rdparty_path = os.getenv('LY_3RDPARTY_PATH')
  86. folder_names = {
  87. #system-name cmake generation, cmake build
  88. 'mac' : ([
  89. '-G', 'Xcode',
  90. '-DTARGET_BUILD_PLATFORM=mac',
  91. '-DNV_CLOTH_ENABLE_CUDA=0', '-DUSE_CUDA=0',
  92. '-DPX_GENERATE_GPU_PROJECTS=0',
  93. '-DPX_STATIC_LIBRARIES=1',
  94. f'-DPX_OUTPUT_DLL_DIR={nvcloth_dir}/bin/osx64-cmake',
  95. f'-DPX_OUTPUT_LIB_DIR={nvcloth_dir}/lib/osx64-cmake',
  96. f'-DPX_OUTPUT_EXE_DIR={nvcloth_dir}/bin/osx64-cmake'
  97. ], []),
  98. 'ios' : ([
  99. '-G', 'Xcode',
  100. f'-DCMAKE_TOOLCHAIN_FILE={cmake_scripts_path}/Platform/iOS/Toolchain_ios.cmake',
  101. '-DPACKAGE_PLATFORM=ios',
  102. '-DTARGET_BUILD_PLATFORM=ios',
  103. '-DCMAKE_XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET="10.0"',
  104. '-DNV_CLOTH_ENABLE_CUDA=0', '-DUSE_CUDA=0',
  105. '-DPX_GENERATE_GPU_PROJECTS=0',
  106. '-DPX_STATIC_LIBRARIES=1',
  107. f'-DPX_OUTPUT_DLL_DIR={nvcloth_dir}/bin/ios-cmake',
  108. f'-DPX_OUTPUT_LIB_DIR={nvcloth_dir}/lib/ios-cmake',
  109. f'-DPX_OUTPUT_EXE_DIR={nvcloth_dir}/bin/ios-cmake'
  110. ], [
  111. '--',
  112. '-destination generic/platform=iOS'
  113. ]),
  114. 'linux' : ([
  115. '-G', 'Ninja Multi-Config',
  116. '-DCMAKE_C_COMPILER=clang-6.0',
  117. '-DCMAKE_CXX_COMPILER=clang++-6.0',
  118. '-DTARGET_BUILD_PLATFORM=linux',
  119. '-DNV_CLOTH_ENABLE_CUDA=0',
  120. '-DPX_GENERATE_GPU_PROJECTS=0',
  121. '-DPX_STATIC_LIBRARIES=1',
  122. f'-DPX_OUTPUT_DLL_DIR={nvcloth_dir}/bin/linux64-cmake',
  123. f'-DPX_OUTPUT_LIB_DIR={nvcloth_dir}/lib/linux64-cmake',
  124. f'-DPX_OUTPUT_EXE_DIR={nvcloth_dir}/bin/linux64-cmake'
  125. ], []),
  126. 'windows' : ([
  127. '-G', 'Visual Studio 15 2017',
  128. '-Ax64',
  129. '-DTARGET_BUILD_PLATFORM=windows',
  130. '-DNV_CLOTH_ENABLE_DX11=0',
  131. '-DNV_CLOTH_ENABLE_CUDA=0',
  132. '-DPX_GENERATE_GPU_PROJECTS=0',
  133. '-DSTATIC_WINCRT=0',
  134. '-DPX_STATIC_LIBRARIES=1',
  135. f'-DPX_OUTPUT_DLL_DIR={nvcloth_dir}/bin/vc141win64-cmake',
  136. f'-DPX_OUTPUT_LIB_DIR={nvcloth_dir}/lib/vc141win64-cmake',
  137. f'-DPX_OUTPUT_EXE_DIR={nvcloth_dir}/bin/vc141win64-cmake'
  138. ], []),
  139. 'android' : ([
  140. '-G', 'Ninja Multi-Config',
  141. f'-DCMAKE_TOOLCHAIN_FILE={cmake_scripts_path}/Platform/Android/Toolchain_android.cmake',
  142. '-DANDROID_ABI=arm64-v8a',
  143. '-DANDROID_ARM_MODE=arm',
  144. '-DANDROID_ARM_NEON=TRUE',
  145. '-DANDROID_NATIVE_API_LEVEL=21',
  146. f'-DLY_NDK_DIR={ly_3rdparty_path}/android-ndk/r21d',
  147. '-DPACKAGE_PLATFORM=android',
  148. '-DPX_STATIC_LIBRARIES=1',
  149. f'-DPX_OUTPUT_DLL_DIR={nvcloth_dir}/bin/android-arm64-v8a-cmake',
  150. f'-DPX_OUTPUT_LIB_DIR={nvcloth_dir}/lib/android-arm64-v8a-cmake',
  151. f'-DPX_OUTPUT_EXE_DIR={nvcloth_dir}/bin/android-arm64-v8a-cmake'
  152. ], []) # Android needs to have ninja in the path
  153. }
  154. # intentionally generate a keyerror if its not a good platform:
  155. cmake_generation, cmake_build = folder_names[self.platform]
  156. build_dir = os.path.join(nvcloth_dir, 'build', self.platform)
  157. os.makedirs(build_dir, exist_ok=True)
  158. # Generate
  159. cmake_generate_call =['cmake', f'{nvcloth_dir}/compiler/cmake/{self.platform}', f'-B{build_dir}']
  160. if cmake_generation:
  161. cmake_generate_call += cmake_generation
  162. print(cmake_generate_call)
  163. self.check_call(cmake_generate_call)
  164. # Build
  165. for config in ('debug', 'profile', 'release'):
  166. cmake_build_call =['cmake', '--build', build_dir, '--config', config]
  167. if cmake_build:
  168. cmake_build_call += cmake_build
  169. print(cmake_build_call)
  170. self.check_call(cmake_build_call)
  171. def copyBuildOutputTo(self, packageDir: pathlib.Path):
  172. if packageDir.exists():
  173. shutil.rmtree(packageDir)
  174. for dirname in ('NvCloth/lib', 'NvCloth/include', 'NvCloth/extensions/include', 'PxShared/include'):
  175. shutil.copytree(
  176. src=self.workingDir / dirname,
  177. dst=packageDir / dirname,
  178. symlinks=True,
  179. )
  180. shutil.copy2(
  181. src=self.workingDir / 'README.md',
  182. dst=packageDir / 'README.md',
  183. )
  184. shutil.copy2(
  185. src=self.workingDir / 'NvCloth/license.txt',
  186. dst=packageDir / 'NvCloth/license.txt',
  187. )
  188. shutil.copy2(
  189. src=self.workingDir / 'PxShared/license.txt',
  190. dst=packageDir / 'PxShared/license.txt',
  191. )
  192. def writePackageInfoFile(self, packageDir: pathlib.Path, settings: dict):
  193. with (packageDir / 'PackageInfo.json').open('w') as fh:
  194. json.dump(settings, fh, indent=4)
  195. def main():
  196. parser = argparse.ArgumentParser()
  197. parser.add_argument(
  198. '--platform-name',
  199. dest='platformName',
  200. choices=['windows', 'linux', 'linux-aarch64', 'android', 'mac', 'ios'],
  201. default=VcpkgBuilder.defaultPackagePlatformName(),
  202. )
  203. args = parser.parse_args()
  204. vcpkg_platform_map = {
  205. 'windows': 'windows',
  206. 'android': 'android',
  207. 'mac': 'mac',
  208. 'ios': 'ios',
  209. 'linux': 'linux',
  210. 'linux-aarch64': 'linux' }
  211. vcpkg_platform = vcpkg_platform_map[args.platformName]
  212. if args.platformName == 'linux-aarch64':
  213. os.environ['VCPKG_FORCE_SYSTEM_BINARIES'] = '1'
  214. packageSystemDir = Path(__file__).resolve().parents[1]
  215. packageSourceDir = packageSystemDir / 'NvCloth'
  216. packageRoot = packageSystemDir / f'NvCloth-{args.platformName}'
  217. cmakeFindFile = packageSourceDir / f'FindNvCloth_{vcpkg_platform}.cmake'
  218. if not cmakeFindFile.exists():
  219. cmakeFindFile = packageSourceDir / 'FindNvCloth.cmake'
  220. with TemporaryDirectory() as tempdir:
  221. tempdir = Path(tempdir)
  222. builder = NvClothBuilder(workingDir=tempdir, basePackageSystemDir=packageSystemDir, targetPlatform=vcpkg_platform)
  223. builder.clone('8e100cca5888d09f40f4721cc433f284b1841e65')
  224. builder.build()
  225. builder.copyBuildOutputTo(packageRoot/'NvCloth')
  226. # Version v1.1.6-4-gd243404-pr58 describes commit 8e100cc,
  227. # which is 4 commits above 1.1.6 release (commit d243404),
  228. # plus pull request 58 applied on top.
  229. builder.writePackageInfoFile(
  230. packageRoot,
  231. settings={
  232. 'PackageName': f'NvCloth-v1.1.6-4-gd243404-pr58-rev1-{args.platformName}',
  233. 'URL': 'https://github.com/NVIDIAGameWorks/NvCloth.git',
  234. 'License': 'custom',
  235. 'LicenseFile': 'NvCloth/NvCloth/license.txt',
  236. },
  237. )
  238. shutil.copy2(
  239. src=cmakeFindFile,
  240. dst=packageRoot / 'FindNvCloth.cmake'
  241. )
  242. if __name__ == '__main__':
  243. main()